child-rekey: Only rekey installed CHILD_SAs
authorTobias Brunner <tobias@strongswan.org>
Fri, 10 Jun 2016 14:00:25 +0000 (16:00 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 17 Jun 2016 16:48:08 +0000 (18:48 +0200)
Depending on the lifetimes a CHILD_SA we rekeyed as responder might
expire shortly afterwards.  We don't want to rekey it again.

When retrying due to an INVALID_KE_PAYLOAD notify the expected state
is CHILD_REKEYING if it is anything else (e.g. due to a collision) we
ignore it.

We also abort the exchange properly if we don't find the CHILD_SA, no
need for an empty INFORMATIONAL exchange anymore.

src/libcharon/sa/ikev2/tasks/child_rekey.c

index 95e4a3d..c04ec14 100644 (file)
@@ -160,14 +160,21 @@ METHOD(task_t, build_i, status_t,
        {       /* check if it is an outbound CHILD_SA */
                this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
                                                                                                        this->spi, FALSE);
-               if (!this->child_sa)
-               {       /* CHILD_SA is gone, unable to rekey. As an empty CREATE_CHILD_SA
-                        * exchange is invalid, we fall back to an INFORMATIONAL exchange.*/
-                       message->set_exchange_type(message, INFORMATIONAL);
-                       return SUCCESS;
+               if (this->child_sa)
+               {
+                       /* we work only with the inbound SPI */
+                       this->spi = this->child_sa->get_spi(this->child_sa, TRUE);
                }
-               /* we work only with the inbound SPI */
-               this->spi = this->child_sa->get_spi(this->child_sa, TRUE);
+       }
+       if (!this->child_sa ||
+               (!this->child_create &&
+                 this->child_sa->get_state(this->child_sa) != CHILD_INSTALLED) ||
+               (this->child_create &&
+                this->child_sa->get_state(this->child_sa) != CHILD_REKEYING))
+       {
+               /* CHILD_SA is gone or in the wrong state, unable to rekey */
+               message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
+               return SUCCESS;
        }
        config = this->child_sa->get_config(this->child_sa);