diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-06-14 21:12:57 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-06-14 21:12:57 +0000 |
commit | 86b6e87721275c7172d5d598edf873f5d845d237 (patch) | |
tree | aa5e8a3b5892816ca45edf0b308a6a35e7db66cc /sbin/iked | |
parent | 504cdf8986e42ed00a3b9ce7ed9b0504ff4fa4d2 (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.h | 10 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 347 | ||||
-rw-r--r-- | sbin/iked/ikev2_msg.c | 13 | ||||
-rw-r--r-- | sbin/iked/ikev2_pld.c | 14 | ||||
-rw-r--r-- | sbin/iked/pfkey.c | 4 | ||||
-rw-r--r-- | sbin/iked/policy.c | 35 |
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); |