]> git.ipfire.org Git - people/ms/strongswan.git/blobdiff - src/libcharon/sa/ike_sa.c
Merge branch 'ikev1-clean' into ikev1-master
[people/ms/strongswan.git] / src / libcharon / sa / ike_sa.c
index bcc98709c1b2d4ca23888ebcd237b66223491dd9..5d0a5aea8d97670087bbfc3d593b12be34a39e1d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -33,6 +33,7 @@
 #include <processing/jobs/send_dpd_job.h>
 #include <processing/jobs/send_keepalive_job.h>
 #include <processing/jobs/rekey_ike_sa_job.h>
+#include <sa/ikev2/tasks/ike_auth_lifetime.h>
 
 #ifdef ME
 #include <sa/ikev2/tasks/ike_me.h>
@@ -195,9 +196,9 @@ struct private_ike_sa_t {
        linked_list_t *attributes;
 
        /**
-        * list of peers additional addresses, transmitted via MOBIKE
+        * list of peer's addresses, additional ones transmitted via MOBIKE
         */
-       linked_list_t *additional_addresses;
+       linked_list_t *peer_addresses;
 
        /**
         * previously value of received DESTINATION_IP hash
@@ -668,7 +669,6 @@ METHOD(ike_sa_t, set_state, void,
                                        lib->scheduler->schedule_job(lib->scheduler, job, t);
                                        DBG1(DBG_IKE, "maximum IKE_SA lifetime %ds", t);
                                }
-
                                trigger_dpd = this->peer_cfg->get_dpd(this->peer_cfg);
                        }
                        break;
@@ -770,28 +770,28 @@ METHOD(ike_sa_t, get_virtual_ip, host_t*,
        }
 }
 
-METHOD(ike_sa_t, add_additional_address, void,
+METHOD(ike_sa_t, add_peer_address, void,
        private_ike_sa_t *this, host_t *host)
 {
-       this->additional_addresses->insert_last(this->additional_addresses, host);
+       this->peer_addresses->insert_last(this->peer_addresses, host);
 }
 
-METHOD(ike_sa_t, create_additional_address_enumerator, enumerator_t*,
+METHOD(ike_sa_t, create_peer_address_enumerator, enumerator_t*,
        private_ike_sa_t *this)
 {
-       return this->additional_addresses->create_enumerator(
-                                                                                               this->additional_addresses);
+       return this->peer_addresses->create_enumerator(this->peer_addresses);
 }
 
-METHOD(ike_sa_t, remove_additional_addresses, void,
+METHOD(ike_sa_t, clear_peer_addresses, void,
        private_ike_sa_t *this)
 {
-       enumerator_t *enumerator = create_additional_address_enumerator(this);
+       enumerator_t *enumerator = create_peer_address_enumerator(this);
        host_t *host;
+
        while (enumerator->enumerate(enumerator, (void**)&host))
        {
-               this->additional_addresses->remove_at(this->additional_addresses,
-                                                                                         enumerator);
+               this->peer_addresses->remove_at(this->peer_addresses,
+                                                                               enumerator);
                host->destroy(host);
        }
        enumerator->destroy(enumerator);
@@ -1386,17 +1386,25 @@ METHOD(ike_sa_t, reauth, status_t,
 #endif /* ME */
                        )
                {
-                       time_t now = time_monotonic(NULL);
+                       time_t del, now;
 
-                       DBG1(DBG_IKE, "IKE_SA will timeout in %V",
-                                &now, &this->stats[STAT_DELETE]);
+                       del = this->stats[STAT_DELETE];
+                       now = time_monotonic(NULL);
+                       DBG1(DBG_IKE, "IKE_SA %s[%d] will timeout in %V",
+                                get_name(this), this->unique_id, &now, &del);
                        return FAILED;
                }
                else
                {
-                       DBG1(DBG_IKE, "reauthenticating actively");
+                       DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d] actively",
+                                get_name(this), this->unique_id);
                }
        }
+       else
+       {
+               DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d]",
+                        get_name(this), this->unique_id);
+       }
        this->task_manager->queue_ike_reauth(this->task_manager);
        return this->task_manager->initiate(this->task_manager);
 }
@@ -1558,6 +1566,7 @@ METHOD(ike_sa_t, retransmit, status_t,
                                        DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
                                                 this->keyingtry + 1, tries);
                                        reset(this);
+                                       resolve_hosts(this);
                                        this->task_manager->queue_ike(this->task_manager);
                                        return this->task_manager->initiate(this->task_manager);
                                }
@@ -1579,35 +1588,67 @@ METHOD(ike_sa_t, retransmit, status_t,
        return SUCCESS;
 }
 
