summaryrefslogtreecommitdiff
path: root/sbin/iked/ikev2.c
diff options
context:
space:
mode:
authorTobias Heider <tobhe@cvs.openbsd.org>2022-07-08 19:51:12 +0000
committerTobias Heider <tobhe@cvs.openbsd.org>2022-07-08 19:51:12 +0000
commit1c47409c702d965373f525a9d584bcd3b0c59af6 (patch)
treeaa843e1ff540a03e291a8c956f132b3751292efc /sbin/iked/ikev2.c
parent97ce1f22ec6f74bbf922bf0ccf58003f95edb5f3 (diff)
Support sending certificate chains with intermediate CAs in multiple CERT
payloads. Local certificate chains as required with LetsEncrypt certs will work between iked and other IKEv2 implementations, iked to iked connections won't work yet because of missing support to receive multiple CERT payloads. from Katsuhiro Ueno tested by and ok sthen@
Diffstat (limited to 'sbin/iked/ikev2.c')
-rw-r--r--sbin/iked/ikev2.c89
1 files changed, 88 insertions, 1 deletions
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index e3a51fcbb90..783d9cb5dfa 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.348 2022/07/04 08:39:55 tobhe Exp $ */
+/* $OpenBSD: ikev2.c,v 1.349 2022/07/08 19:51:11 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -315,6 +315,7 @@ ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg)
size_t len;
struct iked_id *id = NULL;
int ignore = 0;
+ int i;
switch (imsg->hdr.type) {
case IMSG_CERTREQ:
@@ -416,6 +417,51 @@ ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg)
if (ikev2_ike_auth(env, sa) != 0)
log_debug("%s: failed to send ike auth", __func__);
break;
+ case IMSG_SCERT:
+ if ((sa = ikev2_getimsgdata(env, imsg,
+ &sh, &type, &ptr, &len)) == NULL) {
+ log_debug("%s: invalid supplemental cert reply",
+ __func__);
+ break;
+ }
+
+ if (sa->sa_stateflags & IKED_REQ_CERT ||
+ type == IKEV2_CERT_NONE)
+ ignore = 1;
+
+ log_debug("%s: supplemental cert type %s length %zu, %s",
+ __func__,
+ print_map(type, ikev2_cert_map), len,
+ ignore ? "ignored" : "ok");
+
+ if (ignore)
+ break;
+
+ for (i = 0; i < IKED_SCERT_MAX; i++) {
+ id = &sa->sa_scert[i];
+ if (id->id_type == IKEV2_CERT_NONE)
+ break;
+ id = NULL;
+ }
+
+ if (id == NULL) {
+ log_debug("%s: too many supplemental cert. ignored",
+ __func__);
+ break;
+ }
+
+ id->id_type = type;
+ id->id_offset = 0;
+ ibuf_release(id->id_buf);
+ id->id_buf = NULL;
+
+ if (len <= 0 || (id->id_buf = ibuf_new(ptr, len)) == NULL) {
+ log_debug("%s: failed to get supplemental cert payload",
+ __func__);
+ break;
+ }
+
+ break;
case IMSG_AUTH:
if ((sa = ikev2_getimsgdata(env, imsg,
&sh, &type, &ptr, &len)) == NULL) {
@@ -1490,6 +1536,7 @@ ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa)
uint8_t firstpayload;
int ret = -1;
ssize_t len;
+ int i;
if (!sa_stateok(sa, IKEV2_STATE_SA_INIT))
return (0);
@@ -1544,6 +1591,22 @@ ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa)
goto done;
len = ibuf_size(certid->id_buf) + sizeof(*cert);
+ for (i = 0; i < IKED_SCERT_MAX; i++) {
+ if (sa->sa_scert[i].id_type == IKEV2_CERT_NONE)
+ break;
+ if (ikev2_next_payload(pld, len,
+ IKEV2_PAYLOAD_CERT) == -1)
+ goto done;
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL)
+ goto done;
+ cert->cert_type = sa->sa_scert[i].id_type;
+ if (ibuf_cat(e, sa->sa_scert[i].id_buf) != 0)
+ goto done;
+ len = ibuf_size(sa->sa_scert[i].id_buf) + sizeof(*cert);
+ }
+
/* CERTREQ payload(s) */
if ((len = ikev2_add_certreq(e, &pld,
len, env->sc_certreq, env->sc_certreqtype)) == -1)
@@ -3722,6 +3785,7 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
uint8_t firstpayload;
int ret = -1;
ssize_t len;
+ int i;
if (sa == NULL)
return (-1);
@@ -3781,6 +3845,24 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
if (ibuf_cat(e, certid->id_buf) != 0)
goto done;
len = ibuf_size(certid->id_buf) + sizeof(*cert);
+
+ for (i = 0; i < IKED_SCERT_MAX; i++) {
+ if (sa->sa_scert[i].id_type == IKEV2_CERT_NONE)
+ break;
+ if (ikev2_next_payload(pld, len,
+ IKEV2_PAYLOAD_CERT) == -1)
+ goto done;
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((cert = ibuf_advance(e,
+ sizeof(*cert))) == NULL)
+ goto done;
+ cert->cert_type = sa->sa_scert[i].id_type;
+ if (ibuf_cat(e, sa->sa_scert[i].id_buf) != 0)
+ goto done;
+ len = ibuf_size(sa->sa_scert[i].id_buf)
+ + sizeof(*cert);
+ }
}
if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH) == -1)
@@ -4458,6 +4540,7 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa)
struct iked_childsa *csa, *csatmp, *ipcomp;
struct iked_flow *flow, *flowtmp;
struct iked_proposal *prop, *proptmp;
+ int i;
log_debug("%s: IKE SA %p ispi %s rspi %s replaced"
" by SA %p ispi %s rspi %s ",
@@ -4535,11 +4618,15 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa)
nsa->sa_icert = sa->sa_rcert;
nsa->sa_rcert = sa->sa_icert;
}
+ for (i = 0; i < IKED_SCERT_MAX; i++)
+ nsa->sa_scert[i] = sa->sa_scert[i];
/* duplicate the actual buffer */
nsa->sa_iid.id_buf = ibuf_dup(nsa->sa_iid.id_buf);
nsa->sa_rid.id_buf = ibuf_dup(nsa->sa_rid.id_buf);
nsa->sa_icert.id_buf = ibuf_dup(nsa->sa_icert.id_buf);
nsa->sa_rcert.id_buf = ibuf_dup(nsa->sa_rcert.id_buf);
+ for (i = 0; i < IKED_SCERT_MAX; i++)
+ nsa->sa_scert[i].id_buf = ibuf_dup(nsa->sa_scert[i].id_buf);
/* Transfer sa_addrpool address */
if (sa->sa_addrpool) {