summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-05-11 16:30:23 +0000
committerpatrick <patrick@openbsd.org>2019-05-11 16:30:23 +0000
commit65c540d0d4c3c425b69019d3eae1aa2518f32bde (patch)
tree150ad3767935bf59142593e7240ff5aa7ede908f
parentAdd a manpage for fusbtc(4). (diff)
downloadwireguard-openbsd-65c540d0d4c3c425b69019d3eae1aa2518f32bde.tar.xz
wireguard-openbsd-65c540d0d4c3c425b69019d3eae1aa2518f32bde.zip
Add support for IKEv2 Message Fragmentation as defined in RFC 7383.
ok sthen@
-rw-r--r--regress/sbin/iked/parser/common.c7
-rw-r--r--regress/sbin/iked/parser/test_parser_fuzz.c65
-rw-r--r--sbin/iked/config.c43
-rw-r--r--sbin/iked/iked.c5
-rw-r--r--sbin/iked/iked.conf.510
-rw-r--r--sbin/iked/iked.h25
-rw-r--r--sbin/iked/ikev2.c96
-rw-r--r--sbin/iked/ikev2.h14
-rw-r--r--sbin/iked/ikev2_msg.c152
-rw-r--r--sbin/iked/ikev2_pld.c197
-rw-r--r--sbin/iked/parse.y11
-rw-r--r--sbin/iked/types.h4
12 files changed, 600 insertions, 29 deletions
diff --git a/regress/sbin/iked/parser/common.c b/regress/sbin/iked/parser/common.c
index 904af476b3f..b0066e41683 100644
--- a/regress/sbin/iked/parser/common.c
+++ b/regress/sbin/iked/parser/common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: common.c,v 1.1 2017/05/29 20:59:28 markus Exp $ */
+/* $OpenBSD: common.c,v 1.2 2019/05/11 16:30:23 patrick Exp $ */
/*
* A bunch of stub functions so we can compile and link ikev2_pld.c
* in a standalone program for testing purposes.
@@ -166,6 +166,11 @@ config_add_proposal(struct iked_proposals *head, u_int id, u_int proto)
return (NULL);
}
+void config_free_fragments(struct iked_frag *frag)
+{
+ return;
+}
+
int
ikev2_send_informational(struct iked *env, struct iked_message *msg)
{
diff --git a/regress/sbin/iked/parser/test_parser_fuzz.c b/regress/sbin/iked/parser/test_parser_fuzz.c
index 3d0d86c6263..2c85e8b3906 100644
--- a/regress/sbin/iked/parser/test_parser_fuzz.c
+++ b/regress/sbin/iked/parser/test_parser_fuzz.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_parser_fuzz.c,v 1.2 2018/03/22 21:11:49 patrick Exp $ */
+/* $OpenBSD: test_parser_fuzz.c,v 1.3 2019/05/11 16:30:23 patrick Exp $ */
/*
* Fuzz tests for payload parsing
*
@@ -183,6 +183,50 @@ u_int8_t ts_pld[] = {
0xac, 0x28, 0x7d, 0x00, 0xac, 0x28, 0x7d, 0xff
};
+uint8_t skf_1of1_pld[] = {
+ 0x21, 0x00, 0x01, 0x98, 0x00, 0x01, 0x00, 0x01, 0x14, 0x77,
+ 0x25, 0x7b, 0x82, 0xc0, 0xdb, 0x0b, 0x24, 0x36, 0x36, 0x13,
+ 0x36, 0xe4, 0x99, 0xad, 0xf5, 0xaf, 0x26, 0x6f, 0x47, 0xd2,
+ 0x0d, 0x65, 0xe1, 0xa8, 0xcb, 0x35, 0x1e, 0x53, 0xce, 0x6d,
+ 0x8e, 0xf9, 0xe4, 0x51, 0xe3, 0x27, 0x10, 0x43, 0x38, 0x84,
+ 0x54, 0x1d, 0x7a, 0x1a, 0x89, 0x34, 0x06, 0xb3, 0x62, 0x86,
+ 0x98, 0x3b, 0x39, 0x91, 0x6e, 0xe8, 0x65, 0x3e, 0x31, 0xa8,
+ 0x08, 0xfe, 0x83, 0x56, 0x30, 0xd3, 0xe0, 0xfd, 0x73, 0x92,
+ 0x85, 0x2d, 0xae, 0x1d, 0x7d, 0xdb, 0x47, 0x05, 0x57, 0xe7,
+ 0x8e, 0xc5, 0xa5, 0x1b, 0x0e, 0x85, 0x1f, 0x12, 0x6d, 0xe6,
+ 0xdb, 0x3a, 0x3e, 0x99, 0xd1, 0x23, 0x41, 0xa4, 0x1c, 0x46,
+ 0x38, 0xd1, 0xa8, 0x84, 0x96, 0x13, 0xdb, 0x2a, 0x1d, 0x3b,
+ 0xb8, 0xd2, 0x04, 0xb3, 0x0d, 0xb4, 0x71, 0x90, 0xdb, 0xf6,
+ 0x2d, 0x60, 0x01, 0xc2, 0xb2, 0x89, 0xbd, 0xe9, 0x95, 0x7b,
+ 0x53, 0xa4, 0x94, 0x7e, 0x12, 0xe9, 0x5f, 0xfc, 0x51, 0x17,
+ 0x94, 0x3e, 0xba, 0xc2, 0xa5, 0x4d, 0x3a, 0x4d, 0x4b, 0x95,
+ 0x6d, 0x91, 0xc2, 0xb0, 0x2d, 0xb7, 0x24, 0xe8, 0x3b, 0xbd,
+ 0xe0, 0xcc, 0x09, 0x50, 0x11, 0x83, 0xc0, 0xcd, 0x29, 0x33,
+ 0xd5, 0x8f, 0x8a, 0xd1, 0xe3, 0xe8, 0x4f, 0x6a, 0x10, 0x4a,
+ 0x64, 0x97, 0x0f, 0x38, 0x58, 0x8d, 0x7f, 0x5d, 0xb4, 0x6b,
+ 0xa0, 0x42, 0x5e, 0x95, 0xe6, 0x08, 0x3e, 0x01, 0xf8, 0x82,
+ 0x90, 0x81, 0xd4, 0x70, 0xb5, 0xb2, 0x8c, 0x64, 0xa9, 0x56,
+ 0xdd, 0xc2, 0xda, 0xe1, 0xd3, 0xad, 0xf8, 0x5b, 0x99, 0x0b,
+ 0x19, 0x5e, 0x88, 0x0d, 0x81, 0x04, 0x4d, 0xc1, 0x43, 0x41,
+ 0xf1, 0xd3, 0x45, 0x65, 0x62, 0x70, 0x2f, 0xfa, 0x62, 0xbe,
+ 0x7d, 0xf4, 0x94, 0x91, 0xe0, 0xbb, 0xb1, 0xbc, 0xe5, 0x27,
+ 0xc8, 0x15, 0xd4, 0xcb, 0x82, 0x97, 0x15, 0x46, 0x82, 0xbb,
+ 0x48, 0xbb, 0x16, 0x25, 0xbe, 0x82, 0xe4, 0x27, 0x80, 0xf3,
+ 0xc2, 0x92, 0x3b, 0xd6, 0xc3, 0x65, 0x20, 0xec, 0x50, 0xdb,
+ 0x6a, 0xcb, 0x47, 0x73, 0xf7, 0x98, 0xf1, 0x66, 0x5e, 0xc4,
+ 0xe9, 0x87, 0xf8, 0xcb, 0x1e, 0x06, 0xa7, 0x67, 0xf5, 0xec,
+ 0x73, 0xe5, 0xc7, 0x4d, 0xc2, 0x90, 0xe4, 0xdf, 0x9d, 0x1f,
+ 0x05, 0x67, 0x99, 0xd6, 0xf0, 0xc4, 0x20, 0xbc, 0xf8, 0xf5,
+ 0x3e, 0x19, 0xe9, 0x3a, 0x12, 0xe1, 0xcc, 0x9f, 0x81, 0x55,
+ 0x1e, 0xad, 0xc8, 0xa3, 0xe5, 0x98, 0xbe, 0xe0, 0x4d, 0xb7,
+ 0x6b, 0xd5, 0xbe, 0x6a, 0x3d, 0x76, 0xb6, 0xe2, 0xa5, 0xa7,
+ 0x96, 0x68, 0xeb, 0x91, 0xee, 0x02, 0xfc, 0xe4, 0x01, 0xc3,
+ 0x24, 0xda, 0x4c, 0xff, 0x10, 0x27, 0x78, 0xb0, 0x0b, 0x55,
+ 0x5c, 0xce, 0x62, 0x7d, 0x33, 0x2b, 0x25, 0x99, 0xaa, 0x99,
+ 0xea, 0xa3, 0x1d, 0xd8, 0x2b, 0x57, 0xb5, 0xe4, 0x04, 0x21,
+ 0x75, 0xd9, 0xc4, 0xd0, 0x3d, 0xa1, 0xa5, 0x8f
+};
+
u_int8_t sk_pld[] = {
0x21, 0x00, 0x01, 0x94, 0x14, 0x77, 0x25, 0x7b, 0x82, 0xc0,
0xdb, 0x0b, 0x24, 0x36, 0x36, 0x13, 0x36, 0xe4, 0x99, 0xad,
@@ -454,6 +498,25 @@ parser_fuzz_tests(void)
perform_test(fuzz);
TEST_DONE();
+ TEST_START("fuzz skf_1of1 payload");
+ ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL);
+ ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0);
+ ASSERT_INT_EQ(ibuf_add(data, skf_1of1_pld, sizeof(skf_1of1_pld)), 0);
+ set_length(ibuf_data(data), ibuf_size(data));
+ set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_SKF);
+ print_hex(ibuf_data(data), 0, ibuf_size(data));
+ prepare_header(&hdr, data);
+ prepare_message(&msg, data);
+ ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0);
+ fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP |
+ FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END |
+ FUZZ_BASE64,
+ ibuf_data(data), ibuf_size(data));
+ ibuf_free(data);
+ perform_test(fuzz);
+ TEST_DONE();
+
TEST_START("fuzz sa payload");
ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL);
ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0);
diff --git a/sbin/iked/config.c b/sbin/iked/config.c
index 8214ac01fb5..9ebf24616d2 100644
--- a/sbin/iked/config.c
+++ b/sbin/iked/config.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: config.c,v 1.49 2017/11/27 18:39:35 patrick Exp $ */
+/* $OpenBSD: config.c,v 1.50 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -94,12 +95,29 @@ config_free_kex(struct iked_kex *kex)
}
void
+config_free_fragments(struct iked_frag *frag)
+{
+ size_t i;
+
+ if (frag && frag->frag_arr) {
+ for (i = 0; i < frag->frag_total; i++) {
+ if (frag->frag_arr[i] != NULL)
+ free(frag->frag_arr[i]->frag_data);
+ free(frag->frag_arr[i]);
+ }
+ free(frag->frag_arr);
+ bzero(frag, sizeof(struct iked_frag));
+ }
+}
+
+void
config_free_sa(struct iked *env, struct iked_sa *sa)
{
timer_del(env, &sa->sa_timer);
timer_del(env, &sa->sa_keepalive);
timer_del(env, &sa->sa_rekey);
+ config_free_fragments(&sa->sa_fragments);
config_free_proposals(&sa->sa_proposals, 0);
config_free_childsas(env, &sa->sa_childsas, NULL, NULL);
sa_free_flows(env, &sa->sa_flows);
@@ -838,6 +856,29 @@ config_getmobike(struct iked *env, struct imsg *imsg)
}
int
+config_setfragmentation(struct iked *env)
+{
+ unsigned int boolval;
+
+ boolval = env->sc_frag;
+ proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CTL_FRAGMENTATION,
+ &boolval, sizeof(boolval));
+ return (0);
+}
+
+int
+config_getfragmentation(struct iked *env, struct imsg *imsg)
+{
+ unsigned int boolval;
+
+ IMSG_SIZE_CHECK(imsg, &boolval);
+ memcpy(&boolval, imsg->data, sizeof(boolval));
+ env->sc_frag = boolval;
+ log_debug("%s: %sfragmentation", __func__, env->sc_frag ? "" : "no ");
+ return (0);
+}
+
+int
config_setocsp(struct iked *env)
{
if (env->sc_opts & IKED_OPT_NOACTION)
diff --git a/sbin/iked/iked.c b/sbin/iked/iked.c
index 5669f5a45b0..b417ad8ddf7 100644
--- a/sbin/iked/iked.c
+++ b/sbin/iked/iked.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: iked.c,v 1.36 2017/11/27 18:39:35 patrick Exp $ */
+/* $OpenBSD: iked.c,v 1.37 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -251,6 +252,7 @@ parent_configure(struct iked *env)
fatal("pledge");
config_setmobike(env);
+ config_setfragmentation(env);
config_setcoupled(env, env->sc_decoupled ? 0 : 1);
config_setmode(env, env->sc_passive ? 1 : 0);
config_setocsp(env);
@@ -282,6 +284,7 @@ parent_reload(struct iked *env, int reset, const char *filename)
config_setcompile(env, PROC_IKEV2);
config_setmobike(env);
+ config_setfragmentation(env);
config_setcoupled(env, env->sc_decoupled ? 0 : 1);
config_setmode(env, env->sc_passive ? 1 : 0);
config_setocsp(env);
diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5
index 9364ce35701..e259ec00838 100644
--- a/sbin/iked/iked.conf.5
+++ b/sbin/iked/iked.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: iked.conf.5,v 1.54 2019/04/02 09:42:55 sthen Exp $
+.\" $OpenBSD: iked.conf.5,v 1.55 2019/05/11 16:30:23 patrick Exp $
.\"
.\" Copyright (c) 2010 - 2014 Reyk Floeter <reyk@openbsd.org>
.\" Copyright (c) 2004 Mathieu Sauve-Frankel All rights reserved.
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: April 2 2019 $
+.Dd $Mdocdate: May 11 2019 $
.Dt IKED.CONF 5
.Os
.Sh NAME
@@ -136,6 +136,12 @@ This is the default.
.It Ic set decouple
Don't load the negotiated SAs and flows from the kernel.
This mode is only useful for testing and debugging.
+.It Ic set fragmentation
+Enable IKEv2 Message Fragmentation (RFC 7383) support.
+This allows IKEv2 to operate in environments that might block IP fragments.
+.It Ic set nofragmentation
+Disables IKEv2 Message Fragmentation support.
+This is the default.
.It Ic set mobike
Enable MOBIKE (RFC 4555) support.
This is the default.
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index ce55aec2aa5..626f6a6f8c6 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,6 +1,7 @@
-/* $OpenBSD: iked.h,v 1.120 2019/05/10 15:02:17 patrick Exp $ */
+/* $OpenBSD: iked.h,v 1.121 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -362,6 +363,21 @@ struct iked_kex {
struct ibuf *kex_dhpeer; /* pointer to i or r */
};
+struct iked_frag_entry {
+ uint8_t *frag_data;
+ size_t frag_size;
+};
+
+struct iked_frag {
+ struct iked_frag_entry **frag_arr; /* list of fragment buffers */
+ size_t frag_count; /* number of fragments received */
+#define IKED_FRAG_TOTAL_MAX 111 /* upper limit (64kB / 576B) */
+ size_t frag_total; /* total numbe of fragments */
+ size_t frag_total_size;
+ uint8_t frag_nextpayload;
+
+};
+
struct iked_sa {
struct iked_sahdr sa_hdr;
uint32_t sa_msgid; /* Last request rcvd */
@@ -378,6 +394,8 @@ struct iked_sa {
struct iked_addr sa_local;
int sa_fd;
+ struct iked_frag sa_fragments;
+
int sa_natt; /* for IKE messages */
int sa_udpencap; /* for pfkey */
int sa_usekeepalive;/* NAT-T keepalive */
@@ -446,6 +464,7 @@ struct iked_sa {
uint16_t sa_cpi_in; /* IPcomp incoming*/
int sa_mobike; /* MOBIKE */
+ int sa_frag; /* fragmentation */
struct iked_timer sa_timer; /* SA timeouts */
#define IKED_IKE_SA_EXCHANGE_TIMEOUT 300 /* 5 minutes */
@@ -604,6 +623,7 @@ struct iked {
uint8_t sc_decoupled;
uint8_t sc_mobike; /* MOBIKE */
+ uint8_t sc_frag; /* fragmentation */
struct iked_policies sc_policies;
struct iked_policy *sc_defaultcon;
@@ -655,6 +675,7 @@ int control_listen(struct control_sock *);
struct iked_policy *
config_new_policy(struct iked *);
void config_free_kex(struct iked_kex *);
+void config_free_fragments(struct iked_frag *);
void config_free_sa(struct iked *, struct iked_sa *);
struct iked_sa *
config_new_sa(struct iked *, int);
@@ -703,6 +724,8 @@ int config_setkeys(struct iked *);
int config_getkey(struct iked *, struct imsg *);
int config_setmobike(struct iked *);
int config_getmobike(struct iked *, struct imsg *);
+int config_setfragmentation(struct iked *);
+int config_getfragmentation(struct iked *, struct imsg *);
/* policy.c */
void policy_init(struct iked *);
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index bc05262ed06..b68955a951e 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: ikev2.c,v 1.170 2019/05/10 15:18:04 patrick Exp $ */
+/* $OpenBSD: ikev2.c,v 1.171 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -144,6 +145,8 @@ ssize_t ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **,
ssize_t);
ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *,
struct ikev2_payload **, struct iked_message *, ssize_t);
+ssize_t ikev2_add_fragmentation(struct iked *, struct ibuf *,
+ struct ikev2_payload **, struct iked_message *, ssize_t);
ssize_t ikev2_add_mobike(struct iked *, struct ibuf *,
struct ikev2_payload **, ssize_t, struct iked_sa *);
@@ -202,6 +205,8 @@ ikev2_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
return (0);
case IMSG_CTL_MOBIKE:
return (config_getmobike(env, imsg));
+ case IMSG_CTL_FRAGMENTATION:
+ return (config_getfragmentation(env, imsg));
case IMSG_UDP_SOCKET:
return (config_getsocket(env, imsg, ikev2_msg_cb));
case IMSG_PFKEY_SOCKET:
@@ -399,9 +404,9 @@ void
ikev2_recv(struct iked *env, struct iked_message *msg)
{
struct ike_header *hdr;
- struct iked_message *m;
struct iked_sa *sa;
- unsigned int initiator, flag = 0;
+ unsigned int removed, initiator, flag = 0;
+ struct iked_message *m, *m_old;
hdr = ibuf_seek(msg->msg_data, msg->msg_offset, sizeof(*hdr));
@@ -439,14 +444,16 @@ ikev2_recv(struct iked *env, struct iked_message *msg)
flag = IKED_REQ_INF;
if (hdr->ike_exchange != IKEV2_EXCHANGE_IKE_SA_INIT &&
- hdr->ike_nextpayload != IKEV2_PAYLOAD_SK)
+ hdr->ike_nextpayload != IKEV2_PAYLOAD_SK &&
+ hdr->ike_nextpayload != IKEV2_PAYLOAD_SKF)
return;
if (msg->msg_response) {
if (msg->msg_msgid > sa->sa_reqid)
return;
if (hdr->ike_exchange != IKEV2_EXCHANGE_INFORMATIONAL &&
- !ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr))
+ !ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr) &&
+ sa->sa_fragments.frag_count == 0)
return;
if (flag) {
if ((sa->sa_stateflags & flag) == 0)
@@ -458,10 +465,17 @@ ikev2_recv(struct iked *env, struct iked_message *msg)
initiator = 1;
}
/*
- * There's no need to keep the request around anymore
+ * There's no need to keep the request (fragments) around
*/
- if ((m = ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr)))
- ikev2_msg_dispose(env, &sa->sa_requests, m);
+ TAILQ_FOREACH_SAFE(m, &sa->sa_requests, msg_entry, m_old) {
+ if (m->msg_msgid == msg->msg_msgid &&
+ m->msg_exchange == hdr->ike_exchange) {
+ TAILQ_REMOVE(&sa->sa_requests, m, msg_entry);
+ timer_del(env, &m->msg_timer);
+ ikev2_msg_cleanup(env, m);
+ free(m);
+ }
+ }
} else {
/*
* IKE_SA_INIT is special since it always uses the message id 0.
@@ -487,14 +501,23 @@ ikev2_recv(struct iked *env, struct iked_message *msg)
/*
* See if we have responded to this request before
*/
- if ((m = ikev2_msg_lookup(env, &sa->sa_responses, msg, hdr))) {
- if (ikev2_msg_retransmit_response(env, sa, m)) {
- log_warn("%s: failed to retransmit a "
- "response", __func__);
- sa_free(env, sa);
+ removed = 0;
+ TAILQ_FOREACH_SAFE(m, &sa->sa_responses, msg_entry, m_old) {
+ if (m->msg_msgid == msg->msg_msgid &&
+ m->msg_exchange == hdr->ike_exchange) {
+ if (ikev2_msg_retransmit_response(env, sa, m)) {
+ log_warn("%s: failed to retransmit a "
+ "response", __func__);
+ sa_free(env,sa);
+ return;
+ }
+ removed++;
}
+ }
+ if (removed > 0)
return;
- } else if (sa->sa_msgid_set && msg->msg_msgid == sa->sa_msgid) {
+ else if (sa->sa_msgid_set && msg->msg_msgid == sa->sa_msgid &&
+ !(sa->sa_fragments.frag_count)) {
/*
* Response is being worked on, most likely we're
* waiting for the CA process to get back to us
@@ -811,6 +834,9 @@ ikev2_init_recv(struct iked *env, struct iked_message *msg,
return;
}
+ if (sa->sa_fragments.frag_count != 0)
+ return;
+
if (!ikev2_msg_frompeer(msg))
return;
@@ -1030,6 +1056,13 @@ ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy *pol,
goto done;
len = ibuf_size(sa->sa_inonce);
+ /* Fragmentation Notify */
+ if (env->sc_frag) {
+ if ((len = ikev2_add_fragmentation(env, buf, &pld, &req, len))
+ == -1)
+ goto done;
+ }
+
if ((env->sc_opts & IKED_OPT_NONATT) == 0) {
if (ntohs(port) == IKED_NATT_PORT) {
/* Enforce NAT-T on the initiator side */
@@ -1661,6 +1694,29 @@ ikev2_add_mobike(struct iked *env, struct ibuf *e,
}
ssize_t
+ikev2_add_fragmentation(struct iked *env, struct ibuf *buf,
+ struct ikev2_payload **pld, struct iked_message *msg, ssize_t len)
+{
+ struct ikev2_notify *n;
+ uint8_t *ptr;
+
+ if (*pld != NULL)
+ if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY) == -1)
+ return (-1);
+ if ((*pld = ikev2_add_payload(buf)) == NULL)
+ return (-1);
+ len = sizeof(*n);
+ if ((ptr = ibuf_advance(buf, len)) == NULL)
+ return (-1);
+ n = (struct ikev2_notify *) ptr;
+ n->n_protoid = 0;
+ n->n_spisize = 0;
+ n->n_type = htobe16(IKEV2_N_FRAGMENTATION_SUPPORTED);
+
+ return (len);
+}
+
+ssize_t
ikev2_add_sighashnotify(struct ibuf *e, struct ikev2_payload **pld,
ssize_t len)
{
@@ -2293,6 +2349,9 @@ ikev2_resp_recv(struct iked *env, struct iked_message *msg,
msg->msg_valid = 1;
+ if (sa->sa_fragments.frag_count !=0)
+ return;
+
if (msg->msg_natt && sa->sa_natt == 0) {
log_debug("%s: NAT-T message received, updated SA", __func__);
sa->sa_natt = 1;
@@ -2417,6 +2476,13 @@ ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg)
goto done;
len = ibuf_size(sa->sa_rnonce);
+ /* Fragmentation Notify*/
+ if (sa->sa_frag) {
+ if ((len = ikev2_add_fragmentation(env, buf, &pld, &resp, len))
+ == -1)
+ goto done;
+ }
+
if ((env->sc_opts & IKED_OPT_NONATT) == 0 &&
msg->msg_local.ss_family != AF_UNSPEC) {
if ((len = ikev2_add_nat_detection(env, buf, &pld, &resp, len))
@@ -2495,6 +2561,7 @@ ikev2_send_auth_failed(struct iked *env, struct iked_sa *sa)
timer_del(env, &sa->sa_timer);
timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa);
timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT);
+ config_free_fragments(&sa->sa_fragments);
return (ret);
}
@@ -3446,6 +3513,7 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa)
nsa->sa_udpencap = sa->sa_udpencap;
nsa->sa_usekeepalive = sa->sa_usekeepalive;
nsa->sa_mobike = sa->sa_mobike;
+ nsa->sa_frag = sa->sa_frag;
/* Transfer old addresses */
memcpy(&nsa->sa_local, &sa->sa_local, sizeof(nsa->sa_local));
diff --git a/sbin/iked/ikev2.h b/sbin/iked/ikev2.h
index 7d3f8fdd4d0..90d683b9ce4 100644
--- a/sbin/iked/ikev2.h
+++ b/sbin/iked/ikev2.h
@@ -1,6 +1,7 @@
-/* $OpenBSD: ikev2.h,v 1.29 2019/04/02 09:42:55 sthen Exp $ */
+/* $OpenBSD: ikev2.h,v 1.30 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -78,6 +79,11 @@ struct ikev2_payload {
uint16_t pld_length; /* Payload length with header */
} __packed;
+struct ikev2_frag_payload {
+ uint16_t frag_num; /* current fragment message number */
+ uint16_t frag_total; /* total number of fragment messages */
+} __packed;
+
#define IKEV2_CRITICAL_PAYLOAD 0x01 /* First bit in the reserved field */
/* IKEv2 payload types */
@@ -99,6 +105,7 @@ struct ikev2_payload {
#define IKEV2_PAYLOAD_CP 47 /* Configuration Payload */
#define IKEV2_PAYLOAD_EAP 48 /* Extensible Authentication */
#define IKEV2_PAYLOAD_GSPM 49 /* RFC6467 Generic Secure Password */
+#define IKEV2_PAYLOAD_SKF 53 /* RFC7383 Encrypted Fragment Payload */
extern struct iked_constmap ikev2_payload_map[];
@@ -244,6 +251,11 @@ extern struct iked_constmap ikev2_xformauth_map[];
extern struct iked_constmap ikev2_xformdh_map[];
+#define IKEV2_IPV4_OVERHEAD (20 + 8 + 28) /* IPv4 + UDP + IKE_HDR*/
+#define IKEV2_MAXLEN_IPV4_FRAG (576 - IKEV2_IPV4_OVERHEAD)
+#define IKEV2_IPV6_OVERHEAD (40 + 8 + 28) /* IPv6 + UDP + IKE_HDR*/
+#define IKEV2_MAXLEN_IPV6_FRAG (1280 - IKEV2_IPV6_OVERHEAD)
+
#define IKEV2_XFORMESN_NONE 0 /* No ESN */
#define IKEV2_XFORMESN_ESN 1 /* ESN */
diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c
index b559990bec4..fff0b9c01bd 100644
--- a/sbin/iked/ikev2_msg.c
+++ b/sbin/iked/ikev2_msg.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: ikev2_msg.c,v 1.54 2019/05/10 15:02:17 patrick Exp $ */
+/* $OpenBSD: ikev2_msg.c,v 1.55 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -46,6 +47,9 @@
void ikev1_recv(struct iked *, struct iked_message *);
void ikev2_msg_response_timeout(struct iked *, void *);
void ikev2_msg_retransmit_timeout(struct iked *, void *);
+int ikev2_check_frag_oversize(struct iked_sa *sa, struct ibuf *buf);
+int ikev2_send_encrypted_fragments(struct iked *env, struct iked_sa *sa,
+ struct ibuf *in,uint8_t exchange, uint8_t firstpayload, int response);
void
ikev2_msg_cb(int fd, short event, void *arg)
@@ -616,7 +620,8 @@ ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
__func__, outlen, encrlen, pad);
print_hex(ibuf_data(out), 0, ibuf_size(out));
- if (ibuf_setsize(out, outlen) != 0)
+ /* Strip padding and padding length */
+ if (ibuf_setsize(out, outlen - pad - 1) != 0)
goto done;
ibuf_release(src);
@@ -629,6 +634,26 @@ ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
}
int
+ikev2_check_frag_oversize(struct iked_sa *sa, struct ibuf *buf) {
+ size_t len = ibuf_length(buf);
+ sa_family_t sa_fam;
+ size_t max;
+ size_t ivlen, integrlen, blocklen;
+
+ sa_fam = ((struct sockaddr *)&sa->sa_local.addr)->sa_family;
+
+ max = sa_fam == AF_INET ? IKEV2_MAXLEN_IPV4_FRAG
+ : IKEV2_MAXLEN_IPV6_FRAG;
+
+ blocklen = cipher_length(sa->sa_encr);
+ ivlen = cipher_ivlength(sa->sa_encr);
+ integrlen = hash_length(sa->sa_integr);
+
+ /* Estimated maximum packet size (with 0 < padding < blocklen) */
+ return ((len + ivlen + blocklen + integrlen) >= max) && sa->sa_frag;
+}
+
+int
ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf **ep,
uint8_t exchange, uint8_t firstpayload, int response)
{
@@ -638,6 +663,12 @@ ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf **ep,
struct ibuf *buf, *e = *ep;
int ret = -1;
+ /* Check if msg needs to be fragmented */
+ if (ikev2_check_frag_oversize(sa, e)) {
+ return ikev2_send_encrypted_fragments(env, sa, e, exchange,
+ firstpayload, response);
+ }
+
if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr,
sa->sa_peer.addr.ss_len, &sa->sa_local.addr,
sa->sa_local.addr.ss_len, response)) == NULL)
@@ -689,6 +720,123 @@ ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf **ep,
return (ret);
}
+int
+ikev2_send_encrypted_fragments(struct iked *env, struct iked_sa *sa,
+ struct ibuf *in, uint8_t exchange, uint8_t firstpayload, int response) {
+ struct iked_message resp;
+ struct ibuf *buf, *e;
+ struct ike_header *hdr;
+ struct ikev2_payload *pld;
+ struct ikev2_frag_payload *frag;
+ sa_family_t sa_fam;
+ size_t ivlen, integrlen, blocklen;
+ size_t max_len, left, offset=0;;
+ size_t frag_num = 1, frag_total;
+ uint8_t *data;
+ uint32_t msgid;
+ int ret = -1;
+
+ sa_fam = ((struct sockaddr *)&sa->sa_local.addr)->sa_family;
+
+ left = ibuf_length(in);
+
+ /* Calculate max allowed size of a fragments payload */
+ blocklen = cipher_length(sa->sa_encr);
+ ivlen = cipher_ivlength(sa->sa_encr);
+ integrlen = hash_length(sa->sa_integr);
+ max_len = (sa_fam == AF_INET ? IKEV2_MAXLEN_IPV4_FRAG
+ : IKEV2_MAXLEN_IPV6_FRAG)
+ - ivlen - blocklen - integrlen;
+
+ /* Total number of fragments to send */
+ frag_total = (left / max_len) + 1;
+
+ msgid = response ? sa->sa_msgid_current : ikev2_msg_id(env, sa);
+
+ while (frag_num <= frag_total) {
+ if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr,
+ sa->sa_peer.addr.ss_len, &sa->sa_local.addr,
+ sa->sa_local.addr.ss_len, response)) == NULL)
+ goto done;
+
+ resp.msg_msgid = msgid;
+
+ /* IKE header */
+ if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid,
+ IKEV2_PAYLOAD_SKF, exchange, response ? IKEV2_FLAG_RESPONSE
+ : 0)) == NULL)
+ goto done;
+
+ /* Payload header */
+ if ((pld = ikev2_add_payload(buf)) == NULL)
+ goto done;
+
+ /* Fragment header */
+ if ((frag = ibuf_advance(buf, sizeof(*frag))) == NULL) {
+ log_debug("%s: failed to add SKF fragment header",
+ __func__);
+ goto done;
+ }
+ frag->frag_num = htobe16(frag_num);
+ frag->frag_total = htobe16(frag_total);
+
+ /* Encrypt message and add as an E payload */
+ data = ibuf_seek(in, offset, 0);
+ if((e=ibuf_new(data, MIN(left, max_len))) == NULL) {
+ goto done;
+ }
+ if ((e = ikev2_msg_encrypt(env, sa, e)) == NULL) {
+ log_debug("%s: encryption failed", __func__);
+ goto done;
+ }
+ if (ibuf_cat(buf, e) != 0)
+ goto done;
+
+ if (ikev2_next_payload(pld, ibuf_size(e) + sizeof(*frag),
+ firstpayload) == -1)
+ goto done;
+
+ if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1)
+ goto done;
+
+ /* Add integrity checksum (HMAC) */
+ if (ikev2_msg_integr(env, sa, buf) != 0) {
+ log_debug("%s: integrity checksum failed", __func__);
+ goto done;
+ }
+
+ log_debug("%s: Fragment %zu of %zu has size of %zu bytes.",
+ __func__, frag_num, frag_total,
+ ibuf_size(buf) - sizeof(*hdr));
+ print_hex(ibuf_data(buf), 0, ibuf_size(buf));
+
+ resp.msg_data = buf;
+ resp.msg_sa = sa;
+ resp.msg_fd = sa->sa_fd;
+ TAILQ_INIT(&resp.msg_proposals);
+
+ if (ikev2_msg_send(env, &resp) == -1)
+ goto done;
+
+ offset += MIN(left, max_len);
+ left -= MIN(left, max_len);
+ frag_num++;
+
+ /* MUST be zero after first fragment */
+ firstpayload = 0;
+
+ ikev2_msg_cleanup(env, &resp);
+ ibuf_release(e);
+ e = NULL;
+ }
+
+ return 0;
+done:
+ ikev2_msg_cleanup(env, &resp);
+ ibuf_release(e);
+ return ret;
+}
+
struct ibuf *
ikev2_msg_auth(struct iked *env, struct iked_sa *sa, int response)
{
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index 9d881ccc95f..822af60dad3 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: ikev2_pld.c,v 1.70 2018/03/22 21:11:49 patrick Exp $ */
+/* $OpenBSD: ikev2_pld.c,v 1.71 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2014 Hans-Joerg Hoexer
*
@@ -95,6 +96,10 @@ int ikev2_pld_auth(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_pld_e(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
+int ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
+ struct iked_message *msg, size_t offset, size_t left);
+int ikev2_frags_reassemble(struct iked *env,
+ struct ikev2_payload *pld, struct iked_message *msg);
int ikev2_validate_cp(struct iked_message *, size_t, size_t,
struct ikev2_cp *);
int ikev2_pld_cp(struct iked *, struct ikev2_payload *,
@@ -249,6 +254,9 @@ ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
case IKEV2_PAYLOAD_SK:
ret = ikev2_pld_e(env, &pld, msg, offset, left);
break;
+ case IKEV2_PAYLOAD_SKF:
+ ret = ikev2_pld_ef(env, &pld, msg, offset, left);
+ break;
case IKEV2_PAYLOAD_CP | IKED_E:
ret = ikev2_pld_cp(env, &pld, msg, offset, left);
break;
@@ -266,8 +274,9 @@ ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
return (-1);
}
- /* Encrypted payload must appear last */
- if (payload == IKEV2_PAYLOAD_SK)
+ /* Encrypted payloads must appear last */
+ if ((payload == IKEV2_PAYLOAD_SK) ||
+ (payload == IKEV2_PAYLOAD_SKF))
return (0);
payload = pld.pld_nextpayload;
@@ -1251,6 +1260,23 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,
}
msg->msg_parent->msg_cookie = msg->msg_cookie;
break;
+ case IKEV2_N_FRAGMENTATION_SUPPORTED:
+ if (msg->msg_e) {
+ log_debug("%s: N_FRAGMENTATION_SUPPORTED encrypted",
+ __func__);
+ return (-1);
+ }
+ if (len != 0) {
+ log_debug("%s: ignoring malformed fragmentation"
+ " notification: %zu", __func__, len);
+ return (0);
+ }
+ if (!env->sc_frag) {
+ log_debug("%s: fragmentation disabled", __func__);
+ return (0);
+ }
+ msg->msg_sa->sa_frag = 1;
+ break;
case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:
if (msg->msg_e) {
log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted",
@@ -1585,6 +1611,164 @@ ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld,
}
int
+ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
+ struct iked_message *msg, size_t offset, size_t left)
+{
+ struct iked_sa *sa = msg->msg_sa;
+ struct iked_frag *sa_frag = &sa->sa_fragments;
+ struct iked_frag_entry *el;
+ struct ikev2_frag_payload frag;
+ uint8_t *msgbuf = ibuf_data(msg->msg_data);
+ uint8_t *buf;
+ struct ibuf *e = NULL;
+ size_t frag_num, frag_total;
+ size_t len;
+ int ret = -1;
+ ssize_t elen;
+
+ buf = msgbuf + offset;
+ memcpy(&frag, buf, sizeof(frag));
+ frag_num = betoh16(frag.frag_num);
+ frag_total = betoh16(frag.frag_total);
+
+ offset += sizeof(frag);
+ buf = msgbuf + offset;
+ len = left - sizeof(frag);
+
+ /* Limit number of total fragments to avoid DOS */
+ if (frag_total > IKED_FRAG_TOTAL_MAX ) {
+ log_debug("%s: Total Fragments too big %zu",
+ __func__, frag_total);
+ goto dropall;
+ }
+
+ /* Check sanity of fragment header */
+ if (frag_num == 0 || frag_total == 0) {
+ log_debug("%s: Malformed fragment received: %zu of %zu",
+ __func__, frag_num, frag_total);
+ goto done;
+ }
+ log_debug("%s: Received fragment: %zu of %zu",
+ __func__, frag_num, frag_total);
+
+ /* Check new fragmented message */
+ if (sa_frag->frag_arr == NULL) {
+ sa_frag->frag_arr = recallocarray(NULL, 0, frag_total,
+ sizeof(struct iked_frag_entry*));
+ sa_frag->frag_total = frag_total;
+ sa_frag->frag_nextpayload = pld->pld_nextpayload;
+ }
+
+ /* Drop all fragments if frag_num or frag_total don't match */
+ if (frag_num > sa_frag->frag_total || frag_total != sa_frag->frag_total)
+ goto dropall;
+
+ /* Silent drop if fragment already stored */
+ if (sa_frag->frag_arr[frag_num-1] != NULL)
+ goto done;
+
+ /* Decrypt fragment */
+ if ((e = ibuf_new(buf, len)) == NULL)
+ goto done;
+
+ if ((e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e))
+ == NULL ) {
+ log_debug("%s: Failed to decrypt fragment: %zu of %zu",
+ __func__, frag_num, frag_total);
+ goto done;
+ }
+ elen = ibuf_length(e);
+
+ /* Insert new list element */
+ el = calloc(1, sizeof(struct iked_frag_entry));
+ if (el == NULL) {
+ log_debug("%s: Failed allocating new fragment: %zu of %zu",
+ __func__, frag_num, frag_total);
+ goto done;
+ }
+
+ sa_frag->frag_arr[frag_num-1] = el;
+ el->frag_size = elen;
+ el->frag_data = calloc(1, elen);
+ if (el->frag_data == NULL) {
+ log_debug("%s: Failed allocating new fragment data: %zu of %zu",
+ __func__, frag_num, frag_total);
+ goto done;
+ }
+
+ /* Copy plaintext to fragment */
+ memcpy(el->frag_data, ibuf_seek(e, 0, 0), elen);
+ sa_frag->frag_total_size += elen;
+ sa_frag->frag_count++;
+
+ /* If all frags are received start reassembly */
+ if (sa_frag->frag_count == sa_frag->frag_total) {
+ log_debug("%s: All fragments received: %zu of %zu",
+ __func__, frag_num, frag_total);
+ ret = ikev2_frags_reassemble(env, pld, msg);
+ } else {
+ ret = 0;
+ }
+done:
+ ibuf_release(e);
+ return (ret);
+dropall:
+ config_free_fragments(sa_frag);
+ ibuf_release(e);
+ return -1;
+}
+
+int
+ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld,
+ struct iked_message *msg)
+{
+ struct iked_frag *sa_frag = &msg->msg_sa->sa_fragments;
+ struct ibuf *e = NULL;
+ struct iked_frag_entry *el;
+ size_t offset;
+ size_t i;
+ struct iked_message emsg;
+ int ret = -1;
+
+ /* Reassemble fragments to single buffer */
+ if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) {
+ log_debug("%s: Failed allocating SK buffer.", __func__);
+ goto done;
+ }
+
+ /* Empty queue to new buffer */
+ offset = 0;
+ for (i = 0; i < sa_frag->frag_total; i++) {
+ if ((el = sa_frag->frag_arr[i]) == NULL)
+ fatalx("Tried to reassemble shallow frag_arr");
+ memcpy(ibuf_seek(e, offset, 0), el->frag_data, el->frag_size);
+ offset += el->frag_size;
+ }
+
+ log_debug("%s: Defragmented length %zd", __func__,
+ sa_frag->frag_total_size);
+ print_hex(ibuf_data(e), 0, sa_frag->frag_total_size);
+
+ /*
+ * Parse decrypted payload
+ */
+ bzero(&emsg, sizeof(emsg));
+ memcpy(&emsg, msg, sizeof(*msg));
+ emsg.msg_data = e;
+ emsg.msg_e = 1;
+ emsg.msg_parent = msg;
+ TAILQ_INIT(&emsg.msg_proposals);
+
+ ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
+ sa_frag->frag_nextpayload);
+done:
+ config_free_fragments(sa_frag);
+ ibuf_release(e);
+
+ return (ret);
+}
+
+int
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
struct iked_message *msg, size_t offset, size_t left)
{
@@ -1596,6 +1780,13 @@ ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
size_t len;
int ret = -1;
+ if (sa->sa_fragments.frag_arr != NULL) {
+ log_warn("%s: Received SK payload when SKFs are in queue.",
+ __func__);
+ config_free_fragments(&sa->sa_fragments);
+ return (ret);
+ }
+
buf = msgbuf + offset;
len = left;
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
index 1ef4fe5ceee..e6abde0a2fd 100644
--- a/sbin/iked/parse.y
+++ b/sbin/iked/parse.y
@@ -1,6 +1,7 @@
-/* $OpenBSD: parse.y,v 1.79 2019/04/02 09:42:55 sthen Exp $ */
+/* $OpenBSD: parse.y,v 1.80 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -105,6 +106,7 @@ static int rules = 0;
static int passive = 0;
static int decouple = 0;
static int mobike = 1;
+static int fragmentation = 0;
static char *ocsp_url = NULL;
struct ipsec_xf {
@@ -395,6 +397,7 @@ typedef struct {
%token IKEV1 FLOW SA TCPMD5 TUNNEL TRANSPORT COUPLE DECOUPLE SET
%token INCLUDE LIFETIME BYTES INET INET6 QUICK SKIP DEFAULT
%token IPCOMP OCSP IKELIFETIME MOBIKE NOMOBIKE
+%token FRAGMENTATION NOFRAGMENTATION
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.string> string
@@ -455,6 +458,8 @@ set : SET ACTIVE { passive = 0; }
| SET PASSIVE { passive = 1; }
| SET COUPLE { decouple = 0; }
| SET DECOUPLE { decouple = 1; }
+ | SET FRAGMENTATION { fragmentation = 1; }
+ | SET NOFRAGMENTATION { fragmentation = 0; }
| SET MOBIKE { mobike = 1; }
| SET NOMOBIKE { mobike = 0; }
| SET OCSP STRING {
@@ -1167,6 +1172,7 @@ lookup(char *s)
{ "esp", ESP },
{ "file", FILENAME },
{ "flow", FLOW },
+ { "fragmentation", FRAGMENTATION },
{ "from", FROM },
{ "group", GROUP },
{ "ike", IKEV1 },
@@ -1181,6 +1187,7 @@ lookup(char *s)
{ "local", LOCAL },
{ "mobike", MOBIKE },
{ "name", NAME },
+ { "nofragmentation", NOFRAGMENTATION },
{ "nomobike", NOMOBIKE },
{ "ocsp", OCSP },
{ "passive", PASSIVE },
@@ -1579,6 +1586,7 @@ parse_config(const char *filename, struct iked *x_env)
free(ocsp_url);
mobike = 1;
+ fragmentation = 0;
decouple = passive = 0;
ocsp_url = NULL;
@@ -1592,6 +1600,7 @@ parse_config(const char *filename, struct iked *x_env)
env->sc_passive = passive ? 1 : 0;
env->sc_decoupled = decouple ? 1 : 0;
env->sc_mobike = mobike;
+ env->sc_frag = fragmentation;
env->sc_ocsp_url = ocsp_url;
if (!rules)
diff --git a/sbin/iked/types.h b/sbin/iked/types.h
index d905323a795..4af62afae10 100644
--- a/sbin/iked/types.h
+++ b/sbin/iked/types.h
@@ -1,6 +1,7 @@
-/* $OpenBSD: types.h,v 1.29 2017/11/27 18:39:35 patrick Exp $ */
+/* $OpenBSD: types.h,v 1.30 2019/05/11 16:30:23 patrick Exp $ */
/*
+ * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -103,6 +104,7 @@ enum imsg_type {
IMSG_CTL_ACTIVE,
IMSG_CTL_PASSIVE,
IMSG_CTL_MOBIKE,
+ IMSG_CTL_FRAGMENTATION,
IMSG_COMPILE,
IMSG_UDP_SOCKET,
IMSG_PFKEY_SOCKET,