Integrated main parts of IKE_REAUTH task into ike_sa_t.reestablish.
authorTobias Brunner <tobias@strongswan.org>
Wed, 9 May 2012 13:14:34 +0000 (15:14 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 25 May 2012 15:05:53 +0000 (17:05 +0200)
src/libcharon/sa/ike_sa.c
src/libcharon/sa/ikev2/tasks/ike_reauth.c

index 30b3afe..71a0729 100644 (file)
@@ -239,6 +239,11 @@ struct private_ike_sa_t {
         * Flush auth configs once established?
         */
        bool flush_auth_cfg;
+
+       /**
+        * TRUE if we are currently reauthenticating this IKE_SA
+        */
+       bool is_reauthenticating;
 };
 
 /**
@@ -1411,6 +1416,7 @@ METHOD(ike_sa_t, reauth, status_t,
                DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d]",
                         get_name(this), this->unique_id);
        }
+       this->is_reauthenticating = TRUE;
        this->task_manager->queue_ike_reauth(this->task_manager);
        return this->task_manager->initiate(this->task_manager);
 }
@@ -1427,39 +1433,58 @@ METHOD(ike_sa_t, reestablish, status_t,
        bool restart = FALSE;
        status_t status = FAILED;
 
-       /* check if we have children to keep up at all */
-       enumerator = this->child_sas->create_enumerator(this->child_sas);
-       while (enumerator->enumerate(enumerator, (void**)&child_sa))
-       {
-               if (this->state == IKE_DELETING)
+       if (this->is_reauthenticating)
+       {       /* only reauthenticate if we have children */
+               if (this->child_sas->get_count(this->child_sas) == 0
+#ifdef ME
+                       /* allow reauth of mediation connections without CHILD_SAs */
+                       && !this->peer_cfg->is_mediation(this->peer_cfg)
+#endif /* ME */
+                       )
                {
-                       action = child_sa->get_close_action(child_sa);
+                       DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA "
+                                "to recreate");
                }
                else
                {
-                       action = child_sa->get_dpd_action(child_sa);
+                       restart = TRUE;
                }
-               switch (action)
+       }
+       else
+       {       /* check if we have children to keep up at all */
+               enumerator = this->child_sas->create_enumerator(this->child_sas);
+               while (enumerator->enumerate(enumerator, (void**)&child_sa))
                {
-                       case ACTION_RESTART:
-                               restart = TRUE;
-                               break;
-                       case ACTION_ROUTE:
-                               charon->traps->install(charon->traps, this->peer_cfg,
-                                                                          child_sa->get_config(child_sa));
-                               break;
-                       default:
-                               break;
+                       if (this->state == IKE_DELETING)
+                       {
+                               action = child_sa->get_close_action(child_sa);
+                       }
+                       else
+                       {
+                               action = child_sa->get_dpd_action(child_sa);
+                       }
+                       switch (action)
+                       {
+                               case ACTION_RESTART:
+                                       restart = TRUE;
+                                       break;
+                               case ACTION_ROUTE:
+                                       charon->traps->install(charon->traps, this->peer_cfg,
+                                                                                  child_sa->get_config(child_sa));
+                                       break;
+                               default:
+                                       break;
+                       }
                }
-       }
-       enumerator->destroy(enumerator);
+               enumerator->destroy(enumerator);
 #ifdef ME
-       /* mediation connections have no children, keep them up anyway */
-       if (this->peer_cfg->is_mediation(this->peer_cfg))
-       {
-               restart = TRUE;
-       }
+               /* mediation connections have no children, keep them up anyway */
+               if (this->peer_cfg->is_mediation(this->peer_cfg))
+               {
+                       restart = TRUE;
+               }
 #endif /* ME */
+       }
        if (!restart)
        {
                return FAILED;
@@ -1507,13 +1532,34 @@ METHOD(ike_sa_t, reestablish, status_t,
                enumerator = this->child_sas->create_enumerator(this->child_sas);
                while (enumerator->enumerate(enumerator, (void**)&child_sa))
                {
-                       if (this->state == IKE_DELETING)
+                       if (this->is_reauthenticating)
                        {
-                               action = child_sa->get_close_action(child_sa);
+                               switch (child_sa->get_state(child_sa))
+                               {
+                                       case CHILD_ROUTED:
+                                       {       /* move routed child directly */
+                                               this->child_sas->remove_at(this->child_sas, enumerator);
+                                               new->add_child_sa(new, child_sa);
+                                               action = ACTION_NONE;
+                                               break;
+                                       }
+                                       default:
+                                       {       /* initiate/queue all other CHILD_SAs */
+                                               action = ACTION_RESTART;
+                                               break;
+                                       }
+                               }
                        }
                        else
-                       {
-                               action = child_sa->get_dpd_action(child_sa);
+                       {       /* only restart CHILD_SAs that are configured accordingly */
+                               if (this->state == IKE_DELETING)
+                               {
+                                       action = child_sa->get_close_action(child_sa);
+                               }
+                               else
+                               {
+                                       action = child_sa->get_dpd_action(child_sa);
+                               }
                        }
                        switch (action)
                        {
index 8371b8b..6f90339 100644 (file)
@@ -51,100 +51,16 @@ METHOD(task_t, build_i, status_t,
 METHOD(task_t, process_i, status_t,
        private_ike_reauth_t *this, message_t *message)
 {
-       ike_sa_t *new;
-       host_t *host;
-       enumerator_t *enumerator;
-       child_sa_t *child_sa;
-       peer_cfg_t *peer_cfg;
-
        /* process delete response first */
        this->ike_delete->task.process(&this->ike_delete->task, message);
 
-       peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-
-       /* reauthenticate only if we have children */
-       if (this->ike_sa->get_child_count(this->ike_sa) == 0
-#ifdef ME
-               /* we allow peers to reauth mediation connections (without children) */
-               && !peer_cfg->is_mediation(peer_cfg)
-#endif /* ME */
-               )
+       /* reestablish the IKE_SA with all children */
+       if (this->ike_sa->reestablish(this->ike_sa) != SUCCESS)
        {
-               DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate");
+               DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
                return FAILED;
        }
 
-       new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
-                                                               this->ike_sa->get_version(this->ike_sa), TRUE);
-       if (!new)
-       {       /* shouldn't happen */
-               return FAILED;
-       }
-
-       new->set_peer_cfg(new, peer_cfg);
-       host = this->ike_sa->get_other_host(this->ike_sa);
-       new->set_other_host(new, host->clone(host));
-       host = this->ike_sa->get_my_host(this->ike_sa);
-       new->set_my_host(new, host->clone(host));
-       /* if we already have a virtual IP, we reuse it */
-       host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
-       if (host)
-       {
-               new->set_virtual_ip(new, TRUE, host);
-       }
-
-#ifdef ME
-       /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */
-       if (peer_cfg->is_mediation(peer_cfg))
-       {
-               if (new->initiate(new, NULL, 0, NULL, NULL) == DESTROY_ME)
-               {
-                       charon->ike_sa_manager->checkin_and_destroy(
-                                                               charon->ike_sa_manager, new);
-                       /* set threads active IKE_SA after checkin */
-                       charon->bus->set_sa(charon->bus, this->ike_sa);
-                       DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
-                       return FAILED;
-               }
-       }
-#endif /* ME */
-
-       enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
-       while (enumerator->enumerate(enumerator, (void**)&child_sa))
-       {
-               switch (child_sa->get_state(child_sa))
-               {
-                       case CHILD_ROUTED:
-                       {
-                               /* move routed child directly */
-                               this->ike_sa->remove_child_sa(this->ike_sa, enumerator);
-                               new->add_child_sa(new, child_sa);
-                               break;
-                       }
-                       default:
-                       {
-                               /* initiate/queue all child SAs */
-                               child_cfg_t *child_cfg = child_sa->get_config(child_sa);
-                               child_cfg->get_ref(child_cfg);
-                               if (new->initiate(new, child_cfg, 0, NULL, NULL) == DESTROY_ME)
-                               {
-                                       enumerator->destroy(enumerator);
-                                       charon->ike_sa_manager->checkin_and_destroy(
-                                                                               charon->ike_sa_manager, new);
-                                       /* set threads active IKE_SA after checkin */
-                                       charon->bus->set_sa(charon->bus, this->ike_sa);
-                                       DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
-                                       return FAILED;
-                               }
-                               break;
-                       }
-               }
-       }
-       enumerator->destroy(enumerator);
-       charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
-       /* set threads active IKE_SA after checkin */
-       charon->bus->set_sa(charon->bus, this->ike_sa);
-
        /* we always destroy the obsolete IKE_SA */
        return DESTROY_ME;
 }