summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2017-03-13 18:28:03 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2017-03-13 18:28:03 +0000
commit2774c0fa9f40ac08dc98142148c20ed5b4b6b3f3 (patch)
treef09c53a4966afceeb2b5617b08af57a1ac3d8f19 /sbin
parent15eb0e67aaa69fe7bfac0029c5e86804ab5f2dd1 (diff)
Make sure that proposal contains a DH group when rekeying with PFS enabled
Via markus, OK mikeb@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/iked/iked.h4
-rw-r--r--sbin/iked/ikev2.c53
2 files changed, 39 insertions, 18 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index 92df7b01b26..449bd943bba 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.106 2017/03/13 17:23:45 mikeb Exp $ */
+/* $OpenBSD: iked.h,v 1.107 2017/03/13 18:28:02 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -761,7 +761,7 @@ pid_t ikev2(struct privsep *, struct privsep_proc *);
void ikev2_recv(struct iked *, struct iked_message *);
void ikev2_init_ike_sa(struct iked *, void *);
int ikev2_sa_negotiate(struct iked_proposals *, struct iked_proposals *,
- struct iked_proposals *);
+ struct iked_proposals *, int);
int ikev2_policy2id(struct iked_static_id *, struct iked_id *, int);
int ikev2_childsa_enable(struct iked *, struct iked_sa *);
int ikev2_childsa_delete(struct iked *, struct iked_sa *,
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index 905c33324e5..acd89cd3538 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.140 2017/03/13 17:41:14 reyk Exp $ */
+/* $OpenBSD: ikev2.c,v 1.141 2017/03/13 18:28:02 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -106,7 +106,7 @@ int ikev2_set_sa_proposal(struct iked_sa *, struct iked_policy *,
int ikev2_childsa_negotiate(struct iked *, struct iked_sa *,
struct iked_kex *, struct iked_proposals *, int, int, int);
int ikev2_match_proposals(struct iked_proposal *, struct iked_proposal *,
- struct iked_transform **);
+ struct iked_transform **, int);
int ikev2_valid_proposal(struct iked_proposal *,
struct iked_transform **, struct iked_transform **, int *);
@@ -640,8 +640,9 @@ ikev2_ike_auth_recv(struct iked *env, struct iked_sa *sa,
if (!TAILQ_EMPTY(&msg->msg_proposals)) {
if (ikev2_sa_negotiate(&sa->sa_proposals,
- &sa->sa_policy->pol_proposals, &msg->msg_proposals) != 0) {
- log_debug("%s: no proposal chosen", __func__);
+ &sa->sa_policy->pol_proposals, &msg->msg_proposals,
+ 0) != 0) {
+ log_info("%s: no proposal chosen", __func__);
msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
return (-1);
} else
@@ -2836,7 +2837,7 @@ ikev2_init_create_child_sa(struct iked *env, struct iked_message *msg)
}
if (ikev2_sa_negotiate(&sa->sa_proposals, &sa->sa_proposals,
- &msg->msg_proposals) != 0) {
+ &msg->msg_proposals, 1) != 0) {
log_debug("%s: no proposal chosen", __func__);
return (-1);
}
@@ -3167,8 +3168,10 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
}
if (ikev2_sa_negotiate(&proposals,
- &sa->sa_policy->pol_proposals, &msg->msg_proposals) != 0) {
- log_debug("%s: no proposal chosen", __func__);
+ &sa->sa_policy->pol_proposals, &msg->msg_proposals,
+ 1) != 0) {
+ log_info("%s: no proposal chosen", __func__);
+ msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
goto fail;
}
@@ -3529,16 +3532,27 @@ ikev2_psk(struct iked_sa *sa, uint8_t *data, size_t length,
int
ikev2_match_proposals(struct iked_proposal *local, struct iked_proposal *peer,
- struct iked_transform **xforms)
+ struct iked_transform **xforms, int rekey)
{
struct iked_transform *tpeer, *tlocal;
- unsigned int i, j, type, score;
+ unsigned int i, j, type, score, requiredh = 0;
uint8_t protoid = peer->prop_protoid;
for (i = 0; i < peer->prop_nxforms; i++) {
tpeer = peer->prop_xforms + i;
for (j = 0; j < local->prop_nxforms; j++) {
tlocal = local->prop_xforms + j;
+
+ /*
+ * We require a DH group for ESP if there is any
+ * local proposal with DH enabled.
+ */
+ if (rekey && requiredh == 0 &&
+ protoid == IKEV2_SAPROTO_ESP &&
+ tlocal->xform_type == IKEV2_XFORMTYPE_DH)
+ requiredh = 1;
+
+ /* Compare peer and local proposals */
if (tpeer->xform_type != tlocal->xform_type ||
tpeer->xform_id != tlocal->xform_id ||
tpeer->xform_length != tlocal->xform_length)
@@ -3576,7 +3590,8 @@ ikev2_match_proposals(struct iked_proposal *local, struct iked_proposal *peer,
score = 0;
break;
} else if (protoid == IKEV2_SAPROTO_ESP && xforms[i] == NULL &&
- (i == IKEV2_XFORMTYPE_ENCR || i == IKEV2_XFORMTYPE_ESN)) {
+ (i == IKEV2_XFORMTYPE_ENCR || i == IKEV2_XFORMTYPE_ESN ||
+ (requiredh && i == IKEV2_XFORMTYPE_DH))) {
score = 0;
break;
} else if (xforms[i] == NULL)
@@ -3588,9 +3603,14 @@ ikev2_match_proposals(struct iked_proposal *local, struct iked_proposal *peer,
return (score);
}
+/*
+ * The 'rekey' parameter indicates a CREATE_CHILD_SA exchange where
+ * an extra group is necessary for PFS. For the initial IKE_AUTH exchange
+ * the ESP SA proposal never includes an explicit DH group.
+ */
int
ikev2_sa_negotiate(struct iked_proposals *result, struct iked_proposals *local,
- struct iked_proposals *peer)
+ struct iked_proposals *peer, int rekey)
{
struct iked_proposal *ppeer = NULL, *plocal, *prop, vpeer, vlocal;
struct iked_transform chosen[IKEV2_XFORMTYPE_MAX];
@@ -3614,7 +3634,8 @@ ikev2_sa_negotiate(struct iked_proposals *result, struct iked_proposals *local,
if (ppeer->prop_protoid != plocal->prop_protoid)
continue;
bzero(match, sizeof(match));
- score = ikev2_match_proposals(plocal, ppeer, match);
+ score = ikev2_match_proposals(plocal, ppeer, match,
+ rekey);
log_debug("%s: score %d", __func__, score);
if (score && (!chosen_score || score < chosen_score)) {
chosen_score = score;
@@ -3760,8 +3781,8 @@ ikev2_sa_initiator(struct iked *env, struct iked_sa *sa,
/* XXX we need a better way to get this */
if (ikev2_sa_negotiate(&sa->sa_proposals,
- &msg->msg_policy->pol_proposals, &msg->msg_proposals) != 0) {
- log_debug("%s: no proposal chosen", __func__);
+ &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0) != 0) {
+ log_info("%s: no proposal chosen", __func__);
msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
return (-1);
} else if (sa_stateok(sa, IKEV2_STATE_SA_INIT))
@@ -3894,8 +3915,8 @@ ikev2_sa_responder(struct iked *env, struct iked_sa *sa, struct iked_sa *osa,
/* XXX we need a better way to get this */
if (ikev2_sa_negotiate(&sa->sa_proposals,
- &msg->msg_policy->pol_proposals, &msg->msg_proposals) != 0) {
- log_debug("%s: no proposal chosen", __func__);
+ &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0) != 0) {
+ log_info("%s: no proposal chosen", __func__);
msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
return (-1);
} else if (sa_stateok(sa, IKEV2_STATE_SA_INIT))