diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-06-14 08:10:33 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-06-14 08:10:33 +0000 |
commit | e834fcd4ecac4135ad6e8ed7ea7be646efaea5cd (patch) | |
tree | b1e904ba3cd6d6a0811d72756affe0b53d9562fb /sbin/iked | |
parent | e1944808d62d45bb05963968faa0fde7ab36feed (diff) |
More code for initiator mode (not finished yet)
Diffstat (limited to 'sbin/iked')
-rw-r--r-- | sbin/iked/config.c | 19 | ||||
-rw-r--r-- | sbin/iked/iked.h | 14 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 204 | ||||
-rw-r--r-- | sbin/iked/ikev2_msg.c | 36 | ||||
-rw-r--r-- | sbin/iked/ikev2_pld.c | 49 | ||||
-rw-r--r-- | sbin/iked/policy.c | 43 | ||||
-rw-r--r-- | sbin/iked/timer.c | 12 |
7 files changed, 313 insertions, 64 deletions
diff --git a/sbin/iked/config.c b/sbin/iked/config.c index 89003de41f0..beb00fcdbd7 100644 --- a/sbin/iked/config.c +++ b/sbin/iked/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.3 2010/06/10 14:08:37 reyk Exp $ */ +/* $OpenBSD: config.c,v 1.4 2010/06/14 08:10:32 reyk Exp $ */ /* $vantronix: config.c,v 1.30 2010/05/28 15:34:35 reyk Exp $ */ /* @@ -57,6 +57,7 @@ config_new_sa(struct iked *env, int initiator) TAILQ_INIT(&sa->sa_childsas); TAILQ_INIT(&sa->sa_flows); sa->sa_hdr.sh_initiator = initiator; + sa->sa_type = IKED_SATYPE_LOCAL; if (initiator) sa->sa_hdr.sh_ispi = config_getspi(); @@ -504,7 +505,7 @@ int config_getsocket(struct iked *env, struct imsg *imsg, void (*cb)(int, short, void *)) { - struct iked_socket *sock; + struct iked_socket *sock, **sptr; log_debug("%s: received socket fd %d", __func__, imsg->fd); @@ -517,6 +518,20 @@ config_getsocket(struct iked *env, struct imsg *imsg, sock->sock_fd = imsg->fd; sock->sock_env = env; + switch (sock->sock_addr.ss_family) { + case AF_INET: + sptr = &env->sc_sock4; + break; + case AF_INET6: + sptr = &env->sc_sock6; + break; + default: + fatal("config_getsocket: socket af"); + /* NOTREACHED */ + } + if (*sptr == NULL) + *sptr = sock; + event_set(&sock->sock_ev, sock->sock_fd, EV_READ|EV_PERSIST, cb, sock); event_add(&sock->sock_ev, NULL); diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index edbd6b0d17a..bc001a35d0e 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.5 2010/06/11 12:47:18 reyk Exp $ */ +/* $OpenBSD: iked.h,v 1.6 2010/06/14 08:10:32 reyk Exp $ */ /* $vantronix: iked.h,v 1.61 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -292,6 +292,10 @@ struct iked_sa { struct iked_sahdr sa_hdr; u_int32_t sa_msgid; + int sa_type; +#define IKED_SATYPE_LOOKUP 0 /* Used for lookup */ +#define IKED_SATYPE_LOCAL 1 /* Local SA */ + struct iked_addr sa_peer; struct iked_addr sa_local; int sa_fd; @@ -418,6 +422,9 @@ struct iked { u_int8_t sc_certreqtype; struct ibuf *sc_certreq; + struct iked_socket *sc_sock4; + struct iked_socket *sc_sock6; + struct control_sock sc_csock; /* Event and signal handlers */ @@ -617,6 +624,9 @@ struct ibuf * ikev2_msg_decrypt(struct iked *, struct iked_sa *, struct ibuf *, struct ibuf *); int ikev2_msg_integr(struct iked *, struct iked_sa *, struct ibuf *); +int ikev2_msg_frompeer(struct iked_message *); +struct iked_socket * + ikev2_msg_getsocket(struct iked *, int); /* ikev2_pld.c */ int ikev2_pld_parse(struct iked *, struct ike_header *, @@ -651,7 +661,7 @@ char *ca_x509_name(void *); /* timer.c */ void timer_register_initiator(struct iked *, - void (*)(struct iked *, struct iked_policy *)); + int (*)(struct iked *, struct iked_policy *)); void timer_unregister_initiator(struct iked *); /* proc.c */ diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index e7c5adfd4df..ef6291e2083 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.6 2010/06/11 12:47:18 reyk Exp $ */ +/* $OpenBSD: ikev2.c,v 1.7 2010/06/14 08:10:32 reyk Exp $ */ /* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -57,7 +57,8 @@ struct iked_sa * void ikev2_cb(int, short, void *); void ikev2_recv(struct iked *, struct iked_message *); -void ikev2_initiator(struct iked *, struct iked_policy *); + +int ikev2_init_ike_sa(struct iked *, struct iked_policy *); int ikev2_resp_ike_sa_init(struct iked *, struct iked_message *); int ikev2_resp_ike_auth(struct iked *, struct iked_sa *); @@ -65,6 +66,7 @@ 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_tag(struct iked_sa *, struct iked_id *); int ikev2_childsa_negotiate(struct iked *, struct iked_sa *, @@ -111,7 +113,7 @@ ikev2_dispatch_parent(int fd, struct iked_proc *p, struct imsg *imsg) if (env->sc_passive) timer_unregister_initiator(env); else - timer_register_initiator(env, ikev2_initiator); + timer_register_initiator(env, ikev2_init_ike_sa); return (0); case IMSG_UDP_SOCKET: return (config_getsocket(env, imsg, ikev2_msg_cb)); @@ -405,7 +407,7 @@ ikev2_recv(struct iked *env, struct iked_message *msg) return; } - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return; switch (hdr->ike_exchange) { @@ -419,6 +421,12 @@ ikev2_recv(struct iked *env, struct iked_message *msg) 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__); @@ -431,6 +439,7 @@ ikev2_recv(struct iked *env, struct iked_message *msg) return; } + if (ikev2_policy2id(&msg->msg_policy->pol_localid, &sa->sa_rid, 1) != 0) { log_debug("%s: failed to get responder id", __func__); @@ -471,11 +480,144 @@ ikev2_recv(struct iked *env, struct iked_message *msg) sa_free(env, msg->msg_sa); } -void -ikev2_initiator(struct iked *env, struct iked_policy *pol) +int +ikev2_init_ike_sa(struct iked *env, struct iked_policy *pol) { - /* XXX */ - log_debug("%s: not implemented", __func__); + struct iked_message req; + struct ike_header *hdr; + struct ikev2_payload *pld; + struct ikev2_keyexchange *ke; + struct ikev2_notify *n; + struct iked_sa *sa; + struct ibuf *buf; + struct group *group; + u_int8_t *ptr; + ssize_t len; + int ret = -1; + struct iked_socket *sock; + in_port_t port; + + if ((sock = ikev2_msg_getsocket(env, + pol->pol_peer.ss_family)) == NULL) + return (-1); + + /* Create a new initiator SA */ + if ((sa = sa_new(env, 0, 0, 1, pol)) == NULL) + return (-1); + + if (ikev2_sa_initiator(sa) == -1) + goto done; + + if ((buf = ikev2_msg_init(env, &req, + &pol->pol_peer, pol->pol_peer.ss_len, + &pol->pol_local, pol->pol_local.ss_len, 0)) == NULL) + goto done; + + /* Inherit the port from the 1st send socket */ + port = htons(socket_getport(&sock->sock_addr)); + (void)socket_af((struct sockaddr *)&req.msg_local, port); + (void)socket_af((struct sockaddr *)&req.msg_peer, port); + + req.msg_fd = sock->sock_fd; + req.msg_sa = sa; + + /* IKE header */ + if ((hdr = ikev2_add_header(buf, sa, 0, + IKEV2_PAYLOAD_SA, IKEV2_EXCHANGE_IKE_SA_INIT, + IKEV2_FLAG_INITIATOR)) == NULL) + goto done; + + /* SA payload */ + if ((pld = ikev2_add_payload(buf)) == NULL) + goto done; + if ((len = ikev2_add_proposals(buf, &pol->pol_proposals, + IKEV2_SAPROTO_IKE)) == -1) + goto done; + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE) == -1) + goto done; + + /* KE payload */ + if ((pld = ikev2_add_payload(buf)) == NULL) + goto done; + if ((ke = ibuf_advance(buf, sizeof(*ke))) == NULL) + goto done; + if ((group = sa->sa_dhgroup) == NULL) { + log_debug("%s: invalid dh", __func__); + goto done; + } + ke->kex_dhgroup = htobe16(group->id); + if (ikev2_add_buf(buf, sa->sa_dhiexchange) == -1) + goto done; + len = sizeof(*ke) + dh_getlen(group); + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE) == -1) + goto done; + + /* NONCE payload */ + if ((pld = ikev2_add_payload(buf)) == NULL) + goto done; + if (ikev2_add_buf(buf, sa->sa_inonce) == -1) + goto done; + len = ibuf_size(sa->sa_inonce); + + if ((env->sc_opts & IKED_OPT_NONATT) == 0) { + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NOTIFY) == -1) + goto done; + + /* NAT-T notify payloads */ + if ((pld = ikev2_add_payload(buf)) == NULL) + goto done; + if ((n = ibuf_advance(buf, sizeof(*n))) == NULL) + goto done; + n->n_type = htobe16(IKEV2_N_NAT_DETECTION_SOURCE_IP); + len = ikev2_nat_detection(&req, NULL, 0, 0, 0); + if ((ptr = ibuf_advance(buf, len)) == NULL) + goto done; + if ((len = ikev2_nat_detection(&req, ptr, len, + betoh16(n->n_type), 0)) == -1) + goto done; + len += sizeof(*n); + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NOTIFY) == -1) + goto done; + + if ((pld = ikev2_add_payload(buf)) == NULL) + goto done; + if ((n = ibuf_advance(buf, sizeof(*n))) == NULL) + goto done; + n->n_type = htobe16(IKEV2_N_NAT_DETECTION_DESTINATION_IP); + len = ikev2_nat_detection(&req, NULL, 0, 0, 0); + if ((ptr = ibuf_advance(buf, len)) == NULL) + goto done; + if ((len = ikev2_nat_detection(&req, ptr, len, + betoh16(n->n_type), 0)) == -1) + goto done; + len += sizeof(*n); + } + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE) == -1) + goto done; + + if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) + goto done; + + (void)ikev2_pld_parse(env, hdr, &req, 0); + + ibuf_release(sa->sa_1stmsg); + if ((sa->sa_1stmsg = ibuf_dup(buf)) == NULL) { + log_debug("%s: failed to copy 1st message", __func__); + goto done; + } + + ret = ikev2_msg_send(env, req.msg_fd, &req); + + done: + if (ret == -1) + sa_free(env, sa); + message_cleanup(env, &req); + + return (ret); } int @@ -1436,7 +1578,7 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg) struct iked_sa *sa = msg->msg_sa; struct iked_spi *rekey = &msg->msg_rekey; - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); log_debug("%s: rekey %s spi %s", __func__, @@ -1785,6 +1927,50 @@ ikev2_sa_negotiate(struct iked_sa *sa, struct iked_proposals *local, } int +ikev2_sa_initiator(struct iked_sa *sa) +{ + 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, + IKEV2_XFORMTYPE_DH)) == NULL) { + log_debug("%s: did not find dh transform", __func__); + return (-1); + } + if ((sa->sa_dhgroup = + group_get(xform->xform_id)) == NULL) { + log_debug("%s: invalid dh", __func__); + return (-1); + } + } + group = sa->sa_dhgroup; + + if (!ibuf_length(sa->sa_dhiexchange)) { + if ((sa->sa_dhiexchange = ibuf_new(NULL, + dh_getlen(group))) == NULL) { + log_debug("%s: failed to alloc dh exchange", __func__); + return (-1); + } + if (dh_create_exchange(group, 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) { + log_debug("%s: failed to get local nonce", __func__); + return (-1); + } + } + + return (0); +} + +int ikev2_sa_keys(struct iked_sa *sa) { struct iked_transform *xform; diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c index 85d82138539..115f2a459d2 100644 --- a/sbin/iked/ikev2_msg.c +++ b/sbin/iked/ikev2_msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_msg.c,v 1.1 2010/06/10 08:29:47 reyk Exp $ */ +/* $OpenBSD: ikev2_msg.c,v 1.2 2010/06/14 08:10:32 reyk Exp $ */ /* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -786,3 +786,37 @@ ikev2_msg_authsign(struct iked *env, struct iked_sa *sa, return (ret); } + +int +ikev2_msg_frompeer(struct iked_message *msg) +{ + struct iked_sa *sa = msg->msg_sa; + struct ike_header *hdr; + + if (sa == NULL || + (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL) + return (0); + + if (!sa->sa_hdr.sh_initiator && + (hdr->ike_flags & IKEV2_FLAG_INITIATOR)) + return (1); + else if (sa->sa_hdr.sh_initiator && + (hdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0) + return (1); + + return (0); +} + +struct iked_socket * +ikev2_msg_getsocket(struct iked *env, int af) +{ + switch (af) { + case AF_INET: + return (env->sc_sock4); + case AF_INET6: + return (env->sc_sock6); + } + + log_debug("%s: af socket %d not available", __func__, af); + return (NULL); +} diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index e75d81a6c91..07a241debfb 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.1 2010/06/10 08:29:47 reyk Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.2 2010/06/14 08:10:32 reyk Exp $ */ /* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */ /* @@ -199,7 +199,7 @@ ikev2_pld_payloads(struct iked *env, struct iked_message *msg, break; } - if (ret != 0 && !msg->msg_response) { + if (ret != 0 && ikev2_msg_frompeer(msg)) { (void)ikev2_send_informational(env, msg); return (-1); } @@ -259,7 +259,7 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize, sap.sap_transforms, print_spi(spi, sap.sap_spisize)); - if (!msg->msg_response) { + if (ikev2_msg_frompeer(msg)) { if ((msg->msg_prop = config_add_proposal(&msg->msg_proposals, sap.sap_proposalnr, sap.sap_protoid)) == NULL) { log_debug("%s: invalid proposal", __func__); @@ -278,7 +278,7 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, return (-1); } - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); /* XXX we need a better way to get this */ @@ -345,7 +345,7 @@ ikev2_pld_xform(struct iked *env, struct ikev2_sa_proposal *sap, ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm), betoh16(xfrm.xfrm_length) - sizeof(xfrm)); - if (!msg->msg_response) { + if (ikev2_msg_frompeer(msg)) { if (config_add_transform(msg->msg_prop, xfrm.xfrm_type, betoh16(xfrm.xfrm_id), msg->msg_attrlength, msg->msg_attrlength) == NULL) { @@ -422,7 +422,7 @@ ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld, print_hex(buf, 0, len); - if (!msg->msg_response) { + if (ikev2_msg_frompeer(msg)) { if ((msg->msg_sa->sa_dhiexchange = ibuf_new(buf, len)) == NULL) { log_debug("%s: failed to get exchange", __func__); @@ -465,7 +465,7 @@ ikev2_pld_id(struct iked *env, struct ikev2_payload *pld, log_debug("%s: id %s/%s length %d", __func__, print_map(id.id_type, ikev2_id_map), idstr, len); - if (msg->msg_response) { + if (!ikev2_msg_frompeer(msg)) { ibuf_release(idb.id_buf); return (0); } @@ -516,7 +516,7 @@ ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld, print_hex(buf, 0, len); - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); if (!sa->sa_hdr.sh_initiator && !msg->msg_response) { @@ -559,7 +559,7 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, __func__, print_map(cert.cert_type, ikev2_cert_map), len); print_hex(buf, 0, len); - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); if (!len || (len % SHA_DIGEST_LENGTH) != 0) { @@ -604,7 +604,7 @@ ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld, print_hex(buf, 0, len); - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); memcpy(&ikeauth, &policy->pol_auth, sizeof(ikeauth)); @@ -672,35 +672,26 @@ ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld, u_int8_t *buf; u_int8_t *msgbuf = ibuf_data(msg->msg_data); struct iked_sa *sa = msg->msg_sa; - struct ibuf *localnonce, *peernonce; + struct ibuf *peernonce; buf = msgbuf + offset; len = betoh16(pld->pld_length) - sizeof(*pld); print_hex(buf, 0, len); - if (!msg->msg_response) { + if (ikev2_msg_frompeer(msg)) { if ((peernonce = ibuf_new(buf, len)) == NULL) { log_debug("%s: failed to get peer nonce", __func__); return (-1); } - if ((localnonce = - ibuf_random(IKED_NONCE_SIZE)) == NULL) { - log_debug("%s: failed to get local nonce", __func__); - ibuf_release(peernonce); - return (-1); - } - - ibuf_release(sa->sa_inonce); - ibuf_release(sa->sa_rnonce); - log_debug("%s: updating nonces", __func__); + log_debug("%s: updating peer nonce", __func__); if (sa->sa_hdr.sh_initiator) { - sa->sa_inonce = localnonce; + ibuf_release(sa->sa_rnonce); sa->sa_rnonce = peernonce; } else { + ibuf_release(sa->sa_inonce); sa->sa_inonce = peernonce; - sa->sa_rnonce = localnonce; } } @@ -827,7 +818,7 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, case 8: break; default: - if (!msg->msg_response && + if (ikev2_msg_frompeer(msg) && del->del_protoid == IKEV2_SAPROTO_IKE) { sa_state(env, sa, IKEV2_STATE_DELETE); return (0); @@ -842,7 +833,7 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, return (-1); } - if (!msg->msg_response && + if (ikev2_msg_frompeer(msg) && (localspi = calloc(cnt, sizeof(u_int64_t))) == NULL) { log_warn("%s", __func__); return (-1); @@ -860,7 +851,7 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, spi = betoh64(spi64); break; } - if (msg->msg_response) { + if (!ikev2_msg_frompeer(msg)) { log_debug("%s: spi %s", __func__, print_spi(spi, sz)); continue; } @@ -872,7 +863,7 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, found++; } - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); if ((resp = ibuf_static()) == NULL) @@ -1066,7 +1057,7 @@ ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld, i += betoh16(cfg->cfg_length) + sizeof(*cfg); } - if (msg->msg_response) + if (!ikev2_msg_frompeer(msg)) return (0); if (sa) diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c index c0d80aefe57..a17ff2938ad 100644 --- a/sbin/iked/policy.c +++ b/sbin/iked/policy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: policy.c,v 1.3 2010/06/10 12:06:34 reyk Exp $ */ +/* $OpenBSD: policy.c,v 1.4 2010/06/14 08:10:32 reyk Exp $ */ /* $vantronix: policy.c,v 1.29 2010/05/28 15:34:35 reyk Exp $ */ /* @@ -173,7 +173,8 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi, { struct iked_sa *sa; - if ((sa = sa_lookup(env, ispi, rspi, initiator)) == NULL) { + if ((ispi == 0 && rspi == 0) || + (sa = sa_lookup(env, ispi, rspi, initiator)) == NULL) { /* Create new SA */ sa = config_new_sa(env, initiator); } @@ -181,20 +182,22 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi, log_debug("%s: failed to get sa", __func__); return (NULL); } - if (sa->sa_policy == NULL) { + if (sa->sa_policy == NULL) sa->sa_policy = policy; + + if (!initiator) { + sa->sa_staterequire = IKED_REQ_AUTH|IKED_REQ_SA; + if (policy != NULL && policy->pol_auth.auth_eap) { + sa->sa_staterequire |= IKED_REQ_CERT; + } else if (policy != NULL && policy->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; } - sa->sa_staterequire = IKED_REQ_AUTH|IKED_REQ_SA; - if (policy != NULL && policy->pol_auth.auth_eap) { - sa->sa_staterequire |= IKED_REQ_CERT; - } else if (policy != NULL && - policy->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; /* Re-insert node into the tree */ (void)RB_REMOVE(iked_sas, &env->sc_sas, sa); @@ -268,12 +271,19 @@ sa_lookup(struct iked *env, u_int64_t ispi, u_int64_t rspi, if ((sa = RB_FIND(iked_sas, &env->sc_sas, &key)) != NULL) gettimeofday(&sa->sa_timeused, NULL); + return (sa); } static __inline int sa_cmp(struct iked_sa *a, struct iked_sa *b) { + log_debug("%s: ispi %s rspi %s <-> ispi %s rspi %s", __func__, + print_spi(a->sa_hdr.sh_ispi, 8), + print_spi(a->sa_hdr.sh_rspi, 8), + print_spi(b->sa_hdr.sh_ispi, 8), + print_spi(b->sa_hdr.sh_rspi, 8)); + if (a->sa_hdr.sh_initiator != b->sa_hdr.sh_initiator) return (-2); @@ -282,8 +292,9 @@ sa_cmp(struct iked_sa *a, struct iked_sa *b) if (a->sa_hdr.sh_ispi < b->sa_hdr.sh_ispi) return (1); - /* Responder SPI is not yet set */ - if (a->sa_hdr.sh_rspi == 0) + /* Responder SPI is not yet set in the local IKE SADB */ + if ((b->sa_type == IKED_SATYPE_LOCAL && b->sa_hdr.sh_rspi == 0) || + (a->sa_type == IKED_SATYPE_LOCAL && a->sa_hdr.sh_rspi == 0)) return (0); if (a->sa_hdr.sh_rspi > b->sa_hdr.sh_rspi) diff --git a/sbin/iked/timer.c b/sbin/iked/timer.c index 44a5ce7a9ec..2664ed41251 100644 --- a/sbin/iked/timer.c +++ b/sbin/iked/timer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: timer.c,v 1.1 2010/06/11 12:47:18 reyk Exp $ */ +/* $OpenBSD: timer.c,v 1.2 2010/06/14 08:10:32 reyk Exp $ */ /* * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net> @@ -39,7 +39,7 @@ struct timer_cbarg { struct timeval tmr_first; struct timeval tmr_last; struct timeval tmr_tv; - void (*tmr_initcb)(struct iked *, struct iked_policy *); + int (*tmr_initcb)(struct iked *, struct iked_policy *); } timer_initiator; void timer_initiator_cb(int, short, void *); @@ -49,7 +49,7 @@ void timer_initiator_cb(int, short, void *); void timer_register_initiator(struct iked *env, - void (*cb)(struct iked *, struct iked_policy *)) + int (*cb)(struct iked *, struct iked_policy *)) { struct timer_cbarg *tmr; @@ -102,8 +102,10 @@ timer_initiator_cb(int fd, short event, void *arg) log_debug("%s: initiating \"%s\"", __func__, pol->pol_name); - if (tmr->tmr_initcb != NULL) - tmr->tmr_initcb(env, pol); + if (tmr->tmr_initcb != NULL) { + /* Ignore error but what should we do on failure? */ + (void)tmr->tmr_initcb(env, pol); + } } tmr->tmr_tv.tv_sec = IKED_TIMER_INITIATOR_INTERVAL; |