ha: Properly sync IKEv1 IV if gateway is initiator
authorTobias Brunner <tobias@strongswan.org>
Tue, 26 Jan 2016 10:13:13 +0000 (11:13 +0100)
committerTobias Brunner <tobias@strongswan.org>
Mon, 1 Feb 2016 09:51:02 +0000 (10:51 +0100)
To handle Phase 2 exchanges on the other HA host we need to sync the last
block of the last Phase 1 message (or the last expected IV).  If the
gateway is the initiator of a Main Mode SA the last message is an
inbound message.  When handling such messages the expected IV is not
updated until it is successfully decrypted so we can't sync the IV
when processing the still encrypted (!plain) message.  However, as responder,
i.e. if the last message is an outbound message, the reverse applies, that
is, we get the next IV after successfully encrypting the message, not
while handling the plain message.

Fixes #1267.

src/libcharon/plugins/ha/ha_ike.c

index f0671c5..3ffcaee 100644 (file)
@@ -314,27 +314,31 @@ METHOD(listener_t, message_hook, bool,
                        sync_vips(this, ike_sa);
                }
        }
                        sync_vips(this, ike_sa);
                }
        }
-       if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
+       if (ike_sa->get_version(ike_sa) == IKEV1)
        {
                ha_message_t *m;
                keymat_v1_t *keymat;
        {
                ha_message_t *m;
                keymat_v1_t *keymat;
-               u_int32_t mid;
                chunk_t iv;
 
                chunk_t iv;
 
-               mid = message->get_message_id(message);
-               if (mid == 0)
+               /* we need the last block (or expected next IV) of Phase 1, which gets
+                * upated after successful en-/decryption depending on direction */
+               if (incoming == plain)
                {
                {
-                       keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
-                       if (keymat->get_iv(keymat, mid, &iv))
+                       if (message->get_message_id(message) == 0)
                        {
                        {
-                               m = ha_message_create(HA_IKE_IV);
-                               m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
-                               m->add_attribute(m, HA_IV, iv);
-                               this->socket->push(this->socket, m);
-                               this->cache->cache(this->cache, ike_sa, m);
+                               keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+                               if (keymat->get_iv(keymat, 0, &iv))
+                               {
+                                       m = ha_message_create(HA_IKE_IV);
+                                       m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+                                       m->add_attribute(m, HA_IV, iv);
+                                       this->socket->push(this->socket, m);
+                                       this->cache->cache(this->cache, ike_sa, m);
+                               }
                        }
                }
                        }
                }
-               if (!incoming && message->get_exchange_type(message) == TRANSACTION)
+               if (!plain && !incoming &&
+                       message->get_exchange_type(message) == TRANSACTION)
                {
                        sync_vips(this, ike_sa);
                }
                {
                        sync_vips(this, ike_sa);
                }