Add an option to send a vendor ID, allows us to properly support private extensions
authorMartin Willi <martin@strongswan.org>
Thu, 7 Jan 2010 09:26:58 +0000 (10:26 +0100)
committerMartin Willi <martin@strongswan.org>
Thu, 7 Jan 2010 09:37:27 +0000 (09:37 +0000)
src/charon/Makefile.am
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/task_manager.c
src/charon/sa/tasks/ike_init.c
src/charon/sa/tasks/ike_vendor.c [new file with mode: 0644]
src/charon/sa/tasks/ike_vendor.h [new file with mode: 0644]
src/charon/sa/tasks/task.c
src/charon/sa/tasks/task.h

index 2a82b4b..cb31b76 100644 (file)
@@ -91,6 +91,7 @@ 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/ike_vendor.c sa/tasks/ike_vendor.h \
 sa/tasks/task.c sa/tasks/task.h \
 credentials/credential_manager.c credentials/credential_manager.h \
 credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
index 6f72fcc..975a090 100644 (file)
@@ -40,6 +40,7 @@
 #include <sa/tasks/ike_reauth.h>
 #include <sa/tasks/ike_delete.h>
 #include <sa/tasks/ike_dpd.h>
+#include <sa/tasks/ike_vendor.h>
 #include <sa/tasks/child_create.h>
 #include <sa/tasks/child_delete.h>
 #include <sa/tasks/child_rekey.h>
@@ -1192,6 +1193,8 @@ static status_t initiate(private_ike_sa_t *this,
 
                task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
                this->task_manager->queue_task(this->task_manager, task);
+               task = (task_t*)ike_vendor_create(&this->public, TRUE);
+               this->task_manager->queue_task(this->task_manager, task);
                task = (task_t*)ike_natd_create(&this->public, TRUE);
                this->task_manager->queue_task(this->task_manager, task);
                task = (task_t*)ike_cert_pre_create(&this->public, TRUE);
index 83d2c9c..122e238 100644 (file)
@@ -86,6 +86,11 @@ enum ike_extension_t {
         * peer supports multiple authentication exchanges, RFC4739
         */
        EXT_MULTIPLE_AUTH = (1<<3),
+
+       /**
+        * peer uses strongSwan, accept private use extensions
+        */
+       EXT_STRONGSWAN = (1<<4),
 };
 
 /**
index f02c58c..e6b0128 100644 (file)
@@ -30,6 +30,7 @@
 #include <sa/tasks/ike_delete.h>
 #include <sa/tasks/ike_config.h>
 #include <sa/tasks/ike_dpd.h>
+#include <sa/tasks/ike_vendor.h>
 #include <sa/tasks/child_create.h>
 #include <sa/tasks/child_rekey.h>
 #include <sa/tasks/child_delete.h>
@@ -295,6 +296,7 @@ static status_t build_request(private_task_manager_t *this)
                                {
                                        this->initiating.mid = 0;
                                        exchange = IKE_SA_INIT;
+                                       activate_task(this, IKE_VENDOR);
                                        activate_task(this, IKE_NATD);
                                        activate_task(this, IKE_CERT_PRE);
 #ifdef ME
@@ -681,6 +683,8 @@ static status_t process_request(private_task_manager_t *this,
                        {
                                task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
                                this->passive_tasks->insert_last(this->passive_tasks, task);
+                               task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
+                               this->passive_tasks->insert_last(this->passive_tasks, task);
                                task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
                                this->passive_tasks->insert_last(this->passive_tasks, task);
                                task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
index a8bfc1d..63c0889 100644 (file)
@@ -24,7 +24,6 @@
 #include <encoding/payloads/sa_payload.h>
 #include <encoding/payloads/ke_payload.h>
 #include <encoding/payloads/nonce_payload.h>
-#include <encoding/payloads/vendor_id_payload.h>
 
 /** maximum retries to do with cookies/other dh groups */
 #define MAX_RETRIES 5
@@ -212,13 +211,6 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
                                this->other_nonce = nonce_payload->get_nonce(nonce_payload);
                                break;
                        }
-                       case VENDOR_ID:
-                       {
-                               vendor_id_payload_t *vendor_id = (vendor_id_payload_t*)payload;
-                               chunk_t vid = vendor_id->get_data(vendor_id);
-
-                               DBG1(DBG_ENC, "received vendor id: %#B", &vid);
-                       }
                        default:
                                break;
                }
diff --git a/src/charon/sa/tasks/ike_vendor.c b/src/charon/sa/tasks/ike_vendor.c
new file mode 100644 (file)
index 0000000..7c435b6
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009 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_vendor.h"
+
+#include <daemon.h>
+#include <encoding/payloads/vendor_id_payload.h>
+
+typedef struct private_ike_vendor_t private_ike_vendor_t;
+
+/**
+ * Private data of an ike_vendor_t object.
+ */
+struct private_ike_vendor_t {
+
+       /**
+        * Public ike_vendor_t interface.
+        */
+       ike_vendor_t public;
+
+       /**
+        * Associated IKE_SA
+        */
+       ike_sa_t *ike_sa;
+
+       /**
+        * Are we the inititator of this task
+        */
+       bool initiator;
+};
+
+/**
+ * strongSwan specific vendor ID without version, MD5("strongSwan")
+ */
+static chunk_t strongswan_vid = chunk_from_chars(
+       0x88,0x2f,0xe5,0x6d,0x6f,0xd2,0x0d,0xbc,
+       0x22,0x51,0x61,0x3b,0x2e,0xbe,0x5b,0xeb
+);
+
+METHOD(task_t, build, status_t,
+       private_ike_vendor_t *this, message_t *message)
+{
+       if (lib->settings->get_bool(lib->settings,
+                                                               "charon.send_vendor_id", FALSE))
+       {
+               vendor_id_payload_t *vid;
+
+               vid = vendor_id_payload_create_data(chunk_clone(strongswan_vid));
+               message->add_payload(message, &vid->payload_interface);
+       }
+
+       return this->initiator ? NEED_MORE : SUCCESS;
+}
+
+METHOD(task_t, process, status_t,
+       private_ike_vendor_t *this, message_t *message)
+{
+       enumerator_t *enumerator;
+       payload_t *payload;
+
+       enumerator = message->create_payload_enumerator(message);
+       while (enumerator->enumerate(enumerator, &payload))
+       {
+               if (payload->get_type(payload) == VENDOR_ID)
+               {
+                       vendor_id_payload_t *vid;
+                       chunk_t data;
+
+                       vid = (vendor_id_payload_t*)payload;
+                       data = vid->get_data(vid);
+
+                       if (chunk_equals(data, strongswan_vid))
+                       {
+                               DBG1(DBG_IKE, "received strongSwan vendor id");
+                               this->ike_sa->enable_extension(this->ike_sa, EXT_STRONGSWAN);
+                       }
+                       else
+                       {
+                               DBG1(DBG_ENC, "received unknown vendor id: %#B", &data);
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       return this->initiator ? SUCCESS : NEED_MORE;
+}
+
+METHOD(task_t, migrate, void,
+       private_ike_vendor_t *this, ike_sa_t *ike_sa)
+{
+       this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, get_type, task_type_t,
+       private_ike_vendor_t *this)
+{
+       return IKE_VENDOR;
+}
+
+METHOD(task_t, destroy, void,
+       private_ike_vendor_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator)
+{
+       private_ike_vendor_t *this;
+
+       INIT(this,
+               .public.task = {
+                       .build = _build,
+                       .process = _process,
+                       .migrate = _migrate,
+                       .get_type = _get_type,
+                       .destroy = _destroy,
+               },
+               .initiator = initiator,
+               .ike_sa = ike_sa,
+       );
+
+       return &this->public;
+}
+
diff --git a/src/charon/sa/tasks/ike_vendor.h b/src/charon/sa/tasks/ike_vendor.h
new file mode 100644 (file)
index 0000000..dcdd374
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+/**
+ * @defgroup ike_vendor ike_vendor
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_VENDOR_H_
+#define IKE_VENDOR_H_
+
+typedef struct ike_vendor_t ike_vendor_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Vendor ID processing task.
+ */
+struct ike_vendor_t {
+
+       /**
+        * Implements task interface.
+        */
+       task_t task;
+};
+
+/**
+ * Create a ike_vendor instance.
+ *
+ * @param ike_sa               IKE_SA this task works for
+ * @param initiator            TRUE if thask is the original initator
+ */
+ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** IKE_VENDOR_H_ @}*/
index 9e35b62..0d73831 100644 (file)
@@ -30,6 +30,7 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
        "IKE_REAUTH",
        "IKE_DELETE",
        "IKE_DPD",
+       "IKE_VENDOR",
        "IKE_ME",
        "CHILD_CREATE",
        "CHILD_DELETE",
@@ -49,6 +50,7 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
        "IKE_REAUTH",
        "IKE_DELETE",
        "IKE_DPD",
+       "IKE_VENDOR",
        "CHILD_CREATE",
        "CHILD_DELETE",
        "CHILD_REKEY",
index b53b2cc..4468f2e 100644 (file)
@@ -57,6 +57,8 @@ enum task_type_t {
        IKE_DELETE,
        /** liveness check */
        IKE_DPD,
+       /** Vendor ID processing */
+       IKE_VENDOR,
 #ifdef ME
        /** handle ME stuff */
        IKE_ME,