Handling of initial contact
authorClavister OpenSource <opensource@clavister.com>
Fri, 9 Dec 2011 10:41:26 +0000 (11:41 +0100)
committerClavister OpenSource <opensource@clavister.com>
Tue, 20 Mar 2012 16:31:14 +0000 (17:31 +0100)
src/libcharon/sa/ike_sa.h [changed mode: 0644->0755]
src/libcharon/sa/ike_sa_manager.c [changed mode: 0644->0755]
src/libcharon/sa/tasks/main_mode.c

old mode 100644 (file)
new mode 100755 (executable)
index 27eab54..15fd35c
@@ -153,6 +153,11 @@ enum ike_condition_t {
         * IKE_SA is stale, the peer is currently unreachable (MOBIKE)
         */
        COND_STALE = (1<<7),
+
+       /**
+        * Initial contact received
+        */
+       COND_INIT_CONTACT_SEEN = (1<<8),
 };
 
 /**
old mode 100644 (file)
new mode 100755 (executable)
index ffbc2ec..776b2b7
@@ -1358,6 +1358,17 @@ METHOD(ike_sa_manager_t, checkin, void,
        if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
                entry->my_id == NULL && entry->other_id == NULL)
        {
+               if (ike_sa->get_version(ike_sa) == IKEV1)
+               {
+                       /* If authenticated and received INITIAL_CONTACT,
+                        * delete any existing IKE_SAs with that peer. */
+                       if (ike_sa->has_condition(ike_sa, COND_INIT_CONTACT_SEEN))
+                       {
+                               this->public.check_uniqueness(&this->public, ike_sa, TRUE);
+                               ike_sa->set_condition(ike_sa, COND_INIT_CONTACT_SEEN, FALSE);
+                       }
+               }
+
                entry->my_id = my_id->clone(my_id);
                entry->other_id = other_id->clone(other_id);
                if (!entry->other)
index ab38ec2..e1f583c 100755 (executable)
@@ -263,6 +263,52 @@ static auth_method_t get_auth_method(private_main_mode_t *this)
                        return AUTH_RSA;
        }
 }
+/**
+ * Check for notify errors, return TRUE if error found
+ */
+static bool has_notify_errors(private_main_mode_t *this, message_t *message)
+{
+       enumerator_t *enumerator;
+       payload_t *payload;
+       bool err = FALSE;
+
+       enumerator = message->create_payload_enumerator(message);
+       while (enumerator->enumerate(enumerator, &payload))
+       {
+               if (payload->get_type(payload) == NOTIFY_V1)
+               {
+                       notify_payload_t *notify;
+                       notify_type_t type;
+
+                       notify = (notify_payload_t*)payload;
+                       type = notify->get_notify_type(notify);
+                       if (type < 16384)
+                       {
+                               DBG1(DBG_IKE, "received %N error notify",
+                                        notify_type_names, type);
+                               err = TRUE;
+                       }
+                       else if (type == INITIAL_CONTACT_IKEV1)
+                       {
+                               if (!this->initiator && this->state == MM_AUTH)
+                               {
+                                       /* If authenticated and received INITIAL_CONTACT,
+                                        * delete any existing IKE_SAs with that peer.
+                                        * The delete takes place when the SA is checked in due
+                                        * to other id not known until the 3rd message.*/
+                                       this->ike_sa->set_condition(this->ike_sa, COND_INIT_CONTACT_SEEN, TRUE);
+                               }
+                       }
+                       else
+                       {
+                               DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       return err;
+}
 
 METHOD(task_t, build_i, status_t,
        private_main_mode_t *this, message_t *message)
@@ -503,6 +549,11 @@ METHOD(task_t, process_r, status_t,
                                return FAILED;
                        }
                        this->state = MM_AUTH;
+
+                       if (has_notify_errors(this, message))
+                       {
+                               return FAILED;
+                       }
                        return NEED_MORE;
                }
                default: