moved AUTH_LIFETIME handling in its own task (cleaner separation, proper payload...
authorMartin Willi <martin@strongswan.org>
Mon, 3 Dec 2007 10:52:18 +0000 (10:52 -0000)
committerMartin Willi <martin@strongswan.org>
Mon, 3 Dec 2007 10:52:18 +0000 (10:52 -0000)
src/charon/Makefile.am
src/charon/sa/ike_sa.c
src/charon/sa/task_manager.c
src/charon/sa/tasks/ike_auth.c
src/charon/sa/tasks/ike_auth_lifetime.c [new file with mode: 0644]
src/charon/sa/tasks/ike_auth_lifetime.h [new file with mode: 0644]
src/charon/sa/tasks/task.c
src/charon/sa/tasks/task.h

index 8e53d22..bbefb29 100644 (file)
@@ -83,6 +83,7 @@ sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
 sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
 sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
 sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
+sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
 sa/tasks/task.c sa/tasks/task.h
 
 if USE_RAW_SOCKET
index 798b0e7..673429a 100644 (file)
@@ -51,6 +51,7 @@
 #include <sa/tasks/ike_natd.h>
 #include <sa/tasks/ike_mobike.h>
 #include <sa/tasks/ike_auth.h>
+#include <sa/tasks/ike_auth_lifetime.h>
 #include <sa/tasks/ike_config.h>
 #include <sa/tasks/ike_cert.h>
 #include <sa/tasks/ike_rekey.h>
@@ -258,6 +259,11 @@ struct private_ike_sa_t {
         * how many times we have retried so far (keyingtries)
         */
        u_int32_t keyingtry;
+       
+       /**
+        * are we the initiator of this IKE_SA (rekeying does not affect this flag)
+        */
+       bool ike_initiator;
 };
 
 /**
@@ -1007,6 +1013,8 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
                        return DESTROY_ME;
                }
                
+               this->ike_initiator = TRUE;
+               
                task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
                this->task_manager->queue_task(this->task_manager, task);
                task = (task_t*)ike_natd_create(&this->public, TRUE);
@@ -1017,6 +1025,8 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
                this->task_manager->queue_task(this->task_manager, task);
                task = (task_t*)ike_config_create(&this->public, TRUE);
                this->task_manager->queue_task(this->task_manager, task);
+               task = (task_t*)ike_auth_lifetime_create(&this->public, TRUE);
+               this->task_manager->queue_task(this->task_manager, task);
                if (this->peer_cfg->use_mobike(this->peer_cfg))
                {
                        task = (task_t*)ike_mobike_create(&this->public, TRUE);
@@ -1107,6 +1117,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
                this->task_manager->queue_task(this->task_manager, task);
                task = (task_t*)ike_config_create(&this->public, TRUE);
                this->task_manager->queue_task(this->task_manager, task);
+               task = (task_t*)ike_auth_lifetime_create(&this->public, TRUE);
+               this->task_manager->queue_task(this->task_manager, task);
                if (this->peer_cfg->use_mobike(this->peer_cfg))
                {
                        task = (task_t*)ike_mobike_create(&this->public, TRUE);
@@ -1501,6 +1513,8 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
                                        task = (task_t*)child_create_create(&new->public, child_cfg);
                                        new->task_manager->queue_task(new->task_manager, task);
                                }               
+                               task = (task_t*)ike_auth_lifetime_create(&new->public, TRUE);
+                               new->task_manager->queue_task(new->task_manager, task);
                                if (this->peer_cfg->use_mobike(this->peer_cfg))
                                {
                                        task = (task_t*)ike_mobike_create(&new->public, TRUE);
@@ -1938,7 +1952,7 @@ static status_t reestablish(private_ike_sa_t *this)
        /* we can't reauthenticate as responder when we use EAP or virtual IPs.
         * If the peer does not support RFC4478, there is no way to keep the
         * IKE_SA up. */
-       if (!this->ike_sa_id->is_initiator(this->ike_sa_id))
+       if (!this->ike_initiator)
        {
                DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
                if (this->other_virtual_ip != NULL ||
@@ -2055,6 +2069,7 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
        this->other_host = other->other_host->clone(other->other_host);
        this->my_id = other->my_id->clone(other->my_id);
        this->other_id = other->other_id->clone(other->other_id);
+       this->ike_initiator = other->ike_initiator;
        
        /* apply virtual assigned IPs... */
        if (other->my_virtual_ip)
@@ -2405,6 +2420,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->additional_addresses = linked_list_create();
        this->pending_updates = 0;
        this->keyingtry = 0;
+       this->ike_initiator = FALSE;
 #ifdef P2P
        this->server_reflexive_host = NULL;
 #endif /* P2P */
index ef00014..8522a59 100644 (file)
@@ -30,6 +30,7 @@
 #include <sa/tasks/ike_natd.h>
 #include <sa/tasks/ike_mobike.h>
 #include <sa/tasks/ike_auth.h>
+#include <sa/tasks/ike_auth_lifetime.h>
 #include <sa/tasks/ike_cert.h>
 #include <sa/tasks/ike_rekey.h>
 #include <sa/tasks/ike_delete.h>
@@ -338,6 +339,7 @@ static status_t build_request(private_task_manager_t *this)
                                        activate_task(this, IKE_AUTHENTICATE);
                                        activate_task(this, IKE_CONFIG);
                                        activate_task(this, CHILD_CREATE);
+                                       activate_task(this, IKE_AUTH_LIFETIME);
                                        activate_task(this, IKE_MOBIKE);
                                }
                                break;
@@ -690,13 +692,15 @@ static status_t process_request(private_task_manager_t *this,
 #ifdef P2P                     
                        task = (task_t*)ike_p2p_create(this->ike_sa, FALSE);
                        this->passive_tasks->insert_last(this->passive_tasks, task);
-#endif /* P2P */                       
+#endif /* P2P */
                        task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
                        this->passive_tasks->insert_last(this->passive_tasks, task);
                        task = (task_t*)ike_config_create(this->ike_sa, FALSE);
                        this->passive_tasks->insert_last(this->passive_tasks, task);
                        task = (task_t*)child_create_create(this->ike_sa, NULL);
                        this->passive_tasks->insert_last(this->passive_tasks, task);
+                       task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
+                       this->passive_tasks->insert_last(this->passive_tasks, task);
                        task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
                        this->passive_tasks->insert_last(this->passive_tasks, task);
                        break;
@@ -772,18 +776,15 @@ static status_t process_request(private_task_manager_t *this,
                                                        case UNACCEPTABLE_ADDRESSES:
                                                        case UNEXPECTED_NAT_DETECTED:
                                                        case COOKIE2:
-                                                               task = (task_t*)ike_mobike_create(this->ike_sa,
-                                                                                                                                 FALSE);
-                                                               break;
-                                                       default:
+                                                               task = (task_t*)ike_mobike_create(
+                                                                                                               this->ike_sa, FALSE);
                                                                break;
                                                        case AUTH_LIFETIME:
-                                                       {       /* hackish: a separate task would be overkill here */
-                                                               chunk_t data = notify->get_notification_data(notify);
-                                                               u_int32_t lifetime = ntohl(*(u_int32_t*)data.ptr);
-                                                               this->ike_sa->set_auth_lifetime(this->ike_sa, lifetime);
+                                                               task = (task_t*)ike_auth_lifetime_create(
+                                                                                                               this->ike_sa, FALSE);
+                                                               break;
+                                                       default:
                                                                break;
-                                                       }
                                                }
                                                break;
                                        }
index 0a9aef2..e8fab1d 100644 (file)
@@ -297,22 +297,6 @@ static status_t collect_other_init_data(private_ike_auth_t *this, message_t *mes
        return NEED_MORE; 
 }
 
-/**
- * add the AUTH_LIFETIME notify to the message
- */
-static void add_auth_lifetime(private_ike_auth_t *this, message_t *message)
-{
-       chunk_t chunk;
-       u_int32_t lifetime;
-       
-       lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH_TIME);
-       if (lifetime)
-       {
-               chunk = chunk_from_thing(lifetime);
-               *(u_int32_t*)chunk.ptr = htonl(lifetime);
-               message->add_notify(message, FALSE, AUTH_LIFETIME, chunk);
-       }
-}
 
 /**
  * Implementation of task_t.build to create AUTH payload from EAP data
@@ -343,7 +327,6 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
                        this->ike_sa->get_my_host(this->ike_sa),
                        this->ike_sa->get_other_host(this->ike_sa),
                        this->ike_sa->get_other_id(this->ike_sa));
-               add_auth_lifetime(this, message);
                return SUCCESS;
        }
        return NEED_MORE;
@@ -600,7 +583,6 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
                        this->ike_sa->get_my_host(this->ike_sa),
                        this->ike_sa->get_other_host(this->ike_sa),
                        this->ike_sa->get_other_id(this->ike_sa));
-               add_auth_lifetime(this, message);
                return SUCCESS;
        }
        
@@ -666,12 +648,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
                                        /* handled in ike_mobike task */
                                        break;
                                case AUTH_LIFETIME:
-                               {
-                                       chunk_t data = notify->get_notification_data(notify);
-                                       u_int32_t lifetime = ntohl(*(u_int32_t*)data.ptr);
-                                       this->ike_sa->set_auth_lifetime(this->ike_sa, lifetime);
+                                       /* handled in ike_auth_lifetime task */
                                        break;
-                               }
                                default:
                                {
                                        if (type < 16383)
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c
new file mode 100644 (file)
index 0000000..8820afd
--- /dev/null
@@ -0,0 +1,200 @@
+/**
+ * @file ike_auth_lifetime.c
+ *
+ * @brief Implementation of the ike_auth_lifetime task.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "ike_auth_lifetime.h"
+
+#include <daemon.h>
+#include <encoding/payloads/notify_payload.h>
+
+
+typedef struct private_ike_auth_lifetime_t private_ike_auth_lifetime_t;
+
+/**
+ * Private members of a ike_auth_lifetime_t task.
+ */
+struct private_ike_auth_lifetime_t {
+       
+       /**
+        * Public methods and task_t interface.
+        */
+       ike_auth_lifetime_t public;
+       
+       /**
+        * Assigned IKE_SA.
+        */
+       ike_sa_t *ike_sa;
+};
+
+/**
+ * add the AUTH_LIFETIME notify to the message
+ */
+static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *message)
+{
+       chunk_t chunk;
+       u_int32_t lifetime;
+       
+       lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH_TIME);
+       if (lifetime)
+       {
+               chunk = chunk_from_thing(lifetime);
+               *(u_int32_t*)chunk.ptr = htonl(lifetime);
+               message->add_notify(message, FALSE, AUTH_LIFETIME, chunk);
+       }
+}
+
+/**
+ * read notifys from message and evaluate them
+ */
+static void process_payloads(private_ike_auth_lifetime_t *this, message_t *message)
+{
+       iterator_t *iterator;
+       payload_t *payload;
+       notify_payload_t *notify;
+       
+       iterator = message->get_payload_iterator(message);
+       while (iterator->iterate(iterator, (void**)&payload))
+       {
+               if (payload->get_type(payload) == NOTIFY)
+               {
+                       notify = (notify_payload_t*)payload;
+                       switch (notify->get_notify_type(notify))
+                       {
+                               case AUTH_LIFETIME:                                     
+                               {
+                                       chunk_t data = notify->get_notification_data(notify);
+                                       u_int32_t lifetime = ntohl(*(u_int32_t*)data.ptr);
+                                       this->ike_sa->set_auth_lifetime(this->ike_sa, lifetime);
+                                       break;
+                               }
+                               default:
+                                       break;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_auth_lifetime_t *this, message_t *message)
+{
+       if (message->get_exchange_type(message) == INFORMATIONAL)
+       {
+               add_auth_lifetime(this, message);
+               return SUCCESS;
+       }
+       return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_auth_lifetime_t *this, message_t *message)
+{
+       if (message->get_exchange_type(message) == INFORMATIONAL)
+       {
+               process_payloads(this, message);
+               return SUCCESS;
+       }
+       return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_auth_lifetime_t *this, message_t *message)
+{
+       if (message->get_exchange_type(message) == IKE_AUTH &&
+               message->get_payload(message, SECURITY_ASSOCIATION))
+       {
+               add_auth_lifetime(this, message);
+               return SUCCESS;
+       }
+       return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_auth_lifetime_t *this, message_t *message)
+{
+       if (message->get_exchange_type(message) == IKE_AUTH &&
+               message->get_payload(message, SECURITY_ASSOCIATION))
+       {
+               process_payloads(this, message);
+               return SUCCESS;
+       }
+       return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_auth_lifetime_t *this)
+{
+       return IKE_AUTH_LIFETIME;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_auth_lifetime_t *this, ike_sa_t *ike_sa)
+{
+       this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_auth_lifetime_t *this)
+{
+       free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator)
+{
+       private_ike_auth_lifetime_t *this = malloc_thing(private_ike_auth_lifetime_t);
+
+       this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+       this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+       this->public.task.destroy = (void(*)(task_t*))destroy;
+       
+       if (initiator)
+       {
+               this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+               this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+       }
+       else
+       {
+               this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+               this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+       }
+       
+       this->ike_sa = ike_sa;
+       
+       return &this->public;
+}
+
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.h b/src/charon/sa/tasks/ike_auth_lifetime.h
new file mode 100644 (file)
index 0000000..500b89d
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * @file ike_auth_lifetime.h
+ * 
+ * @brief Interface ike_auth_lifetime_t.
+ * 
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef IKE_AUTH_LIFETIME_H_
+#define IKE_AUTH_LIFETIME_H_
+
+typedef struct ike_auth_lifetime_t ike_auth_lifetime_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * @brief Task of type IKE_AUTH_LIFETIME, implements RFC4478.
+ *
+ * This task exchanges lifetimes for IKE_AUTH to force a client to 
+ * reauthenticate before the responders lifetime reaches the limit.
+ *
+ * @b Constructors:
+ *  - ike_auth_lifetime_create()
+ * 
+ * @ingroup tasks
+ */
+struct ike_auth_lifetime_t {
+
+       /**
+        * Implements the task_t interface
+        */
+       task_t task;
+};
+
+/**
+ * @brief Create a new IKE_AUTH_LIFETIME task.
+ *
+ * @param ike_sa               IKE_SA this task works for
+ * @param initiator            TRUE if taks is initiated by us
+ * @return                             ike_auth_lifetime task to handle by the task_manager
+ */
+ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /* IKE_MOBIKE_H_ */
+
index e9d0c4d..cc20a88 100644 (file)
@@ -28,6 +28,7 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
        "IKE_NATD",
        "IKE_MOBIKE",
        "IKE_AUTHENTICATE",
+       "IKE_AUTH_LIFETIME",
        "IKE_CERT",
        "IKE_CONFIG",
        "IKE_REKEY",
index dd2bb8a..a592077 100644 (file)
@@ -45,6 +45,8 @@ enum task_type_t {
        IKE_MOBIKE,
        /** authenticate the initiated IKE_SA */
        IKE_AUTHENTICATE,
+       /** AUTH_LIFETIME negotiation, RFC4478 */
+       IKE_AUTH_LIFETIME,
        /** exchange certificates and requests */
        IKE_CERT,
        /** Configuration payloads, virtual IP and such */