diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2000-12-12 01:53:43 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2000-12-12 01:53:43 +0000 |
commit | 2de37717b27de8863c1253b2e873f79de9c7daea (patch) | |
tree | fd2f994acedddf86c10455cb43d12ae88233897e /sbin | |
parent | 15c0f0c58bc4162933d065d8f4849ca9a98c5d7e (diff) |
listen to pfkeyv2 acquire messages and set up SAs accordingly.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/photurisd/kernel.c | 208 | ||||
-rw-r--r-- | sbin/photurisd/kernel.h | 5 | ||||
-rw-r--r-- | sbin/photurisd/server.c | 8 |
3 files changed, 158 insertions, 63 deletions
diff --git a/sbin/photurisd/kernel.c b/sbin/photurisd/kernel.c index 75b513c980e..3741fb61a0e 100644 --- a/sbin/photurisd/kernel.c +++ b/sbin/photurisd/kernel.c @@ -39,7 +39,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: kernel.c,v 1.11 2000/12/11 21:37:46 provos Exp $"; +static char rcsid[] = "$Id: kernel.c,v 1.12 2000/12/12 01:53:41 provos Exp $"; #endif #include <time.h> @@ -242,6 +242,20 @@ kernel_set_socket_policy(int sd) log_fatal("setsockopt: can not bypass ipsec esp network policy"); } +struct sadb_ext * +pfkey_find_extension(struct sadb_ext *start, void *end, u_int16_t type) +{ + struct sadb_ext *p = start; + + while ((void *)p < end) { + if (p->sadb_ext_type == type) + return (p); + p = (struct sadb_ext *)((u_char *)p + p->sadb_ext_len * 8); + } + + return (NULL); +} + int kernel_xf_set(int sd, char *buffer, int blen, struct iovec *iov, int cnt, int len) @@ -1001,6 +1015,7 @@ void kernel_handle_notify(int sd) { struct sadb_msg *sres = (struct sadb_msg *)buffer; + size_t len; if (!kernel_xf_read(regsd, buffer, BUFFER_SIZE, 0)) return; @@ -1013,8 +1028,18 @@ kernel_handle_notify(int sd) log_print("PFKEYV2 SA Expiration - not yet supported."); return; case SADB_ACQUIRE: - LOG_DBG((LOG_KERNEL, 60, "Got Notify SA Request (SADB_ACQUIRE)")); - kernel_request_sa(sres); + LOG_DBG((LOG_KERNEL, 60, "Got Notify SA Request (SADB_ACQUIRE): %d", + sres->sadb_msg_len * 8)); + LOG_DBG_BUF((LOG_KERNEL, 60, "acquire buf", + (u_char *)sres, sres->sadb_msg_len * 8)); + + len = sres->sadb_msg_len * 8; + sres = malloc(len); + if (sres) { + memcpy(sres, buffer, len); + kernel_request_sa(sres); + free(sres); + } break; default: /* discard silently */ @@ -1022,67 +1047,136 @@ kernel_handle_notify(int sd) } } +struct sadb_msg * +pfkey_askpolicy(int seq) +{ + struct sadb_msg smsg; + struct sadb_policy policy; + struct iovec iov[2]; + int cnt = 0; + + bzero(&smsg, sizeof(smsg)); + + /* Ask the kernel for the matching policy */ + smsg.sadb_msg_len = sizeof(smsg) / 8; + smsg.sadb_msg_version = PF_KEY_V2; + smsg.sadb_msg_seq = pfkey_seq++; + smsg.sadb_msg_pid = pfkey_pid; + smsg.sadb_msg_type = SADB_X_ASKPOLICY; + iov[cnt].iov_base = &smsg; + iov[cnt++].iov_len = sizeof(smsg); + + memset(&policy, 0, sizeof(policy)); + policy.sadb_policy_exttype = SADB_X_EXT_POLICY; + policy.sadb_policy_len = sizeof(policy) / 8; + policy.sadb_policy_seq = seq; + iov[cnt].iov_base = &policy; + iov[cnt++].iov_len = sizeof(policy); + smsg.sadb_msg_len += sizeof(policy) / 8; + + if (!kernel_xf_set(regsd, buffer, BUFFER_SIZE, iov, cnt, + smsg.sadb_msg_len*8)) { + log_error(__FUNCTION__": kernel_xf_set"); + return (NULL); + } + + return ((struct sadb_msg *)buffer); +} + /* * Tries to establish a new SA according to the information in a * REQUEST_SA notify message received from the kernel. */ int -kernel_request_sa(void *em /*struct encap_msghdr *em*/) +kernel_request_sa(struct sadb_msg *sadb) { -/* struct stateob *st; - time_t tm; - char *address = inet_ntoa(em->em_not_dst); - - /#* Try to find an already established exchange which is still valid *#/ - st = state_find(address); - - tm = time(NULL); - while (st != NULL && (st->lifetime <= tm || st->phase >= SPI_UPDATE)) - st = state_find_next(st, address); - - if (st == NULL) { - /#* No established exchange found, start a new one *#/ - if ((st = state_new()) == NULL) { - log_print("state_new() failed in kernel_request_sa() for remote ip %s", - address); - return (-1); - } - /#* Set up the state information *#/ - strncpy(st->address, address, sizeof(st->address)-1); - st->port = global_port; - st->sport = em->em_not_sport; - st->dport = em->em_not_dport; - st->protocol = em->em_not_protocol; - - /#* - * For states which were created by kernel notifies we wont - * set up routes since other keying daemons might habe beaten - * us in establishing SAs. The kernel has to decide which SA - * will actually be routed. - *#/ - st->flags = IPSEC_NOTIFY; - if (em->em_not_satype & NOTIFY_SATYPE_CONF) - st->flags |= IPSEC_OPT_ENC; - if (em->em_not_satype & NOTIFY_SATYPE_AUTH) - st->flags |= IPSEC_OPT_AUTH; - /#* XXX - handling of tunnel requests missing *#/ - if (start_exchange(global_socket, st, st->address, st->port) == -1) { - log_print("start_exchange() in kernel_request_sa() - informing kernel of failure"); - /#* Inform kernel of our failure *#/ - kernel_notify_result(st, NULL, 0); - state_value_reset(st); - free(st); - return (-1); - } else - state_insert(st); - } else { - /#* - * We need different attributes for this exchange, send - * an SPI_NEEDED message. - *#/ - } -*/ + struct stateob *st; + time_t tm; + struct sadb_msg *res; + struct sadb_address *dst, *src; + struct sockaddr *dstaddr, *srcaddr; + struct sadb_ext *ext = (struct sadb_ext *)(sadb + 1); + char srcbuf[NI_MAXHOST], dstbuf[NI_MAXHOST]; + void *end; + + memset(srcbuf, 0, sizeof(srcbuf)); + memset(dstbuf, 0, sizeof(dstbuf)); + + end = (struct sadb_ext *)((u_char *)sadb + sadb->sadb_msg_len * 8); + + dst = (struct sadb_address *)pfkey_find_extension(ext, end, + SADB_EXT_ADDRESS_DST); + src = (struct sadb_address *)pfkey_find_extension(ext, end, + SADB_EXT_ADDRESS_SRC); + + if (dst) { + dstaddr = (struct sockaddr *)(dst + 1); + switch (dstaddr->sa_family) { + case AF_INET: + if (inet_ntop (AF_INET, &((struct sockaddr_in *)dstaddr)->sin_addr, + dstbuf, sizeof(dstbuf)) == NULL) { + log_error (__FUNCTION__": inet_ntop failed"); + return (-1); + } + break; + default: + log_error(__FUNCTION__ + ": unsupported address family %d", + dstaddr->sa_family); + return (-1); + } + + LOG_DBG((LOG_KERNEL, 20, __FUNCTION__": dst: %s", dstbuf)); + } else + return (-1); + + /* Try to find an already established exchange which is still valid */ + st = state_find(dstbuf); + + tm = time(NULL); + while (st != NULL && (st->lifetime <= tm || st->phase >= SPI_UPDATE)) + st = state_find_next(st, dstbuf); + + if (st == NULL) { + /* No established exchange found, start a new one */ + if ((st = state_new()) == NULL) { + log_print("state_new() failed in kernel_request_sa() for remote ip %s", + dstbuf); + return (-1); + } + /* Set up the state information */ + strncpy(st->address, dstbuf, sizeof(st->address) - 1); + st->port = global_port; + st->sport = 0; + st->dport = 0; + st->protocol = 0; + + st->flags = IPSEC_NOTIFY; + st->flags |= IPSEC_OPT_ENC; + + /* XXX - maybe see if we needs this + if (em->em_not_satype & NOTIFY_SATYPE_AUTH) + st->flags |= IPSEC_OPT_AUTH; + */ + + /* XXX - handling of tunnel requests missing */ + if (start_exchange(global_socket, st, st->address, + st->port) == -1) { + log_print(__FUNCTION__": start_exchange() - informing kernel of failure"); + /* Inform kernel of our failure */ + kernel_notify_result(st, NULL, 0); + state_value_reset(st); + free(st); + return (-1); + } else + state_insert(st); + } else { + /* + * We need different attributes for this exchange, send + * an SPI_NEEDED message. + */ + } } /* diff --git a/sbin/photurisd/kernel.h b/sbin/photurisd/kernel.h index d36f81d3310..4f391d00efb 100644 --- a/sbin/photurisd/kernel.h +++ b/sbin/photurisd/kernel.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: kernel.h,v 1.6 2000/12/11 20:32:15 provos Exp $ */ +/* $Id: kernel.h,v 1.7 2000/12/12 01:53:42 provos Exp $ */ /* * kernel.h: * security paramter index creation. @@ -92,7 +92,8 @@ int kernel_bind_spis(struct spiob *spi1, struct spiob *spi2); int kernel_delete_spi(char *address, u_int32_t spi, int proto); -int kernel_request_sa(void *em /* struct encap_msghdr *em */); +struct sadb_msg; +int kernel_request_sa(struct sadb_msg *); #else #define EXTERN extern #endif diff --git a/sbin/photurisd/server.c b/sbin/photurisd/server.c index a14fc6f4f56..210e090d367 100644 --- a/sbin/photurisd/server.c +++ b/sbin/photurisd/server.c @@ -35,7 +35,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: server.c,v 1.4 2000/12/11 21:21:18 provos Exp $"; +static char rcsid[] = "$Id: server.c,v 1.5 2000/12/12 01:53:42 provos Exp $"; #endif #define _SERVER_C_ @@ -80,7 +80,7 @@ init_server(void) int sock, d, i, ip, on = 1; struct ifconf ifconf; void *newbuf; - char buf[1024]; + char buf[4096]; readfds = normfds = NULL; @@ -111,7 +111,7 @@ init_server(void) /* get the local addresses */ - ifconf.ifc_len = 1024; + ifconf.ifc_len = sizeof(buf); ifconf.ifc_buf = buf; bzero(buf, 1024); @@ -154,7 +154,7 @@ init_server(void) i = 1; /* One interface already */ #ifdef IPSEC - /* We also listen on PF_ENCAP for notify messages */ + /* We also listen on pfkeyv2 for notify messages */ newbuf = realloc(addresses, (i + 2) * sizeof(char *)); if (newbuf == NULL) { if (addresses != NULL) |