aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-09-04 10:35:26 +0200
committerMartin Willi <martin@revosec.ch>2013-09-04 10:35:26 +0200
commitf7cb6eaaa88d8f43e7d65fbca5f81d9c117aa959 (patch)
treee4065153815b9eebc0e7bf2b19a8b8372b046760 /src
parent0b47bb5377193520d8d95fe66d6d3644abaf2307 (diff)
parenta858064455bc2fda9f54889395eccee8f91fd424 (diff)
downloadstrongswan-f7cb6eaaa88d8f43e7d65fbca5f81d9c117aa959.tar.bz2
strongswan-f7cb6eaaa88d8f43e7d65fbca5f81d9c117aa959.tar.xz
Merge branch 'ikev1-pushmode'
Implements Mode Config Push mode in IKEv1 using the existing modeconfig=push ipsec.conf option.
Diffstat (limited to 'src')
-rw-r--r--src/charon-cmd/cmd/cmd_connection.c2
-rw-r--r--src/charon-nm/nm/nm_service.c2
-rw-r--r--src/conftest/config.c4
-rw-r--r--src/frontends/android/jni/libandroidbridge/backend/android_service.c2
-rw-r--r--src/frontends/osx/charon-xpc/xpc_dispatch.c2
-rw-r--r--src/libcharon/config/peer_cfg.c18
-rw-r--r--src/libcharon/config/peer_cfg.h12
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c4
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c2
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c6
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c2
-rw-r--r--src/libcharon/plugins/sql/sql_config.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c9
-rw-r--r--src/libcharon/plugins/uci/uci_config.c2
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c34
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c67
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c66
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.c269
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.h3
-rw-r--r--src/starter/starterstroke.c1
-rw-r--r--src/stroke/stroke_msg.h1
22 files changed, 415 insertions, 97 deletions
diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index 5c459f99f..a697da804 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -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));
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index 901abd348..f97c11c18 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -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)
diff --git a/src/conftest/config.c b/src/conftest/config.c
index 7f05e9c72..1aa931004 100644
--- a/src/conftest/config.c
+++ b/src/conftest/config.c
@@ -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);
diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c
index c35d348ba..59a4e14cf 100644
--- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c
+++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c
@@ -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));
diff --git a/src/frontends/osx/charon-xpc/xpc_dispatch.c b/src/frontends/osx/charon-xpc/xpc_dispatch.c
index 0a5de15fd..0757e9baf 100644
--- a/src/frontends/osx/charon-xpc/xpc_dispatch.c
+++ b/src/frontends/osx/charon-xpc/xpc_dispatch.c
@@ -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));
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index eb983199b..d198503d0 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -100,6 +100,11 @@ struct private_peer_cfg_t {
bool aggressive;
/**
+ * Use pull or push in mode config?
+ */
+ bool pull_mode;
+
+ /**
* Time before starting rekeying
*/
u_int32_t rekey_time;
@@ -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(),
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index e62e03ec5..7e82b517f 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -248,6 +248,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.
*
* @return dpd_delay in seconds
@@ -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);
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index 4e656e73b..26d152c8f 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -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);
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index ebadf44ca..26c9871f0 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -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);
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index d7539c2da..f04bc5a4c 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -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));
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 2bff70307..e852e3f47 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -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 */
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index 06339220a..45487a976 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -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);
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index c3471a078..e6b69a4f4 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -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)
{
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 079e65f11..2e36ce3a3 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -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;
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index b58d120c1..040d8a84f 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -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();
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index dfceb5446..d97ef0ebe 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -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;
+
+ local = FALSE;
}
- enumerator->destroy(enumerator);
+ 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
{
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 6b00706bf..46cbb879b 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -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;
}
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index 441bd7a78..81638169a 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -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))
+ {
+ 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))
{
- 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, 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;
}
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index ce897727a..17fe02538 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -42,14 +42,19 @@ 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);
}
@@ -189,6 +194,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
*/
static void process_payloads(private_mode_config_t *this, message_t *message)
@@ -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(),
);
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.h b/src/libcharon/sa/ikev1/tasks/mode_config.h
index 462bee374..c2da7a086 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.h
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.h
@@ -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_ @}*/
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index cc447c41f..f4541937b 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -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);
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index a4dfc5e7a..6c8dcf5f9 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -258,6 +258,7 @@ struct stroke_msg_t {
int mode;
int mobike;
int aggressive;
+ int pushmode;
int force_encap;
int fragmentation;
int ipcomp;