summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authortobhe <tobhe@cvs.openbsd.org>2020-03-10 18:54:53 +0000
committertobhe <tobhe@cvs.openbsd.org>2020-03-10 18:54:53 +0000
commitb874ea54931b57bbdad778db396825933357c74d (patch)
tree8ffdb0fddcaca69ad9b5d150d22799b634f891de /sbin
parent89ed148f5add72062812c42d299ecd4683dacf44 (diff)
Relookup policy based on received cryptographic parameter proposal.
The IKEv2 responder does not know which policy is negotiated until the ID payload is received in the IKE_AUTH exchange. iked therefore chooses a default policy until the final policy is selected. This change adds a policy relookup during the IKE_SA_INIT. If the received proposal is not compatible with the default policy we switch to the next highest ranked policy that is compatible with the received proposal. ok kn@ markus@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/iked/iked.h5
-rw-r--r--sbin/iked/ikev2.c32
-rw-r--r--sbin/iked/policy.c10
3 files changed, 36 insertions, 11 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index dec990e965e..785d6039c77 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.135 2020/03/01 19:17:58 tobhe Exp $ */
+/* $OpenBSD: iked.h,v 1.136 2020/03/10 18:54:52 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -777,7 +777,8 @@ int config_getnattport(struct iked *, struct imsg *);
/* policy.c */
void policy_init(struct iked *);
-int policy_lookup(struct iked *, struct iked_message *);
+int policy_lookup(struct iked *, struct iked_message *,
+ struct iked_proposals *proposals);
struct iked_policy *
policy_test(struct iked *, struct iked_policy *);
int policy_generate_ts(struct iked_policy *);
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index 60f7f971ea9..2dd2b2c648d 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.194 2020/03/10 10:19:22 tobhe Exp $ */
+/* $OpenBSD: ikev2.c,v 1.195 2020/03/10 18:54:52 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -444,7 +444,7 @@ ikev2_recv(struct iked *env, struct iked_message *msg)
betoh64(hdr->ike_ispi), betoh64(hdr->ike_rspi),
initiator);
msg->msg_msgid = betoh32(hdr->ike_msgid);
- if (policy_lookup(env, msg) != 0)
+ if (policy_lookup(env, msg, NULL) != 0)
return;
log_info("%srecv %s %s %u peer %s local %s, %ld bytes, policy '%s'",
@@ -633,7 +633,7 @@ ikev2_ike_auth_recv(struct iked *env, struct iked_sa *sa,
struct iked_policy *old = sa->sa_policy;
sa->sa_policy = NULL;
- if (policy_lookup(env, msg) == 0 && msg->msg_policy &&
+ if (policy_lookup(env, msg, &sa->sa_proposals) == 0 && msg->msg_policy &&
msg->msg_policy != old) {
/* move sa to new policy */
policy = sa->sa_policy = msg->msg_policy;
@@ -4618,6 +4618,7 @@ ikev2_sa_responder(struct iked *env, struct iked_sa *sa, struct iked_sa *osa,
struct iked_message *msg)
{
struct iked_transform *xform;
+ struct iked_policy *old;
sa_state(env, sa, IKEV2_STATE_SA_INIT);
@@ -4641,12 +4642,31 @@ ikev2_sa_responder(struct iked *env, struct iked_sa *sa, struct iked_sa *osa,
}
/* XXX we need a better way to get this */
- if (proposals_negotiate(&sa->sa_proposals,
- &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0) != 0) {
+ old = sa->sa_policy;
+ sa->sa_policy = NULL;
+ if (policy_lookup(env, msg, &msg->msg_proposals) != 0 || msg->msg_policy == NULL) {
+ sa->sa_policy = old;
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))
+ }
+ sa->sa_policy = msg->msg_policy;
+ /* move sa to new policy */
+ sa->sa_policy = msg->msg_policy;
+ TAILQ_REMOVE(&old->pol_sapeers, sa, sa_peer_entry);
+ TAILQ_INSERT_TAIL(&sa->sa_policy->pol_sapeers,
+ sa, sa_peer_entry);
+ if (old->pol_flags & IKED_POLICY_REFCNT)
+ policy_unref(env, old);
+ if (sa->sa_policy->pol_flags & IKED_POLICY_REFCNT)
+ policy_ref(env, sa->sa_policy);
+
+ if (proposals_negotiate(&sa->sa_proposals,
+ &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0) != 0) {
+ log_info("%s: proposals_negotiate", __func__);
+ return (-1);
+ }
+ if (sa_stateok(sa, IKEV2_STATE_SA_INIT))
sa_stateflags(sa, IKED_REQ_SA);
if (sa->sa_encr == NULL) {
diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c
index 6c9baa9b619..67d0b8baa31 100644
--- a/sbin/iked/policy.c
+++ b/sbin/iked/policy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: policy.c,v 1.56 2020/03/09 11:50:43 tobhe Exp $ */
+/* $OpenBSD: policy.c,v 1.57 2020/03/10 18:54:52 tobhe Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -64,12 +64,15 @@ policy_init(struct iked *env)
* Lookup an iked policy matching the IKE_AUTH message msg
* and store a pointer to the found policy in msg. If no policy
* matches a pointer to the default policy is stored in msg.
+ * If 'proposals' is not NULL policy_lookup only returns policies
+ * compatible with 'proposals'.
*
* Returns 0 on success and -1 if no matching policy was
* found and no default exists.
*/
int
-policy_lookup(struct iked *env, struct iked_message *msg)
+policy_lookup(struct iked *env, struct iked_message *msg,
+ struct iked_proposals *proposals)
{
struct iked_policy pol;
char *s, idstr[IKED_ID_SIZE];
@@ -82,13 +85,14 @@ policy_lookup(struct iked *env, struct iked_message *msg)
}
bzero(&pol, sizeof(pol));
+ if (proposals != NULL)
+ pol.pol_proposals = *proposals;
pol.pol_af = msg->msg_peer.ss_family;
memcpy(&pol.pol_peer.addr, &msg->msg_peer, sizeof(msg->msg_peer));
memcpy(&pol.pol_local.addr, &msg->msg_local, sizeof(msg->msg_local));
if (msg->msg_id.id_type &&
ikev2_print_id(&msg->msg_id, idstr, IKED_ID_SIZE) == 0 &&
(s = strchr(idstr, '/')) != NULL) {
- pol.pol_proposals = msg->msg_sa->sa_proposals;
pol.pol_peerid.id_type = msg->msg_id.id_type;
pol.pol_peerid.id_length = strlen(s+1);
strlcpy(pol.pol_peerid.id_data, s+1,