Added an option that allows to force IKEv1 fragmentation

This commit is contained in:
Tobias Brunner
2013-01-12 11:54:32 +01:00
parent 97973f8609
commit 365d9a6f67
20 changed files with 76 additions and 33 deletions
+9 -4
View 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
+2 -1
View 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 */
+2 -1
View 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)
{
@@ -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,
+3 -3
View 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;
+16 -2
View 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_ @}*/
@@ -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,
+1 -1
View 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,
@@ -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,
+1 -1
View 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,
+3 -2
View 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));
+2 -1
View 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));
+2 -1
View 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;
}
+4 -2
View 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));
+5 -2
View 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;
+1 -1
View 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,
+8 -1
View 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 },
-3
View 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;
+9 -2
View 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;
+1 -1
View 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;