Added an option that allows to force IKEv1 fragmentation
authorTobias Brunner <tobias@strongswan.org>
Mon, 24 Dec 2012 11:59:30 +0000 (12:59 +0100)
committerTobias Brunner <tobias@strongswan.org>
Sat, 12 Jan 2013 10:54:32 +0000 (11:54 +0100)
20 files changed:
man/ipsec.conf.5.in
src/charon-nm/nm/nm_service.c
src/conftest/config.c
src/frontends/android/jni/libandroidbridge/backend/android_service.c
src/libcharon/config/ike_cfg.c
src/libcharon/config/ike_cfg.h
src/libcharon/plugins/android/android_service.c
src/libcharon/plugins/ha/ha_tunnel.c
src/libcharon/plugins/load_tester/load_tester_config.c
src/libcharon/plugins/maemo/maemo_service.c
src/libcharon/plugins/medcli/medcli_config.c
src/libcharon/plugins/medsrv/medsrv_config.c
src/libcharon/plugins/sql/sql_config.c
src/libcharon/plugins/uci/uci_config.c
src/libcharon/sa/ikev1/task_manager_v1.c
src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
src/starter/args.c
src/starter/confread.c
src/starter/confread.h
src/starter/starterstroke.c

index 01c7c38..2766cc4 100644 (file)
@@ -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 " = <cipher suites>"
 comma-separated list of IKE/ISAKMP SA encryption/authentication algorithms
index 7eb5e85..eb18749 100644 (file)
@@ -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 */
index e270546..22c9d23 100644 (file)
@@ -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)
        {
index f7fe290..cce5ff0 100644 (file)
@@ -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,
index e87b47e..5e5fbba 100644 (file)
@@ -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;
 
index 0c44842..5a7fae1 100644 (file)
@@ -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 <library.h>
@@ -45,6 +47,18 @@ enum ike_version_t {
 };
 
 /**
+ * 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
  */
 extern enum_name_t *ike_version_names;
@@ -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_ @}*/
index 0188b0c..6af35e5 100644 (file)
@@ -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,
index e7db1ff..130c86e 100644 (file)
@@ -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,
index a9d399b..c6288c5 100644 (file)
@@ -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,
index 759bd96..806e4cd 100644 (file)
@@ -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,
index 12ffc1a..4be3dea 100644 (file)
@@ -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));
 
index d167581..be14380 100644 (file)
@@ -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));
 
index 44a593c..37bd866 100644 (file)
@@ -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;
        }
index 6dae14e..de0bf91 100644 (file)
@@ -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));
 
index 320aa5e..60ec231 100644 (file)
@@ -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;
index 32eeee3..1bf7bf6 100644 (file)
@@ -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,
index ad73a16..390062a 100644 (file)
@@ -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                    },
index dfe7e2c..fecb998 100644 (file)
@@ -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;
index 5e0e0f2..a0f6234 100644 (file)
@@ -50,7 +50,7 @@ typedef enum {
 typedef enum {
                STRICT_NO,
                STRICT_YES,
-               STRICT_IFURI
+               STRICT_IFURI,
 } strict_t;
 
 typedef enum {
@@ -70,6 +70,13 @@ typedef enum {
 } 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? */
                SA_OPTION_COMPRESS      = 1 << 1, /* use IPComp */
@@ -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;
index 4128853..4f9e8fb 100644 (file)
@@ -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;