From: Tobias Brunner Date: Mon, 24 Dec 2012 11:28:01 +0000 (+0100) Subject: Use a connection specific option to en-/disable IKEv1 fragmentation X-Git-Tag: 5.0.2dr4~8^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=97973f860924e4472be9c842c34843cd95680642;p=thirdparty%2Fstrongswan.git Use a connection specific option to en-/disable IKEv1 fragmentation --- diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in index 303fb78fac..01c7c3848b 100644 --- a/man/ipsec.conf.5.in +++ b/man/ipsec.conf.5.in @@ -403,6 +403,16 @@ force UDP encapsulation for ESP packets even if no NAT situation is detected. This may help to surmount restrictive firewalls. In order to force the peer to encapsulate packets, NAT detection payloads are faked. .TP +.BR fragmentation " = yes | " no +whether to use IKE fragmentation (proprietary IKEv1 extension). Acceptable +values are +.B yes +and +.B no +(the default). Fragmented messages sent by a peer are always accepted +irrespective of the value of this option. If enabled, and the peer supports it, +larger IKE messages will be sent in fragments. +.TP .BR ike " = " comma-separated list of IKE/ISAKMP SA encryption/authentication algorithms to be used, e.g. diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index 14caccb3a5..8000951ab4 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -178,11 +178,6 @@ openly transmitted hash of the PSK) .BR charon.ignore_routing_tables A space-separated list of routing tables to be excluded from route lookups .TP -.BR charon.ike_fragmentation " [no]" -Enables IKE fragmentation (proprietary IKEv1 extension). Fragmented messages -are always accepted irrespective of the value of this option. If the peer -supports it larger messages will be sent in fragments. -.TP .BR charon.ikesa_table_segments " [1]" Number of exclusively locked segments in the hash table .TP diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c index 6fa5e51a42..7eb5e85650 100644 --- a/src/charon-nm/nm/nm_service.c +++ b/src/charon-nm/nm/nm_service.c @@ -500,7 +500,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, */ ike_cfg = ike_cfg_create(IKEV2, TRUE, encap, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - (char*)address, FALSE, IKEV2_UDP_PORT); + (char*)address, FALSE, IKEV2_UDP_PORT, FALSE); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create(priv->name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */ diff --git a/src/conftest/config.c b/src/conftest/config.c index f896b95377..e2705467fe 100644 --- a/src/conftest/config.c +++ b/src/conftest/config.c @@ -106,7 +106,7 @@ static ike_cfg_t *load_ike_config(private_config_t *this, settings->get_str(settings, "configs.%s.lhost", "%any", config), FALSE, settings->get_int(settings, "configs.%s.lport", 500, config), settings->get_str(settings, "configs.%s.rhost", "%any", config), FALSE, - settings->get_int(settings, "configs.%s.rport", 500, config)); + settings->get_int(settings, "configs.%s.rport", 500, config), FALSE); token = settings->get_str(settings, "configs.%s.proposal", NULL, config); if (token) { diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c index 6c23bf2688..f7fe29070b 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c +++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c @@ -471,7 +471,7 @@ static job_requeue_t initiate(private_android_service_t *this) ike_cfg = ike_cfg_create(IKEV2, TRUE, TRUE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - this->gateway, FALSE, IKEV2_UDP_PORT); + this->gateway, FALSE, IKEV2_UDP_PORT, FALSE); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED, diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c index 1006fc295e..e87b47e69c 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -89,6 +89,11 @@ struct private_ike_cfg_t { */ bool force_encap; + /** + * use IKEv1 fragmentation + */ + bool fragmentation; + /** * List of proposals to use */ @@ -113,6 +118,12 @@ METHOD(ike_cfg_t, force_encap_, bool, return this->force_encap; } +METHOD(ike_cfg_t, fragmentation, bool, + private_ike_cfg_t *this) +{ + return this->fragmentation; +} + METHOD(ike_cfg_t, get_my_addr, char*, private_ike_cfg_t *this, bool *allow_any) { @@ -268,6 +279,7 @@ METHOD(ike_cfg_t, equals, bool, this->version == other->version && this->certreq == other->certreq && this->force_encap == other->force_encap && + this->fragmentation == other->fragmentation && streq(this->me, other->me) && streq(this->other, other->other) && this->my_port == other->my_port && @@ -299,7 +311,8 @@ METHOD(ike_cfg_t, destroy, void, */ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, char *me, bool my_allow_any, u_int16_t my_port, - char *other, bool other_allow_any, u_int16_t other_port) + char *other, bool other_allow_any, u_int16_t other_port, + bool fragmentation) { private_ike_cfg_t *this; @@ -308,6 +321,7 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, .get_version = _get_version, .send_certreq = _send_certreq, .force_encap = _force_encap_, + .fragmentation = _fragmentation, .get_my_addr = _get_my_addr, .get_other_addr = _get_other_addr, .get_my_port = _get_my_port, @@ -324,6 +338,7 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, .version = version, .certreq = certreq, .force_encap = force_encap, + .fragmentation = fragmentation, .me = strdup(me), .other = strdup(other), .my_allow_any = my_allow_any, diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h index fa2aaa3259..0c44842525 100644 --- a/src/libcharon/config/ike_cfg.h +++ b/src/libcharon/config/ike_cfg.h @@ -134,10 +134,17 @@ struct ike_cfg_t { /** * Enforce UDP encapsulation by faking NATD notifies? * - * @return TRUE to enfoce UDP encapsulation + * @return TRUE to enforce UDP encapsulation */ bool (*force_encap) (ike_cfg_t *this); + /** + * Use proprietary IKEv1 fragmentation + * + * @return TRUE to use fragmentation + */ + bool (*fragmentation) (ike_cfg_t *this); + /** * Get the DH group to use for IKE_SA setup. * @@ -183,10 +190,12 @@ struct ike_cfg_t { * @param other address/DNS name of remote peer * @param other_allow_any allow override of remote address by any address * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating + * @param fragmentation use IKEv1 fragmentation * @return ike_cfg_t object. */ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, char *me, bool my_allow_any, u_int16_t my_port, - char *other, bool other_allow_any, u_int16_t other_port); + char *other, bool other_allow_any, u_int16_t other_port, + bool fragmentation); #endif /** IKE_CFG_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c index d398b136f2..0188b0c2ba 100644 --- a/src/libcharon/plugins/android/android_service.c +++ b/src/libcharon/plugins/android/android_service.c @@ -266,7 +266,7 @@ static job_requeue_t initiate(private_android_service_t *this) ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - hostname, FALSE, IKEV2_UDP_PORT); + hostname, FALSE, IKEV2_UDP_PORT, FALSE); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED, diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index 05f522e8e1..e7db1ff0f5 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -205,7 +205,7 @@ static void setup_tunnel(private_ha_tunnel_t *this, /* create config and backend */ ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote, FALSE, IKEV2_UDP_PORT); + remote, FALSE, IKEV2_UDP_PORT, FALSE); 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, diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index 9e16156865..a9d399b9d7 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -490,14 +490,14 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) { ike_cfg = ike_cfg_create(this->version, TRUE, FALSE, local, FALSE, this->port + num - 1, - remote, FALSE, IKEV2_NATT_PORT); + remote, FALSE, IKEV2_NATT_PORT, FALSE); } else { ike_cfg = ike_cfg_create(this->version, TRUE, FALSE, local, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote, FALSE, IKEV2_UDP_PORT); + remote, FALSE, IKEV2_UDP_PORT, FALSE); } ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal)); peer_cfg = peer_cfg_create("load-test", ike_cfg, diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index dca01fbaa2..759bd9646c 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -325,7 +325,7 @@ static gboolean initiate_connection(private_maemo_service_t *this, ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - hostname, FALSE, IKEV2_UDP_PORT); + hostname, FALSE, IKEV2_UDP_PORT, FALSE); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create(this->current, ike_cfg, diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index 42c158231e..12ffc1ae43 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -105,7 +105,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - address, FALSE, IKEV2_UDP_PORT); + address, FALSE, IKEV2_UDP_PORT, FALSE); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); med_cfg = peer_cfg_create( "mediation", ike_cfg, @@ -380,7 +380,7 @@ medcli_config_t *medcli_config_create(database_t *db) .ike = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - "0.0.0.0", FALSE, IKEV2_UDP_PORT), + "0.0.0.0", FALSE, IKEV2_UDP_PORT, FALSE), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c index a2d7489f4a..d167581119 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.c +++ b/src/libcharon/plugins/medsrv/medsrv_config.c @@ -142,7 +142,7 @@ medsrv_config_t *medsrv_config_create(database_t *db) .ike = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - "0.0.0.0", FALSE, IKEV2_UDP_PORT), + "0.0.0.0", FALSE, IKEV2_UDP_PORT, FALSE), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c index 565c8584ba..44a593c7b7 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -261,7 +261,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, ike_cfg = ike_cfg_create(IKEV2, certreq, force_encap, local, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote, FALSE, IKEV2_UDP_PORT); + remote, FALSE, IKEV2_UDP_PORT, FALSE); add_ike_proposals(this, ike_cfg, id); return ike_cfg; } diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index de3f4472e4..0ab94f2a7d 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -233,7 +233,8 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg ikeport, msg->add_conn.other.address, msg->add_conn.other.allow_any, - msg->add_conn.other.ikeport); + msg->add_conn.other.ikeport, + msg->add_conn.fragmentation); add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL); return ike_cfg; } diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index 76dce125bb..6dae14e3dc 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -155,7 +155,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool, ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote_addr, FALSE, IKEV2_UDP_PORT); + remote_addr, FALSE, IKEV2_UDP_PORT, FALSE); ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); this->peer_cfg = peer_cfg_create( name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO, @@ -253,7 +253,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool, this->ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote_addr, FALSE, IKEV2_UDP_PORT); + remote_addr, FALSE, IKEV2_UDP_PORT, FALSE); this->ike_cfg->add_proposal(this->ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 606a981d09..320aa5e6b1 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -225,11 +225,6 @@ struct private_task_manager_t { } frag; - /** - * TRUE if fragmentation (as sender) is enabled in config - */ - bool fragmentation; - /** * List of queued tasks not yet in action */ @@ -411,12 +406,14 @@ static bool send_fragment(private_task_manager_t *this, bool request, static bool send_packet(private_task_manager_t *this, bool request, packet_t *packet) { + ike_cfg_t *ike_cfg; host_t *src, *dst; chunk_t data; + ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); data = packet->get_data(packet); if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_FRAGMENTATION) && - this->fragmentation && data.len > MAX_FRAGMENT_SIZE) + ike_cfg->fragmentation(ike_cfg) && data.len > MAX_FRAGMENT_SIZE) { fragment_payload_t *fragment; u_int8_t num, count; @@ -2001,8 +1998,6 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa) "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, charon->name), .retransmit_base = lib->settings->get_double(lib->settings, "%s.retransmit_base", RETRANSMIT_BASE, charon->name), - .fragmentation = lib->settings->get_bool(lib->settings, - "%s.ike_fragmentation", FALSE, charon->name), ); if (!this->rng) diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c index f83f114b94..32eeee3539 100644 --- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c +++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2009 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -156,14 +157,15 @@ METHOD(task_t, build, status_t, { vendor_id_payload_t *vid_payload; bool strongswan, cisco_unity, fragmentation; + ike_cfg_t *ike_cfg; int i; strongswan = lib->settings->get_bool(lib->settings, "%s.send_vendor_id", FALSE, charon->name); cisco_unity = lib->settings->get_bool(lib->settings, "%s.cisco_unity", FALSE, charon->name); - fragmentation = lib->settings->get_bool(lib->settings, - "%s.ike_fragmentation", FALSE, charon->name); + ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); + fragmentation = ike_cfg->fragmentation(ike_cfg); if (!this->initiator && fragmentation) { fragmentation = this->ike_sa->supports_extension(this->ike_sa, diff --git a/src/starter/args.c b/src/starter/args.c index 1c16e0b9c8..ad73a16352 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -138,6 +138,7 @@ static const token_info_t token_info[] = { ARG_STR, offsetof(starter_conn_t, aaa_identity), NULL }, { ARG_MISC, 0, NULL /* KW_MOBIKE */ }, { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ }, + { ARG_MISC, 0, NULL /* KW_FRAGMENTATION */ }, { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL }, { ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL }, { ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL }, diff --git a/src/starter/confread.c b/src/starter/confread.c index fecb998df6..dfe7e2c89f 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -567,6 +567,9 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg case KW_FORCEENCAPS: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FORCE_ENCAP) break; + case KW_FRAGMENTATION: + KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FRAGMENTATION) + break; case KW_MODECONFIG: KW_SA_OPTION_FLAG("push", "pull", SA_OPTION_MODECFG_PUSH) break; diff --git a/src/starter/confread.h b/src/starter/confread.h index 3f20798836..5e0e0f2554 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -81,6 +81,7 @@ typedef enum { SA_OPTION_XAUTH_SERVER = 1 << 5, /* are we an XAUTH server? */ SA_OPTION_MOBIKE = 1 << 6, /* enable MOBIKE for IKEv2 */ SA_OPTION_FORCE_ENCAP = 1 << 7, /* force UDP encapsulation */ + SA_OPTION_FRAGMENTATION = 1 << 8, /* enable IKEv1 fragmentation */ } sa_option_t; typedef struct starter_end starter_end_t; diff --git a/src/starter/keywords.h b/src/starter/keywords.h index 537bceb075..f776f33c97 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -42,6 +42,7 @@ typedef enum { KW_AAA_IDENTITY, KW_MOBIKE, KW_FORCEENCAPS, + KW_FRAGMENTATION, KW_IKELIFETIME, KW_KEYLIFE, KW_REKEYMARGIN, diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index 8366f52094..1f1641287a 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -40,6 +40,7 @@ eap_identity, KW_EAP_IDENTITY aaa_identity, KW_AAA_IDENTITY mobike, KW_MOBIKE forceencaps, KW_FORCEENCAPS +fragmentation, KW_FRAGMENTATION ikelifetime, KW_IKELIFETIME lifetime, KW_KEYLIFE keylife, KW_KEYLIFE diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 68e6fd5eab..41288531d8 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -180,6 +180,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn) } msg.add_conn.mobike = conn->options & SA_OPTION_MOBIKE; msg.add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP; + msg.add_conn.fragmentation = conn->options & SA_OPTION_FRAGMENTATION; msg.add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS; msg.add_conn.install_policy = conn->install_policy; msg.add_conn.aggressive = conn->aggressive; diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index 1ce44f9eb4..e972a5984e 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -254,6 +254,7 @@ struct stroke_msg_t { int mobike; int aggressive; int force_encap; + int fragmentation; int ipcomp; time_t inactivity; int proxy_mode;