summaryrefslogtreecommitdiff
path: root/sbin/iked
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2010-06-14 21:12:57 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2010-06-14 21:12:57 +0000
commit86b6e87721275c7172d5d598edf873f5d845d237 (patch)
treeaa5e8a3b5892816ca45edf0b308a6a35e7db66cc /sbin/iked
parent504cdf8986e42ed00a3b9ce7ed9b0504ff4fa4d2 (diff)
Initial support for initiator mode which allows to run iked as a
"client" or to configure iked to iked (OpenBSD to OpenBSD) IKEv2 VPNs. It currently only supports psk (pre-shared keys) and no certificates, doesn't do any rekeying or SA timeouts, and needs more cleanup. So it is not quite production ready yet - but ready for simple tests...
Diffstat (limited to 'sbin/iked')
-rw-r--r--sbin/iked/iked.h10
-rw-r--r--sbin/iked/ikev2.c347
-rw-r--r--sbin/iked/ikev2_msg.c13
-rw-r--r--sbin/iked/ikev2_pld.c14
-rw-r--r--sbin/iked/pfkey.c4
-rw-r--r--sbin/iked/policy.c35
6 files changed, 349 insertions, 74 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index 16fbfcc0a01..d6e39200e77 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.9 2010/06/14 14:03:15 reyk Exp $ */
+/* $OpenBSD: iked.h,v 1.10 2010/06/14 21:12:56 reyk Exp $ */
/* $vantronix: iked.h,v 1.61 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -142,8 +142,9 @@ struct iked_childsa {
u_int csa_dir; /* in/out */
u_int64_t csa_peerspi; /* peer relation */
- u_int csa_loaded; /* pfkey done */
- u_int csa_rekey; /* will be deleted */
+ u_int8_t csa_loaded; /* pfkey done */
+ u_int8_t csa_rekey; /* will be deleted */
+ u_int8_t csa_allocated; /* from the kernel */
struct iked_spi csa_spi;
@@ -321,6 +322,7 @@ struct iked_sa {
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_hash *sa_prf; /* PRF alg */
struct iked_hash *sa_integr; /* integrity alg */
@@ -367,6 +369,8 @@ struct iked_message {
struct sockaddr_storage msg_peer;
socklen_t msg_peerlen;
+ struct iked_socket *msg_sock;
+
int msg_fd;
int msg_response;
int msg_natt;
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index 1ee0a2c5f54..2db3bd36d2f 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.12 2010/06/14 14:17:49 reyk Exp $ */
+/* $OpenBSD: ikev2.c,v 1.13 2010/06/14 21:12:56 reyk Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -60,6 +60,8 @@ void ikev2_recv(struct iked *, struct iked_message *);
void ikev2_init_recv(struct iked *, struct iked_message *,
struct ike_header *);
int ikev2_init_ike_sa(struct iked *, struct iked_policy *);
+int ikev2_init_ike_auth(struct iked *, struct iked_message *);
+int ikev2_init_done(struct iked *, struct iked_message *);
void ikev2_resp_recv(struct iked *, struct iked_message *,
struct ike_header *);
@@ -80,7 +82,8 @@ int ikev2_childsa_enable(struct iked *, struct iked_sa *);
int ikev2_valid_proposal(struct iked_proposal *,
struct iked_transform **, struct iked_transform **);
-ssize_t ikev2_add_proposals(struct ibuf *, struct iked_proposals *, u_int8_t);
+ssize_t ikev2_add_proposals(struct iked *, struct iked_sa *, struct ibuf *,
+ struct iked_proposals *, u_int8_t);
ssize_t ikev2_add_cp(struct iked *, struct iked_sa *, struct ibuf *);
ssize_t ikev2_add_transform(struct ibuf *,
u_int8_t, u_int8_t, u_int16_t, u_int16_t);
@@ -394,6 +397,14 @@ ikev2_init_recv(struct iked *env, struct iked_message *msg,
switch (hdr->ike_exchange) {
case IKEV2_EXCHANGE_IKE_SA_INIT:
+ /* Update the SPIs */
+ if ((sa = sa_new(env,
+ betoh64(hdr->ike_ispi), betoh64(hdr->ike_rspi), 1,
+ NULL)) == NULL || sa != msg->msg_sa) {
+ log_debug("%s: invalid new SA %p", sa);
+ sa_free(env, sa);
+ }
+ break;
case IKEV2_EXCHANGE_IKE_AUTH:
case IKEV2_EXCHANGE_CREATE_CHILD_SA:
case IKEV2_EXCHANGE_INFORMATIONAL:
@@ -414,17 +425,17 @@ ikev2_init_recv(struct iked *env, struct iked_message *msg,
switch (hdr->ike_exchange) {
case IKEV2_EXCHANGE_IKE_SA_INIT:
+ (void)ikev2_init_ike_auth(env, msg);
+ break;
case IKEV2_EXCHANGE_IKE_AUTH:
+ (void)ikev2_init_done(env, msg);
+ break;
case IKEV2_EXCHANGE_CREATE_CHILD_SA:
+ default:
log_debug("%s: exchange %s not implemented", __func__,
print_map(hdr->ike_exchange, ikev2_exchange_map));
break;
- default:
- break;
}
-
- if (sa->sa_state == IKEV2_STATE_DELETE)
- sa_free(env, sa);
}
int
@@ -467,17 +478,17 @@ ikev2_init_ike_sa(struct iked *env, struct iked_policy *pol)
req.msg_fd = sock->sock_fd;
req.msg_sa = sa;
+ req.msg_sock = sock;
/* IKE header */
if ((hdr = ikev2_add_header(buf, sa, 0,
- IKEV2_PAYLOAD_SA, IKEV2_EXCHANGE_IKE_SA_INIT,
- IKEV2_FLAG_INITIATOR)) == NULL)
+ IKEV2_PAYLOAD_SA, IKEV2_EXCHANGE_IKE_SA_INIT, 0)) == NULL)
goto done;
/* SA payload */
if ((pld = ikev2_add_payload(buf)) == NULL)
goto done;
- if ((len = ikev2_add_proposals(buf, &pol->pol_proposals,
+ if ((len = ikev2_add_proposals(env, sa, buf, &pol->pol_proposals,
IKEV2_SAPROTO_IKE)) == -1)
goto done;
@@ -557,7 +568,8 @@ ikev2_init_ike_sa(struct iked *env, struct iked_policy *pol)
goto done;
}
- ret = ikev2_msg_send(env, req.msg_fd, &req);
+ if ((ret = ikev2_msg_send(env, req.msg_fd, &req)) == 0)
+ sa_state(env, sa, IKEV2_STATE_SA_INIT);
done:
if (ret == -1)
@@ -568,6 +580,171 @@ ikev2_init_ike_sa(struct iked *env, struct iked_policy *pol)
}
int
+ikev2_init_ike_auth(struct iked *env, struct iked_message *msg)
+{
+ struct iked_sa *sa = msg->msg_sa;
+ struct iked_policy *pol = sa->sa_policy;
+ struct ikev2_payload *pld;
+ struct ikev2_cert *cert;
+ struct ikev2_auth *auth;
+ struct iked_id *id, *certid;
+ struct ibuf *e = NULL;
+ u_int8_t firstpayload;
+ int ret = -1;
+ ssize_t len;
+ struct ibuf *authmsg;
+
+ if (sa == NULL)
+ return (-1);
+
+ if (ikev2_sa_initiator(env, sa, msg) == -1) {
+ log_debug("%s: failed to get IKE keys", __func__);
+ return (-1);
+ }
+
+ if ((authmsg = ikev2_msg_auth(env, sa,
+ !sa->sa_hdr.sh_initiator)) == NULL) {
+ log_debug("%s: failed to get auth data", __func__);
+ return (-1);
+ }
+
+ /* XXX this doesn't work with certificates */
+ ca_setauth(env, sa, authmsg, PROC_CERT);
+
+ if (!sa_stateok(sa, IKEV2_STATE_SA_INIT))
+ return (0); /* ignore */
+
+ if (!sa->sa_localauth.id_type) {
+ log_debug("%s: no local auth", __func__);
+ return (-1);
+ }
+
+ /* New encrypted message buffer */
+ if ((e = ibuf_static()) == NULL)
+ goto done;
+
+ id = &sa->sa_iid;
+ certid = &sa->sa_icert;
+
+ /* ID payload */
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ firstpayload = IKEV2_PAYLOAD_IDi;
+ if (ibuf_cat(e, id->id_buf) != 0)
+ goto done;
+ len = ibuf_size(id->id_buf);
+
+ /* CERT payload */
+ if ((sa->sa_staterequire & IKED_REQ_CERT) &&
+ (certid->id_type != IKEV2_CERT_NONE)) {
+ 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 = certid->id_type;
+ if (ibuf_cat(e, certid->id_buf) != 0)
+ goto done;
+ len = ibuf_size(certid->id_buf) + sizeof(*cert);
+ }
+
+ if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH) == -1)
+ goto done;
+
+ /* AUTH payload */
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((auth = ibuf_advance(e, sizeof(*auth))) == NULL)
+ goto done;
+ auth->auth_method = sa->sa_localauth.id_type;
+ if (ibuf_cat(e, sa->sa_localauth.id_buf) != 0)
+ goto done;
+ len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth);
+
+ /* CP payload */
+ if (sa->sa_cp) {
+ if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CP) == -1)
+ goto done;
+
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((len = ikev2_add_cp(env, sa, e)) == -1)
+ goto done;
+ }
+
+ if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA) == -1)
+ goto done;
+
+ /* SA payload */
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((len = ikev2_add_proposals(env, sa, e, &pol->pol_proposals,
+ IKEV2_SAPROTO_ESP)) == -1)
+ goto done;
+
+ if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_TSi) == -1)
+ goto done;
+
+ /* TSi payload */
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((len = ikev2_add_ts(e, IKEV2_PAYLOAD_TSi, sa)) == -1)
+ goto done;
+
+ if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_TSr) == -1)
+ goto done;
+
+ /* TSr payload */
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((len = ikev2_add_ts(e, IKEV2_PAYLOAD_TSr, sa)) == -1)
+ goto done;
+
+ if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE) == -1)
+ goto done;
+
+ ret = ikev2_msg_send_encrypt(env, sa, &e,
+ IKEV2_EXCHANGE_IKE_AUTH, firstpayload, 0);
+
+ done:
+ ibuf_release(e);
+
+ return (ret);
+}
+
+int
+ikev2_init_done(struct iked *env, struct iked_message *msg)
+{
+ struct iked_sa *sa = msg->msg_sa;
+ int ret;
+
+ if (!TAILQ_EMPTY(&msg->msg_proposals)) {
+ if (ikev2_sa_negotiate(sa,
+ &sa->sa_policy->pol_proposals,
+ &msg->msg_proposals, IKEV2_SAPROTO_ESP) != 0) {
+ log_debug("%s: no proposal chosen", __func__);
+ msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN;
+ sa_state(env, sa, IKEV2_STATE_DELETE);
+ return (-1);
+ } else
+ sa_stateflags(sa, IKED_REQ_SA);
+ }
+
+ if (!sa_stateok(sa, IKEV2_STATE_VALID))
+ return (0); /* ignored */
+
+ ret = ikev2_childsa_negotiate(env, sa, NULL);
+ if (ret == 0)
+ ret = ikev2_childsa_enable(env, sa);
+ if (ret == 0)
+ sa_state(env, sa, IKEV2_STATE_RUNNING);
+
+ return (ret);
+}
+
+int
ikev2_policy2id(struct iked_static_id *polid, struct iked_id *id, int srcid)
{
struct ikev2_id hdr;
@@ -996,25 +1173,43 @@ ikev2_add_cp(struct iked *env, struct iked_sa *sa, struct ibuf *buf)
}
ssize_t
-ikev2_add_proposals(struct ibuf *buf, struct iked_proposals *proposals,
- u_int8_t protoid)
+ikev2_add_proposals(struct iked *env, struct iked_sa *sa, struct ibuf *buf,
+ struct iked_proposals *proposals, u_int8_t protoid)
{
struct ikev2_sa_proposal *sap;
struct iked_transform *xform;
struct iked_proposal *prop;
+ struct iked_childsa csa;
ssize_t i, length = 0, saplength, ret, n;
u_int64_t spi64;
- u_int32_t spi32;
+ u_int32_t spi32, spi;
n = 0;
TAILQ_FOREACH(prop, proposals, prop_entry) {
if (prop->prop_protoid != protoid)
continue;
+ if (protoid != IKEV2_SAPROTO_IKE &&
+ sa->sa_hdr.sh_initiator) {
+ bzero(&csa, sizeof(csa));
+ csa.csa_ikesa = sa;
+ csa.csa_saproto = protoid;
+ csa.csa_local = &sa->sa_peer;
+ csa.csa_peer = &sa->sa_local;
+
+ if (pfkey_sa_init(env->sc_pfkey, &csa, &spi) == -1)
+ return (-1);
+
+ prop->prop_localspi.spi = spi;
+ prop->prop_localspi.spi_size = 4;
+ prop->prop_localspi.spi_protoid = protoid;
+ }
+
if ((sap = ibuf_advance(buf, sizeof(*sap))) == NULL) {
log_debug("%s: failed to add proposal", __func__);
return (-1);
}
+
sap->sap_proposalnr = prop->prop_id;
sap->sap_protoid = prop->prop_protoid;
sap->sap_spisize = prop->prop_localspi.spi_size;
@@ -1256,7 +1451,7 @@ ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg)
/* SA payload */
if ((pld = ikev2_add_payload(buf)) == NULL)
goto done;
- if ((len = ikev2_add_proposals(buf, &sa->sa_proposals,
+ if ((len = ikev2_add_proposals(env, sa, buf, &sa->sa_proposals,
IKEV2_SAPROTO_IKE)) == -1)
goto done;
@@ -1475,7 +1670,7 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
/* SA payload */
if ((pld = ikev2_add_payload(e)) == NULL)
goto done;
- if ((len = ikev2_add_proposals(e, &sa->sa_proposals,
+ if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals,
IKEV2_SAPROTO_ESP)) == -1)
goto done;
@@ -1670,7 +1865,7 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg)
if ((pld = ikev2_add_payload(e)) == NULL)
goto done;
firstpayload = IKEV2_PAYLOAD_SA;
- if ((len = ikev2_add_proposals(e, &sa->sa_proposals,
+ if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals,
IKEV2_SAPROTO_ESP)) == -1)
goto done;
@@ -1856,14 +2051,15 @@ int
ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local,
struct iked_proposals *peer, u_int8_t protoid)
{
- struct iked_proposal *ppeer = NULL, *plocal, *prop, values;
+ struct iked_proposal *ppeer = NULL, *plocal, *prop, vpeer, vlocal;
struct iked_transform *tpeer, *tlocal;
struct iked_transform *match[IKEV2_XFORMTYPE_MAX];
struct iked_transform *chosen[IKEV2_XFORMTYPE_MAX];
u_int type, i, j, match_score, chosen_score = 0;
bzero(chosen, sizeof(chosen));
- bzero(&values, sizeof(values));
+ bzero(&vlocal, sizeof(vlocal));
+ bzero(&vpeer, sizeof(vpeer));
if (TAILQ_EMPTY(peer)) {
log_debug("%s: peer did not send %s proposals", __func__,
@@ -1951,7 +2147,8 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local,
chosen_score = match_score;
for (i = 0; i < IKEV2_XFORMTYPE_MAX; i++)
chosen[i] = match[i];
- memcpy(&values, ppeer, sizeof(values));
+ memcpy(&vpeer, ppeer, sizeof(vpeer));
+ memcpy(&vlocal, plocal, sizeof(vlocal));
}
}
if (chosen_score != 0)
@@ -1964,12 +2161,15 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local,
return (0);
(void)config_free_proposals(&sa->sa_proposals, protoid);
- prop = config_add_proposal(&sa->sa_proposals, values.prop_id, protoid);
+ prop = config_add_proposal(&sa->sa_proposals, vpeer.prop_id, protoid);
- if (values.prop_localspi.spi_size) {
- prop->prop_peerspi = values.prop_peerspi;
- prop->prop_localspi.spi_size = values.prop_localspi.spi_size;
- prop->prop_localspi.spi = 0;
+ if (vpeer.prop_localspi.spi_size) {
+ prop->prop_localspi.spi_size = vpeer.prop_localspi.spi_size;
+ prop->prop_peerspi = vpeer.prop_peerspi;
+ }
+ if (vlocal.prop_localspi.spi_size) {
+ prop->prop_localspi.spi_size = vlocal.prop_localspi.spi_size;
+ prop->prop_localspi.spi = vlocal.prop_localspi.spi;
}
for (i = 0; i < IKEV2_XFORMTYPE_MAX; i++) {
@@ -2064,7 +2264,66 @@ ikev2_sa_initiator(struct iked *env, struct iked_sa *sa,
}
}
- return (0);
+ /* Set a pointer to the peer exchange */
+ sa->sa_dhpeer = sa->sa_dhrexchange;
+
+ /* XXX we need a better way to get this */
+ if (ikev2_sa_negotiate(sa,
+ &msg->msg_policy->pol_proposals,
+ &msg->msg_proposals, IKEV2_SAPROTO_IKE) != 0) {
+ log_debug("%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_stateflags(sa, IKED_REQ_SA);
+
+ if (sa->sa_encr == NULL) {
+ if ((xform = config_findtransform(&sa->sa_proposals,
+ IKEV2_XFORMTYPE_ENCR)) == NULL) {
+ log_debug("%s: did not find encr transform", __func__);
+ return (-1);
+ }
+ if ((sa->sa_encr = cipher_new(xform->xform_type,
+ xform->xform_id, xform->xform_length)) == NULL) {
+ log_debug("%s: failed to get encr", __func__);
+ return (-1);
+ }
+ }
+
+ if (sa->sa_prf == NULL) {
+ if ((xform = config_findtransform(&sa->sa_proposals,
+ IKEV2_XFORMTYPE_PRF)) == NULL) {
+ log_debug("%s: did not find prf transform", __func__);
+ return (-1);
+ }
+ if ((sa->sa_prf =
+ hash_new(xform->xform_type, xform->xform_id)) == NULL) {
+ log_debug("%s: failed to get prf", __func__);
+ return (-1);
+ }
+ }
+
+ if (sa->sa_integr == NULL) {
+ if ((xform = config_findtransform(&sa->sa_proposals,
+ IKEV2_XFORMTYPE_INTEGR)) == NULL) {
+ log_debug("%s: did not find integr transform",
+ __func__);
+ return (-1);
+ }
+ if ((sa->sa_integr =
+ hash_new(xform->xform_type, xform->xform_id)) == NULL) {
+ log_debug("%s: failed to get integr", __func__);
+ return (-1);
+ }
+ }
+
+ ibuf_release(sa->sa_2ndmsg);
+ if ((sa->sa_2ndmsg = ibuf_dup(msg->msg_data)) == NULL) {
+ log_debug("%s: failed to copy 2nd message", __func__);
+ return (-1);
+ }
+
+ return (ikev2_sa_keys(env, sa));
}
int
@@ -2181,6 +2440,9 @@ ikev2_sa_responder(struct iked *env, struct iked_sa *sa,
}
}
+ /* Set a pointer to the peer exchange */
+ sa->sa_dhpeer = sa->sa_dhiexchange;
+
return (ikev2_sa_keys(env, sa));
}
@@ -2247,11 +2509,11 @@ ikev2_sa_keys(struct iked *env, struct iked_sa *sa)
goto done;
}
if (dh_create_shared(group, dhsecret->buf,
- sa->sa_dhiexchange->buf) == -1) {
+ sa->sa_dhpeer->buf) == -1) {
log_debug("%s: failed to get dh secret"
" group %d len %d secret %d exchange %d", __func__,
group->id, dh_getlen(group), ibuf_length(dhsecret),
- ibuf_length(sa->sa_dhiexchange));
+ ibuf_length(sa->sa_dhpeer));
goto done;
}
@@ -2538,8 +2800,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
peerid = &sa->sa_rid;
localid = &sa->sa_iid;
} else {
- localid = &sa->sa_rid;
peerid = &sa->sa_iid;
+ localid = &sa->sa_rid;
}
if (ikev2_sa_tag(sa, peerid) == -1)
@@ -2690,23 +2952,27 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
csa->csa_ikesa = sa;
csa->csa_srcid = localid;
csa->csa_dstid = peerid;
- csa->csa_peerspi = prop->prop_peerspi.spi;
+
if (sa->sa_hdr.sh_initiator) {
/* Initiator -> Responder */
csa->csa_dir = IPSP_DIRECTION_OUT;
csa->csa_local = &sa->sa_local;
csa->csa_peer = &sa->sa_peer;
-
- if ((ret = pfkey_sa_init(env->sc_pfkey,
- csa, &spi)) != 0)
- goto done;
- csa->csa_spi.spi = prop->prop_localspi.spi = spi;
+ csa->csa_peerspi = spi = prop->prop_localspi.spi;
+ csa->csa_spi.spi = prop->prop_peerspi.spi;
} else {
/* Responder <- Initiator */
csa->csa_dir = IPSP_DIRECTION_IN;
- csa->csa_spi.spi = prop->prop_peerspi.spi;
csa->csa_local = &sa->sa_peer;
csa->csa_peer = &sa->sa_local;
+
+ if ((ret = pfkey_sa_init(env->sc_pfkey,
+ csa, &spi)) != 0)
+ goto done;
+
+ csa->csa_peerspi = prop->prop_peerspi.spi;
+ csa->csa_spi.spi = prop->prop_localspi.spi = spi;
+ csa->csa_allocated = 1;
}
if ((csa->csa_encrkey = ibuf_copy(keymat,
@@ -2728,14 +2994,11 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
}
memcpy(csb, csa, sizeof(*csb));
+ csb->csa_spi.spi = csa->csa_peerspi;
+ csb->csa_peerspi = csa->csa_spi.spi;
+ csb->csa_allocated = csa->csa_allocated ? 0 : 1;
csb->csa_dir = csa->csa_dir == IPSP_DIRECTION_IN ?
IPSP_DIRECTION_OUT : IPSP_DIRECTION_IN;
- if (spi == 0) {
- if ((ret = pfkey_sa_init(env->sc_pfkey,
- csa, &spi)) != 0)
- goto done;
- csa->csa_spi.spi = prop->prop_localspi.spi = spi;
- }
csb->csa_local = csa->csa_peer;
csb->csa_peer = csa->csa_local;
diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c
index 11a22fe7d31..446d8a399a1 100644
--- a/sbin/iked/ikev2_msg.c
+++ b/sbin/iked/ikev2_msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2_msg.c,v 1.4 2010/06/14 11:33:55 reyk Exp $ */
+/* $OpenBSD: ikev2_msg.c,v 1.5 2010/06/14 21:12:56 reyk Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -211,18 +211,19 @@ ikev2_msg_valid_ike_sa(struct iked *env, struct ike_header *oldhdr,
int
ikev2_msg_send(struct iked *env, int fd, struct iked_message *msg)
{
- struct ibuf *buf = msg->msg_data;
- u_int32_t natt = 0x00000000;
+ struct ibuf *buf = msg->msg_data;
+ u_int32_t natt = 0x00000000;
struct ike_header *hdr;
if (buf == NULL || (hdr = ibuf_seek(msg->msg_data,
msg->msg_offset, sizeof(*hdr))) == NULL)
return (-1);
- log_info("%s: %s to %s from %s", __func__,
+ log_info("%s: %s from %s to %s, %ld bytes", __func__,
print_map(hdr->ike_exchange, ikev2_exchange_map),
+ print_host(&msg->msg_local, NULL, 0),
print_host(&msg->msg_peer, NULL, 0),
- print_host(&msg->msg_local, NULL, 0));
+ ibuf_length(buf));
if (msg->msg_natt || (msg->msg_sa && msg->msg_sa->sa_natt)) {
if (ibuf_prepend(buf, &natt, sizeof(natt)) == -1) {
@@ -565,9 +566,7 @@ ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa,
resp.msg_sa = sa;
TAILQ_INIT(&resp.msg_proposals);
- sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
(void)ikev2_pld_parse(env, hdr, &resp, 0);
- sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
ret = ikev2_msg_send(env, sa->sa_fd, &resp);
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index d021c038ea4..e40597be833 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2_pld.c,v 1.5 2010/06/14 14:03:15 reyk Exp $ */
+/* $OpenBSD: ikev2_pld.c,v 1.6 2010/06/14 21:12:56 reyk Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -972,6 +972,7 @@ int
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
struct iked_message *msg, off_t offset)
{
+ struct iked_sa *sa = msg->msg_sa;
struct ibuf *e = NULL;
u_int8_t *msgbuf = ibuf_data(msg->msg_data);
struct iked_message emsg;
@@ -985,8 +986,15 @@ ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
if ((e = ibuf_new(buf, len)) == NULL)
goto done;
- if ((e = ikev2_msg_decrypt(env, msg->msg_sa,
- msg->msg_data, e)) == NULL)
+ if (ikev2_msg_frompeer(msg)) {
+ e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
+ } else {
+ sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
+ e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
+ sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
+ }
+
+ if (e == NULL)
goto done;
/*
diff --git a/sbin/iked/pfkey.c b/sbin/iked/pfkey.c
index 1407222098e..bcdd3636a9e 100644
--- a/sbin/iked/pfkey.c
+++ b/sbin/iked/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.4 2010/06/10 14:08:37 reyk Exp $ */
+/* $OpenBSD: pfkey.c,v 1.5 2010/06/14 21:12:56 reyk Exp $ */
/* $vantronix: pfkey.c,v 1.11 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -980,7 +980,7 @@ pfkey_sa_add(int fd, struct iked_childsa *sa, struct iked_childsa *last)
if (pfkey_map(pfkey_satype, sa->csa_saproto, &satype) == -1)
return (-1);
- if (sa->csa_dir == IPSP_DIRECTION_IN || sa->csa_loaded)
+ if (sa->csa_allocated || sa->csa_loaded)
cmd = SADB_UPDATE;
else
cmd = SADB_ADD;
diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c
index 1bec78a9b5e..2833a8616cd 100644
--- a/sbin/iked/policy.c
+++ b/sbin/iked/policy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: policy.c,v 1.6 2010/06/14 12:06:33 reyk Exp $ */
+/* $OpenBSD: policy.c,v 1.7 2010/06/14 21:12:56 reyk Exp $ */
/* $vantronix: policy.c,v 1.29 2010/05/28 15:34:35 reyk Exp $ */
/*
@@ -188,25 +188,26 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi,
else
pol = sa->sa_policy;
- if (initiator) {
+ sa->sa_staterequire = IKED_REQ_AUTH|IKED_REQ_SA;
+ if (pol != NULL && pol->pol_auth.auth_eap) {
+ sa->sa_staterequire |= IKED_REQ_CERT;
+ } else if (pol != NULL && pol->pol_auth.auth_method !=
+ IKEV2_AUTH_SHARED_KEY_MIC) {
+ sa->sa_staterequire |= IKED_REQ_VALID|IKED_REQ_CERT;
+ }
+
+ if (sa->sa_hdr.sh_ispi == 0)
+ sa->sa_hdr.sh_ispi = ispi;
+ if (sa->sa_hdr.sh_rspi == 0)
+ sa->sa_hdr.sh_rspi = rspi;
+
+ if (initiator)
localid = &sa->sa_iid;
- } else {
+ else
localid = &sa->sa_rid;
- sa->sa_staterequire = IKED_REQ_AUTH|IKED_REQ_SA;
- if (pol != NULL && pol->pol_auth.auth_eap) {
- sa->sa_staterequire |= IKED_REQ_CERT;
- } else if (pol != NULL && pol->pol_auth.auth_method !=
- IKEV2_AUTH_SHARED_KEY_MIC) {
- sa->sa_staterequire |= IKED_REQ_VALID|IKED_REQ_CERT;
- }
- if (sa->sa_hdr.sh_ispi == 0)
- sa->sa_hdr.sh_ispi = ispi;
- if (sa->sa_hdr.sh_rspi == 0)
- sa->sa_hdr.sh_rspi = rspi;
- }
-
- if (ikev2_policy2id(&pol->pol_localid, localid, 1) != 0) {
+ if (!ibuf_length(localid->id_buf) &&
+ ikev2_policy2id(&pol->pol_localid, localid, 1) != 0) {
log_debug("%s: failed to get local id", __func__);
sa_free(env, sa);
return (NULL);