Merge branch 'ikev1-pushmode'

Implements Mode Config Push mode in IKEv1 using the existing modeconfig=push
ipsec.conf option.
This commit is contained in:
Martin Willi
2013-09-04 10:35:26 +02:00
23 changed files with 417 additions and 100 deletions
+1 -2
View File
@@ -931,8 +931,7 @@ Accepted values are
and
.B pull
(the default).
Push mode is currently not supported in charon, hence this parameter has no
effect.
Push mode is currently not supported with IKEv2.
.TP
.BR reauth " = " yes " | no"
whether rekeying of an IKE_SA should also reauthenticate the peer. In IKEv1,
+1 -1
View File
@@ -170,7 +170,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, aggressive, /* mobike, aggressive */
TRUE, aggressive, TRUE, /* mobike, aggressive, pull */
30, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation */
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
+1 -1
View File
@@ -536,7 +536,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
0, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation */
if (virtual)
+2 -2
View File
@@ -249,8 +249,8 @@ static peer_cfg_t *load_peer_config(private_config_t *this,
ike_cfg = load_ike_config(this, settings, config);
peer_cfg = peer_cfg_create(config, ike_cfg, CERT_ALWAYS_SEND,
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, 0, 0,
FALSE, NULL, NULL);
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, TRUE,
0, 0, FALSE, NULL, NULL);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
@@ -535,7 +535,7 @@ static job_requeue_t initiate(private_android_service_t *this)
UNIQUE_REPLACE, 0, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
0, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation */
peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET));
+1 -1
View File
@@ -91,7 +91,7 @@ static peer_cfg_t* create_peer_cfg(char *name, char *host)
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
30, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation */
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
+16 -2
View File
@@ -99,6 +99,11 @@ struct private_peer_cfg_t {
*/
bool aggressive;
/**
* Use pull or push in mode config?
*/
bool pull_mode;
/**
* Time before starting rekeying
*/
@@ -390,6 +395,12 @@ METHOD(peer_cfg_t, use_aggressive, bool,
return this->aggressive;
}
METHOD(peer_cfg_t, use_pull_mode, bool,
private_peer_cfg_t *this)
{
return this->pull_mode;
}
METHOD(peer_cfg_t, get_dpd, u_int32_t,
private_peer_cfg_t *this)
{
@@ -588,6 +599,7 @@ METHOD(peer_cfg_t, equals, bool,
this->over_time == other->over_time &&
this->dpd == other->dpd &&
this->aggressive == other->aggressive &&
this->pull_mode == other->pull_mode &&
auth_cfg_equal(this, other)
#ifdef ME
&& this->mediation == other->mediation &&
@@ -638,8 +650,8 @@ peer_cfg_t *peer_cfg_create(char *name,
unique_policy_t unique, u_int32_t keyingtries,
u_int32_t rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd,
u_int32_t dpd_timeout,
bool mobike, bool aggressive, bool pull_mode,
u_int32_t dpd, u_int32_t dpd_timeout,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id)
{
@@ -671,6 +683,7 @@ peer_cfg_t *peer_cfg_create(char *name,
.get_over_time = _get_over_time,
.use_mobike = _use_mobike,
.use_aggressive = _use_aggressive,
.use_pull_mode = _use_pull_mode,
.get_dpd = _get_dpd,
.get_dpd_timeout = _get_dpd_timeout,
.add_virtual_ip = _add_virtual_ip,
@@ -701,6 +714,7 @@ peer_cfg_t *peer_cfg_create(char *name,
.over_time = over_time,
.use_mobike = mobike,
.aggressive = aggressive,
.pull_mode = pull_mode,
.dpd = dpd,
.dpd_timeout = dpd_timeout,
.vips = linked_list_create(),
+10 -2
View File
@@ -247,6 +247,13 @@ struct peer_cfg_t {
*/
bool (*use_aggressive)(peer_cfg_t *this);
/**
* Use pull or push mode for mode config?
*
* @return TRUE to use pull, FALSE to use push mode
*/
bool (*use_pull_mode)(peer_cfg_t *this);
/**
* Get the DPD check interval.
*
@@ -366,6 +373,7 @@ struct peer_cfg_t {
* @param over_time maximum overtime before closing a rekeying/reauth SA
* @param mobike use MOBIKE (RFC4555) if peer supports it
* @param aggressive use/accept aggressive mode with IKEv1
* @param pullmode TRUE to use modeconfig pull, FALSE for push
* @param dpd DPD check interval, 0 to disable
* @param dpd_timeout DPD timeout interval (IKEv1 only), if 0 default applies
* @param mediation TRUE if this is a mediation connection
@@ -378,8 +386,8 @@ peer_cfg_t *peer_cfg_create(char *name,
unique_policy_t unique, u_int32_t keyingtries,
u_int32_t rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd,
u_int32_t dpd_timeout,
bool mobike, bool aggressive, bool pull_mode,
u_int32_t dpd, u_int32_t dpd_timeout,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id);
+2 -2
View File
@@ -208,8 +208,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
0, FALSE, NULL, NULL);
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE,
TRUE, 30, 0, FALSE, NULL, NULL);
auth_cfg = auth_cfg_create();
auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
@@ -561,7 +561,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */
this->ike_rekey, 0, /* rekey, reauth */
0, this->ike_rekey, /* jitter, overtime */
FALSE, FALSE, /* mobike, aggressive mode */
FALSE, FALSE, TRUE, /* mobike, aggressive, pull */
this->dpd_delay, /* dpd_delay */
this->dpd_timeout, /* dpd_timeout */
FALSE, NULL, NULL);
+1 -1
View File
@@ -334,7 +334,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
0, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation */
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
+3 -3
View File
@@ -112,7 +112,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
this->dpd, 0, /* DPD delay, timeout */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
@@ -149,7 +149,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
this->dpd, 0, /* DPD delay, timeout */
FALSE, med_cfg, /* mediation, med by */
identification_create_from_encoding(ID_KEY_ID, other));
@@ -224,7 +224,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
this->dpd, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation, med by, peer id */
+1 -1
View File
@@ -92,7 +92,7 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressiv */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
this->dpd, 0, /* DPD delay, timeout */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
+1 -1
View File
@@ -374,7 +374,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
peer_cfg = peer_cfg_create(
name, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime,
mobike, FALSE, dpd_delay, 0,
mobike, FALSE, TRUE, dpd_delay, 0,
mediation, mediated_cfg, peer_id);
if (vip)
{
+8 -1
View File
@@ -731,6 +731,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
msg->add_conn.me.sendcert, unique,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.aggressive,
msg->add_conn.pushmode == 0,
msg->add_conn.dpd.delay, msg->add_conn.dpd.timeout,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
@@ -780,7 +781,13 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
enumerator->destroy(enumerator);
}
if (msg->add_conn.me.sourceip)
if (msg->add_conn.me.sourceip && msg->add_conn.other.sourceip)
{
DBG1(DBG_CFG, "'%s' has both left- and rightsourceip, but IKE can "
"negotiate one virtual IP only, ignoring local virtual IP",
msg->add_conn.name);
}
else if (msg->add_conn.me.sourceip)
{
enumerator_t *enumerator;
char *token;
+1 -1
View File
@@ -162,7 +162,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
1800, 900, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
60, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
+27 -9
View File
@@ -539,23 +539,40 @@ static bool mode_config_expected(private_task_manager_t *this)
enumerator_t *enumerator;
peer_cfg_t *peer_cfg;
char *pool;
bool local;
host_t *host;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg)
{
enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
if (!enumerator->enumerate(enumerator, &pool))
{ /* no pool configured */
if (peer_cfg->use_pull_mode(peer_cfg))
{
enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
if (!enumerator->enumerate(enumerator, &pool))
{ /* no pool configured */
enumerator->destroy(enumerator);
return FALSE;
}
enumerator->destroy(enumerator);
return FALSE;
}
enumerator->destroy(enumerator);
local = FALSE;
}
else
{
enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
if (!enumerator->enumerate(enumerator, &host))
{ /* not requesting a vip */
enumerator->destroy(enumerator);
return FALSE;
}
enumerator->destroy(enumerator);
local = TRUE;
}
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
FALSE);
local);
if (!enumerator->enumerate(enumerator, &host))
{ /* have a pool, but no VIP assigned yet */
{ /* expecting a VIP exchange, but no VIP assigned yet */
enumerator->destroy(enumerator);
return TRUE;
}
@@ -1087,7 +1104,8 @@ static status_t process_request(private_task_manager_t *this,
case TRANSACTION:
if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
{
task = (task_t *)mode_config_create(this->ike_sa, FALSE);
task = (task_t *)mode_config_create(this->ike_sa,
FALSE, TRUE);
}
else
{
+52 -15
View File
@@ -196,6 +196,17 @@ static status_t send_delete(private_aggressive_mode_t *this)
return ALREADY_DONE;
}
/**
* Schedule a timeout for the IKE_SA should it not establish
*/
static void schedule_timeout(ike_sa_t *ike_sa)
{
job_t *job;
job = (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE);
lib->scheduler->schedule_job(lib->scheduler, job, HALF_OPEN_IKE_SA_TIMEOUT);
}
METHOD(task_t, build_i, status_t,
private_aggressive_mode_t *this, message_t *message)
{
@@ -300,20 +311,15 @@ METHOD(task_t, build_i, status_t,
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA:
case AUTH_HYBRID_INIT_RSA:
{ /* wait for XAUTH request, since this may never come,
* we queue a timeout */
job_t *job = (job_t*)delete_ike_sa_job_create(
this->ike_sa->get_id(this->ike_sa), FALSE);
lib->scheduler->schedule_job(lib->scheduler, job,
HALF_OPEN_IKE_SA_TIMEOUT);
/* wait for XAUTH request */
schedule_timeout(this->ike_sa);
break;
}
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
case AUTH_HYBRID_RESP_RSA:
this->ike_sa->queue_task(this->ike_sa,
(task_t*)xauth_create(this->ike_sa, TRUE));
return SUCCESS;
break;
default:
if (charon->ike_sa_manager->check_uniqueness(
charon->ike_sa_manager, this->ike_sa, FALSE))
@@ -328,10 +334,30 @@ METHOD(task_t, build_i, status_t,
}
break;
}
/* check for and prepare mode config push/pull */
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
}
else
{
schedule_timeout(this->ike_sa);
}
}
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
{
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
{
schedule_timeout(this->ike_sa);
}
else
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
}
}
return SUCCESS;
}
@@ -482,7 +508,7 @@ METHOD(task_t, process_r, status_t,
case AUTH_HYBRID_INIT_RSA:
this->ike_sa->queue_task(this->ike_sa,
(task_t*)xauth_create(this->ike_sa, TRUE));
return SUCCESS;
break;
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
case AUTH_HYBRID_RESP_RSA:
@@ -505,11 +531,22 @@ METHOD(task_t, process_r, status_t,
this->ike_sa->get_id(this->ike_sa)));
break;
}
if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
/* check for and prepare mode config push/pull */
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
}
}
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
{
if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
}
}
return SUCCESS;
}
+51 -15
View File
@@ -504,7 +504,7 @@ METHOD(task_t, build_r, status_t,
case AUTH_HYBRID_INIT_RSA:
this->ike_sa->queue_task(this->ike_sa,
(task_t*)xauth_create(this->ike_sa, TRUE));
return SUCCESS;
break;
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
case AUTH_HYBRID_RESP_RSA:
@@ -527,11 +527,21 @@ METHOD(task_t, build_r, status_t,
this->ike_sa->get_id(this->ike_sa)));
break;
}
if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
}
}
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
{
if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
}
}
return SUCCESS;
}
@@ -540,6 +550,17 @@ METHOD(task_t, build_r, status_t,
}
}
/**
* Schedule a timeout for the IKE_SA should it not establish
*/
static void schedule_timeout(ike_sa_t *ike_sa)
{
job_t *job;
job = (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE);
lib->scheduler->schedule_job(lib->scheduler, job, HALF_OPEN_IKE_SA_TIMEOUT);
}
METHOD(task_t, process_i, status_t,
private_main_mode_t *this, message_t *message)
{
@@ -639,20 +660,15 @@ METHOD(task_t, process_i, status_t,
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA:
case AUTH_HYBRID_INIT_RSA:
{ /* wait for XAUTH request, since this may never come,
* we queue a timeout */
job_t *job = (job_t*)delete_ike_sa_job_create(
this->ike_sa->get_id(this->ike_sa), FALSE);
lib->scheduler->schedule_job(lib->scheduler, job,
HALF_OPEN_IKE_SA_TIMEOUT);
/* wait for XAUTH request */
schedule_timeout(this->ike_sa);
break;
}
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
case AUTH_HYBRID_RESP_RSA:
this->ike_sa->queue_task(this->ike_sa,
(task_t*)xauth_create(this->ike_sa, TRUE));
return SUCCESS;
break;
default:
if (charon->ike_sa_manager->check_uniqueness(
charon->ike_sa_manager, this->ike_sa, FALSE))
@@ -667,10 +683,30 @@ METHOD(task_t, process_i, status_t,
}
break;
}
/* check for and prepare mode config push/pull */
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
}
else
{
schedule_timeout(this->ike_sa);
}
}
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
{
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
{
schedule_timeout(this->ike_sa);
}
else
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
}
}
return SUCCESS;
}
+232 -37
View File
@@ -41,15 +41,20 @@ struct private_mode_config_t {
*/
bool initiator;
/**
* Use pull (CFG_REQUEST/RESPONSE) or push (CFG_SET/ACK)?
*/
bool pull;
/**
* Received list of virtual IPs, host_t*
*/
linked_list_t *vips;
/**
* list of attributes requested and its handler, entry_t
* Requested/received list of attributes, entry_t
*/
linked_list_t *requested;
linked_list_t *attributes;
/**
* Identifier to include in response
@@ -58,12 +63,12 @@ struct private_mode_config_t {
};
/**
* Entry for a requested attribute and the requesting handler
* Entry for a attribute and associated handler
*/
typedef struct {
/** attribute requested */
/** attribute type */
configuration_attribute_type_t type;
/** handler requesting this attribute */
/** handler for this attribute */
attribute_handler_t *handler;
} entry_t;
@@ -117,13 +122,13 @@ static void handle_attribute(private_mode_config_t *this,
entry_t *entry;
/* find the handler which requested this attribute */
enumerator = this->requested->create_enumerator(this->requested);
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->type == ca->get_type(ca))
{
handler = entry->handler;
this->requested->remove_at(this->requested, enumerator);
this->attributes->remove_at(this->attributes, enumerator);
free(entry);
break;
}
@@ -180,7 +185,7 @@ static void process_attribute(private_mode_config_t *this,
}
default:
{
if (this->initiator)
if (this->initiator == this->pull)
{
handle_attribute(this, ca);
}
@@ -188,6 +193,24 @@ static void process_attribute(private_mode_config_t *this,
}
}
/**
* Check if config allows push mode when acting as task responder
*/
static bool accept_push(private_mode_config_t *this)
{
enumerator_t *enumerator;
peer_cfg_t *config;
bool vip;
host_t *host;
config = this->ike_sa->get_peer_cfg(this->ike_sa);
enumerator = config->create_virtual_ip_enumerator(config);
vip = enumerator->enumerate(enumerator, &host);
enumerator->destroy(enumerator);
return vip && !config->use_pull_mode(config);
}
/**
* Scan for configuration payloads and attributes
*/
@@ -206,6 +229,15 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
switch (cp->get_type(cp))
{
case CFG_SET:
/* when acting as a responder, we detect the mode using
* the type of configuration payload. But we should double
* check the peer is allowed to use push mode on us. */
if (!this->initiator && accept_push(this))
{
this->pull = FALSE;
}
/* FALL */
case CFG_REQUEST:
this->identifier = cp->get_identifier(cp);
/* FALL */
@@ -219,6 +251,8 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
}
attributes->destroy(attributes);
break;
case CFG_ACK:
break;
default:
DBG1(DBG_IKE, "ignoring %N config payload",
config_type_names, cp->get_type(cp));
@@ -229,8 +263,29 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
enumerator->destroy(enumerator);
}
METHOD(task_t, build_i, status_t,
private_mode_config_t *this, message_t *message)
/**
* Add an attribute to a configuration payload, and store it in task
*/
static void add_attribute(private_mode_config_t *this, cp_payload_t *cp,
configuration_attribute_type_t type, chunk_t data,
attribute_handler_t *handler)
{
entry_t *entry;
cp->add_attribute(cp,
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
type, data));
INIT(entry,
.type = type,
.handler = handler,
);
this->attributes->insert_last(this->attributes, entry);
}
/**
* Build a CFG_REQUEST as initiator
*/
static status_t build_request(private_mode_config_t *this, message_t *message)
{
cp_payload_t *cp;
enumerator_t *enumerator;
@@ -279,18 +334,7 @@ METHOD(task_t, build_i, status_t,
this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
entry_t *entry;
DBG2(DBG_IKE, "building %N attribute",
configuration_attribute_type_names, type);
cp->add_attribute(cp,
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
type, data));
INIT(entry,
.type = type,
.handler = handler,
);
this->requested->insert_last(this->requested, entry);
add_attribute(this, cp, type, data, handler);
}
enumerator->destroy(enumerator);
@@ -301,15 +345,121 @@ METHOD(task_t, build_i, status_t,
return NEED_MORE;
}
/**
* Build a CFG_SET as initiator
*/
static status_t build_set(private_mode_config_t *this, message_t *message)
{
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
cp_payload_t *cp;
peer_cfg_t *config;
identification_t *id;
linked_list_t *pools;
host_t *any4, *any6, *found;
char *name;
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET);
id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(this->ike_sa);
any4 = host_create_any(AF_INET);
any6 = host_create_any(AF_INET6);
this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
/* in push mode, we ask each configured pool for an address */
enumerator = config->create_pool_enumerator(config);
while (enumerator->enumerate(enumerator, &name))
{
pools = linked_list_create_with_items(name, NULL);
/* try IPv4, then IPv6 */
found = hydra->attributes->acquire_address(hydra->attributes,
pools, id, any4);
if (!found)
{
found = hydra->attributes->acquire_address(hydra->attributes,
pools, id, any6);
}
pools->destroy(pools);
if (found)
{
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
cp->add_attribute(cp, build_vip(found));
this->vips->insert_last(this->vips, found);
}
}
enumerator->destroy(enumerator);
any4->destroy(any4);
any6->destroy(any6);
/* query registered providers for additional attributes to include */
pools = linked_list_create_from_enumerator(
config->create_pool_enumerator(config));
enumerator = hydra->attributes->create_responder_enumerator(
hydra->attributes, pools, id, this->vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
add_attribute(this, cp, type, value, NULL);
}
enumerator->destroy(enumerator);
pools->destroy(pools);
message->add_payload(message, (payload_t*)cp);
return SUCCESS;
}
METHOD(task_t, build_i, status_t,
private_mode_config_t *this, message_t *message)
{
if (this->pull)
{
return build_request(this, message);
}
return build_set(this, message);
}
/**
* Store received virtual IPs to the IKE_SA, install them
*/
static void install_vips(private_mode_config_t *this)
{
enumerator_t *enumerator;
host_t *host;
this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &host))
{
if (!host->is_anyaddr(host))
{
this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
}
}
enumerator->destroy(enumerator);
}
METHOD(task_t, process_r, status_t,
private_mode_config_t *this, message_t *message)
{
process_payloads(this, message);
if (!this->pull)
{
install_vips(this);
}
return NEED_MORE;
}
METHOD(task_t, build_r, status_t,
private_mode_config_t *this, message_t *message)
/**
* Build CFG_REPLY message after receiving CFG_REQUEST
*/
static status_t build_reply(private_mode_config_t *this, message_t *message)
{
enumerator_t *enumerator;
configuration_attribute_type_t type;
@@ -360,8 +510,6 @@ METHOD(task_t, build_r, status_t,
hydra->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
DBG2(DBG_IKE, "building %N attribute",
configuration_attribute_type_names, type);
cp->add_attribute(cp,
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
type, value));
@@ -376,26 +524,72 @@ METHOD(task_t, build_r, status_t,
return SUCCESS;
}
METHOD(task_t, process_i, status_t,
private_mode_config_t *this, message_t *message)
/**
* Build CFG_ACK for a received CFG_SET
*/
static status_t build_ack(private_mode_config_t *this, message_t *message)
{
cp_payload_t *cp;
enumerator_t *enumerator;
host_t *host;
configuration_attribute_type_t type;
entry_t *entry;
process_payloads(this, message);
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK);
this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
/* return empty attributes for installed IPs */
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &host))
{
if (!host->is_anyaddr(host))
type = INTERNAL_IP6_ADDRESS;
if (host->get_family(host) == AF_INET6)
{
this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
type = INTERNAL_IP6_ADDRESS;
}
else
{
type = INTERNAL_IP4_ADDRESS;
}
cp->add_attribute(cp, configuration_attribute_create_chunk(
CONFIGURATION_ATTRIBUTE_V1, type, chunk_empty));
}
enumerator->destroy(enumerator);
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &entry))
{
cp->add_attribute(cp,
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
entry->type, chunk_empty));
}
enumerator->destroy(enumerator);
cp->set_identifier(cp, this->identifier);
message->add_payload(message, (payload_t*)cp);
return SUCCESS;
}
METHOD(task_t, build_r, status_t,
private_mode_config_t *this, message_t *message)
{
if (this->pull)
{
return build_reply(this, message);
}
return build_ack(this, message);
}
METHOD(task_t, process_i, status_t,
private_mode_config_t *this, message_t *message)
{
process_payloads(this, message);
if (this->pull)
{
install_vips(this);
}
return SUCCESS;
}
@@ -411,22 +605,22 @@ METHOD(task_t, migrate, void,
this->ike_sa = ike_sa;
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->vips = linked_list_create();
this->requested->destroy_function(this->requested, free);
this->requested = linked_list_create();
this->attributes->destroy_function(this->attributes, free);
this->attributes = linked_list_create();
}
METHOD(task_t, destroy, void,
private_mode_config_t *this)
{
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->requested->destroy_function(this->requested, free);
this->attributes->destroy_function(this->attributes, free);
free(this);
}
/*
* Described in header.
*/
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator, bool pull)
{
private_mode_config_t *this;
@@ -439,8 +633,9 @@ mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
},
},
.initiator = initiator,
.pull = initiator ? pull : TRUE,
.ike_sa = ike_sa,
.requested = linked_list_create(),
.attributes = linked_list_create(),
.vips = linked_list_create(),
);
+2 -1
View File
@@ -43,8 +43,9 @@ struct mode_config_t {
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE for initiator
* @param pull TRUE to pull, FALSE to push (applies if initiator only)
* @return mode_config task to handle by the task_manager
*/
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator);
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator, bool pull);
#endif /** MODE_CONFIG_H_ @}*/
+1
View File
@@ -186,6 +186,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
msg.add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS;
msg.add_conn.install_policy = conn->install_policy;
msg.add_conn.aggressive = conn->aggressive;
msg.add_conn.pushmode = conn->options & SA_OPTION_MODECFG_PUSH;
msg.add_conn.crl_policy = (crl_policy_t)cfg->setup.strictcrlpolicy;
msg.add_conn.unique = cfg->setup.uniqueids;
msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
+1
View File
@@ -258,6 +258,7 @@ struct stroke_msg_t {
int mode;
int mobike;
int aggressive;
int pushmode;
int force_encap;
int fragmentation;
int ipcomp;