-/* $OpenBSD: config.c,v 1.74 2020/11/29 21:00:43 tobhe Exp $ */
+/* $OpenBSD: config.c,v 1.75 2021/01/21 16:46:47 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
ibuf_release(kex->kex_inonce);
ibuf_release(kex->kex_rnonce);
- if (kex->kex_dhgroup != NULL)
- group_free(kex->kex_dhgroup);
+ group_free(kex->kex_dhgroup);
ibuf_release(kex->kex_dhiexchange);
ibuf_release(kex->kex_dhrexchange);
ibuf_release(sa->sa_inonce);
ibuf_release(sa->sa_rnonce);
- if (sa->sa_dhgroup != NULL)
- group_free(sa->sa_dhgroup);
+ group_free(sa->sa_dhgroup);
ibuf_release(sa->sa_dhiexchange);
ibuf_release(sa->sa_dhrexchange);
}
struct iked_transform *
-config_findtransform(struct iked_proposals *props, uint8_t type,
+config_findtransform_ext(struct iked_proposals *props, uint8_t type, int id,
unsigned int proto)
{
struct iked_proposal *prop;
continue;
for (i = 0; i < prop->prop_nxforms; i++) {
xform = prop->prop_xforms + i;
+ /* optional lookup of specific transform */
+ if (id >= 0 && xform->xform_id != id)
+ continue;
if (xform->xform_type == type)
return (xform);
}
return (NULL);
}
+struct iked_transform *
+config_findtransform(struct iked_proposals *props, uint8_t type,
+ unsigned int proto)
+{
+ return config_findtransform_ext(props, type, -1, proto);
+}
+
struct iked_user *
config_new_user(struct iked *env, struct iked_user *new)
{
-/* $OpenBSD: ikev2.c,v 1.295 2021/01/20 18:44:28 tobhe Exp $ */
+/* $OpenBSD: ikev2.c,v 1.296 2021/01/21 16:46:47 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
struct ibuf *, struct ikev2_payload **, uint8_t *);
int ikev2_send_create_child_sa(struct iked *, struct iked_sa *,
- struct iked_spi *, uint8_t);
+ struct iked_spi *, uint8_t, uint16_t);
int ikev2_ikesa_enable(struct iked *, struct iked_sa *, struct iked_sa *);
void ikev2_ikesa_delete(struct iked *, struct iked_sa *, int);
int ikev2_nonce_cmp(struct ibuf *, struct ibuf *);
initiator = (hdr->ike_flags & IKEV2_FLAG_INITIATOR) ? 0 : 1;
msg->msg_response = (hdr->ike_flags & IKEV2_FLAG_RESPONSE) ? 1 : 0;
+ msg->msg_exchange = hdr->ike_exchange;
msg->msg_sa = sa_lookup(env,
betoh64(hdr->ike_ispi), betoh64(hdr->ike_rspi),
initiator);
{
struct iked_ipcomp *ic;
struct iked_sa *sa;
- uint16_t group;
+ struct iked_spi rekey;
+ struct group *group;
+ uint16_t groupid;
+ unsigned int protoid;
if ((sa = msg->msg_sa) == NULL)
return (-1);
}
if (msg->msg_flags & IKED_MSG_FLAGS_INVALID_KE) {
- /* XXX chould also happen for PFS */
- group = betoh16(msg->msg_group);
- if (!sa->sa_hdr.sh_initiator) {
- log_debug("%s: not an initiator", __func__);
+ groupid = betoh16(msg->msg_group);
+ if (group_getid(groupid) == NULL) {
+ log_debug("%s: unable to select DH group %u",
+ __func__, groupid);
ikev2_ike_sa_setreason(sa,
- "received invalid KE as responder");
+ "unable to select DH group");
sa_state(env, sa, IKEV2_STATE_CLOSED);
msg->msg_sa = NULL;
return (-1);
}
- if (group_getid(group) == NULL) {
- log_debug("%s: unable to select DH group %u", __func__,
- group);
+ log_debug("%s: responder selected DH group %u", __func__,
+ groupid);
+ switch (msg->msg_exchange) {
+ case IKEV2_EXCHANGE_IKE_SA_INIT:
+ protoid = IKEV2_SAPROTO_ESP;
+ if (!sa->sa_hdr.sh_initiator) {
+ log_debug("%s: not an initiator", __func__);
+ ikev2_ike_sa_setreason(sa,
+ "received invalid KE as responder");
+ sa_state(env, sa, IKEV2_STATE_CLOSED);
+ msg->msg_sa = NULL;
+ return (-1);
+ }
+ if (config_findtransform_ext(&msg->msg_policy->pol_proposals,
+ IKEV2_XFORMTYPE_DH, groupid, protoid) == NULL) {
+ log_debug("%s: DH group %u denied by policy",
+ __func__, groupid);
+ ikev2_ike_sa_setreason(sa,
+ "unsupported group in INVALID_KE message");
+ sa_state(env, sa, IKEV2_STATE_CLOSED);
+ msg->msg_sa = NULL;
+ return (-1);
+ }
ikev2_ike_sa_setreason(sa,
- "unable to select DH group");
+ "reinitiating with new DH group");
sa_state(env, sa, IKEV2_STATE_CLOSED);
msg->msg_sa = NULL;
+ msg->msg_policy->pol_peerdh = groupid;
+ timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL);
+ timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INITIAL);
+ return (-1);
+ case IKEV2_EXCHANGE_CREATE_CHILD_SA:
+ if (!(sa->sa_stateflags & IKED_REQ_CHILDSA)) {
+ log_debug("%s: IKED_REQ_CHILDSA missing",
+ __func__);
+ return (-1);
+ }
+ sa->sa_stateflags &= ~IKED_REQ_CHILDSA;
+ protoid = sa->sa_rekeyspi ?
+ IKEV2_SAPROTO_ESP : IKEV2_SAPROTO_IKE;
+ if (config_findtransform_ext(&msg->msg_policy->pol_proposals,
+ IKEV2_XFORMTYPE_DH, groupid, protoid) == NULL) {
+ log_debug("%s: DH group %u denied by policy",
+ __func__, groupid);
+ ikev2_ike_sa_setreason(sa,
+ "unsupported group in INVALID_KE message");
+ sa_state(env, sa, IKEV2_STATE_CLOSED);
+ msg->msg_sa = NULL;
+ return (-1);
+ }
+ if (protoid == IKEV2_SAPROTO_ESP) {
+ /* CHILDSA */
+ rekey.spi = sa->sa_rekeyspi;
+ rekey.spi_size = 4;
+ rekey.spi_protoid = protoid;
+ (void)ikev2_send_create_child_sa(env, sa,
+ &rekey, rekey.spi_protoid, groupid);
+ } else {
+ /* IKESA */
+ if ((group = group_get(groupid)) == NULL)
+ return -1;
+ group_free(sa->sa_dhgroup);
+ sa->sa_dhgroup = group;
+ timer_set(env, &sa->sa_rekey,
+ ikev2_ike_sa_rekey, sa);
+ timer_add(env, &sa->sa_rekey, 0);
+ }
return (-1);
}
- msg->msg_policy->pol_peerdh = group;
- log_debug("%s: responder selected DH group %u", __func__,
- group);
- ikev2_ike_sa_setreason(sa,
- "reinitiating with new DH group");
- sa_state(env, sa, IKEV2_STATE_CLOSED);
- msg->msg_sa = NULL;
-
- /*
- * XXX should also happen for PFS so we have to check state.
- */
- timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL);
- timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INITIAL);
- return (-1);
}
if (msg->msg_flags & IKED_MSG_FLAGS_IPCOMP_SUPPORTED) {
int
ikev2_send_create_child_sa(struct iked *env, struct iked_sa *sa,
- struct iked_spi *rekey, uint8_t protoid)
+ struct iked_spi *rekey, uint8_t protoid, uint16_t proposed_group)
{
struct iked_policy *pol = sa->sa_policy;
struct iked_childsa *csa = NULL, *csb = NULL;
protoid)) {
log_debug("%s: enable PFS", __func__);
ikev2_sa_cleanup_dh(sa);
+ if (proposed_group) {
+ if ((sa->sa_dhgroup =
+ group_get(proposed_group)) == NULL) {
+ log_debug("%s: failed to get group", __func__);
+ goto done;
+ }
+ }
if (ikev2_sa_initiator_dh(sa, NULL, protoid, NULL) < 0) {
log_debug("%s: failed to setup DH", __func__);
goto done;
if (sa->sa_stateflags & (IKED_REQ_CHILDSA|IKED_REQ_INF))
return (-1); /* busy, retry later */
if (ikev2_send_create_child_sa(env, sa, NULL,
- flow->flow_saproto) != 0)
+ flow->flow_saproto, 0) != 0)
log_warnx("%s: failed to initiate a "
"CREATE_CHILD_SA exchange", SPI_SA(sa, __func__));
}
return (-1); /* peer is busy, retry later */
if (csa->csa_allocated) /* Peer SPI died first, get the local one */
rekey->spi = csa->csa_peerspi;
- if (ikev2_send_create_child_sa(env, sa, rekey, rekey->spi_protoid))
+ if (ikev2_send_create_child_sa(env, sa, rekey, rekey->spi_protoid, 0))
log_warnx("%s: failed to initiate a CREATE_CHILD_SA exchange",
SPI_SA(sa, __func__));
return (0);