From: Tobias Brunner Date: Mon, 24 Dec 2012 11:59:30 +0000 (+0100) Subject: Added an option that allows to force IKEv1 fragmentation X-Git-Tag: 5.0.2dr4~8^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=365d9a6f67739bdc4c43130eec362ad97414762c;p=thirdparty%2Fstrongswan.git Added an option that allows to force IKEv1 fragmentation --- diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in index 01c7c3848b..2766cc4edf 100644 --- a/man/ipsec.conf.5.in +++ b/man/ipsec.conf.5.in @@ -403,15 +403,20 @@ 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 +.BR fragmentation " = yes | force | " no whether to use IKE fragmentation (proprietary IKEv1 extension). Acceptable values are -.B yes +.BR yes , +.B force 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. +irrespective of the value of this option. If set to +.BR yes , +and the peer supports it, larger IKE messages will be sent in fragments. +If set to +.B force +the initial IKE message will already be fragmented if required. .TP .BR ike " = " comma-separated list of IKE/ISAKMP SA encryption/authentication algorithms diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c index 7eb5e85650..eb187496d5 100644 --- a/src/charon-nm/nm/nm_service.c +++ b/src/charon-nm/nm/nm_service.c @@ -500,7 +500,8 @@ 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, FALSE); + (char*)address, FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO); 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 e2705467fe..22c9d23e0c 100644 --- a/src/conftest/config.c +++ b/src/conftest/config.c @@ -106,7 +106,8 @@ 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), FALSE); + settings->get_int(settings, "configs.%s.rport", 500, config), + FRAGMENTATION_NO); 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 f7fe29070b..cce5ff0d4d 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c +++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c @@ -471,7 +471,8 @@ 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, FALSE); + this->gateway, FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO); 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 e87b47e69c..5e5fbba42e 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -92,7 +92,7 @@ struct private_ike_cfg_t { /** * use IKEv1 fragmentation */ - bool fragmentation; + fragmentation_t fragmentation; /** * List of proposals to use @@ -118,7 +118,7 @@ METHOD(ike_cfg_t, force_encap_, bool, return this->force_encap; } -METHOD(ike_cfg_t, fragmentation, bool, +METHOD(ike_cfg_t, fragmentation, fragmentation_t, private_ike_cfg_t *this) { return this->fragmentation; @@ -312,7 +312,7 @@ 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, - bool fragmentation) + fragmentation_t fragmentation) { private_ike_cfg_t *this; diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h index 0c44842525..5a7fae1e90 100644 --- a/src/libcharon/config/ike_cfg.h +++ b/src/libcharon/config/ike_cfg.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -23,6 +24,7 @@ #define IKE_CFG_H_ typedef enum ike_version_t ike_version_t; +typedef enum fragmentation_t fragmentation_t; typedef struct ike_cfg_t ike_cfg_t; #include @@ -44,6 +46,18 @@ enum ike_version_t { IKEV2 = 2, }; +/** + * Proprietary IKEv1 fragmentation + */ +enum fragmentation_t { + /** disable fragmentation */ + FRAGMENTATION_NO, + /** enable fragmentation if supported by peer */ + FRAGMENTATION_YES, + /** force use of fragmentation (even for the first message) */ + FRAGMENTATION_FORCE, +}; + /** * enum strings fro ike_version_t */ @@ -143,7 +157,7 @@ struct ike_cfg_t { * * @return TRUE to use fragmentation */ - bool (*fragmentation) (ike_cfg_t *this); + fragmentation_t (*fragmentation) (ike_cfg_t *this); /** * Get the DH group to use for IKE_SA setup. @@ -196,6 +210,6 @@ struct ike_cfg_t { 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, - bool fragmentation); + fragmentation_t fragmentation); #endif /** IKE_CFG_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c index 0188b0c2ba..6af35e5df7 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, FALSE); + hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); 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 e7db1ff0f5..130c86e48d 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, FALSE); + remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); 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 a9d399b9d7..c6288c5d91 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -490,14 +490,16 @@ 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, FALSE); + remote, FALSE, IKEV2_NATT_PORT, + FRAGMENTATION_NO); } else { ike_cfg = ike_cfg_create(this->version, TRUE, FALSE, local, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote, FALSE, IKEV2_UDP_PORT, FALSE); + remote, FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO); } 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 759bd9646c..806e4cd652 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, FALSE); + hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); 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 12ffc1ae43..4be3dea026 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, FALSE); + address, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); med_cfg = peer_cfg_create( "mediation", ike_cfg, @@ -380,7 +380,8 @@ 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, FALSE), + "0.0.0.0", FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO), ); 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 d167581119..be14380ea6 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.c +++ b/src/libcharon/plugins/medsrv/medsrv_config.c @@ -142,7 +142,8 @@ 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, FALSE), + "0.0.0.0", FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO), ); 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 44a593c7b7..37bd86671f 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -261,7 +261,8 @@ 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, FALSE); + remote, FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO); add_ike_proposals(this, ike_cfg, id); return ike_cfg; } diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index 6dae14e3dc..de0bf91af6 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -155,7 +155,8 @@ 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, FALSE); + remote_addr, FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO); 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 +254,8 @@ 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, FALSE); + remote_addr, FALSE, IKEV2_UDP_PORT, + FRAGMENTATION_NO); 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 320aa5e6b1..60ec231992 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -406,14 +406,17 @@ 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) { + fragmentation_t fragmentation; ike_cfg_t *ike_cfg; host_t *src, *dst; chunk_t data; ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); + fragmentation = ike_cfg->fragmentation(ike_cfg); data = packet->get_data(packet); - if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_FRAGMENTATION) && - ike_cfg->fragmentation(ike_cfg) && data.len > MAX_FRAGMENT_SIZE) + if (data.len > MAX_FRAGMENT_SIZE && (fragmentation == FRAGMENTATION_FORCE || + (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_FRAGMENTATION) && + fragmentation == FRAGMENTATION_YES))) { fragment_payload_t *fragment; u_int8_t num, count; diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c index 32eeee3539..1bf7bf643e 100644 --- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c +++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c @@ -165,7 +165,7 @@ METHOD(task_t, build, status_t, cisco_unity = lib->settings->get_bool(lib->settings, "%s.cisco_unity", FALSE, charon->name); ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); - fragmentation = ike_cfg->fragmentation(ike_cfg); + fragmentation = ike_cfg->fragmentation(ike_cfg) != FRAGMENTATION_NO; 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 ad73a16352..390062a99e 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -108,6 +108,13 @@ static const char *LST_authby[] = { NULL }; +static const char *LST_fragmentation[] = { + "no", + "yes", + "force", + NULL +}; + typedef struct { arg_t type; size_t offset; @@ -138,7 +145,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_ENUM, offsetof(starter_conn_t, fragmentation), LST_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 dfe7e2c89f..fecb998df6 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -567,9 +567,6 @@ 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 5e0e0f2554..a0f6234f9d 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -50,7 +50,7 @@ typedef enum { typedef enum { STRICT_NO, STRICT_YES, - STRICT_IFURI + STRICT_IFURI, } strict_t; typedef enum { @@ -69,6 +69,13 @@ typedef enum { DPD_ACTION_UNKNOW, } dpd_action_t; +typedef enum { + /* same as in ike_cfg.h */ + FRAGMENTATION_NO, + FRAGMENTATION_YES, + FRAGMENTATION_FORCE, +} fragmentation_t; + typedef enum { /* IPsec options */ SA_OPTION_AUTHENTICATE = 1 << 0, /* use AH instead of ESP? */ @@ -81,7 +88,6 @@ 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; @@ -141,6 +147,7 @@ struct starter_conn { char *authby; ipsec_mode_t mode; bool proxy_mode; + fragmentation_t fragmentation; sa_option_t options; time_t sa_ike_life_seconds; time_t sa_ipsec_life_seconds; diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 41288531d8..4f9e8fb145 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -180,7 +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.fragmentation = conn->fragmentation; msg.add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS; msg.add_conn.install_policy = conn->install_policy; msg.add_conn.aggressive = conn->aggressive;