child-sa: Fix refcounting of allocated reqids
authorTobias Brunner <tobias@strongswan.org>
Fri, 31 Jul 2015 14:51:35 +0000 (16:51 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 17 Aug 2015 09:59:15 +0000 (11:59 +0200)
During a rekeying we want to reuse the current reqid, but if the new SA
does not allocate it via kernel-interface the state there will disappear
when the old SA is destroyed after the rekeying.  When the IKE_SA is
later reauthenticated with make-before-break reauthentication the new
CHILD_SAs there will get new reqids as no existing state is found in the
kernel-interface, breaking policy installation in the kernel.

Fixes: a49393954f31 ("child-sa: Use any fixed reqid configured on the CHILD_SA config")

src/libcharon/sa/child_sa.c

index 94cf07c..73f2ec9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
  * Copyright (C) 2005-2008 Martin Willi
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005 Jan Hutter
@@ -106,6 +106,11 @@ struct private_child_sa_t {
         */
        bool reqid_allocated;
 
+       /**
+        * Is the reqid statically configured
+        */
+       bool static_reqid;
+
        /*
         * Unique CHILD_SA identifier
         */
@@ -698,7 +703,7 @@ METHOD(child_sa_t, install, status_t,
        this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
                                                                  &esn, NULL);
 
-       if (!this->reqid_allocated && !this->reqid)
+       if (!this->reqid_allocated && !this->static_reqid)
        {
                status = hydra->kernel_interface->alloc_reqid(hydra->kernel_interface,
                                                        my_ts, other_ts, this->mark_in, this->mark_out,
@@ -826,7 +831,7 @@ METHOD(child_sa_t, add_policies, status_t,
        traffic_selector_t *my_ts, *other_ts;
        status_t status = SUCCESS;
 
-       if (!this->reqid_allocated && !this->reqid)
+       if (!this->reqid_allocated && !this->static_reqid)
        {
                /* trap policy, get or confirm reqid */
                status = hydra->kernel_interface->alloc_reqid(
@@ -1305,6 +1310,10 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
                        this->reqid = charon->traps->find_reqid(charon->traps, config);
                }
        }
+       else
+       {
+               this->static_reqid = TRUE;
+       }
 
        /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
        if (config->get_mode(config) == MODE_TRANSPORT &&