]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
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 01c7c3848b167758aa316844c72102b672a89ba0..2766cc4edffa700733ef656693b95e8ea2d3a368 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 7eb5e856503369638c83e479d532f6cf2607925b..eb187496d505f3f3d707598f161dbd25047f8d77 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 e2705467fe0cf97f4136c855f23add6993cfda4b..22c9d23e0cc0c2d49bd89550adc340e7625d65fd 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 f7fe29070b22222c444490ad8d86772e9da92a90..cce5ff0d4d7ed6835d6d2fa64cc511637e4bf47a 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 e87b47e69c8a57b83a14c070d89fc7e5ca593cb4..5e5fbba42e75b9c6d0a4a8e90531044ffaa17d8c 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 0c4484252536fbb565d1e3a1f17cde13a7470876..5a7fae1e90bffa21682fc82c218a2b3d99ba704b 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>
@@ -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_ @}*/
index 0188b0c2ba6801621d01e9e9397b0c9db63cb294..6af35e5df7cce949bce2fdee253e64b10e9a996d 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 e7db1ff0f5788c5551c81de8a70d03af50ad3c4c..130c86e48df3b8b2680c1143c3a3aa8599a8bedd 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 a9d399b9d73244b3ea2b5aab9e88f573a1ae11db..c6288c5d9167102a7b9548d6c91b7fc9f27ab65a 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 759bd9646c8c2f9b15d18d84dce8401b099e3e54..806e4cd65286fb4bf2357883f728dcb8b71e5f27 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 12ffc1ae4336fcfa535411ce479aac988f049523..4be3dea026b60df9ef52d4574096c77d6232c2c1 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 d167581119b60b8f7fc170c512802ab4cd702487..be14380ea65fb5fdd529399a072f3c98fcf49a65 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 44a593c7b7dfe78b4b9c22935731a88f1bcac354..37bd86671f7c6f62629a30f942ae6425965436b3 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 6dae14e3dcc7222dead660b576a38c11dd0f1e49..de0bf91af6a7654f59da026c119f7ff59535e670 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 320aa5e6b1d1ce2e4f473bcf781aa3197acff663..60ec23199274dd8b52a64c4d80583f03981da9b5 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 32eeee353973a3879b7538622d7573b151bcba25..1bf7bf643ebaf51d9a91af4284d249c7169e6a3b 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 ad73a163526f73a399fdfe00dce2b97a0a6931ac..390062a99eb63106ee9123fc25bf35ac893aa30b 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 dfe7e2c89f0afcaf11201d7f4be697e18ba91131..fecb998df654df95daceb447d52926e6de67e685 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 5e0e0f255476a68202a4821ce109d308b20a7279..a0f6234f9ddd360de4ea2e6d7b4fec0cb218a402 100644 (file)
@@ -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;
index 41288531d85f889702b13e9c075c4ab08d8145ac..4f9e8fb145885ccb49d77e00e0ed40a0ae97be0b 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;