diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/Makefile.am | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_config.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa.c | 10 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa.h | 10 | ||||
-rw-r--r-- | src/libcharon/sa/task_manager_v1.c | 61 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/ike_vendor.c | 28 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/task.h | 2 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/xauth_request.c | 185 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/xauth_request.h | 37 | ||||
-rw-r--r-- | src/libstrongswan/credentials/auth_cfg.h | 2 |
10 files changed, 335 insertions, 7 deletions
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index d76ba491c..2bead3beb 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -93,7 +93,8 @@ sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \ sa/tasks/ike_vendor.c sa/tasks/ike_vendor.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 +sa/tasks/task.c sa/tasks/task.h \ +sa/tasks/xauth_request.c sa/tasks/xauth_request.h daemon.lo : $(top_builddir)/config.status diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 4a49704ef..97d2a7836 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -469,6 +469,10 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); } + else if (streq(auth, "xauthpsk")) + { + cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH_PSK); + } else if (strneq(auth, "eap", 3)) { enumerator_t *enumerator; diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index d2dffea8b..0da289ada 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -46,6 +46,7 @@ #include <sa/tasks/child_rekey.h> #include <sa/tasks/main_mode.h> #include <sa/tasks/quick_mode.h> +#include <sa/tasks/xauth_request.h> #include <processing/jobs/retransmit_job.h> #include <processing/jobs/delete_ike_sa_job.h> #include <processing/jobs/send_dpd_job.h> @@ -2128,6 +2129,15 @@ METHOD(ike_sa_t, destroy, void, free(this); } +METHOD(ike_sa_t, initiate_xauth, void, + private_ike_sa_t *this) +{ + xauth_request_t *xauth_request_task = xauth_request_create(this, TRUE); + this->task_manager->queue_task(this->task_manager, (task_t*)xauth_request_task); + + this->task_manager->initiate_later(this->task_manager); +} + /* * Described in header. */ diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index 2708b0be6..ecfb04e02 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -102,6 +102,11 @@ enum ike_extension_t { * peer is probably a Windows 7 RAS client */ EXT_MS_WINDOWS = (1<<6), + + /** + * peer supports XAuth authentication, draft-ietf-ipsec-isakmp-xauth-06 + */ + EXT_XAUTH = (1<<7), }; /** @@ -953,6 +958,11 @@ struct ike_sa_t { * Destroys a ike_sa_t object. */ void (*destroy) (ike_sa_t *this); + + /** + * Initiate XAUTH authentication + */ + status_t (*initiate_xauth)(ike_sa_t *this); }; /** diff --git a/src/libcharon/sa/task_manager_v1.c b/src/libcharon/sa/task_manager_v1.c index 1764a8036..fbc8da7cc 100644 --- a/src/libcharon/sa/task_manager_v1.c +++ b/src/libcharon/sa/task_manager_v1.c @@ -131,6 +131,13 @@ struct private_task_manager_t { * Base to calculate retransmission timeout */ double retransmit_base; + + /** + * Flag to tell the task manager to initiate a transaction at + * a later time. + */ + bool initiate_later_flag; + }; /** @@ -149,12 +156,6 @@ static void flush(private_task_manager_t *this) this->active_tasks = linked_list_create(); } -METHOD(task_manager_t, retransmit, status_t, - private_task_manager_t *this, u_int32_t message_id) -{ - return FAILED; -} - /** * move a task of a specific type from the queue to the active list */ @@ -180,6 +181,49 @@ static bool activate_task(private_task_manager_t *this, task_type_t type) return found; } +METHOD(task_manager_t, retransmit, status_t, + private_task_manager_t *this, u_int32_t message_id) +{ + if (message_id == this->initiating.mid) + { + u_int32_t timeout; + job_t *job; + enumerator_t *enumerator; + packet_t *packet; + task_t *task; + + if (this->initiating.retransmitted <= this->retransmit_tries) + { + timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 * + pow(this->retransmit_base, this->initiating.retransmitted)); + } + else + { + DBG1(DBG_IKE, "giving up after %d retransmits", + this->initiating.retransmitted - 1); + if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) + { + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + } + return DESTROY_ME; + } + + if (this->initiating.retransmitted) + { + DBG1(DBG_IKE, "retransmit %d of request with message ID %d", + this->initiating.retransmitted, message_id); + } + packet = this->initiating.packet->clone(this->initiating.packet); + charon->sender->send(charon->sender, packet); + + this->initiating.retransmitted++; + job = (job_t*)retransmit_job_create(this->initiating.mid, + this->ike_sa->get_id(this->ike_sa)); + lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout); + } + return SUCCESS; +} + METHOD(task_manager_t, initiate, status_t, private_task_manager_t *this) { @@ -220,6 +264,11 @@ METHOD(task_manager_t, initiate, status_t, { exchange = QUICK_MODE; } + + if (activate_task(this, TASK_XAUTH_REQUEST)) + { + exchange = TRANSACTION; + } break; default: break; diff --git a/src/libcharon/sa/tasks/ike_vendor.c b/src/libcharon/sa/tasks/ike_vendor.c index 7b3cc6e91..b8fe9fe91 100644 --- a/src/libcharon/sa/tasks/ike_vendor.c +++ b/src/libcharon/sa/tasks/ike_vendor.c @@ -49,6 +49,10 @@ 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) { @@ -60,6 +64,11 @@ 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; @@ -92,6 +101,25 @@ 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/task.h b/src/libcharon/sa/tasks/task.h index 8a8143967..ad41bae7f 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, + /** Request the user/pass with XAUTH */ + TASK_XAUTH_REQUEST, }; /** diff --git a/src/libcharon/sa/tasks/xauth_request.c b/src/libcharon/sa/tasks/xauth_request.c new file mode 100644 index 000000000..a50d0fb43 --- /dev/null +++ b/src/libcharon/sa/tasks/xauth_request.c @@ -0,0 +1,185 @@ + +#include "xauth_request.h" + +#include <daemon.h> +#include <hydra.h> +#include <encoding/payloads/attribute_payload_v1.h> +#include <encoding/payloads/data_attribute_v1.h> +#include <encoding/payloads/hash_payload.h> +#include <encoding/generator.h> + +typedef struct private_xauth_request_t private_xauth_request_t; + +/** + * Private members of a xauth_request_t task. + */ +struct private_xauth_request_t { + + /** + * Public methods and task_t interface. + */ + xauth_request_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Are we the initiator? + */ + bool initiator; + + /** + * virtual ip + */ + host_t *virtual_ip; + + /** + * list of attributes requested and its handler, entry_t + */ + linked_list_t *requested; +}; + +/** + * Entry for a requested attribute and the requesting handler + */ +typedef struct { + /** attribute requested */ + configuration_attribute_type_t type; + /** handler requesting this attribute */ + attribute_handler_t *handler; +} entry_t; + +/** + * Scan for configuration payloads and attributes + */ +static void process_payloads(private_xauth_request_t *this, message_t *message) +{ +} + +METHOD(task_t, build_i, status_t, + private_xauth_request_t *this, message_t *message) +{ + attribute_payload_v1_t *ap = NULL; + chunk_t chunk = chunk_empty; + data_attribute_v1_t *da = NULL; + hash_payload_t *hash_payload = NULL; + generator_t *generator; + chunk_t attr_chunk; + chunk_t mid_chunk; + u_int32_t *lenpos; + u_int32_t message_id; + keymat_t *keymat; + prf_t *prf; + chunk_t hash_in, hash_out; + + DBG1(DBG_IKE, "BUILDING XAUTH REQUEST PACKET"); + /* TODO1: Create ATTR payload */ + ap = attribute_payload_v1_create(); + + da = data_attribute_v1_create_value(XAUTH_USER_NAME, chunk); + ap->add_attribute(ap, da); + + da = data_attribute_v1_create_value(XAUTH_USER_PASSWORD, chunk); + ap->add_attribute(ap, da); + + /* Create HASH payload */ + hash_payload = hash_payload_create(); + /* TODO1: Add data into the hash */ + + /* Calculate the chunk for the ATTR payload */ + generator = generator_create(); + ap->payload_interface.set_next_type(&ap->payload_interface, NO_PAYLOAD); + generator->generate_payload(generator, (payload_t *)ap); + attr_chunk = generator->get_chunk(generator, &lenpos); + + /* Get the message ID in network order */ + htoun32(&message_id, message->get_message_id(message)); + mid_chunk = chunk_from_thing(message_id); + + /* Get the hashed data */ + hash_in = chunk_cat("cc", mid_chunk, attr_chunk); + + message->add_payload(message, (payload_t *)hash_payload); + message->add_payload(message, (payload_t *)ap); + + return NEED_MORE; +} + +METHOD(task_t, process_r, status_t, + private_xauth_request_t *this, message_t *message) +{ + return NEED_MORE; +} + +METHOD(task_t, build_r, status_t, + private_xauth_request_t *this, message_t *message) +{ + return NEED_MORE; +} + +METHOD(task_t, process_i, status_t, + private_xauth_request_t *this, message_t *message) +{ + return NEED_MORE; +} + +METHOD(task_t, get_type, task_type_t, + private_xauth_request_t *this) +{ + return TASK_XAUTH_REQUEST; +} + +METHOD(task_t, migrate, void, + private_xauth_request_t *this, ike_sa_t *ike_sa) +{ + DESTROY_IF(this->virtual_ip); + + this->ike_sa = ike_sa; + this->virtual_ip = NULL; + this->requested->destroy_function(this->requested, free); + this->requested = linked_list_create(); +} + +METHOD(task_t, destroy, void, + private_xauth_request_t *this) +{ + DESTROY_IF(this->virtual_ip); + this->requested->destroy_function(this->requested, free); + free(this); +} + +/* + * Described in header. + */ +xauth_request_t *xauth_request_create(ike_sa_t *ike_sa, bool initiator) +{ + private_xauth_request_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .migrate = _migrate, + .destroy = _destroy, + }, + }, + .initiator = initiator, + .ike_sa = ike_sa, + .requested = linked_list_create(), + ); + + if (initiator) + { + this->public.task.build = _build_i; + this->public.task.process = _process_i; + } + else + { + this->public.task.build = _build_r; + this->public.task.process = _process_r; + } + + return &this->public; +} diff --git a/src/libcharon/sa/tasks/xauth_request.h b/src/libcharon/sa/tasks/xauth_request.h new file mode 100644 index 000000000..6324ca0de --- /dev/null +++ b/src/libcharon/sa/tasks/xauth_request.h @@ -0,0 +1,37 @@ + +/** + * @defgroup xauth_request xauth_request + * @{ @ingroup tasks + */ + +#ifndef XAUTH_REQUEST_H_ +#define XAUTH_REQUEST_H_ + +typedef struct xauth_request_t xauth_request_t; + +#include <library.h> +#include <sa/ike_sa.h> +#include <sa/tasks/task.h> + +/** + * Task of type XAUTH_REQUEST, gets the username and password from the ISAKMP_SA + * initializer. + */ +struct xauth_request_t { + + /** + * Implements the task_t interface + */ + task_t task; +}; + +/** + * Create a new xauth_request task. + * + * @param ike_sa IKE_SA this task works for + * @param initiator TRUE for initiator + * @return ike_config task to handle by the task_manager + */ +xauth_request_t *xauth_request_create(ike_sa_t *ike_sa, bool initiator); + +#endif /** XAUTH_REQUEST_H_ @}*/ diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h index 7e747c37d..2554b3f2e 100644 --- a/src/libstrongswan/credentials/auth_cfg.h +++ b/src/libstrongswan/credentials/auth_cfg.h @@ -42,6 +42,8 @@ enum auth_class_t { AUTH_CLASS_PSK = 2, /** authentication using EAP */ AUTH_CLASS_EAP = 3, + /** authentication using pre-shared secrets in combination with XAuth */ + AUTH_CLASS_XAUTH_PSK = 4, }; /** |