diff options
-rw-r--r-- | sbin/iked/iked.h | 3 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 59 | ||||
-rw-r--r-- | sbin/iked/ikev2_msg.c | 5 | ||||
-rw-r--r-- | sbin/iked/ikev2_pld.c | 23 | ||||
-rw-r--r-- | sbin/iked/types.h | 5 |
5 files changed, 82 insertions, 13 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index b2bda61d145..997ec1a56e4 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.110 2017/03/27 10:06:41 reyk Exp $ */ +/* $OpenBSD: iked.h,v 1.111 2017/03/27 10:21:19 reyk Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -502,6 +502,7 @@ struct iked_message { struct iked_id msg_auth; /* AUTH payload */ struct iked_id msg_id; struct iked_id msg_cert; + struct ibuf *msg_cookie; /* Parse stack */ struct iked_proposal *msg_prop; diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index 6f01901925d..0f11d9ea293 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.144 2017/03/27 10:06:41 reyk Exp $ */ +/* $OpenBSD: ikev2.c,v 1.145 2017/03/27 10:21:19 reyk Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -63,7 +63,7 @@ void ikev2_init_recv(struct iked *, struct iked_message *, struct ike_header *); void ikev2_init_ike_sa_timeout(struct iked *, void *); int ikev2_init_ike_sa_peer(struct iked *, struct iked_policy *, - struct iked_addr *); + struct iked_addr *, struct iked_message *); int ikev2_init_ike_auth(struct iked *, struct iked_sa *); int ikev2_init_auth(struct iked *, struct iked_message *); int ikev2_init_done(struct iked *, struct iked_sa *); @@ -734,6 +734,7 @@ ikev2_init_recv(struct iked *env, struct iked_message *msg, struct iked_sa *sa; in_port_t port; struct iked_socket *sock; + struct iked_policy *pol; if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) { log_debug("%s: unknown SA", __func__); @@ -799,6 +800,14 @@ ikev2_init_recv(struct iked *env, struct iked_message *msg, switch (hdr->ike_exchange) { case IKEV2_EXCHANGE_IKE_SA_INIT: + if (ibuf_length(msg->msg_cookie)) { + pol = sa->sa_policy; + if (ikev2_init_ike_sa_peer(env, pol, + &pol->pol_peer, msg) != 0) + log_warnx("%s: failed to initiate a " + "IKE_SA_INIT exchange", __func__); + break; + } (void)ikev2_init_auth(env, msg); break; case IKEV2_EXCHANGE_IKE_AUTH: @@ -833,7 +842,7 @@ ikev2_init_ike_sa(struct iked *env, void *arg) log_debug("%s: initiating \"%s\"", __func__, pol->pol_name); - if (ikev2_init_ike_sa_peer(env, pol, &pol->pol_peer)) + if (ikev2_init_ike_sa_peer(env, pol, &pol->pol_peer, NULL)) log_debug("%s: failed to initiate with peer %s", __func__, print_host((struct sockaddr *)&pol->pol_peer.addr, @@ -858,15 +867,16 @@ ikev2_init_ike_sa_timeout(struct iked *env, void *arg) int ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy *pol, - struct iked_addr *peer) + struct iked_addr *peer, struct iked_message *retry) { struct sockaddr_storage ss; struct iked_message req; struct ike_header *hdr; struct ikev2_payload *pld; struct ikev2_keyexchange *ke; - struct iked_sa *sa; - struct ibuf *buf; + struct ikev2_notify *n; + struct iked_sa *sa = NULL; + struct ibuf *buf, *cookie = NULL; struct group *group; ssize_t len; int ret = -1; @@ -876,13 +886,21 @@ ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy *pol, if ((sock = ikev2_msg_getsocket(env, peer->addr_af, 0)) == NULL) return (-1); + if (retry != NULL) { + sa = retry->msg_sa; + cookie = retry->msg_cookie; + sa_state(env, sa, IKEV2_STATE_INIT); + } + /* Create a new initiator SA */ - if ((sa = sa_new(env, 0, 0, 1, pol)) == NULL) + if (sa == NULL && + (sa = sa_new(env, 0, 0, 1, pol)) == NULL) return (-1); /* Pick peer's DH group if asked */ /* XXX free old sa_dhgroup ? */ sa->sa_dhgroup = pol->pol_peerdh; + sa->sa_reqid = 0; if (ikev2_sa_initiator(env, sa, NULL, NULL) == -1) goto done; @@ -909,9 +927,31 @@ ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy *pol, /* IKE header */ if ((hdr = ikev2_add_header(buf, sa, req.msg_msgid, - IKEV2_PAYLOAD_SA, IKEV2_EXCHANGE_IKE_SA_INIT, 0)) == NULL) + cookie == NULL ? IKEV2_PAYLOAD_SA : IKEV2_PAYLOAD_NOTIFY, + IKEV2_EXCHANGE_IKE_SA_INIT, 0)) == NULL) goto done; + /* Reflect COOKIE */ + if (cookie) { + if ((pld = ikev2_add_payload(buf)) == NULL) + goto done; + if ((n = ibuf_advance(buf, sizeof(*n))) == NULL) + goto done; + n->n_protoid = IKEV2_SAPROTO_NONE; + n->n_spisize = 0; + n->n_type = htobe16(IKEV2_N_COOKIE); + if (ikev2_add_buf(buf, cookie) == -1) + goto done; + len = sizeof(*n) + ibuf_size(cookie); + + log_debug("%s: added cookie, len %zu", __func__, + ibuf_size(cookie)); + print_hex(ibuf_data(cookie), 0, ibuf_size(cookie)); + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA) == -1) + goto done; + } + /* SA payload */ if ((pld = ikev2_add_payload(buf)) == NULL) goto done; @@ -5176,7 +5216,8 @@ ikev2_acquire_sa(struct iked *env, struct iked_flow *acquire) log_debug("%s: found matching policy '%s'", __func__, p->pol_name); - if (ikev2_init_ike_sa_peer(env, p, acquire->flow_peer) != 0) + if (ikev2_init_ike_sa_peer(env, p, + acquire->flow_peer, NULL) != 0) log_warnx("%s: failed to initiate a " "IKE_SA_INIT exchange", __func__); } else { diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c index 37bb8995425..6658414e57b 100644 --- a/sbin/iked/ikev2_msg.c +++ b/sbin/iked/ikev2_msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_msg.c,v 1.50 2017/03/27 10:06:41 reyk Exp $ */ +/* $OpenBSD: ikev2_msg.c,v 1.51 2017/03/27 10:21:19 reyk Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -183,12 +183,15 @@ ikev2_msg_cleanup(struct iked *env, struct iked_message *msg) ibuf_release(msg->msg_auth.id_buf); ibuf_release(msg->msg_id.id_buf); ibuf_release(msg->msg_cert.id_buf); + ibuf_release(msg->msg_cookie); msg->msg_nonce = NULL; msg->msg_ke = NULL; msg->msg_auth.id_buf = NULL; msg->msg_id.id_buf = NULL; msg->msg_cert.id_buf = NULL; + msg->msg_cookie = NULL; + config_free_proposals(&msg->msg_proposals, 0); } diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index 51a95b488fc..9aeb61eb987 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.59 2017/03/13 18:48:16 mikeb Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.60 2017/03/27 10:21:19 reyk Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -1289,6 +1289,27 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, msg->msg_sa->sa_cpi_out = betoh16(cpi); } break; + case IKEV2_N_COOKIE: + if (msg->msg_e) { + log_debug("%s: N_COOKIE encrypted", + __func__); + return (-1); + } + if (len < IKED_COOKIE_MIN || len > IKED_COOKIE_MAX) { + log_debug("%s: ignoring malformed cookie" + " notification: %zu", __func__, len); + return (0); + } + log_debug("%s: received cookie, len %zu", __func__, len); + print_hex(buf, 0, len); + + ibuf_release(msg->msg_cookie); + if ((msg->msg_cookie = ibuf_new(buf, len)) == NULL) { + log_debug("%s: failed to get peer cookie", __func__); + return (-1); + } + msg->msg_parent->msg_cookie = msg->msg_cookie; + break; case IKEV2_N_SIGNATURE_HASH_ALGORITHMS: if (msg->msg_e) { log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted", diff --git a/sbin/iked/types.h b/sbin/iked/types.h index 0e878887ea7..8e29d39f0ee 100644 --- a/sbin/iked/types.h +++ b/sbin/iked/types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: types.h,v 1.26 2017/01/03 17:51:38 reyk Exp $ */ +/* $OpenBSD: types.h,v 1.27 2017/03/27 10:21:19 reyk Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -56,6 +56,9 @@ #define IKED_NONCE_MIN 16 /* XXX 128 bits */ #define IKED_NONCE_SIZE 32 /* XXX 256 bits */ +#define IKED_COOKIE_MIN 1 /* min 1 bytes */ +#define IKED_COOKIE_MAX 64 /* max 64 bytes */ + #define IKED_ID_SIZE 1024 /* XXX should be dynamic */ #define IKED_PSK_SIZE 1024 /* XXX should be dynamic */ #define IKED_MSGBUF_MAX 8192 |