From 126dface48f6f55826ca957bbe6e4b53a7ba777b Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Thu, 14 Dec 2000 23:29:00 +0000 Subject: queue pfkey acquire and expire messages if we are currently waiting for another pfkey transaction to return. some cleanup. --- sbin/photurisd/handle_spi_update.c | 4 +- sbin/photurisd/kernel.c | 181 +++++++++++++++++++++++---------- sbin/photurisd/kernel.h | 3 +- sbin/photurisd/log.h | 6 +- sbin/photurisd/photurisd.c | 8 +- sbin/photurisd/server.c | 10 +- sbin/photurisd/spi.c | 201 +++++++++++++++++-------------------- sbin/photurisd/spi.h | 10 +- 8 files changed, 246 insertions(+), 177 deletions(-) (limited to 'sbin') diff --git a/sbin/photurisd/handle_spi_update.c b/sbin/photurisd/handle_spi_update.c index 6fc1ed8df79..19c61296011 100644 --- a/sbin/photurisd/handle_spi_update.c +++ b/sbin/photurisd/handle_spi_update.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_spi_update.c,v 1.4 2000/12/11 21:21:17 provos Exp $"; +static char rcsid[] = "$Id: handle_spi_update.c,v 1.5 2000/12/14 23:28:57 provos Exp $"; #endif #include @@ -150,8 +150,8 @@ handle_spi_update(u_char *packet, int size, char *address, #ifdef IPSEC kernel_unlink_spi(spi); #endif - spi_unlink(spi); spi_value_reset(spi); + spi_unlink(spi); return 0; } diff --git a/sbin/photurisd/kernel.c b/sbin/photurisd/kernel.c index 3dfa10b93ff..d876cf6a114 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.14 2000/12/14 18:32:25 provos Exp $"; +static char rcsid[] = "$Id: kernel.c,v 1.15 2000/12/14 23:28:58 provos Exp $"; #endif #include @@ -91,6 +91,14 @@ static int regsd; /* PFKEY socket for Register and Acquire */ static int pfkey_seq; static pid_t pfkey_pid; +struct pfmsg { + TAILQ_ENTRY(pfmsg) next; + + struct sadb_msg *smsg; +}; + +TAILQ_HEAD(pflist, pfmsg) pfqueue; + /* * Translate a Photuris ID into a data structure for the * corresponding Kernel transform. @@ -213,18 +221,20 @@ kernel_valid_auth(attrib_t *auth, u_int8_t *flag, u_int16_t size) int init_kernel(void) { - if ((sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1) - log_fatal(__FUNCTION__": socket(PF_KEY) for IPSec keyengine"); - if ((regsd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1) - log_fatal(__FUNCTION__": socket() for PFKEY register"); + TAILQ_INIT(&pfqueue); + + if ((sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1) + log_fatal(__FUNCTION__": socket(PF_KEY) for IPSec keyengine"); + if ((regsd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1) + log_fatal(__FUNCTION__": socket() for PFKEY register"); - pfkey_seq = 0; - pfkey_pid = getpid(); + pfkey_seq = 0; + pfkey_pid = getpid(); - if (kernel_register(regsd) == -1) - log_fatal(__FUNCTION__": PFKEY socket registration failed"); + if (kernel_register(regsd) == -1) + log_fatal(__FUNCTION__": PFKEY socket registration failed"); - return (1); + return (1); } int @@ -289,11 +299,37 @@ kernel_xf_set(int sd, char *buffer, int blen, struct iovec *iov, return (1); } +void +kernel_queue_msg(struct sadb_msg *smsg) +{ + struct pfmsg *pfmsg; + + LOG_DBG((LOG_KERNEL, 50, __FUNCTION__": queuing message type %d", + smsg->sadb_msg_type)); + + pfmsg = malloc(sizeof(pfmsg)); + if (pfmsg == NULL) { + log_error(__FUNCTION__": malloc"); + return; + } + + pfmsg->smsg = malloc(smsg->sadb_msg_len * 8); + if (pfmsg->smsg == NULL) { + log_error(__FUNCTION__": malloc"); + free(pfmsg); + return; + } + + memcpy(pfmsg->smsg, smsg, smsg->sadb_msg_len * 8); + + TAILQ_INSERT_TAIL(&pfqueue, pfmsg, next); +} + int kernel_xf_read(int sd, char *buffer, int blen, int seq) { struct sadb_msg *sres = (struct sadb_msg *)buffer; - int len; + int len, forus; /* * Read in response from the kernel. If seq number and/or PID are @@ -302,7 +338,7 @@ kernel_xf_read(int sd, char *buffer, int blen, int seq) */ do { if (recv(sd, sres, sizeof(*sres), MSG_PEEK) != sizeof(*sres)) { - perror("read() in kernel_xf_read()"); + log_error(__FUNCTION__": read()"); return (0); } len = sres->sadb_msg_len * 8; @@ -314,10 +350,26 @@ kernel_xf_read(int sd, char *buffer, int blen, int seq) log_error(__FUNCTION__": read()"); return (0); } - } while (seq && (sres->sadb_msg_seq != seq || - (sres->sadb_msg_pid && sres->sadb_msg_pid != pfkey_pid) - )); - + + forus = !(sres->sadb_msg_pid && sres->sadb_msg_pid != pfkey_pid) && + !(seq && sres->sadb_msg_seq != seq); + + if (!forus) { + switch (sres->sadb_msg_type) { + case SADB_ACQUIRE: + case SADB_EXPIRE: + kernel_queue_msg(sres); + break; + default: + LOG_DBG((LOG_KERNEL, 50, __FUNCTION__ + ": skipping message type %d", + sres->sadb_msg_type)); + break; + } + } + + } while (!forus); + if (sres->sadb_msg_errno) { LOG_DBG((LOG_KERNEL, 40, __FUNCTION__": PFKEYV2 result: %s", strerror(sres->sadb_msg_errno))); @@ -325,9 +377,6 @@ kernel_xf_read(int sd, char *buffer, int blen, int seq) return (0); } - if (sres->sadb_msg_pid && sres->sadb_msg_pid != pfkey_pid) - return (0); - return (1); } @@ -1054,6 +1103,48 @@ kernel_unlink_spi(struct spiob *ospi) return (1); } +void +kernel_dispatch_notify(struct sadb_msg *sres) +{ + LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got PFKEYV2 message: type %d", + sres->sadb_msg_type)); + + switch (sres->sadb_msg_type) { + case SADB_EXPIRE: + LOG_DBG((LOG_KERNEL, 55, __FUNCTION__": Got SA Expiration")); + kernel_handle_expire(sres); + break; + case SADB_ACQUIRE: + LOG_DBG((LOG_KERNEL, 55, __FUNCTION__ + ": 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)); + + + kernel_request_sa(sres); + break; + default: + /* discard silently */ + return; + } +} + +void +kernel_handle_queue() +{ + struct pfmsg *pfmsg; + + while (pfmsg = TAILQ_FIRST(&pfqueue)) { + TAILQ_REMOVE(&pfqueue, pfmsg, next); + + kernel_dispatch_notify(pfmsg->smsg); + + free(pfmsg->smsg); + free(pfmsg); + } +} + /* * Handles Notifies from the kernel, which can include Requests for new * SAs, soft and hard expirations for already established SAs. @@ -1062,39 +1153,25 @@ kernel_unlink_spi(struct spiob *ospi) 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; - - LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got PFKEYV2 message: type %d", - sres->sadb_msg_type)); - - switch (sres->sadb_msg_type) { - case SADB_EXPIRE: - LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got SA Expiration")); - kernel_handle_expire(sres); - break; - case SADB_ACQUIRE: - LOG_DBG((LOG_KERNEL, 60, __FUNCTION__ - ": 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 */ - return; - } + struct sadb_msg *sres = (struct sadb_msg *)buffer; + size_t len; + + if (!kernel_xf_read(regsd, buffer, BUFFER_SIZE, 0)) { + LOG_DBG((LOG_KERNEL, 65, __FUNCTION__": nothing to read")); + return; + } + + len = sres->sadb_msg_len * 8; + sres = malloc(len); + if (!sres) { + log_error(__FUNCTION__": malloc"); + return; + } + memcpy(sres, buffer, len); + + kernel_dispatch_notify(sres); + + free(sres); } struct sadb_msg * diff --git a/sbin/photurisd/kernel.h b/sbin/photurisd/kernel.h index 7a6c54ada86..194eb181a9c 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.8 2000/12/14 18:32:25 provos Exp $ */ +/* $Id: kernel.h,v 1.9 2000/12/14 23:28:58 provos Exp $ */ /* * kernel.h: * security paramter index creation. @@ -115,5 +115,6 @@ EXTERN int kernel_get_socket(void); EXTERN void kernel_set_socket_policy(int sd); EXTERN void kernel_handle_notify(int sd); EXTERN void kernel_notify_result(struct stateob *, struct spiob *, int); +EXTERN void kernel_handle_queue(void); #endif /* _KERNEL_H */ diff --git a/sbin/photurisd/log.h b/sbin/photurisd/log.h index 2b395cad014..43d5379ded9 100644 --- a/sbin/photurisd/log.h +++ b/sbin/photurisd/log.h @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.1 2000/12/11 21:21:18 provos Exp $ */ +/* $OpenBSD: log.h,v 1.2 2000/12/14 23:28:58 provos Exp $ */ /* $EOM: log.h,v 1.19 2000/03/30 14:27:23 ho Exp $ */ /* @@ -47,11 +47,11 @@ #define LOG_SIZE 200 enum log_classes { - LOG_MISC, LOG_TRANSPORT, LOG_CRYPTO, LOG_TIMER, LOG_SA, LOG_KERNEL, + LOG_MISC, LOG_TRANSPORT, LOG_CRYPTO, LOG_TIMER, LOG_SPI, LOG_KERNEL, LOG_ENDCLASS }; #define LOG_CLASSES_TEXT \ - { "Misc", "Trpt", "Cryp", "Timr", "SA ", "Kern" } + { "Misc", "Trpt", "Cryp", "Timr", "SPI ", "Kern" } /* * "Class" LOG_REPORT will always be logged to the current log channel, diff --git a/sbin/photurisd/photurisd.c b/sbin/photurisd/photurisd.c index 58c09faff95..ab6c29d3576 100644 --- a/sbin/photurisd/photurisd.c +++ b/sbin/photurisd/photurisd.c @@ -32,7 +32,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photurisd.c,v 1.6 2000/12/11 21:21:18 provos Exp $"; +static char rcsid[] = "$Id: photurisd.c,v 1.7 2000/12/14 23:28:58 provos Exp $"; #endif #define _PHOTURIS_C_ @@ -162,6 +162,8 @@ main(int argc, char **argv) argc -= optind; argv += optind; + spi_init(); + init_vars(); init_times(); @@ -170,12 +172,12 @@ main(int argc, char **argv) init_schemes(); -#ifndef DEBUG +#ifndef USE_DEBUG init_signals(); if (fork()) exit(0); daemon_mode = 1; -#endif +#endif /* USE_DEBUG */ #ifdef IPSEC init_kernel(); diff --git a/sbin/photurisd/server.c b/sbin/photurisd/server.c index 210e090d367..13ac367262d 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.5 2000/12/12 01:53:42 provos Exp $"; +static char rcsid[] = "$Id: server.c,v 1.6 2000/12/14 23:28:59 provos Exp $"; #endif #define _SERVER_C_ @@ -320,6 +320,14 @@ server(void) } } +#ifdef IPSEC + /* + * Deal with queue acquire and expire message, since we + * dont have proper timeout code, it needs to go here. + */ + kernel_handle_queue(); +#endif + schedule_process(global_socket); fflush(stdout); fflush(stderr); diff --git a/sbin/photurisd/spi.c b/sbin/photurisd/spi.c index c8345d6d50a..fb140b3a8f2 100644 --- a/sbin/photurisd/spi.c +++ b/sbin/photurisd/spi.c @@ -33,11 +33,13 @@ */ #ifndef lint -static char rcsid[] = "$Id: spi.c,v 1.4 2000/12/11 21:21:18 provos Exp $"; +static char rcsid[] = "$Id: spi.c,v 1.5 2000/12/14 23:28:59 provos Exp $"; #endif #define _SPI_C_ +#include +#include #include #include #include @@ -58,13 +60,19 @@ static char rcsid[] = "$Id: spi.c,v 1.4 2000/12/11 21:21:18 provos Exp $"; #endif -static struct spiob *spiob = NULL; +TAILQ_HEAD(spilist, spiob) spihead; + +void +spi_init(void) +{ + TAILQ_INIT(&spihead); +} time_t getspilifetime(struct stateob *st) { /* XXX - destination depend lifetimes */ - return st->spi_lifetime; + return (st->spi_lifetime); } int @@ -78,7 +86,7 @@ make_spi(struct stateob *st, char *local_address, if(*attributes == NULL) { /* We are in need of attributes */ if (select_attrib(st, attributes, attribsize) == -1) { log_print("select_attrib() in make_spi()"); - return -1; + return (-1); } } @@ -102,104 +110,96 @@ make_spi(struct stateob *st, char *local_address, *lifetime = getspilifetime(st) + (arc4random() & 0x1F); - return 0; + return (0); } int spi_insert(struct spiob *ob) { - struct spiob *tmp; - - ob->next = NULL; + TAILQ_INSERT_TAIL(&spihead, ob, next); - if(spiob == NULL) { - spiob = ob; - return 1; - } - - tmp=spiob; - while(tmp->next!=NULL) - tmp = tmp->next; - - tmp->next = ob; - return 1; + return (1); } int spi_unlink(struct spiob *ob) { - struct spiob *tmp; - if(spiob == ob) { - spiob = ob->next; - free(ob); - return 1; - } + LOG_DBG((LOG_SPI, 45, __FUNCTION__": unlinking %s spi %x", + ob->flags & SPI_OWNER ? "Owner" : "User", + ntohl(*(u_int32_t *)ob->SPI))); - for(tmp=spiob; tmp!=NULL; tmp=tmp->next) { - if(tmp->next==ob) { - tmp->next=ob->next; - free(ob); - return 1; - } - } - return 0; + TAILQ_REMOVE(&spihead, ob, next); + free(ob); + + return (1); } struct spiob * spi_new(char *address, u_int8_t *spi) { struct spiob *p; + if (spi_find(address, spi) != NULL) - return NULL; + return (NULL); if ((p = calloc(1, sizeof(struct spiob))) == NULL) - return NULL; + return (NULL); if ((p->address = strdup(address)) == NULL) { free(p); - return NULL; + return (NULL); } bcopy(spi, p->SPI, SPI_SIZE); - return p; + return (p); } int spi_value_reset(struct spiob *ob) { - if (ob->address != NULL) - free(ob->address); - if (ob->local_address != NULL) - free(ob->local_address); - if (ob->attributes != NULL) - free(ob->attributes); - if (ob->sessionkey != NULL) - free(ob->sessionkey); - - return 1; + if (ob->address != NULL) { + free(ob->address); + ob->address = NULL; + } + if (ob->local_address != NULL) { + free(ob->local_address); + ob->local_address = NULL; + } + if (ob->attributes != NULL) { + free(ob->attributes); + ob->attributes = NULL; + } + if (ob->sessionkey != NULL) { + memset(ob->sessionkey, 0, ob->sessionkeysize); + free(ob->sessionkey); + ob->sessionkey = NULL; + } + + return (1); } struct spiob * spi_find_attrib(char *address, u_int8_t *attrib, u_int16_t attribsize) { - struct spiob *tmp = spiob; + struct spiob *tmp; u_int16_t i; - while(tmp!=NULL) { - if(!strcmp(address, tmp->address)) { - for(i=0;iaddress)) { + for (i = 0; i < attribsize; i += attrib[i + 1] + 2) { + if (attrib[i] == AT_AH_ATTRIB || + attrib[i] == AT_ESP_ATTRIB) + continue; if (!isinattrib(tmp->attributes, tmp->attribsize, attrib[i])) break; } if (i == attribsize) - return tmp; + return (tmp); } - tmp = tmp->next; } - return NULL; + + return (NULL); } /* @@ -211,67 +211,48 @@ spi_find_attrib(char *address, u_int8_t *attrib, u_int16_t attribsize) struct spiob * spi_find(char *address, u_int8_t *spi) { - struct spiob *tmp = spiob; - while(tmp!=NULL) { - if ((address == NULL || (tmp->flags & SPI_OWNER ? - !strcmp(address, tmp->local_address) : - !strcmp(address, tmp->address))) && - !bcmp(spi, tmp->SPI, SPI_SIZE)) - return tmp; - tmp = tmp->next; - } - return NULL; -} + struct spiob *tmp; -struct spiob * -spi_root(void) -{ - return spiob; -} + for (tmp = TAILQ_FIRST(&spihead); tmp; tmp = TAILQ_NEXT(tmp, next)) { + if (bcmp(spi, tmp->SPI, SPI_SIZE)) + continue; -void -spi_cleanup() -{ - struct spiob *p; - struct spiob *tmp = spiob; - while(tmp!=NULL) { - p = tmp; - tmp = tmp->next; - spi_value_reset(p); - free(p); - } - spiob = NULL; + if (address == NULL) + break; + + if (tmp->flags & SPI_OWNER ? + !strcmp(address, tmp->local_address) : + !strcmp(address, tmp->address)) + break; + } + + return (tmp); } void spi_expire(void) { - struct spiob *tmp = spiob, *p; - time_t tm; - - tm = time(NULL); - while (tmp != NULL) { - if (tmp->lifetime == -1 || - tmp->lifetime + (tmp->flags & SPI_OWNER ? - CLEANUP_TIMEOUT : 0) > tm) { - tmp = tmp->next; - continue; - } -#ifdef DEBUG - { - int i = BUFFER_SIZE; - bin2hex(buffer, &i, tmp->SPI, 4); - printf("Expiring %s spi %s to %s\n", - tmp->flags & SPI_OWNER ? "Owner" : "User", - buffer, tmp->address); - } -#endif + struct spiob *tmp, *next; + time_t tm; + + tm = time(NULL); + for (tmp = TAILQ_FIRST(&spihead); tmp; tmp = next) { + next = TAILQ_NEXT(tmp, next); + + if (tmp->lifetime == -1 || + tmp->lifetime + (tmp->flags & SPI_OWNER ? + CLEANUP_TIMEOUT : 0) > tm) + continue; + + LOG_DBG((LOG_SPI, 30, __FUNCTION__ + ": expiring %s spi %x to %s", + tmp->flags & SPI_OWNER ? "Owner" : "User", + ntohl(*(u_int32_t *)tmp->SPI), tmp->address)); + #ifdef IPSEC - kernel_unlink_spi(tmp); + kernel_unlink_spi(tmp); #endif - p = tmp; - tmp = tmp->next; - spi_value_reset(p); - spi_unlink(p); - } + spi_value_reset(tmp); + spi_unlink(tmp); + } } diff --git a/sbin/photurisd/spi.h b/sbin/photurisd/spi.h index 19ca0535560..b20224fb4d7 100644 --- a/sbin/photurisd/spi.h +++ b/sbin/photurisd/spi.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: spi.h,v 1.3 2000/12/11 20:32:15 provos Exp $ */ +/* $Id: spi.h,v 1.4 2000/12/14 23:28:59 provos Exp $ */ /* * spi.h: * security paramter index creation. @@ -35,7 +35,7 @@ #ifndef _SPI_H_ #define _SPI_H_ - +#include #include "state.h" #undef EXTERN @@ -53,7 +53,8 @@ #define SPI_ESP 8 /* Is used for ESP */ struct spiob { - struct spiob *next; /* Linked list */ + TAILQ_ENTRY(spiob) next; /* Linked list */ + char *address; char *local_address; int flags; @@ -66,6 +67,7 @@ struct spiob { time_t lifetime; /* Lifetime for the SPI */ }; +EXTERN void spi_init(void); EXTERN time_t getspilifetime(struct stateob *st); EXTERN int make_spi(struct stateob *st, char *local_address, u_int8_t *SPI, time_t *lifetime, @@ -78,8 +80,6 @@ EXTERN int spi_value_reset(struct spiob *); EXTERN struct spiob *spi_find_attrib(char *address, u_int8_t *attrib, u_int16_t attribsize); EXTERN struct spiob *spi_find(char *, u_int8_t *); -EXTERN struct spiob *spi_root(void); -EXTERN void spi_cleanup(void); EXTERN void spi_expire(void); #endif /* _SPI_H */ -- cgit v1.2.3