diff options
Diffstat (limited to 'sbin/isakmpd')
-rw-r--r-- | sbin/isakmpd/exchange.c | 23 | ||||
-rw-r--r-- | sbin/isakmpd/sa.h | 6 | ||||
-rw-r--r-- | sbin/isakmpd/transport.c | 19 | ||||
-rw-r--r-- | sbin/isakmpd/udp.c | 35 | ||||
-rw-r--r-- | sbin/isakmpd/udp_encap.c | 11 | ||||
-rw-r--r-- | sbin/isakmpd/virtual.c | 95 |
6 files changed, 109 insertions, 80 deletions
diff --git a/sbin/isakmpd/exchange.c b/sbin/isakmpd/exchange.c index 28f48df08e7..b5d232f9c95 100644 --- a/sbin/isakmpd/exchange.c +++ b/sbin/isakmpd/exchange.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exchange.c,v 1.98 2004/06/20 17:17:34 ho Exp $ */ +/* $OpenBSD: exchange.c,v 1.99 2004/06/21 13:09:00 ho Exp $ */ /* $EOM: exchange.c,v 1.143 2000/12/04 00:02:25 angelos Exp $ */ /* @@ -954,6 +954,12 @@ exchange_establish_p2(struct sa *isakmp_sa, u_int8_t type, char *name, memcpy(exchange->cookies, isakmp_sa->cookies, ISAKMP_HDR_COOKIES_LEN); getrandom(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); exchange->flags |= EXCHANGE_FLAG_ENCRYPT; +#if defined (USE_NAT_TRAVERSAL) + if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE) + exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; + if (isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE) + exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; +#endif exchange_enter(exchange); #ifdef USE_DEBUG exchange_dump("exchange_establish_p2", exchange); @@ -1141,6 +1147,12 @@ exchange_setup_p2(struct message *msg, u_int8_t doi) GET_ISAKMP_HDR_RCOOKIE(buf, exchange->cookies + ISAKMP_HDR_ICOOKIE_LEN); GET_ISAKMP_HDR_MESSAGE_ID(buf, exchange->message_id); +#if defined (USE_NAT_TRAVERSAL) + if (msg->isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE) + exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; + if (msg->isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE) + exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; +#endif exchange_enter(exchange); #ifdef USE_DEBUG exchange_dump("exchange_setup_p2", exchange); @@ -1468,12 +1480,19 @@ exchange_finalize(struct message *msg) else id_doi = "<no doi>"; - if (msg->isakmp_sa && msg->isakmp_sa->transport) + if (msg->isakmp_sa->transport) id_trp = msg->isakmp_sa->transport->vtbl->decode_ids(msg->isakmp_sa->transport); else id_trp = "<no transport>"; +#if defined (USE_NAT_TRAVERSAL) + if (exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE) + msg->isakmp_sa->flags |= SA_FLAG_NAT_T_ENABLE; + if (exchange->flags & EXCHANGE_FLAG_NAT_T_KEEPALIVE) + msg->isakmp_sa->flags |= SA_FLAG_NAT_T_KEEPALIVE; +#endif + LOG_DBG((LOG_EXCHANGE, 10, "exchange_finalize: phase 1 done: %s, %s", id_doi, id_trp)); diff --git a/sbin/isakmpd/sa.h b/sbin/isakmpd/sa.h index ee3efd00559..1457d0ecc88 100644 --- a/sbin/isakmpd/sa.h +++ b/sbin/isakmpd/sa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sa.h,v 1.38 2004/06/20 15:20:07 ho Exp $ */ +/* $OpenBSD: sa.h,v 1.39 2004/06/21 13:09:00 ho Exp $ */ /* $EOM: sa.h,v 1.58 2000/10/10 12:39:01 provos Exp $ */ /* @@ -236,6 +236,10 @@ struct sa { /* This SA flag indicates if we should do DPD with the phase 1 SA peer. */ #define SA_FLAG_DPD 0x80 +/* NAT-T encapsulation state. Kept in isakmp_sa for the new p2 exchange. */ +#define SA_FLAG_NAT_T_ENABLE 0x100 +#define SA_FLAG_NAT_T_KEEPALIVE 0x200 + extern void proto_free(struct proto * proto); extern int sa_add_transform(struct sa *, struct payload *, int, struct proto **); diff --git a/sbin/isakmpd/transport.c b/sbin/isakmpd/transport.c index 989d6a5ebaa..749468b01bb 100644 --- a/sbin/isakmpd/transport.c +++ b/sbin/isakmpd/transport.c @@ -1,4 +1,4 @@ -/* $OpenBSD: transport.c,v 1.27 2004/06/20 15:24:05 ho Exp $ */ +/* $OpenBSD: transport.c,v 1.28 2004/06/21 13:09:00 ho Exp $ */ /* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */ /* @@ -75,7 +75,8 @@ transport_init(void) void transport_setup(struct transport *t, int toplevel) { - LOG_DBG((LOG_TRANSPORT, 70, "transport_setup: adding %p", t)); + LOG_DBG((LOG_TRANSPORT, 70, "transport_setup: adding %p%s", t, + toplevel ? " (virtual)" : "")); if (toplevel == 0) LIST_INSERT_HEAD(&transport_list, t, link); else { @@ -199,7 +200,7 @@ transport_fd_set(fd_set * fds) for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) if (t->virtual->flags & TRANSPORT_LISTEN) { - n = t->virtual->vtbl->fd_set(t->virtual, fds, 1); + n = t->vtbl->fd_set(t, fds, 1); if (n > max) max = n; @@ -226,7 +227,7 @@ transport_pending_wfd_set(fd_set * fds) for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { if (TAILQ_FIRST(&t->virtual->sendq) || TAILQ_FIRST(&t->virtual->prio_sendq)) { - n = t->virtual->vtbl->fd_set(t->virtual, fds, 1); + n = t->vtbl->fd_set(t, fds, 1); LOG_DBG((LOG_TRANSPORT,95,"transport_pending_wfd_set: " "transport %p (virtual %p) fd %d pending", t, t->virtual, n)); @@ -248,9 +249,9 @@ transport_handle_messages(fd_set *fds) for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { if ((t->flags & TRANSPORT_LISTEN) && - (*t->virtual->vtbl->fd_isset)(t->virtual, fds)) { - (*t->virtual->vtbl->handle_message)(t->virtual); - (*t->virtual->vtbl->fd_set)(t->virtual, fds, 0); + (*t->vtbl->fd_isset)(t, fds)) { + (*t->virtual->vtbl->handle_message)(t); + (*t->vtbl->fd_set)(t, fds, 0); } } } @@ -285,9 +286,9 @@ transport_send_messages(fd_set * fds) for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { if ((TAILQ_FIRST(&t->virtual->sendq) || TAILQ_FIRST(&t->virtual->prio_sendq)) && - t->virtual->vtbl->fd_isset(t->virtual, fds)) { + t->vtbl->fd_isset(t, fds)) { /* Remove fd bit. */ - t->virtual->vtbl->fd_set(t->virtual, fds, 0); + t->vtbl->fd_set(t, fds, 0); /* Prefer a message from the prioritized sendq. */ if (TAILQ_FIRST(&t->virtual->prio_sendq)) { diff --git a/sbin/isakmpd/udp.c b/sbin/isakmpd/udp.c index cee6630c6b6..2f3c53fa20f 100644 --- a/sbin/isakmpd/udp.c +++ b/sbin/isakmpd/udp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp.c,v 1.75 2004/06/20 15:24:05 ho Exp $ */ +/* $OpenBSD: udp.c,v 1.76 2004/06/21 13:09:01 ho Exp $ */ /* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */ /* @@ -71,9 +71,11 @@ /* These are reused by udp_encap.c, thus not 'static' here. */ struct transport *udp_clone(struct transport *, struct sockaddr *); -void udp_get_dst(struct transport *, struct sockaddr **); -void udp_get_src(struct transport *, struct sockaddr **); -char *udp_decode_ids(struct transport *); +int udp_fd_set(struct transport *, fd_set *, int); +int udp_fd_isset(struct transport *, fd_set *); +void udp_get_dst(struct transport *, struct sockaddr **); +void udp_get_src(struct transport *, struct sockaddr **); +char *udp_decode_ids(struct transport *); static struct transport *udp_create(char *); static void udp_remove(struct transport *); @@ -91,8 +93,8 @@ static struct transport_vtbl udp_transport_vtbl = { 0, udp_remove, udp_report, - 0, - 0, + udp_fd_set, + udp_fd_isset, udp_handle_message, udp_send_message, udp_get_dst, @@ -477,6 +479,27 @@ udp_send_message(struct message *msg, struct transport *t) return 0; } +int +udp_fd_set(struct transport *t, fd_set *fds, int bit) +{ + struct udp_transport *u = (struct udp_transport *)t; + + if (bit) + FD_SET(u->s, fds); + else + FD_CLR(u->s, fds); + + return u->s + 1; +} + +int +udp_fd_isset(struct transport *t, fd_set *fds) +{ + struct udp_transport *u = (struct udp_transport *)t; + + return FD_ISSET(u->s, fds); +} + /* * Get transport T's peer address and stuff it into the sockaddr pointed * to by DST. diff --git a/sbin/isakmpd/udp_encap.c b/sbin/isakmpd/udp_encap.c index aa5ba003726..d6cebf473f5 100644 --- a/sbin/isakmpd/udp_encap.c +++ b/sbin/isakmpd/udp_encap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_encap.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */ +/* $OpenBSD: udp_encap.c,v 1.2 2004/06/21 13:09:01 ho Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -68,6 +68,8 @@ /* Reused, from udp.c */ struct transport *udp_clone (struct transport *, struct sockaddr *); +int udp_fd_set(struct transport *, fd_set *, int); +int udp_fd_isset(struct transport *, fd_set *); void udp_get_dst (struct transport *, struct sockaddr **); void udp_get_src (struct transport *, struct sockaddr **); char *udp_decode_ids (struct transport *); @@ -86,8 +88,8 @@ static struct transport_vtbl udp_encap_transport_vtbl = { 0, udp_encap_remove, udp_encap_report, - 0, - 0, + udp_fd_set, + udp_fd_isset, udp_encap_handle_message, udp_encap_send_message, udp_get_dst, @@ -435,8 +437,7 @@ udp_encap_send_message(struct message *msg, struct transport *t) } new_iov[0].iov_base = ▮ new_iov[0].iov_len = IPSEC_SPI_SIZE; - memcpy (new_iov + sizeof *new_iov, msg->iov, - msg->iovlen * sizeof *new_iov); + memcpy (new_iov + 1, msg->iov, msg->iovlen * sizeof *new_iov); /* * Sending on connected sockets requires that no destination address is diff --git a/sbin/isakmpd/virtual.c b/sbin/isakmpd/virtual.c index 5bcb2d76c06..00a44ad81fd 100644 --- a/sbin/isakmpd/virtual.c +++ b/sbin/isakmpd/virtual.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtual.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */ +/* $OpenBSD: virtual.c,v 1.2 2004/06/21 13:09:01 ho Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -60,8 +60,6 @@ static int virtual_bind_if(char *, struct sockaddr *, void *); static struct transport *virtual_clone(struct transport *, struct sockaddr *); static struct transport *virtual_create(char *); static char *virtual_decode_ids (struct transport *); -static int virtual_fd_set(struct transport *, fd_set *, int); -static int virtual_fd_isset(struct transport *, fd_set *); static void virtual_get_dst(struct transport *, struct sockaddr **); static struct msg_head *virtual_get_queue(struct message *); @@ -80,8 +78,8 @@ static struct transport_vtbl virtual_transport_vtbl = { virtual_reinit, virtual_remove, virtual_report, - virtual_fd_set, - virtual_fd_isset, + 0, + 0, virtual_handle_message, virtual_send_message, virtual_get_dst, @@ -249,6 +247,8 @@ virtual_bind(const struct sockaddr *addr) sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport); v->main = udp_bind((struct sockaddr *)&tmp_sa); + if (!v->main) + return 0; ((struct transport *)v->main)->virtual = (struct transport *)v; #if defined (USE_NAT_TRAVERSAL) @@ -269,6 +269,8 @@ virtual_bind(const struct sockaddr *addr) sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport); v->encap = udp_encap_bind((struct sockaddr *)&tmp_sa); + if (!v->encap) + return 0; ((struct transport *)v->encap)->virtual = (struct transport *)v; #endif v->encap_is_active = 0; @@ -493,25 +495,32 @@ virtual_clone(struct transport *vt, struct sockaddr *raddr) memcpy(v2, v, sizeof *v); - if (v->encap_is_active) { - v2->main = 0; - v2->encap = v->encap->vtbl->clone(v->encap, raddr); - v2->encap->virtual = (struct transport *)v2; - } else { + if (v->encap_is_active) + v2->main = 0; /* No need to clone this. */ + else { v2->main = v->main->vtbl->clone(v->main, raddr); v2->main->virtual = (struct transport *)v2; - v2->encap = 0; } - LOG_DBG((LOG_TRANSPORT, 50, "virtual_clone: old %p new %p (->%s %p)", - v, t, v->encap_is_active ? "encap" : "main", +#if defined (USE_NAT_TRAVERSAL) + /* XXX fix strtol() call */ + sockaddr_set_port(raddr, udp_encap_default_port ? + strtol(udp_encap_default_port, NULL, 10) : UDP_ENCAP_DEFAULT_PORT); + v2->encap = v->encap->vtbl->clone(v->encap, raddr); + v2->encap->virtual = (struct transport *)v2; +#endif + LOG_DBG((LOG_TRANSPORT, 50, "virtual_clone: old %p new %p (%s is %p)", + v, t, v->encap_is_active ? "encap" : "main", v->encap_is_active ? v2->encap : v2->main)); t->flags &= ~TRANSPORT_LISTEN; transport_setup(t, 1); transport_reference(t); - transport_reference(v->encap_is_active ? v2->encap : v2->main); - + if (v2->main) + transport_reference(v2->main); + if (v2->encap) + transport_reference(v2->encap); + return t; } @@ -583,9 +592,8 @@ virtual_report(struct transport *t) static void virtual_handle_message(struct transport *t) { - struct virtual_transport *v = (struct virtual_transport *)t; - - if (t == default_transport || t == default_transport6) { + if (t->virtual == default_transport || + t->virtual == default_transport6) { /* XXX drain pending message. See udp_handle_message(). */ virtual_reinit(); @@ -598,10 +606,7 @@ virtual_handle_message(struct transport *t) return; } - if (v->encap_is_active) - v->encap->vtbl->handle_message(v->encap); - else - v->main->vtbl->handle_message(v->main); + t->vtbl->handle_message(t); } static int @@ -616,10 +621,19 @@ virtual_send_message(struct message *msg, struct transport *t) "transport %p != NULL", t); #if defined (USE_NAT_TRAVERSAL) + /* + * Activate NAT-T Encapsulation if + * - the exchange says we can, and + * - in ID_PROT, after step 4 (draft-ietf-ipsec-nat-t-ike-03), or + * - in other exchange (Aggressive, ), asap + * XXX ISAKMP_EXCH_BASE etc? + */ if (v->encap_is_active == 0 && - (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE)) { + (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE) && + (msg->exchange->type != ISAKMP_EXCH_ID_PROT || + msg->exchange->step > 4)) { LOG_DBG((LOG_MESSAGE, 10, "virtual_send_message: " - "switching to ENCAP")); + "enabling NAT-T encapsulation for this exchange")); v->encap_is_active++; } #endif @@ -630,39 +644,6 @@ virtual_send_message(struct message *msg, struct transport *t) return v->main->vtbl->send_message(msg, v->main); } -static int -virtual_fd_set(struct transport *t, fd_set *fds, int bit) -{ - struct virtual_transport *v = (struct virtual_transport *)t; - struct udp_transport *u; - - if (v->encap_is_active) - u = (struct udp_transport *)v->encap; - else - u = (struct udp_transport *)v->main; - - if (bit) - FD_SET(u->s, fds); - else - FD_CLR(u->s, fds); - - return u->s + 1; -} - -static int -virtual_fd_isset(struct transport *t, fd_set *fds) -{ - struct virtual_transport *v = (struct virtual_transport *)t; - struct udp_transport *u; - - if (v->encap_is_active) - u = (struct udp_transport *)v->encap; - else - u = (struct udp_transport *)v->main; - - return FD_ISSET(u->s, fds); -} - static void virtual_get_src(struct transport *t, struct sockaddr **s) { |