diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-06-14 11:33:56 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-06-14 11:33:56 +0000 |
commit | c85961103b5258cf63dabc3cc217afc966353660 (patch) | |
tree | ae5090f701eaac3ab381db288be7d4216ac43c16 | |
parent | 825ac1c1726f39a4efe4221044ae718b0b17d399 (diff) |
restructure code a bit to move closer to initiator mode:
- split responder/initiator- specific code into different functions and use
shared functions for common stuff.
- first parse the received message and store information in the temporary
message struct instead of modifying the ike sa in the parsing code directly.
-rw-r--r-- | sbin/iked/iked.h | 5 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 403 | ||||
-rw-r--r-- | sbin/iked/ikev2_msg.c | 5 | ||||
-rw-r--r-- | sbin/iked/ikev2_pld.c | 44 | ||||
-rw-r--r-- | sbin/iked/policy.c | 25 | ||||
-rw-r--r-- | sbin/iked/util.c | 4 |
6 files changed, 311 insertions, 175 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index 0a10a159270..19761e2b2a5 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.7 2010/06/14 08:55:59 reyk Exp $ */ +/* $OpenBSD: iked.h,v 1.8 2010/06/14 11:33:55 reyk Exp $ */ /* $vantronix: iked.h,v 1.61 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -380,6 +380,8 @@ struct iked_message { /* Parsed information */ struct iked_proposals msg_proposals; struct iked_spi msg_rekey; + struct ibuf *msg_nonce; /* dh NONCE */ + struct ibuf *msg_ke; /* dh key exchange */ /* Parse stack */ struct iked_proposal *msg_prop; @@ -579,6 +581,7 @@ pid_t ikev2(struct iked *, struct iked_proc *); void ikev2_recv(struct iked *, struct iked_message *); int ikev2_sa_negotiate(struct iked_sa *, struct iked_proposals *, struct iked_proposals *, u_int8_t); +int ikev2_policy2id(struct iked_static_id *, struct iked_id *, int); int ikev2_childsa_delete(struct iked *, struct iked_sa *, u_int8_t, u_int64_t, u_int64_t *, int); struct ibuf * diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index bd6ea7f612c..32fbb023a12 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.8 2010/06/14 08:55:59 reyk Exp $ */ +/* $OpenBSD: ikev2.c,v 1.9 2010/06/14 11:33:55 reyk Exp $ */ /* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -55,19 +55,24 @@ struct iked_sa * ikev2_getimsgdata(struct iked *, struct imsg *, struct iked_sahdr *, u_int8_t *, u_int8_t **, size_t *); -void ikev2_cb(int, short, void *); 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 *); +void ikev2_resp_recv(struct iked *, struct iked_message *, + struct ike_header *); int ikev2_resp_ike_sa_init(struct iked *, struct iked_message *); int ikev2_resp_ike_auth(struct iked *, struct iked_sa *); int ikev2_resp_ike_eap(struct iked *, struct iked_sa *, struct ibuf *); int ikev2_resp_create_child_sa(struct iked *, struct iked_message *); -int ikev2_policy2id(struct iked_static_id *, struct iked_id *, int); -int ikev2_sa_initiator(struct iked_sa *); -int ikev2_sa_keys(struct iked_sa *); +int ikev2_sa_initiator(struct iked *, struct iked_sa *, + struct iked_message *); +int ikev2_sa_responder(struct iked *, struct iked_sa *, + struct iked_message *); +int ikev2_sa_keys(struct iked *, struct iked_sa *); int ikev2_sa_tag(struct iked_sa *, struct iked_id *); int ikev2_childsa_negotiate(struct iked *, struct iked_sa *, struct iked_spi *); @@ -335,51 +340,15 @@ ikev2_recv(struct iked *env, struct iked_message *msg) if (policy_lookup(env, msg) != 0) return; - log_info("%s: %s from %s to %s policy '%s', %ld bytes", __func__, + log_info("%s: %s from %s %s to %s policy '%s', %ld bytes", __func__, print_map(hdr->ike_exchange, ikev2_exchange_map), + initiator ? "initiator" : "responder", print_host(&msg->msg_peer, NULL, 0), print_host(&msg->msg_local, NULL, 0), msg->msg_policy->pol_name, - ibuf_size(msg->msg_data)); - - switch (hdr->ike_exchange) { - case IKEV2_EXCHANGE_IKE_SA_INIT: - if (msg->msg_sa != NULL) { - log_debug("%s: SA already exists", __func__); - return; - } - if ((msg->msg_sa = sa_new(env, - betoh64(hdr->ike_ispi), betoh64(hdr->ike_rspi), - initiator, msg->msg_policy)) == NULL) { - log_debug("%s: failed to get new SA", __func__); - return; - } - break; - case IKEV2_EXCHANGE_IKE_AUTH: - if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) - return; - if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID)) { - log_debug("%s: already authenticated", __func__); - return; - } - break; - case IKEV2_EXCHANGE_CREATE_CHILD_SA: - if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) - return; - break; - case IKEV2_EXCHANGE_INFORMATIONAL: - if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) - return; - break; - default: - log_debug("%s: unsupported exchange: %s", __func__, - print_map(hdr->ike_exchange, ikev2_exchange_map)); - return; - } - - if (msg->msg_sa != NULL) { - sa = msg->msg_sa; + ibuf_length(msg->msg_data)); + if ((sa = msg->msg_sa) != NULL) { log_debug("%s: updating msg, natt %d", __func__, msg->msg_natt); if (msg->msg_natt) @@ -402,6 +371,39 @@ ikev2_recv(struct iked *env, struct iked_message *msg) print_host(&sa->sa_local.addr, NULL, 0)); } + if (initiator) + ikev2_init_recv(env, msg, hdr); + else + ikev2_resp_recv(env, msg, hdr); + + if (sa != NULL && sa->sa_state == IKEV2_STATE_DELETE) + sa_free(env, sa); +} + +void +ikev2_init_recv(struct iked *env, struct iked_message *msg, + struct ike_header *hdr) +{ + struct iked_sa *sa; + + if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) { + log_debug("%s: unknown SA", __func__); + return; + } + sa = msg->msg_sa; + + switch (hdr->ike_exchange) { + case IKEV2_EXCHANGE_IKE_SA_INIT: + case IKEV2_EXCHANGE_IKE_AUTH: + case IKEV2_EXCHANGE_CREATE_CHILD_SA: + case IKEV2_EXCHANGE_INFORMATIONAL: + break; + default: + log_debug("%s: unsupported exchange: %s", __func__, + print_map(hdr->ike_exchange, ikev2_exchange_map)); + return; + } + if (ikev2_pld_parse(env, hdr, msg, msg->msg_offset) != 0) { log_debug("%s: failed to parse message", __func__); return; @@ -412,72 +414,17 @@ ikev2_recv(struct iked *env, struct iked_message *msg) switch (hdr->ike_exchange) { case IKEV2_EXCHANGE_IKE_SA_INIT: - sa = msg->msg_sa; - - if (sa == NULL) { - log_debug("%s: invalid sa", __func__); - return; - } - - sa_state(env, sa, IKEV2_STATE_SA_INIT); - - if ((sa->sa_rnonce = - ibuf_random(IKED_NONCE_SIZE)) == NULL) { - log_debug("%s: failed to get local nonce", __func__); - sa_free(env, sa); - return; - } - if ((ibuf_length(sa->sa_inonce) < IKED_NONCE_MIN) || - (ibuf_length(sa->sa_rnonce) < IKED_NONCE_MIN)) { - log_debug("%s: invalid nonce", __func__); - sa_free(env, sa); - return; - } - if (ikev2_sa_keys(sa) != 0) { - log_debug("%s: failed to get IKE SA keys", __func__); - sa_free(env, sa); - return; - } - - - if (ikev2_policy2id(&msg->msg_policy->pol_localid, - &sa->sa_rid, 1) != 0) { - log_debug("%s: failed to get responder id", __func__); - return; - } - ibuf_release(sa->sa_1stmsg); - if ((sa->sa_1stmsg = ibuf_new(ibuf_data(msg->msg_data), - ibuf_size(msg->msg_data))) == NULL) { - log_debug("%s: failed to copy 1st message", __func__); - return; - } - - if (ikev2_resp_ike_sa_init(env, msg) != 0) { - log_debug("%s: failed to send init response", __func__); - return; - } - break; case IKEV2_EXCHANGE_IKE_AUTH: - sa = msg->msg_sa; - - if (!sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST) && - sa->sa_policy->pol_auth.auth_eap) - sa_state(env, sa, IKEV2_STATE_EAP); - - if (ikev2_resp_ike_auth(env, sa) != 0) { - log_debug("%s: failed to send auth response", __func__); - return; - } - break; case IKEV2_EXCHANGE_CREATE_CHILD_SA: - (void)ikev2_resp_create_child_sa(env, msg); + log_debug("%s: exchange %s not implemented", __func__, + print_map(hdr->ike_exchange, ikev2_exchange_map)); break; default: break; } - if (msg->msg_sa && msg->msg_sa->sa_state == IKEV2_STATE_DELETE) - sa_free(env, msg->msg_sa); + if (sa->sa_state == IKEV2_STATE_DELETE) + sa_free(env, sa); } int @@ -505,7 +452,7 @@ ikev2_init_ike_sa(struct iked *env, struct iked_policy *pol) if ((sa = sa_new(env, 0, 0, 1, pol)) == NULL) return (-1); - if (ikev2_sa_initiator(sa) == -1) + if (ikev2_sa_initiator(env, sa, NULL) == -1) goto done; if ((buf = ikev2_msg_init(env, &req, @@ -1166,6 +1113,104 @@ ikev2_add_buf(struct ibuf *buf, struct ibuf *data) return (0); } +void +ikev2_resp_recv(struct iked *env, struct iked_message *msg, + struct ike_header *hdr) +{ + struct iked_sa *sa; + + switch (hdr->ike_exchange) { + case IKEV2_EXCHANGE_IKE_SA_INIT: + if (msg->msg_sa != NULL) { + log_debug("%s: SA already exists", __func__); + return; + } + if ((msg->msg_sa = sa_new(env, + betoh64(hdr->ike_ispi), betoh64(hdr->ike_rspi), + 0, msg->msg_policy)) == NULL) { + log_debug("%s: failed to get new SA", __func__); + return; + } + break; + case IKEV2_EXCHANGE_IKE_AUTH: + if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) + return; + if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID)) { + log_debug("%s: already authenticated", __func__); + return; + } + break; + case IKEV2_EXCHANGE_CREATE_CHILD_SA: + if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) + return; + break; + case IKEV2_EXCHANGE_INFORMATIONAL: + if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) + return; + break; + default: + log_debug("%s: unsupported exchange: %s", __func__, + print_map(hdr->ike_exchange, ikev2_exchange_map)); + return; + } + + if (ikev2_pld_parse(env, hdr, msg, msg->msg_offset) != 0) { + log_debug("%s: failed to parse message", __func__); + return; + } + + if (!ikev2_msg_frompeer(msg)) + return; + + if ((sa = msg->msg_sa) == NULL) + return; + + switch (hdr->ike_exchange) { + case IKEV2_EXCHANGE_IKE_SA_INIT: + if (ikev2_sa_responder(env, sa, msg) != 0) { + log_debug("%s: failed to get IKE SA keys", __func__); + sa_state(env, sa, IKEV2_STATE_DELETE); + return; + } + if (ikev2_resp_ike_sa_init(env, msg) != 0) { + log_debug("%s: failed to send init response", __func__); + return; + } + break; + case IKEV2_EXCHANGE_IKE_AUTH: + if (!sa_stateok(sa, IKEV2_STATE_SA_INIT)) { + log_debug("%s: state mismatch", __func__); + sa_state(env, sa, IKEV2_STATE_DELETE); + return; + } + + 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; + } else + sa_stateflags(sa, IKED_REQ_SA); + + if (!sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST) && + sa->sa_policy->pol_auth.auth_eap) + sa_state(env, sa, IKEV2_STATE_EAP); + + if (ikev2_resp_ike_auth(env, sa) != 0) { + log_debug("%s: failed to send auth response", __func__); + return; + } + break; + case IKEV2_EXCHANGE_CREATE_CHILD_SA: + (void)ikev2_resp_create_child_sa(env, msg); + break; + default: + break; + } +} + int ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg) { @@ -1182,6 +1227,11 @@ ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg) ssize_t len; int ret = -1; + if (sa->sa_hdr.sh_initiator) { + log_debug("%s: called by initiator", __func__); + return (-1); + } + if ((buf = ikev2_msg_init(env, &resp, &msg->msg_peer, msg->msg_peerlen, &msg->msg_local, msg->msg_locallen, 1)) == NULL) @@ -1805,6 +1855,12 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local, bzero(chosen, sizeof(chosen)); bzero(&values, sizeof(values)); + if (TAILQ_EMPTY(peer)) { + log_debug("%s: peer did not send %s proposals", __func__, + print_map(protoid, ikev2_saproto_map)); + return (-1); + } + TAILQ_FOREACH(plocal, local, prop_entry) { if (plocal->prop_protoid != protoid) continue; @@ -1927,11 +1983,11 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local, } int -ikev2_sa_initiator(struct iked_sa *sa) +ikev2_sa_initiator(struct iked *env, struct iked_sa *sa, + struct iked_message *msg) { struct iked_policy *pol = sa->sa_policy; struct iked_transform *xform; - struct group *group; if (sa->sa_dhgroup == NULL) { if ((xform = config_findtransform(&pol->pol_proposals, @@ -1945,44 +2001,98 @@ ikev2_sa_initiator(struct iked_sa *sa) return (-1); } } - group = sa->sa_dhgroup; if (!ibuf_length(sa->sa_dhiexchange)) { if ((sa->sa_dhiexchange = ibuf_new(NULL, - dh_getlen(group))) == NULL) { + dh_getlen(sa->sa_dhgroup))) == NULL) { log_debug("%s: failed to alloc dh exchange", __func__); return (-1); } - if (dh_create_exchange(group, sa->sa_dhiexchange->buf) == -1) { + if (dh_create_exchange(sa->sa_dhgroup, + sa->sa_dhiexchange->buf) == -1) { log_debug("%s: failed to get dh exchange", __func__); return (-1); } } if (!ibuf_length(sa->sa_inonce)) { - if ((sa->sa_inonce = - ibuf_random(IKED_NONCE_SIZE)) == NULL) { + if ((sa->sa_inonce = ibuf_random(IKED_NONCE_SIZE)) == NULL) { log_debug("%s: failed to get local nonce", __func__); return (-1); } } + /* Initial message */ + if (msg == NULL) + return (0); + + if (!ibuf_length(sa->sa_rnonce)) { + if (!ibuf_length(msg->msg_nonce)) { + log_debug("%s: invalid peer nonce", __func__); + return (01); + } + if ((sa->sa_rnonce = ibuf_dup(msg->msg_nonce)) == NULL) { + log_debug("%s: failed to get peer nonce", __func__); + return (-1); + } + } + + if (!ibuf_length(sa->sa_dhrexchange)) { + if (!ibuf_length(msg->msg_ke)) { + log_debug("%s: invalid peer dh exchange", __func__); + return (01); + } + if ((ssize_t)ibuf_length(msg->msg_ke) != + dh_getlen(sa->sa_dhgroup)) { + log_debug("%s: invalid dh length, size %d", __func__, + dh_getlen(sa->sa_dhgroup) * 8); + return (-1); + } + if ((sa->sa_dhrexchange = ibuf_dup(msg->msg_ke)) == NULL) { + log_debug("%s: failed to copy dh exchange", __func__); + return (-1); + } + } + return (0); } int -ikev2_sa_keys(struct iked_sa *sa) +ikev2_sa_responder(struct iked *env, struct iked_sa *sa, + struct iked_message *msg) { struct iked_transform *xform; - struct iked_hash *prf, *integr; - struct iked_cipher *encr; - struct group *group; - struct ibuf *ninr, *dhsecret, *skeyseed, *s, *t; - size_t nonceminlen, ilen, rlen, tmplen; - u_int64_t ispi, rspi; - int ret = -1; - ninr = dhsecret = skeyseed = s = t = NULL; + sa_state(env, sa, IKEV2_STATE_SA_INIT); + + ibuf_release(sa->sa_1stmsg); + if ((sa->sa_1stmsg = ibuf_dup(msg->msg_data)) == NULL) { + log_debug("%s: failed to copy 1st message", __func__); + return (-1); + } + + if (!ibuf_length(sa->sa_rnonce) && + (sa->sa_rnonce = ibuf_random(IKED_NONCE_SIZE)) == NULL) { + log_debug("%s: failed to get local nonce", __func__); + return (-1); + } + + if (!ibuf_length(sa->sa_inonce) && + ((ibuf_length(msg->msg_nonce) < IKED_NONCE_MIN) || + (sa->sa_inonce = ibuf_dup(msg->msg_nonce)) == NULL)) { + log_debug("%s: failed to get peer nonce", __func__); + return (-1); + } + + /* 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, @@ -1996,7 +2106,6 @@ ikev2_sa_keys(struct iked_sa *sa) return (-1); } } - encr = sa->sa_encr; if (sa->sa_prf == NULL) { if ((xform = config_findtransform(&sa->sa_proposals, @@ -2010,7 +2119,6 @@ ikev2_sa_keys(struct iked_sa *sa) return (-1); } } - prf = sa->sa_prf; if (sa->sa_integr == NULL) { if ((xform = config_findtransform(&sa->sa_proposals, @@ -2025,7 +2133,6 @@ ikev2_sa_keys(struct iked_sa *sa) return (-1); } } - integr = sa->sa_integr; if (sa->sa_dhgroup == NULL) { if ((xform = config_findtransform(&sa->sa_proposals, @@ -2038,28 +2145,56 @@ ikev2_sa_keys(struct iked_sa *sa) log_debug("%s: invalid dh", __func__); return (-1); } - if ((ssize_t)ibuf_length(sa->sa_dhiexchange) != - dh_getlen(sa->sa_dhgroup)) { - /* XXX send notification to peer */ - log_debug("%s: dh mismatch %d", __func__, - dh_getlen(sa->sa_dhgroup) * 8); - return (-1); - } } - group = sa->sa_dhgroup; if (!ibuf_length(sa->sa_dhrexchange)) { if ((sa->sa_dhrexchange = ibuf_new(NULL, - dh_getlen(group))) == NULL) { + dh_getlen(sa->sa_dhgroup))) == NULL) { log_debug("%s: failed to alloc dh exchange", __func__); return (-1); } - if (dh_create_exchange(group, sa->sa_dhrexchange->buf) == -1) { + if (dh_create_exchange(sa->sa_dhgroup, + sa->sa_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))) { + /* XXX send notification to peer */ + log_debug("%s: invalid dh, size %d", __func__, + dh_getlen(sa->sa_dhgroup) * 8); + return (-1); + } + } + + return (ikev2_sa_keys(env, sa)); +} + +int +ikev2_sa_keys(struct iked *env, struct iked_sa *sa) +{ + struct iked_hash *prf, *integr; + struct iked_cipher *encr; + struct group *group; + struct ibuf *ninr, *dhsecret, *skeyseed, *s, *t; + size_t nonceminlen, ilen, rlen, tmplen; + u_int64_t ispi, rspi; + int ret = -1; + + ninr = dhsecret = skeyseed = s = t = NULL; + + if ((encr = sa->sa_encr) == NULL || + (prf = sa->sa_prf) == NULL || + (integr = sa->sa_integr) == NULL || + (group = sa->sa_dhgroup) == NULL) { + log_debug("%s: failed to get key input data", __func__); + return (-1); + } + if (prf->hash_fixedkey) nonceminlen = prf->hash_fixedkey; else diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c index 34ff1f9153a..11a22fe7d31 100644 --- a/sbin/iked/ikev2_msg.c +++ b/sbin/iked/ikev2_msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_msg.c,v 1.3 2010/06/14 08:55:59 reyk Exp $ */ +/* $OpenBSD: ikev2_msg.c,v 1.4 2010/06/14 11:33:55 reyk Exp $ */ /* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -804,6 +804,9 @@ ikev2_msg_frompeer(struct iked_message *msg) struct iked_sa *sa = msg->msg_sa; struct ike_header *hdr; + if (msg->msg_decrypted) + msg = msg->msg_decrypted; + if (sa == NULL || (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL) return (0); diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index 07a241debfb..36bdf17df3d 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.2 2010/06/14 08:10:32 reyk Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.3 2010/06/14 11:33:55 reyk Exp $ */ /* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -228,7 +228,12 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, u_int32_t spi32; u_int64_t spi = 0, spi64; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - struct iked_sa *sa = msg->msg_sa; + struct iked_proposals *props; + + if (msg->msg_decrypted) + props = &msg->msg_decrypted->msg_proposals; + else + props = &msg->msg_proposals; memcpy(&sap, msgbuf + offset, sizeof(sap)); offset += sizeof(sap); @@ -260,7 +265,7 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, sap.sap_transforms, print_spi(spi, sap.sap_spisize)); if (ikev2_msg_frompeer(msg)) { - if ((msg->msg_prop = config_add_proposal(&msg->msg_proposals, + if ((msg->msg_prop = config_add_proposal(props, sap.sap_proposalnr, sap.sap_protoid)) == NULL) { log_debug("%s: invalid proposal", __func__); return (-1); @@ -278,20 +283,6 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, return (-1); } - if (!ikev2_msg_frompeer(msg)) - return (0); - - /* XXX we need a better way to get this */ - if (ikev2_sa_negotiate(sa, - &msg->msg_policy->pol_proposals, - &msg->msg_proposals, msg->msg_decrypted ? - IKEV2_SAPROTO_ESP : 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); - return (0); } @@ -423,8 +414,8 @@ ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld, print_hex(buf, 0, len); if (ikev2_msg_frompeer(msg)) { - if ((msg->msg_sa->sa_dhiexchange = - ibuf_new(buf, len)) == NULL) { + ibuf_release(msg->msg_ke); + if ((msg->msg_ke = ibuf_new(buf, len)) == NULL) { log_debug("%s: failed to get exchange", __func__); return (-1); } @@ -671,28 +662,17 @@ ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld, size_t len; u_int8_t *buf; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - struct iked_sa *sa = msg->msg_sa; - struct ibuf *peernonce; buf = msgbuf + offset; len = betoh16(pld->pld_length) - sizeof(*pld); print_hex(buf, 0, len); if (ikev2_msg_frompeer(msg)) { - if ((peernonce = ibuf_new(buf, len)) == NULL) { + ibuf_release(msg->msg_nonce); + if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) { log_debug("%s: failed to get peer nonce", __func__); return (-1); } - - log_debug("%s: updating peer nonce", __func__); - - if (sa->sa_hdr.sh_initiator) { - ibuf_release(sa->sa_rnonce); - sa->sa_rnonce = peernonce; - } else { - ibuf_release(sa->sa_inonce); - sa->sa_inonce = peernonce; - } } return (0); diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c index a17ff2938ad..6c5440e0521 100644 --- a/sbin/iked/policy.c +++ b/sbin/iked/policy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: policy.c,v 1.4 2010/06/14 08:10:32 reyk Exp $ */ +/* $OpenBSD: policy.c,v 1.5 2010/06/14 11:33:55 reyk Exp $ */ /* $vantronix: policy.c,v 1.29 2010/05/28 15:34:35 reyk Exp $ */ /* @@ -169,9 +169,10 @@ sa_stateok(struct iked_sa *sa, int state) struct iked_sa * sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi, - u_int initiator, struct iked_policy *policy) + u_int initiator, struct iked_policy *pol) { struct iked_sa *sa; + struct iked_id *localid; if ((ispi == 0 && rspi == 0) || (sa = sa_lookup(env, ispi, rspi, initiator)) == NULL) { @@ -183,13 +184,19 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi, return (NULL); } if (sa->sa_policy == NULL) - sa->sa_policy = policy; + sa->sa_policy = pol; + else + pol = sa->sa_policy; + + if (initiator) { + localid = &sa->sa_iid; + } else { + localid = &sa->sa_rid; - if (!initiator) { sa->sa_staterequire = IKED_REQ_AUTH|IKED_REQ_SA; - if (policy != NULL && policy->pol_auth.auth_eap) { + if (pol != NULL && pol->pol_auth.auth_eap) { sa->sa_staterequire |= IKED_REQ_CERT; - } else if (policy != NULL && policy->pol_auth.auth_method != + } else if (pol != NULL && pol->pol_auth.auth_method != IKEV2_AUTH_SHARED_KEY_MIC) { sa->sa_staterequire |= IKED_REQ_VALID|IKED_REQ_CERT; } @@ -199,6 +206,12 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi, sa->sa_hdr.sh_rspi = rspi; } + if (ikev2_policy2id(&pol->pol_localid, localid, 1) != 0) { + log_debug("%s: failed to get local id", __func__); + sa_free(env, sa); + return (NULL); + } + /* Re-insert node into the tree */ (void)RB_REMOVE(iked_sas, &env->sc_sas, sa); RB_INSERT(iked_sas, &env->sc_sas, sa); diff --git a/sbin/iked/util.c b/sbin/iked/util.c index cd54fea4abc..b5bf82ab79b 100644 --- a/sbin/iked/util.c +++ b/sbin/iked/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.3 2010/06/14 08:55:59 reyk Exp $ */ +/* $OpenBSD: util.c,v 1.4 2010/06/14 11:33:55 reyk Exp $ */ /* $vantronix: util.c,v 1.39 2010/06/02 12:22:58 reyk Exp $ */ /* @@ -891,6 +891,8 @@ ibuf_copy(struct ibuf *buf, size_t len) struct ibuf * ibuf_dup(struct ibuf *buf) { + if (buf == NULL) + return (NULL); return (ibuf_new(ibuf_data(buf), ibuf_size(buf))); } |