summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/iked/config.c19
-rw-r--r--sbin/iked/iked.h30
-rw-r--r--sbin/iked/ikev2.c161
3 files changed, 132 insertions, 78 deletions
diff --git a/sbin/iked/config.c b/sbin/iked/config.c
index 00f0b9de7d7..c6fab06bdeb 100644
--- a/sbin/iked/config.c
+++ b/sbin/iked/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.30 2014/05/06 10:24:22 markus Exp $ */
+/* $OpenBSD: config.c,v 1.31 2014/05/06 14:10:53 markus Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -76,6 +76,23 @@ config_getspi(void)
}
void
+config_free_kex(struct iked_kex *kex)
+{
+ if (kex == NULL)
+ return;
+
+ ibuf_release(kex->kex_inonce);
+ ibuf_release(kex->kex_rnonce);
+
+ if (kex->kex_dhgroup != NULL)
+ group_free(kex->kex_dhgroup);
+ ibuf_release(kex->kex_dhiexchange);
+ ibuf_release(kex->kex_dhrexchange);
+
+ free(kex);
+}
+
+void
config_free_sa(struct iked *env, struct iked_sa *sa)
{
timer_del(env, &sa->sa_timer);
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index a386ded6873..d89d19dba38 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.76 2014/05/06 10:24:22 markus Exp $ */
+/* $OpenBSD: iked.h,v 1.77 2014/05/06 14:10:53 markus Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -344,6 +344,16 @@ struct iked_sahdr {
u_int sh_initiator; /* Is initiator? */
} __packed;
+struct iked_kex {
+ struct ibuf *kex_inonce; /* Ni */
+ struct ibuf *kex_rnonce; /* Nr */
+
+ struct group *kex_dhgroup; /* DH group */
+ struct ibuf *kex_dhiexchange;
+ struct ibuf *kex_dhrexchange;
+ struct ibuf *kex_dhpeer; /* pointer to i or r */
+};
+
struct iked_sa {
struct iked_sahdr sa_hdr;
u_int32_t sa_msgid; /* Last request rcvd */
@@ -375,13 +385,14 @@ struct iked_sa {
char *sa_tag;
- struct ibuf *sa_inonce; /* Ni */
- struct ibuf *sa_rnonce; /* Nr */
-
- struct group *sa_dhgroup; /* DH group */
- struct ibuf *sa_dhiexchange;
- struct ibuf *sa_dhrexchange;
- struct ibuf *sa_dhpeer; /* pointer to i or r */
+ struct iked_kex sa_kex;
+/* XXX compat defines until everything is converted */
+#define sa_inonce sa_kex.kex_inonce
+#define sa_rnonce sa_kex.kex_rnonce
+#define sa_dhgroup sa_kex.kex_dhgroup
+#define sa_dhiexchange sa_kex.kex_dhiexchange
+#define sa_dhrexchange sa_kex.kex_dhrexchange
+#define sa_dhpeer sa_kex.kex_dhpeer
struct iked_hash *sa_prf; /* PRF alg */
struct iked_hash *sa_integr; /* integrity alg */
@@ -604,6 +615,7 @@ void control_cleanup(struct control_sock *);
/* config.c */
struct iked_policy *
config_new_policy(struct iked *);
+void config_free_kex(struct iked_kex *);
void config_free_sa(struct iked *, struct iked_sa *);
struct iked_sa *
config_new_sa(struct iked *, int);
@@ -731,7 +743,7 @@ pid_t ikev1(struct privsep *, struct privsep_proc *);
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_sa *, struct iked_proposals *,
+int ikev2_sa_negotiate(struct iked_proposals *, struct iked_proposals *,
struct iked_proposals *);
int ikev2_policy2id(struct iked_static_id *, struct iked_id *, int);
int ikev2_childsa_enable(struct iked *, struct iked_sa *);
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index c4fce4d69bc..a0d02f29533 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.107 2014/05/06 10:24:22 markus Exp $ */
+/* $OpenBSD: ikev2.c,v 1.108 2014/05/06 14:10:53 markus Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -86,13 +86,15 @@ int ikev2_sa_initiator(struct iked *, struct iked_sa *,
int ikev2_sa_responder(struct iked *, struct iked_sa *, struct iked_sa *,
struct iked_message *);
int ikev2_sa_initiator_dh(struct iked_sa *, struct iked_message *, u_int);
-int ikev2_sa_responder_dh(struct iked_sa *, struct iked_message *, u_int);
+int ikev2_sa_responder_dh(struct iked_kex *, struct iked_proposals *,
+ struct iked_message *, u_int);
void ikev2_sa_cleanup_dh(struct iked_sa *);
int ikev2_sa_keys(struct iked *, struct iked_sa *, struct ibuf *);
int ikev2_sa_tag(struct iked_sa *, struct iked_id *);
int ikev2_set_sa_proposal(struct iked_sa *, struct iked_policy *, u_int);
-int ikev2_childsa_negotiate(struct iked *, struct iked_sa *, int, int);
+int ikev2_childsa_negotiate(struct iked *, struct iked_sa *,
+ struct iked_kex *, struct iked_proposals *, int, int);
int ikev2_match_proposals(struct iked_proposal *, struct iked_proposal *,
struct iked_transform **);
int ikev2_valid_proposal(struct iked_proposal *,
@@ -625,8 +627,8 @@ ikev2_ike_auth(struct iked *env, struct iked_sa *sa,
}
if (!TAILQ_EMPTY(&msg->msg_proposals)) {
- if (ikev2_sa_negotiate(sa, &sa->sa_policy->pol_proposals,
- &msg->msg_proposals) != 0) {
+ if (ikev2_sa_negotiate(&sa->sa_proposals,
+ &sa->sa_policy->pol_proposals, &msg->msg_proposals) != 0) {
log_debug("%s: no proposal chosen", __func__);
msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
return (-1);
@@ -1078,7 +1080,8 @@ ikev2_init_done(struct iked *env, struct iked_sa *sa)
if (!sa_stateok(sa, IKEV2_STATE_VALID))
return (0); /* ignored */
- ret = ikev2_childsa_negotiate(env, sa, sa->sa_hdr.sh_initiator, 0);
+ ret = ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals,
+ sa->sa_hdr.sh_initiator, 0);
if (ret == 0)
ret = ikev2_childsa_enable(env, sa);
if (ret == 0) {
@@ -2100,7 +2103,8 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
if (ikev2_cp_setaddr(env, sa) < 0)
return (-1);
- if (ikev2_childsa_negotiate(env, sa, sa->sa_hdr.sh_initiator, 0) == -1)
+ if (ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals,
+ sa->sa_hdr.sh_initiator, 0) < 0)
return (-1);
/* New encrypted message buffer */
@@ -2659,7 +2663,7 @@ ikev2_init_create_child_sa(struct iked *env, struct iked_message *msg)
return (-1);
}
- if (ikev2_sa_negotiate(sa, &sa->sa_proposals,
+ if (ikev2_sa_negotiate(&sa->sa_proposals, &sa->sa_proposals,
&msg->msg_proposals) != 0) {
log_debug("%s: no proposal chosen", __func__);
return (-1);
@@ -2735,7 +2739,8 @@ ikev2_init_create_child_sa(struct iked *env, struct iked_message *msg)
ibuf_release(sa->sa_rnonce);
sa->sa_rnonce = ibuf_dup(msg->msg_nonce);
- if (ikev2_childsa_negotiate(env, sa, 1, pfs)) {
+ if (ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, 1,
+ pfs)) {
log_debug("%s: failed to get CHILD SAs", __func__);
return (-1);
}
@@ -2933,12 +2938,13 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
{
struct iked_childsa *csa;
struct iked_proposal *prop;
+ struct iked_proposals proposals;
+ struct iked_kex *kex, *kextmp = NULL;
struct iked_sa *nsa = NULL, *sa = msg->msg_sa;
struct iked_spi *spi, *rekey = &msg->msg_rekey;
struct ikev2_keyexchange *ke;
struct ikev2_payload *pld = NULL;
struct ibuf *e = NULL, *nonce = NULL;
- struct group *group;
u_int8_t firstpayload;
ssize_t len = 0;
int initiator, protoid, rekeying = 1;
@@ -2950,6 +2956,8 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
if (!ikev2_msg_frompeer(msg) || msg->msg_prop == NULL)
return (0);
+ TAILQ_INIT(&proposals);
+
if ((protoid = rekey->spi_protoid) == 0) {
/*
* If REKEY_SA notification is not present, then it's either
@@ -2995,31 +3003,42 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
sa_state(env, nsa, IKEV2_STATE_AUTH_SUCCESS);
nonce = nsa->sa_rnonce;
+ kex = &nsa->sa_kex;
} else {
/* Child SA creating/rekeying */
+ if ((kex = kextmp = calloc(1, sizeof(*kextmp))) == NULL) {
+ log_debug("%s: calloc kex", __func__);
+ goto fail;
+ }
+
+ if (ikev2_sa_negotiate(&proposals,
+ &sa->sa_policy->pol_proposals, &msg->msg_proposals) != 0) {
+ log_debug("%s: no proposal chosen", __func__);
+ goto fail;
+ }
+
/* check KE payload for PFS */
if (ibuf_length(msg->msg_parent->msg_ke)) {
log_debug("%s: using PFS", __func__);
- ikev2_sa_cleanup_dh(sa);
- if (ikev2_sa_responder_dh(sa, msg->msg_parent,
- protoid) < 0) {
+ if (ikev2_sa_responder_dh(kex, &proposals,
+ msg->msg_parent, protoid) < 0) {
log_debug("%s: failed to setup DH", __func__);
- return (ret);
+ goto fail;
}
pfs = 1;
/* XXX check group against policy ? */
}
/* Update peer SPI */
- TAILQ_FOREACH(prop, &sa->sa_proposals, prop_entry) {
+ TAILQ_FOREACH(prop, &proposals, prop_entry) {
if (prop->prop_protoid == protoid)
break;
}
if (prop == NULL) {
log_debug("%s: failed to find %s proposals", __func__,
print_map(protoid, ikev2_saproto_map));
- return (-1);
+ goto fail;
} else
prop->prop_peerspi = msg->msg_prop->prop_peerspi;
@@ -3030,13 +3049,13 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
log_debug("%s: CHILD SA %s wasn't found",
__func__, print_spi(rekey->spi,
rekey->spi_size));
- return (-1);
+ goto fail;
}
if (!csa->csa_loaded || !csa->csa_peersa ||
!csa->csa_peersa->csa_loaded) {
log_debug("%s: SA is not loaded or no peer SA",
__func__);
- return (-1);
+ goto fail;
}
csa->csa_rekey = 1;
csa->csa_peersa->csa_rekey = 1;
@@ -3045,22 +3064,22 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
/* Update initiator's nonce */
if (!ibuf_length(msg->msg_nonce)) {
log_debug("%s: initiator didn't send nonce", __func__);
- return (-1);
+ goto fail;
}
- ibuf_release(sa->sa_inonce);
- sa->sa_inonce = ibuf_dup(msg->msg_nonce);
+ ibuf_release(kex->kex_inonce);
+ kex->kex_inonce = ibuf_dup(msg->msg_nonce);
/* Generate new responder's nonce */
if ((nonce = ibuf_random(IKED_NONCE_SIZE)) == NULL)
- return (-1);
+ goto fail;
/* Update responder's nonce */
- ibuf_release(sa->sa_rnonce);
- sa->sa_rnonce = nonce;
+ ibuf_release(kex->kex_rnonce);
+ kex->kex_rnonce = nonce;
- if (ikev2_childsa_negotiate(env, sa, 0, pfs)) {
+ if (ikev2_childsa_negotiate(env, sa, kex, &proposals, 0, pfs)) {
log_debug("%s: failed to get CHILD SAs", __func__);
- return (-1);
+ goto fail;
}
}
@@ -3084,7 +3103,7 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
goto done;
if ((len = ikev2_add_proposals(env, nsa ? nsa : sa, e,
- nsa ? &nsa->sa_proposals : &sa->sa_proposals,
+ nsa ? &nsa->sa_proposals : &proposals,
protoid, 0, nsa ? 1 : 0)) == -1)
goto done;
@@ -3108,16 +3127,14 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
goto done;
if ((ke = ibuf_advance(e, sizeof(*ke))) == NULL)
goto done;
- if ((group = nsa ?
- nsa->sa_dhgroup : sa->sa_dhgroup) == NULL) {
+ if (kex->kex_dhgroup == NULL) {
log_debug("%s: invalid dh", __func__);
goto done;
}
- ke->kex_dhgroup = htobe16(group->id);
- if (ikev2_add_buf(e, nsa ?
- nsa->sa_dhrexchange : sa->sa_dhrexchange) == -1)
+ ke->kex_dhgroup = htobe16(kex->kex_dhgroup->id);
+ if (ikev2_add_buf(e, kex->kex_dhrexchange) == -1)
goto done;
- len = sizeof(*ke) + dh_getlen(group);
+ len = sizeof(*ke) + dh_getlen(kex->kex_dhgroup);
}
if (protoid != IKEV2_SAPROTO_IKE)
@@ -3140,7 +3157,14 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
if (ret && protoid != IKEV2_SAPROTO_IKE)
ikev2_childsa_delete(env, sa, 0, 0, NULL, 1);
ibuf_release(e);
+ config_free_proposals(&proposals, 0);
+ config_free_kex(kextmp);
return (ret);
+
+ fail:
+ config_free_proposals(&proposals, 0);
+ config_free_kex(kextmp);
+ return (-1);
}
void
@@ -3392,7 +3416,7 @@ ikev2_match_proposals(struct iked_proposal *local, struct iked_proposal *peer,
}
int
-ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local,
+ikev2_sa_negotiate(struct iked_proposals *result, struct iked_proposals *local,
struct iked_proposals *peer)
{
struct iked_proposal *ppeer = NULL, *plocal, *prop, vpeer, vlocal;
@@ -3436,12 +3460,11 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local,
if (chosen_score == 0)
return (-1);
- else if (sa == NULL)
+ else if (result == NULL)
return (0);
- (void)config_free_proposals(&sa->sa_proposals, vpeer.prop_protoid);
- prop = config_add_proposal(&sa->sa_proposals, vpeer.prop_id,
- vpeer.prop_protoid);
+ (void)config_free_proposals(result, vpeer.prop_protoid);
+ prop = config_add_proposal(result, vpeer.prop_id, vpeer.prop_protoid);
if (vpeer.prop_localspi.spi_size) {
prop->prop_localspi.spi_size = vpeer.prop_localspi.spi_size;
@@ -3562,8 +3585,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, &msg->msg_policy->pol_proposals,
- &msg->msg_proposals) != 0) {
+ 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_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
return (-1);
@@ -3620,17 +3643,18 @@ ikev2_sa_initiator(struct iked *env, struct iked_sa *sa,
}
int
-ikev2_sa_responder_dh(struct iked_sa *sa, struct iked_message *msg, u_int proto)
+ikev2_sa_responder_dh(struct iked_kex *kex, struct iked_proposals *proposals,
+ struct iked_message *msg, u_int proto)
{
struct iked_transform *xform;
- if (sa->sa_dhgroup == NULL) {
- if ((xform = config_findtransform(&sa->sa_proposals,
+ if (kex->kex_dhgroup == NULL) {
+ if ((xform = config_findtransform(proposals,
IKEV2_XFORMTYPE_DH, proto)) == NULL) {
log_debug("%s: did not find dh transform", __func__);
return (-1);
}
- if ((sa->sa_dhgroup =
+ if ((kex->kex_dhgroup =
group_get(xform->xform_id)) == NULL) {
log_debug("%s: invalid dh %d", __func__,
xform->xform_id);
@@ -3638,32 +3662,32 @@ ikev2_sa_responder_dh(struct iked_sa *sa, struct iked_message *msg, u_int proto)
}
}
- if (!ibuf_length(sa->sa_dhrexchange)) {
- if ((sa->sa_dhrexchange = ibuf_new(NULL,
- dh_getlen(sa->sa_dhgroup))) == NULL) {
+ if (!ibuf_length(kex->kex_dhrexchange)) {
+ if ((kex->kex_dhrexchange = ibuf_new(NULL,
+ dh_getlen(kex->kex_dhgroup))) == NULL) {
log_debug("%s: failed to alloc dh exchange", __func__);
return (-1);
}
- if (dh_create_exchange(sa->sa_dhgroup,
- sa->sa_dhrexchange->buf) == -1) {
+ if (dh_create_exchange(kex->kex_dhgroup,
+ kex->kex_dhrexchange->buf) == -1) {
log_debug("%s: failed to get dh exchange", __func__);
return (-1);
}
}
- if (!ibuf_length(sa->sa_dhiexchange)) {
- if ((sa->sa_dhiexchange = ibuf_dup(msg->msg_ke)) == NULL ||
- ((ssize_t)ibuf_length(sa->sa_dhiexchange) !=
- dh_getlen(sa->sa_dhgroup))) {
+ if (!ibuf_length(kex->kex_dhiexchange)) {
+ if ((kex->kex_dhiexchange = ibuf_dup(msg->msg_ke)) == NULL ||
+ ((ssize_t)ibuf_length(kex->kex_dhiexchange) !=
+ dh_getlen(kex->kex_dhgroup))) {
/* XXX send notification to peer */
log_debug("%s: invalid dh, size %d", __func__,
- dh_getlen(sa->sa_dhgroup) * 8);
+ dh_getlen(kex->kex_dhgroup) * 8);
return (-1);
}
}
/* Set a pointer to the peer exchange */
- sa->sa_dhpeer = sa->sa_dhiexchange;
+ kex->kex_dhpeer = kex->kex_dhiexchange;
return (0);
}
int
@@ -3694,8 +3718,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, &msg->msg_policy->pol_proposals,
- &msg->msg_proposals) != 0) {
+ 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_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
return (-1);
@@ -3742,7 +3766,7 @@ ikev2_sa_responder(struct iked *env, struct iked_sa *sa, struct iked_sa *osa,
}
}
- if (ikev2_sa_responder_dh(sa, msg, 0) < 0)
+ if (ikev2_sa_responder_dh(&sa->sa_kex, &sa->sa_proposals, msg, 0) < 0)
return (-1);
return (ikev2_sa_keys(env, sa, osa ? osa->sa_key_d : NULL));
@@ -4119,7 +4143,8 @@ ikev2_sa_tag(struct iked_sa *sa, struct iked_id *id)
}
int
-ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
+ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
+ struct iked_kex *kex, struct iked_proposals *proposals, int initiator,
int pfs)
{
struct iked_proposal *prop;
@@ -4149,7 +4174,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
return (-1);
/* We need to determine the key material length first */
- TAILQ_FOREACH(prop, &sa->sa_proposals, prop_entry) {
+ TAILQ_FOREACH(prop, proposals, prop_entry) {
if (prop->prop_protoid == IKEV2_SAPROTO_IKE)
continue;
log_debug("%s: proposal %d", __func__, prop->prop_id);
@@ -4185,8 +4210,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
}
if (pfs) {
log_debug("%s: using PFS", __func__);
- if (sa->sa_dhpeer == NULL || ibuf_length(sa->sa_dhpeer) == 0 ||
- (group = sa->sa_dhgroup) == NULL) {
+ if (kex->kex_dhpeer == NULL || ibuf_length(kex->kex_dhpeer) == 0 ||
+ (group = kex->kex_dhgroup) == NULL) {
log_debug("%s: no dh group for pfs", __func__);
goto done;
}
@@ -4195,11 +4220,11 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
goto done;
}
if (dh_create_shared(group, dhsecret->buf,
- sa->sa_dhpeer->buf) == -1) {
+ kex->kex_dhpeer->buf) == -1) {
log_debug("%s: failed to get dh secret"
" group %d len %d secret %zu exchange %zu", __func__,
group->id, dh_getlen(group), ibuf_length(dhsecret),
- ibuf_length(sa->sa_dhpeer));
+ ibuf_length(kex->kex_dhpeer));
goto done;
}
if (ibuf_cat(seed, dhsecret) != 0) {
@@ -4207,8 +4232,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
goto done;
}
}
- if (ibuf_cat(seed, sa->sa_inonce) != 0 ||
- ibuf_cat(seed, sa->sa_rnonce) != 0 ||
+ if (ibuf_cat(seed, kex->kex_inonce) != 0 ||
+ ibuf_cat(seed, kex->kex_rnonce) != 0 ||
(keymat = ikev2_prfplus(sa->sa_prf,
sa->sa_key_d, seed, ilen)) == NULL) {
log_debug("%s: failed to get IKE SA key material", __func__);
@@ -4216,7 +4241,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
}
/* Create the new flows */
- TAILQ_FOREACH(prop, &sa->sa_proposals, prop_entry) {
+ TAILQ_FOREACH(prop, proposals, prop_entry) {
if (ikev2_valid_proposal(prop, NULL, NULL, NULL) != 0)
continue;
@@ -4272,7 +4297,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, int initiator,
}
/* create the CHILD SAs using the key material */
- TAILQ_FOREACH(prop, &sa->sa_proposals, prop_entry) {
+ TAILQ_FOREACH(prop, proposals, prop_entry) {
if (ikev2_valid_proposal(prop, &encrxf, &integrxf, &esn) != 0)
continue;