Install fallback drop policies to avoid transmitting unencrypted packets.
authorTobias Brunner <tobias@strongswan.org>
Wed, 27 Jul 2011 11:44:33 +0000 (13:44 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 27 Jul 2011 11:44:33 +0000 (13:44 +0200)
During the update of a CHILD_SA (e.g. caused by MOBIKE) the old policy
is first uninstalled and then the new one is installed.  In the short
time in between, where no policy is available in the kernel, unencrypted
packets could have been transmitted.

src/libcharon/sa/child_sa.c
src/libhydra/kernel/kernel_ipsec.h
src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c

index 4c97b52..e262a2b 100644 (file)
@@ -715,6 +715,17 @@ METHOD(child_sa_t, add_policies, status_t,
                enumerator = create_policy_enumerator(this);
                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                {
+                       /* install outbound drop policy to avoid packets leaving unencrypted
+                        * when updating policies */
+                       if (priority == POLICY_PRIORITY_DEFAULT)
+                       {
+                               status |= hydra->kernel_interface->add_policy(
+                                                       hydra->kernel_interface,
+                                                       this->my_addr, this->other_addr, my_ts, other_ts,
+                                                       POLICY_OUT, POLICY_DROP, &other_sa,
+                                                       this->mark_out, POLICY_PRIORITY_FALLBACK);
+                       }
+
                        /* install 3 policies: out, in and forward */
                        status |= hydra->kernel_interface->add_policy(
                                                        hydra->kernel_interface,
@@ -963,6 +974,12 @@ METHOD(child_sa_t, destroy, void,
                                                other_ts, my_ts, POLICY_FWD, this->reqid,
                                                this->mark_in, priority);
                        }
+                       if (priority == POLICY_PRIORITY_DEFAULT)
+                       {
+                               hydra->kernel_interface->del_policy(hydra->kernel_interface,
+                                               my_ts, other_ts, POLICY_OUT, this->reqid,
+                                               this->mark_out, POLICY_PRIORITY_FALLBACK);
+                       }
                }
                enumerator->destroy(enumerator);
        }
index 3759459..986e21f 100644 (file)
@@ -98,6 +98,8 @@ enum policy_priority_t {
        POLICY_PRIORITY_DEFAULT,
        /** Priority for trap policies */
        POLICY_PRIORITY_ROUTED,
+       /** Priority for fallback drop policies */
+       POLICY_PRIORITY_FALLBACK,
 };
 
 /**
index 26919a6..06720a0 100644 (file)
@@ -575,6 +575,9 @@ static inline u_int32_t get_priority(policy_entry_t *policy,
        u_int32_t priority = PRIO_BASE;
        switch (prio)
        {
+               case POLICY_PRIORITY_FALLBACK:
+                       priority <<= 1;
+                       /* fall-through */
                case POLICY_PRIORITY_ROUTED:
                        priority <<= 1;
                        /* fall-through */
index f96dbcf..2b07fc2 100644 (file)
@@ -509,6 +509,9 @@ static inline u_int32_t get_priority(policy_entry_t *policy,
        u_int32_t priority = PRIO_BASE;
        switch (prio)
        {
+               case POLICY_PRIORITY_FALLBACK:
+                       priority <<= 1;
+                       /* fall-through */
                case POLICY_PRIORITY_ROUTED:
                        priority <<= 1;
                        /* fall-through */