diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index a813e97f1..6f3151ac5 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -89,6 +89,7 @@ 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/ike_vendor_v1.c sa/tasks/ike_vendor_v1.h \ sa/tasks/main_mode.c sa/tasks/main_mode.h \ sa/tasks/quick_mode.c sa/tasks/quick_mode.h \ sa/tasks/task.c sa/tasks/task.h \ diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index b789424c0..7bccfbbc7 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1133,6 +1134,8 @@ METHOD(ike_sa_t, initiate, status_t, if (this->version == IKEV1) { + task = (task_t*)ike_vendor_v1_create(&this->public, TRUE); + this->task_manager->queue_task(this->task_manager, task); task = (task_t*)main_mode_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); } diff --git a/src/libcharon/sa/task_manager_v1.c b/src/libcharon/sa/task_manager_v1.c index 2b22bcdb5..eaab362e6 100644 --- a/src/libcharon/sa/task_manager_v1.c +++ b/src/libcharon/sa/task_manager_v1.c @@ -23,6 +23,7 @@ #include #include #include +#include #include typedef struct exchange_t exchange_t; @@ -285,6 +286,7 @@ METHOD(task_manager_t, initiate, status_t, switch (this->ike_sa->get_state(this->ike_sa)) { case IKE_CREATED: + activate_task(this, TASK_VENDOR_V1); if (activate_task(this, TASK_MAIN_MODE)) { exchange = ID_PROT; @@ -533,7 +535,7 @@ static status_t process_request(private_task_manager_t *this, switch (message->get_exchange_type(message)) { case ID_PROT: - task = (task_t *)ike_vendor_create(this->ike_sa, FALSE); + task = (task_t *)ike_vendor_v1_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); task = (task_t *)main_mode_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); diff --git a/src/libcharon/sa/tasks/ike_vendor.c b/src/libcharon/sa/tasks/ike_vendor.c index b8fe9fe91..7b3cc6e91 100644 --- a/src/libcharon/sa/tasks/ike_vendor.c +++ b/src/libcharon/sa/tasks/ike_vendor.c @@ -49,10 +49,6 @@ static chunk_t strongswan_vid = chunk_from_chars( 0x22,0x51,0x61,0x3b,0x2e,0xbe,0x5b,0xeb ); -static chunk_t xauth6_vid = chunk_from_chars( - 0x09,0x00,0x26,0x89,0xdf,0xd6,0xb7,0x12 -); - METHOD(task_t, build, status_t, private_ike_vendor_t *this, message_t *message) { @@ -64,11 +60,6 @@ METHOD(task_t, build, status_t, vid = vendor_id_payload_create_data(VENDOR_ID, chunk_clone(strongswan_vid)); message->add_payload(message, &vid->payload_interface); - - vid = vendor_id_payload_create_data(VENDOR_ID, - chunk_clone(xauth6_vid)); - message->add_payload(message, &vid->payload_interface); - } return this->initiator ? NEED_MORE : SUCCESS; @@ -101,25 +92,6 @@ METHOD(task_t, process, status_t, DBG1(DBG_ENC, "received unknown vendor id: %#B", &data); } } - - if (payload->get_type(payload) == VENDOR_ID_V1) - { - vendor_id_payload_t *vid; - chunk_t data; - - vid = (vendor_id_payload_t*)payload; - data = vid->get_data(vid); - - if (chunk_equals(data, xauth6_vid)) - { - DBG1(DBG_IKE, "received XAuth vendor id"); - this->ike_sa->enable_extension(this->ike_sa, EXT_XAUTH); - } - else - { - DBG1(DBG_ENC, "received unknown vendor id: %#B", &data); - } - } } enumerator->destroy(enumerator); diff --git a/src/libcharon/sa/tasks/ike_vendor_v1.c b/src/libcharon/sa/tasks/ike_vendor_v1.c new file mode 100644 index 000000000..bf857a314 --- /dev/null +++ b/src/libcharon/sa/tasks/ike_vendor_v1.c @@ -0,0 +1,161 @@ +/* + * 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 . + * + * 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_v1.h" + +#include +#include + +typedef struct private_ike_vendor_v1_t private_ike_vendor_v1_t; + +/** + * Private data of an ike_vendor_v1_t object. + */ +struct private_ike_vendor_v1_t { + + /** + * Public ike_vendor_v1_t interface. + */ + ike_vendor_v1_t public; + + /** + * Associated IKE_SA + */ + ike_sa_t *ike_sa; + + /** + * Are we the inititator of this task + */ + bool initiator; +}; + +static chunk_t xauth6_vid = chunk_from_chars( + 0x09,0x00,0x26,0x89,0xdf,0xd6,0xb7,0x12 +); + +/** + * 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 +); + +/** + * Add a vendor ID to message + */ +static void add_vendor_id(private_ike_vendor_v1_t *this, message_t *message, + chunk_t vid) +{ + vendor_id_payload_t *vid_payload; + + vid_payload = vendor_id_payload_create_data(VENDOR_ID_V1, chunk_clone(vid)); + message->add_payload(message, &vid_payload->payload_interface); +} + +METHOD(task_t, build, status_t, + private_ike_vendor_v1_t *this, message_t *message) +{ + + if (lib->settings->get_bool(lib->settings, + "charon.send_vendor_id", FALSE)) + { + add_vendor_id(this, message, strongswan_vid); + } + + add_vendor_id(this, message, xauth6_vid); + + return this->initiator ? NEED_MORE : SUCCESS; +} + +METHOD(task_t, process, status_t, + private_ike_vendor_v1_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_V1) + { + 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 if (chunk_equals(data, xauth6_vid)) + { + DBG1(DBG_IKE, "received XAuth vendor id"); + this->ike_sa->enable_extension(this->ike_sa, EXT_XAUTH); + } + 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_v1_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; +} + +METHOD(task_t, get_type, task_type_t, + private_ike_vendor_v1_t *this) +{ + return TASK_VENDOR_V1; +} + +METHOD(task_t, destroy, void, + private_ike_vendor_v1_t *this) +{ + free(this); +} + +/** + * See header + */ +ike_vendor_v1_t *ike_vendor_v1_create(ike_sa_t *ike_sa, bool initiator) +{ + private_ike_vendor_v1_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/libcharon/sa/tasks/ike_vendor_v1.h b/src/libcharon/sa/tasks/ike_vendor_v1.h new file mode 100644 index 000000000..60e96ebdc --- /dev/null +++ b/src/libcharon/sa/tasks/ike_vendor_v1.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * 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 . + * + * 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_v1 ike_vendor_v1 + * @{ @ingroup tasks + */ + +#ifndef IKE_VENDOR_V1_H_ +#define IKE_VENDOR_V1_H_ + +typedef struct ike_vendor_v1_t ike_vendor_v1_t; + +#include +#include +#include + +/** + * Vendor ID processing task for IKEv1. + */ +struct ike_vendor_v1_t { + + /** + * Implements task interface. + */ + task_t task; +}; + +/** + * Create a ike_vendor_v1 instance. + * + * @param ike_sa IKE_SA this task works for + * @param initiator TRUE if task is the original initiator + */ +ike_vendor_v1_t *ike_vendor_v1_create(ike_sa_t *ike_sa, bool initiator); + +#endif /** ike_vendor_v1_H_ @}*/ diff --git a/src/libcharon/sa/tasks/task.c b/src/libcharon/sa/tasks/task.c index 83d0478ca..d0eed77e3 100644 --- a/src/libcharon/sa/tasks/task.c +++ b/src/libcharon/sa/tasks/task.c @@ -17,7 +17,7 @@ #include "task.h" #ifdef ME -ENUM(task_type_names, TASK_IKE_INIT, TASK_QUICK_MODE, +ENUM(task_type_names, TASK_IKE_INIT, TASK_XAUTH_REQUEST, "IKE_INIT", "IKE_NATD", "IKE_MOBIKE", @@ -37,9 +37,11 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_QUICK_MODE, "CHILD_REKEY", "MAIN_MODE", "QUICK_MODE", + "VENDOR_V1", + "XAUTH_REQUEST", ); #else -ENUM(task_type_names, TASK_IKE_INIT, TASK_QUICK_MODE, +ENUM(task_type_names, TASK_IKE_INIT, TASK_XAUTH_REQUEST, "IKE_INIT", "IKE_NATD", "IKE_MOBIKE", @@ -58,5 +60,7 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_QUICK_MODE, "CHILD_REKEY", "MAIN_MODE", "QUICK_MODE", + "VENDOR_V1", + "XAUTH_REQUEST", ); #endif /* ME */ diff --git a/src/libcharon/sa/tasks/task.h b/src/libcharon/sa/tasks/task.h index eebfb7a57..e76ffcd8c 100644 --- a/src/libcharon/sa/tasks/task.h +++ b/src/libcharon/sa/tasks/task.h @@ -73,6 +73,8 @@ enum task_type_t { TASK_MAIN_MODE, /** IKEv1 quick mode */ TASK_QUICK_MODE, + /** IKEv1 vendor ID payload handling */ + TASK_VENDOR_V1, /** Request the user/pass with XAUTH */ TASK_XAUTH_REQUEST, };