-METHOD(ike_sa_t, set_auth_lifetime, void,
+METHOD(ike_sa_t, set_auth_lifetime, status_t,
        private_ike_sa_t *this, u_int32_t lifetime)
 {
-       u_int32_t reduction = this->peer_cfg->get_over_time(this->peer_cfg);
-       u_int32_t reauth_time = time_monotonic(NULL) + lifetime - reduction;
+       u_int32_t diff, hard, soft, now;
+       ike_auth_lifetime_t *task;
+       bool send_update;
+
+       diff = this->peer_cfg->get_over_time(this->peer_cfg);
+       now = time_monotonic(NULL);
+       hard = now + lifetime;
+       soft = hard - diff;
 
-       if (lifetime < reduction)
+       /* check if we have to send an AUTH_LIFETIME to enforce the new lifetime.
+        * We send the notify in IKE_AUTH if not yet ESTABLISHED. */
+       send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 &&
+                                 !has_condition(this, COND_ORIGINAL_INITIATOR) &&
+                                 (this->other_virtual_ip != NULL ||
+                                 has_condition(this, COND_EAP_AUTHENTICATED));
+
+       if (lifetime < diff)
        {
-               DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, starting reauthentication",
-                        lifetime);
-               lib->processor->queue_job(lib->processor,
+               this->stats[STAT_REAUTH] = now;
+
+               if (!send_update)
+               {
+                       DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
+                                "starting reauthentication", lifetime);
+                       lib->processor->queue_job(lib->processor,
                                        (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
+               }
        }
        else if (this->stats[STAT_REAUTH] == 0 ||
-                        this->stats[STAT_REAUTH] > reauth_time)
+                        this->stats[STAT_REAUTH] > soft)
        {
-               this->stats[STAT_REAUTH] = reauth_time;
-               DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
-                        " in %ds", lifetime, lifetime - reduction);
-               lib->scheduler->schedule_job(lib->scheduler,
+               this->stats[STAT_REAUTH] = soft;
+               if (!send_update)
+               {
+                       DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling "
+                                "reauthentication in %ds", lifetime, lifetime - diff);
+                       lib->scheduler->schedule_job(lib->scheduler,
                                                (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE),
-                                               lifetime - reduction);
+                                               lifetime - diff);
+               }
        }
        else
        {
                DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
                         "reauthentication already scheduled in %ds", lifetime,
                         this->stats[STAT_REAUTH] - time_monotonic(NULL));
+               send_update = FALSE;
        }
+       /* give at least some seconds to reauthenticate */
+       this->stats[STAT_DELETE] = max(hard, now + 10);
+
+       if (send_update)
+       {
+               task = ike_auth_lifetime_create(&this->public, TRUE);
+               this->task_manager->queue_task(this->task_manager, &task->task);
+               return this->task_manager->initiate(this->task_manager);
+       }
+       return SUCCESS;
 }
 
 /**
@@ -1639,25 +1680,20 @@ static bool is_any_path_valid(private_ike_sa_t *this)
        bool valid = FALSE;
        enumerator_t *enumerator;
        host_t *src, *addr;
+
        DBG1(DBG_IKE, "old path is not available anymore, try to find another");
-       src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
-                                                                                                  this->other_host, NULL);
-       if (!src)
+       enumerator = this->peer_addresses->create_enumerator(this->peer_addresses);
+       while (enumerator->enumerate(enumerator, &addr))
        {
-               enumerator = this->additional_addresses->create_enumerator(
-                                                                                               this->additional_addresses);
-               while (enumerator->enumerate(enumerator, &addr))
+               DBG1(DBG_IKE, "looking for a route to %H ...", addr);
+               src = hydra->kernel_interface->get_source_addr(
+                                                                               hydra->kernel_interface, addr, NULL);
+               if (src)
                {
-                       DBG1(DBG_IKE, "looking for a route to %H ...", addr);
-                       src = hydra->kernel_interface->get_source_addr(
-                                                                       hydra->kernel_interface, addr, NULL);
-                       if (src)
-                       {
-                               break;
-                       }
+                       break;
                }
-               enumerator->destroy(enumerator);
        }
+       enumerator->destroy(enumerator);
        if (src)
        {
                valid = TRUE;
@@ -1900,8 +1936,8 @@ METHOD(ike_sa_t, destroy, void,
                }
                this->other_virtual_ip->destroy(this->other_virtual_ip);
        }
-       this->additional_addresses->destroy_offset(this->additional_addresses,
-                                                                                                       offsetof(host_t, destroy));
+       this->peer_addresses->destroy_offset(this->peer_addresses,
+                                                                                offsetof(host_t, destroy));
 #ifdef ME
        if (this->is_mediation_server)
        {
@@ -1990,9 +2026,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
                        .has_condition = _has_condition,
                        .set_pending_updates = _set_pending_updates,
                        .get_pending_updates = _get_pending_updates,
-                       .create_additional_address_enumerator = _create_additional_address_enumerator,
-                       .add_additional_address = _add_additional_address,
-                       .remove_additional_addresses = _remove_additional_addresses,
+                       .create_peer_address_enumerator = _create_peer_address_enumerator,
+                       .add_peer_address = _add_peer_address,
+                       .clear_peer_addresses = _clear_peer_addresses,
                        .has_mapping_changed = _has_mapping_changed,
                        .retransmit = _retransmit,
                        .delete = _delete_,
@@ -2051,7 +2087,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
                .my_auths = linked_list_create(),
                .other_auths = linked_list_create(),
                .unique_id = ++unique_id,
-               .additional_addresses = linked_list_create(),
+               .peer_addresses = linked_list_create(),
                .attributes = linked_list_create(),
                .keepalive_interval = lib->settings->get_time(lib->settings,
                                                                        "charon.keep_alive", KEEPALIVE_INTERVAL),