Replace xauth_request task with a new stub where we reimplement it

This commit is contained in:
Martin Willi
2012-03-20 17:31:15 +01:00
parent c6d0098c1b
commit 69adeb5bf2
12 changed files with 241 additions and 884 deletions
+1 -2
View File
@@ -57,7 +57,6 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \
processing/jobs/roam_job.c processing/jobs/roam_job.h \
processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
processing/jobs/initiate_xauth_job.c processing/jobs/initiate_xauth_job.h \
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
@@ -100,8 +99,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/ike_vendor_v1.c sa/tasks/ike_vendor_v1.h \
sa/tasks/main_mode.c sa/tasks/main_mode.h \
sa/tasks/xauth.c sa/tasks/xauth.h \
sa/tasks/quick_mode.c sa/tasks/quick_mode.h \
sa/tasks/xauth_request.c sa/tasks/xauth_request.h \
sa/tasks/task.c sa/tasks/task.h
+7 -14
View File
@@ -50,7 +50,6 @@
#include <sa/tasks/quick_mode.h>
#include <sa/tasks/ike_natd_v1.h>
#include <sa/tasks/ike_vendor_v1.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>
@@ -1021,18 +1020,6 @@ METHOD(ike_sa_t, initiate_mediated, status_t,
}
#endif /* ME */
METHOD(ike_sa_t, initiate_xauth, status_t,
private_ike_sa_t *this, bool initiate)
{
xauth_request_t *task = xauth_request_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, (task_t*)task);
if(initiate)
{
return this->task_manager->initiate(this->task_manager);
}
return SUCCESS;
}
/**
* Resolve DNS host in configuration
*/
@@ -1839,6 +1826,12 @@ METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
return this->task_manager->create_task_enumerator(this->task_manager, queue);
}
METHOD(ike_sa_t, queue_task, void,
private_ike_sa_t *this, task_t *task)
{
this->task_manager->queue_task(this->task_manager, task);
}
METHOD(ike_sa_t, inherit, void,
private_ike_sa_t *this, ike_sa_t *other_public)
{
@@ -2095,6 +2088,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.add_configuration_attribute = _add_configuration_attribute,
.set_kmaddress = _set_kmaddress,
.create_task_enumerator = _create_task_enumerator,
.queue_task = _queue_task,
#ifdef ME
.act_as_mediation_server = _act_as_mediation_server,
.get_server_reflexive_host = _get_server_reflexive_host,
@@ -2106,7 +2100,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.callback = _callback,
.respond = _respond,
#endif /* ME */
.initiate_xauth = _initiate_xauth,
},
.ike_sa_id = ike_sa_id->clone(ike_sa_id),
.version = version,
+8 -5
View File
@@ -37,6 +37,7 @@ typedef struct ike_sa_t ike_sa_t;
#include <encoding/payloads/configuration_attribute.h>
#include <sa/ike_sa_id.h>
#include <sa/child_sa.h>
#include <sa/tasks/task.h>
#include <sa/task_manager.h>
#include <sa/keymat.h>
#include <config/peer_cfg.h>
@@ -951,6 +952,13 @@ struct ike_sa_t {
*/
enumerator_t* (*create_task_enumerator)(ike_sa_t *this, task_queue_t queue);
/**
* Queue a task for initiaton to the task manager.
*
* @param task task to queue
*/
void (*queue_task)(ike_sa_t *this, task_t *task);
/**
* Inherit all attributes of other to this after rekeying.
*
@@ -971,11 +979,6 @@ struct ike_sa_t {
* Destroys a ike_sa_t object.
*/
void (*destroy) (ike_sa_t *this);
/**
* Initiate an XAuth authentication exchange.
*/
status_t (*initiate_xauth) (ike_sa_t *this, bool initiate);
};
/**
+15 -5
View File
@@ -22,7 +22,7 @@
#include <sa/tasks/child_delete.h>
#include <sa/tasks/main_mode.h>
#include <sa/tasks/quick_mode.h>
#include <sa/tasks/xauth_request.h>
#include <sa/tasks/xauth.h>
#include <sa/tasks/ike_delete.h>
#include <sa/tasks/ike_natd_v1.h>
#include <sa/tasks/ike_vendor_v1.h>
@@ -280,7 +280,7 @@ METHOD(task_manager_t, initiate, status_t,
}
break;
case IKE_CONNECTING:
if (activate_task(this, TASK_XAUTH_REQUEST))
if (activate_task(this, TASK_XAUTH))
{
exchange = TRANSACTION;
new_mid = TRUE;
@@ -313,7 +313,7 @@ METHOD(task_manager_t, initiate, status_t,
case TASK_QUICK_MODE:
exchange = QUICK_MODE;
break;
case TASK_XAUTH_REQUEST:
case TASK_XAUTH:
exchange = TRANSACTION;
new_mid = TRUE;
break;
@@ -648,7 +648,7 @@ static status_t process_request(private_task_manager_t *this,
enumerator->destroy(enumerator);
break;
case TRANSACTION:
task = (task_t *)xauth_request_create(this->ike_sa, FALSE);
task = (task_t *)xauth_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
break;
default:
@@ -688,7 +688,17 @@ static status_t process_request(private_task_manager_t *this,
if (send_response)
{
return build_response(this, message);
if (build_response(this, message) != SUCCESS)
{
return DESTROY_ME;
}
}
if (this->passive_tasks->get_count(this->passive_tasks) == 0 &&
this->queued_tasks->get_count(this->queued_tasks) > 0)
{
/* passive tasks completed, check if an active task has been queued,
* such as XAUTH or modeconfig push */
return initiate(this);
}
return SUCCESS;
}
+35 -43
View File
@@ -28,7 +28,7 @@
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/hash_payload.h>
#include <processing/jobs/initiate_xauth_job.h>
#include <sa/tasks/xauth.h>
typedef struct private_main_mode_t private_main_mode_t;
@@ -738,6 +738,21 @@ METHOD(task_t, build_r, status_t,
return FAILED;
}
switch (this->auth_method)
{
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA:
this->ike_sa->queue_task(this->ike_sa,
(task_t*)xauth_create(this->ike_sa, TRUE));
return SUCCESS;
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
/* TODO-IKEv1: not yet supported */
return FAILED;
default:
break;
}
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
this->ike_sa->get_name(this->ike_sa),
this->ike_sa->get_unique_id(this->ike_sa),
@@ -746,27 +761,9 @@ METHOD(task_t, build_r, status_t,
this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
switch (this->auth_method)
{
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA: /* There should be more INIT cases here once added */
{
job_t *job = (job_t *) initiate_xauth_job_create(this->ike_sa->get_id(this->ike_sa));
lib->processor->queue_job(lib->processor, job);
break;
}
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA: /* There should be more RESP cases here once added */
{
break;
}
default:
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
break;
}
}
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
return SUCCESS;
}
default:
@@ -858,7 +855,20 @@ METHOD(task_t, process_i, status_t,
return FAILED;
}
/* TODO-IKEv1: check for XAUTH rounds, queue them */
switch (this->auth_method)
{
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA:
/* TODO-IKEv1: wait for XAUTH request */
return SUCCESS;
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
/* TODO-IKEv1: not yet */
return FAILED;
default:
break;
}
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
this->ike_sa->get_name(this->ike_sa),
this->ike_sa->get_unique_id(this->ike_sa),
@@ -867,26 +877,8 @@ METHOD(task_t, process_i, status_t,
this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
switch (this->auth_method)
{
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA: /* There should be more RESP cases here once added */
{
this->ike_sa->initiate_xauth(this->ike_sa, FALSE);
break;
}
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA: /* There should be more INIT cases here once added */
{
break;
}
default:
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
break;
}
}
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
return SUCCESS;
}
+4 -4
View File
@@ -17,7 +17,7 @@
#include "task.h"
#ifdef ME
ENUM(task_type_names, TASK_IKE_INIT, TASK_XAUTH_REQUEST,
ENUM(task_type_names, TASK_IKE_INIT, TASK_IKE_CERT_POST_V1,
"IKE_INIT",
"IKE_NATD",
"IKE_MOBIKE",
@@ -36,15 +36,15 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_XAUTH_REQUEST,
"CHILD_DELETE",
"CHILD_REKEY",
"MAIN_MODE",
"XAUTH",
"QUICK_MODE",
"VENDOR_V1",
"IKE_NATD_V1",
"IKE_CERT_PRE_V1",
"IKE_CERT_POST_V1",
"XAUTH_REQUEST",
);
#else
ENUM(task_type_names, TASK_IKE_INIT, TASK_XAUTH_REQUEST,
ENUM(task_type_names, TASK_IKE_INIT, TASK_IKE_CERT_POST_V1,
"IKE_INIT",
"IKE_NATD",
"IKE_MOBIKE",
@@ -62,11 +62,11 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_XAUTH_REQUEST,
"CHILD_DELETE",
"CHILD_REKEY",
"MAIN_MODE",
"XAUTH",
"QUICK_MODE",
"VENDOR_V1",
"IKE_NATD_V1",
"IKE_CERT_PRE_V1",
"IKE_CERT_POST_V1",
"XAUTH_REQUEST",
);
#endif /* ME */
+2 -2
View File
@@ -71,6 +71,8 @@ enum task_type_t {
TASK_CHILD_REKEY,
/** IKEv1 main mode */
TASK_MAIN_MODE,
/** IKEv1 XAUTH authentication */
TASK_XAUTH,
/** IKEv1 quick mode */
TASK_QUICK_MODE,
/** IKEv1 vendor ID payload handling */
@@ -81,8 +83,6 @@ enum task_type_t {
TASK_IKE_CERT_PRE_V1,
/** IKEv1 post-authentication certificate handling */
TASK_IKE_CERT_POST_V1,
/** Request the user/pass with XAUTH */
TASK_XAUTH_REQUEST,
};
/**
+117
View File
@@ -0,0 +1,117 @@
/*
* 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 <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 "xauth.h"
#include <daemon.h>
#include <hydra.h>
#include <encoding/payloads/cp_payload.h>
typedef struct private_xauth_t private_xauth_t;
/**
* Private members of a xauth_t task.
*/
struct private_xauth_t {
/**
* Public methods and task_t interface.
*/
xauth_t public;
/**
* Assigned IKE_SA.
*/
ike_sa_t *ike_sa;
/**
* Are we the XAUTH initiator?
*/
bool initiator;
};
METHOD(task_t, build_i, status_t,
private_xauth_t *this, message_t *message)
{
return FAILED;
}
METHOD(task_t, process_r, status_t,
private_xauth_t *this, message_t *message)
{
return FAILED;
}
METHOD(task_t, build_r, status_t,
private_xauth_t *this, message_t *message)
{
return FAILED;
}
METHOD(task_t, process_i, status_t,
private_xauth_t *this, message_t *message)
{
return FAILED;
}
METHOD(task_t, get_type, task_type_t,
private_xauth_t *this)
{
return TASK_XAUTH;
}
METHOD(task_t, migrate, void,
private_xauth_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
METHOD(task_t, destroy, void,
private_xauth_t *this)
{
free(this);
}
/*
* Described in header.
*/
xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
{
private_xauth_t *this;
INIT(this,
.public = {
.task = {
.get_type = _get_type,
.migrate = _migrate,
.destroy = _destroy,
},
},
.initiator = initiator,
.ike_sa = ike_sa,
);
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;
}
+50
View File
@@ -0,0 +1,50 @@
/*
* 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 <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 xauth xauth
* @{ @ingroup tasks
*/
#ifndef XAUTH_H_
#define XAUTH_H_
typedef struct xauth_t xauth_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
/**
* Task of type TASK_XAUTH, additional authentication after main/aggressive mode.
*/
struct xauth_t {
/**
* Implements the task_t interface
*/
task_t task;
};
/**
* Create a new xauth task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE for initiator
* @return xauth task to handle by the task_manager
*/
xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator);
#endif /** XAUTH_H_ @}*/
-770
View File
@@ -1,770 +0,0 @@
#include "xauth_request.h"
#include <daemon.h>
#include <hydra.h>
#include <encoding/payloads/cp_payload.h>
#include <sa/authenticators/xauth_authenticator.h>
typedef struct private_xauth_request_t private_xauth_request_t;
enum {
XAUTH_STATUS_FAIL = 0,
XAUTH_STATUS_OK = 1,
};
/**
* 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;
/**
* The current and next state of the task
*/
enum {
TASK_XAUTH_INIT,
TASK_XAUTH_PASS_VERIFY,
TASK_XAUTH_COMPLETE,
} state, next_state;
/**
* The status of the XAuth request
*/
status_t status;
/**
* The current auth config
*/
auth_cfg_t *auth_cfg;
/**
* The received XAuth Status
*/
u_int16_t xauth_status_data;
/**
* The received XAuth user name
*/
chunk_t xauth_user_name;
/**
* The received XAuth user pass
*/
chunk_t xauth_user_pass;
/**
* Whether the user name attribute was received
*/
bool xauth_user_name_recv;
/**
* Whether the user pass attribute was received
*/
bool xauth_user_pass_recv;
/**
* Whether the XAuth status attribute was received
*/
bool xauth_status_recv;
/**
* The XAuth authenticator_t object
*/
authenticator_t *xauth_authenticator;
};
/**
* 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;
/**
* Get the first authentcation config from peer config
*/
static auth_cfg_t *get_auth_cfg(private_xauth_request_t *this, bool local)
{
enumerator_t *enumerator;
auth_cfg_t *cfg = NULL;
peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg,
local);
enumerator->enumerate(enumerator, &cfg);
enumerator->destroy(enumerator);
return cfg;
}
/**
* build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
*/
static configuration_attribute_t *build_vip(payload_type_t ca_type, host_t *vip)
{
configuration_attribute_type_t type;
chunk_t chunk, prefix;
if (vip->get_family(vip) == AF_INET)
{
type = INTERNAL_IP4_ADDRESS;
if (vip->is_anyaddr(vip))
{
chunk = chunk_empty;
}
else
{
chunk = vip->get_address(vip);
}
}
else
{
type = INTERNAL_IP6_ADDRESS;
if (vip->is_anyaddr(vip))
{
chunk = chunk_empty;
}
else
{
prefix = chunk_alloca(1);
*prefix.ptr = 64;
chunk = vip->get_address(vip);
chunk = chunk_cata("cc", chunk, prefix);
}
}
return configuration_attribute_create_chunk(ca_type,
type, chunk);
}
/**
* Handle a received attribute as initiator
*/
static void handle_attribute(private_xauth_request_t *this,
configuration_attribute_t *ca)
{
attribute_handler_t *handler = NULL;
enumerator_t *enumerator;
entry_t *entry;
/* find the handler which requested this attribute */
enumerator = this->requested->create_enumerator(this->requested);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->type == ca->get_type(ca))
{
handler = entry->handler;
this->requested->remove_at(this->requested, enumerator);
free(entry);
break;
}
}
enumerator->destroy(enumerator);
/* and pass it to the handle function */
handler = hydra->attributes->handle(hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), handler,
ca->get_type(ca), ca->get_chunk(ca));
if (handler)
{
this->ike_sa->add_configuration_attribute(this->ike_sa,
handler, ca->get_type(ca), ca->get_chunk(ca));
}
}
/**
* process a single configuration attribute
*/
static void process_attribute(private_xauth_request_t *this,
configuration_attribute_t *ca)
{
host_t *ip;
chunk_t addr;
int family = AF_INET6;
switch (ca->get_type(ca))
{
case XAUTH_USER_NAME:
this->xauth_user_name = ca->get_chunk(ca);
this->xauth_user_name_recv = TRUE;
break;
case XAUTH_USER_PASSWORD:
this->xauth_user_pass = ca->get_chunk(ca);
this->xauth_user_pass_recv = TRUE;
break;
case XAUTH_STATUS:
this->xauth_status_data = ca->get_value(ca);
this->xauth_status_recv = TRUE;
break;
case INTERNAL_IP4_ADDRESS:
family = AF_INET;
/* fall */
case INTERNAL_IP6_ADDRESS:
{
addr = ca->get_chunk(ca);
if (addr.len == 0)
{
ip = host_create_any(family);
}
else
{
/* skip prefix byte in IPv6 payload*/
if (family == AF_INET6)
{
addr.len--;
}
ip = host_create_from_chunk(family, addr, 0);
}
if (ip)
{
DESTROY_IF(this->virtual_ip);
this->virtual_ip = ip;
}
break;
}
case INTERNAL_IP4_SERVER:
case INTERNAL_IP6_SERVER:
/* assume it's a Windows client if we see proprietary attributes */
this->ike_sa->enable_extension(this->ike_sa, EXT_MS_WINDOWS);
/* fall */
default:
{
if (this->initiator)
{
handle_attribute(this, ca);
}
}
}
}
/**
* Scan for configuration payloads and attributes
*/
static status_t process_payloads(private_xauth_request_t *this, message_t *message)
{
enumerator_t *enumerator, *attributes;
payload_t *payload;
enumerator = message->create_payload_enumerator(message);
while (enumerator->enumerate(enumerator, &payload))
{
switch(payload->get_type(payload))
{
case CONFIGURATION:
case CONFIGURATION_V1:
{
cp_payload_t *cp = (cp_payload_t*)payload;
configuration_attribute_t *ca;
switch (cp->get_type(cp))
{
case CFG_REQUEST:
case CFG_REPLY:
case CFG_SET:
case CFG_ACK:
{
attributes = cp->create_attribute_enumerator(cp);
while (attributes->enumerate(attributes, &ca))
{
DBG2(DBG_IKE, "processing %N attribute",
configuration_attribute_type_names, ca->get_type(ca));
process_attribute(this, ca);
}
attributes->destroy(attributes);
break;
}
default:
DBG1(DBG_IKE, "ignoring %N config payload",
config_type_names, cp->get_type(cp));
break;
}
switch(this->state)
{
case TASK_XAUTH_INIT:
if(((cp->get_type(cp) != CFG_REQUEST) && (cp->get_type(cp) != CFG_REPLY)) ||
(this->xauth_user_name_recv != TRUE) ||
(this->xauth_user_pass_recv != TRUE))
{
/* Didn't get an XAuth message, assume we're a ConfigMode message, set state appropriately */
this->state = TASK_XAUTH_COMPLETE;
this->next_state = TASK_XAUTH_COMPLETE;
this->status = SUCCESS;
break;
}
this->next_state = TASK_XAUTH_PASS_VERIFY;
break;
case TASK_XAUTH_PASS_VERIFY:
if(((cp->get_type(cp) != CFG_SET) && (cp->get_type(cp) != CFG_ACK)) ||
(this->xauth_status_recv != TRUE))
{
DBG1(DBG_IKE, "Didn't receive XAuth status.");
return FAILED;
}
/* Set the return status for the build call */
if(cp->get_type(cp) != CFG_ACK)
{
this->status = (this->xauth_status_data == XAUTH_STATUS_OK ? SUCCESS : FAILED);
}
else
{
this->status = SUCCESS;
}
this->next_state = TASK_XAUTH_COMPLETE;
break;
default:
this->next_state = TASK_XAUTH_COMPLETE;
this->status = SUCCESS;
break;
}
}
default:
break;
}
}
enumerator->destroy(enumerator);
if(this->xauth_authenticator)
{
this->xauth_authenticator->process(this->xauth_authenticator, message);
}
return NEED_MORE;
}
METHOD(task_t, build_i, status_t,
private_xauth_request_t *this, message_t *message)
{
cp_payload_t *cp = NULL;
chunk_t chunk = chunk_empty;
ike_version_t version;
payload_type_t cp_type;
payload_type_t ca_type;
host_t *vip;
peer_cfg_t *config;
enumerator_t *enumerator;
attribute_handler_t *handler;
configuration_attribute_type_t type;
chunk_t data;
status_t status;
version = this->ike_sa->get_version(this->ike_sa);
if(version == IKEV1)
{
if(!this->auth_cfg)
{
this->auth_cfg = get_auth_cfg(this, TRUE);
}
switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
{
case AUTH_CLASS_XAUTH_PSK:
case AUTH_CLASS_XAUTH_PUBKEY:
break;
default:
/* We aren't XAuth, so do nothing */
return SUCCESS;
}
cp_type = CONFIGURATION_V1;
ca_type = CONFIGURATION_ATTRIBUTE_V1;
}
else /* IKEv2 */
{
/* IKEv2 does not support XAuth, skip those states. */
this->state = TASK_XAUTH_COMPLETE;
if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */
return NEED_MORE;
}
cp_type = CONFIGURATION;
ca_type = CONFIGURATION_ATTRIBUTE;
}
switch(this->state)
{
case TASK_XAUTH_INIT:
cp = cp_payload_create_type(cp_type, CFG_REQUEST);
cp->add_attribute(cp, configuration_attribute_create_chunk(
ca_type, XAUTH_USER_NAME, chunk));
cp->add_attribute(cp, configuration_attribute_create_chunk(
ca_type, XAUTH_USER_PASSWORD, chunk));
break;
case TASK_XAUTH_PASS_VERIFY:
status = this->xauth_authenticator->build(this->xauth_authenticator, message);
cp = cp_payload_create_type(cp_type, CFG_SET);
cp->add_attribute(cp, configuration_attribute_create_value(
XAUTH_STATUS,
(status == FAILED ? XAUTH_STATUS_FAIL : XAUTH_STATUS_OK)));
break;
case TASK_XAUTH_COMPLETE:
/* ConfigMode stuff */
/* reuse virtual IP if we already have one */
vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
if (!vip)
{
config = this->ike_sa->get_peer_cfg(this->ike_sa);
vip = config->get_virtual_ip(config);
}
if (vip)
{
cp = cp_payload_create_type(cp_type, CFG_REQUEST);
cp->add_attribute(cp, build_vip(ca_type, vip));
}
enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), vip);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
configuration_attribute_t *ca;
entry_t *entry;
/* create configuration attribute */
DBG2(DBG_IKE, "building %N attribute",
configuration_attribute_type_names, type);
ca = configuration_attribute_create_chunk(ca_type,
type, data);
if (!cp)
{
cp = cp_payload_create_type(cp_type, CFG_REQUEST);
}
cp->add_attribute(cp, ca);
/* save handler along with requested type */
entry = malloc_thing(entry_t);
entry->type = type;
entry->handler = handler;
this->requested->insert_last(this->requested, entry);
}
enumerator->destroy(enumerator);
break;
default:
return FAILED;
}
/* Add the payloads into the message */
if(cp)
{
message->add_payload(message, (payload_t *)cp);
}
return NEED_MORE;
}
METHOD(task_t, process_r, status_t,
private_xauth_request_t *this, message_t *message)
{
ike_version_t version;
payload_type_t cp_type;
status_t status;
version = this->ike_sa->get_version(this->ike_sa);
if(version == IKEV1)
{
if(!this->auth_cfg)
{
this->auth_cfg = get_auth_cfg(this, TRUE);
}
switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
{
case AUTH_CLASS_XAUTH_PSK:
case AUTH_CLASS_XAUTH_PUBKEY:
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{
this->state = TASK_XAUTH_COMPLETE;
}
else
{
this->state = TASK_XAUTH_INIT;
}
break;
default:
/* We aren't XAuth, so do we should expect ConfigMode stuff */
this->state = TASK_XAUTH_COMPLETE;
}
if((this->xauth_authenticator == NULL) && (this->state == TASK_XAUTH_INIT))
{
this->xauth_authenticator = (authenticator_t *)xauth_authenticator_create_builder(this->ike_sa);
}
cp_type = CONFIGURATION_V1;
}
else /* IKEv2 */
{
/* IKEv2 does not support XAuth, skip those states. */
this->state = TASK_XAUTH_COMPLETE;
if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */
return NEED_MORE;
}
cp_type = CONFIGURATION;
}
status = process_payloads(this, message);
if(this->xauth_authenticator != NULL)
{
status = this->xauth_authenticator->process(this->xauth_authenticator, message);
}
return status;
}
METHOD(task_t, build_r, status_t,
private_xauth_request_t *this, message_t *message)
{
status_t status;
cp_payload_t *cp = NULL;
payload_type_t cp_type = CONFIGURATION;
payload_type_t ca_type = CONFIGURATION_ATTRIBUTE;
ike_version_t version;
identification_t *id;
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
host_t *vip = NULL;
peer_cfg_t *config;
version = this->ike_sa->get_version(this->ike_sa);
if ((version == IKEV2) && (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED))
{
return NEED_MORE;
}
if(version == IKEV1)
{
if(!this->auth_cfg)
{
this->auth_cfg = get_auth_cfg(this, TRUE);
}
switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
{
case AUTH_CLASS_XAUTH_PSK:
case AUTH_CLASS_XAUTH_PUBKEY:
break;
default:
this->state = TASK_XAUTH_COMPLETE;
return SUCCESS;
}
cp_type = CONFIGURATION_V1;
ca_type = CONFIGURATION_ATTRIBUTE_V1;
}
switch(this->state)
{
case TASK_XAUTH_INIT:
status = this->xauth_authenticator->build(this->xauth_authenticator, message);
this->state = TASK_XAUTH_PASS_VERIFY;
break;
case TASK_XAUTH_PASS_VERIFY:
cp = cp_payload_create_type(cp_type, CFG_ACK);
cp->add_attribute(cp, configuration_attribute_create_value(
XAUTH_STATUS, XAUTH_STATUS_OK));
status = this->status;
this->state = TASK_XAUTH_COMPLETE;
break;
case TASK_XAUTH_COMPLETE:
id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (this->virtual_ip)
{
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
if (config->get_pool(config))
{
vip = hydra->attributes->acquire_address(hydra->attributes,
config->get_pool(config), id, this->virtual_ip);
}
if (vip == NULL)
{
DBG1(DBG_IKE, "no virtual IP found, sending %N",
notify_type_names, INTERNAL_ADDRESS_FAILURE);
message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
chunk_empty);
return SUCCESS;
}
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp = cp_payload_create_type(cp_type, CFG_REPLY);
cp->add_attribute(cp, build_vip(ca_type, vip));
}
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
hydra->attributes, config->get_pool(config), id, vip);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
{
cp = cp_payload_create_type(cp_type, CFG_REPLY);
}
DBG2(DBG_IKE, "building %N attribute",
configuration_attribute_type_names, type);
cp->add_attribute(cp,
configuration_attribute_create_chunk(ca_type,
type, value));
}
enumerator->destroy(enumerator);
status = SUCCESS;
break;
default:
return FAILED;
}
if(cp != NULL)
{
message->add_payload(message, (payload_t *)cp);
}
if(status == SUCCESS)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
}
return status;
}
METHOD(task_t, process_i, status_t,
private_xauth_request_t *this, message_t *message)
{
status_t status;
if (((this->ike_sa->get_version(this->ike_sa) == IKEV2) &&
(this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)) ||
(this->ike_sa->get_version(this->ike_sa) == IKEV1))
{ /* in last IKE_AUTH exchange */
if(this->xauth_authenticator == NULL)
{
this->xauth_authenticator = (authenticator_t *)xauth_authenticator_create_verifier(this->ike_sa);
}
status = process_payloads(this, message);
this->state = this->next_state;
if (this->virtual_ip)
{
this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
}
if(this->state == TASK_XAUTH_COMPLETE)
{
if(this->status == SUCCESS)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
}
return this->status;
}
return status;
}
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);
DESTROY_IF(this->xauth_authenticator);
free(this);
}
METHOD(task_t, swap_initiator, void,
private_xauth_request_t *this)
{
if(this->initiator)
{
this->public.task.build = _build_r;
this->public.task.process = _process_r;
this->initiator = FALSE;
}
else
{
this->public.task.build = _build_i;
this->public.task.process = _process_i;
this->initiator = TRUE;
}
}
/*
* 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,
.swap_initiator = _swap_initiator,
},
},
.initiator = initiator,
.ike_sa = ike_sa,
.requested = linked_list_create(),
.state = TASK_XAUTH_INIT,
.next_state = TASK_XAUTH_INIT,
.xauth_status_data = XAUTH_STATUS_FAIL,
.xauth_user_name = chunk_empty,
.xauth_user_pass = chunk_empty,
.xauth_user_name_recv = FALSE,
.xauth_user_pass_recv = FALSE,
.xauth_status_recv = FALSE,
);
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;
}
-37
View File
@@ -1,37 +0,0 @@
/**
* @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_ @}*/
+2 -2
View File
@@ -18,8 +18,8 @@
* @{ @ingroup libstrongswan
*/
#ifndef XAUTH_H_
#define XAUTH_H_
#ifndef XAUTH_H__
#define XAUTH_H__
typedef enum xauth_type_t xauth_type_t;