Send an AUTH_LIFETIME update after updating the lifetime, but can not reauth actively
authorMartin Willi <martin@revosec.ch>
Wed, 22 Feb 2012 15:07:31 +0000 (16:07 +0100)
committerMartin Willi <martin@revosec.ch>
Mon, 5 Mar 2012 17:06:14 +0000 (18:06 +0100)
src/libcharon/sa/ike_sa.c
src/libcharon/sa/ike_sa.h
src/libcharon/sa/task_manager.c

index 530d535..8fa49b3 100644 (file)
@@ -1774,42 +1774,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 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;
 
+       /* 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 &&
+                                 !has_condition(this, COND_ORIGINAL_INITIATOR) &&
+                                 (this->other_virtual_ip != NULL ||
+                                 has_condition(this, COND_EAP_AUTHENTICATED));
+
        if (lifetime < diff)
        {
                this->stats[STAT_REAUTH] = now;
-               DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, starting reauthentication",
-                        lifetime);
-               lib->processor->queue_job(lib->processor,
+
+               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] > soft)
        {
                this->stats[STAT_REAUTH] = soft;
-               DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
-                        " in %ds", lifetime, lifetime - diff);
-               lib->scheduler->schedule_job(lib->scheduler,
+               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 - 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;
 }
 
 /**
index cf23de3..85fb464 100644 (file)
@@ -869,11 +869,15 @@ struct ike_sa_t {
        status_t (*reestablish) (ike_sa_t *this);
 
        /**
-        * Set the lifetime limit received from a AUTH_LIFETIME notify.
+        * Set the lifetime limit received/to send in a AUTH_LIFETIME notify.
+        *
+        * If the IKE_SA is already ESTABLISHED, an INFORMATIONAL is sent with
+        * an AUTH_LIFETIME notify. The call never fails on unestablished SAs.
         *
         * @param lifetime              lifetime in seconds
+        * @return                              DESTROY_ME to destroy the IKE_SA
         */
-       void (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
+       status_t (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
 
        /**
         * Set the virtual IP to use for this IKE_SA and its children.
index dad533b..7cdcf70 100644 (file)
@@ -366,6 +366,11 @@ METHOD(task_manager_t, initiate, status_t,
                                        exchange = INFORMATIONAL;
                                        break;
                                }
+                               if (activate_task(this, IKE_AUTH_LIFETIME))
+                               {
+                                       exchange = INFORMATIONAL;
+                                       break;
+                               }
 #ifdef ME
                                if (activate_task(this, IKE_ME))
                                {