diff options
Diffstat (limited to 'sbin/isakmpd')
95 files changed, 24054 insertions, 25906 deletions
diff --git a/sbin/isakmpd/app.c b/sbin/isakmpd/app.c index af06b59bb9d..a04aa14a8e4 100644 --- a/sbin/isakmpd/app.c +++ b/sbin/isakmpd/app.c @@ -1,5 +1,5 @@ -/* $OpenBSD: app.c,v 1.8 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: app.c,v 1.6 1999/05/01 20:21:06 niklas Exp $ */ +/* $OpenBSD: app.c,v 1.9 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: app.c,v 1.6 1999/05/01 20:21:06 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -47,17 +47,17 @@ int app_none = 0; /* Initialize applications. */ void -app_init (void) +app_init(void) { - if (app_none) - return; - app_socket = sysdep_app_open (); - if (app_socket == -1) - log_fatal ("app_init: cannot open connection to application"); + if (app_none) + return; + app_socket = sysdep_app_open(); + if (app_socket == -1) + log_fatal("app_init: cannot open connection to application"); } void -app_handler (void) +app_handler(void) { - sysdep_app_handler (app_socket); + sysdep_app_handler(app_socket); } diff --git a/sbin/isakmpd/app.h b/sbin/isakmpd/app.h index 79c53c95486..96a2864e453 100644 --- a/sbin/isakmpd/app.h +++ b/sbin/isakmpd/app.h @@ -1,5 +1,5 @@ -/* $OpenBSD: app.h,v 1.6 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: app.h,v 1.4 1999/04/02 00:58:16 niklas Exp $ */ +/* $OpenBSD: app.h,v 1.7 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: app.h,v 1.4 1999/04/02 00:58:16 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -32,11 +32,11 @@ #ifndef _APP_H_ #define _APP_H_ -extern int app_socket; -extern int app_none; +extern int app_socket; +extern int app_none; -extern void app_conf_init_hook (void); -extern void app_handler (void); -extern void app_init (void); +extern void app_conf_init_hook(void); +extern void app_handler(void); +extern void app_init(void); -#endif /* _APP_H_ */ +#endif /* _APP_H_ */ diff --git a/sbin/isakmpd/attribute.c b/sbin/isakmpd/attribute.c index bfeb3cb9d3d..e1959290162 100644 --- a/sbin/isakmpd/attribute.c +++ b/sbin/isakmpd/attribute.c @@ -1,5 +1,5 @@ -/* $OpenBSD: attribute.c,v 1.9 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: attribute.c,v 1.10 2000/02/20 19:58:36 niklas Exp $ */ +/* $OpenBSD: attribute.c,v 1.10 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: attribute.c,v 1.10 2000/02/20 19:58:36 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -40,22 +40,22 @@ #include "isakmp.h" #include "util.h" -u_int8_t * -attribute_set_basic (u_int8_t *buf, u_int16_t type, u_int16_t value) +u_int8_t * +attribute_set_basic(u_int8_t * buf, u_int16_t type, u_int16_t value) { - SET_ISAKMP_ATTR_TYPE (buf, ISAKMP_ATTR_MAKE (1, type)); - SET_ISAKMP_ATTR_LENGTH_VALUE (buf, value); - return buf + ISAKMP_ATTR_VALUE_OFF; + SET_ISAKMP_ATTR_TYPE(buf, ISAKMP_ATTR_MAKE(1, type)); + SET_ISAKMP_ATTR_LENGTH_VALUE(buf, value); + return buf + ISAKMP_ATTR_VALUE_OFF; } -u_int8_t * -attribute_set_var (u_int8_t *buf, u_int16_t type, u_int8_t *value, - u_int16_t len) +u_int8_t * +attribute_set_var(u_int8_t * buf, u_int16_t type, u_int8_t * value, + u_int16_t len) { - SET_ISAKMP_ATTR_TYPE (buf, ISAKMP_ATTR_MAKE (0, type)); - SET_ISAKMP_ATTR_LENGTH_VALUE (buf, len); - memcpy (buf + ISAKMP_ATTR_VALUE_OFF, value, len); - return buf + ISAKMP_ATTR_VALUE_OFF + len; + SET_ISAKMP_ATTR_TYPE(buf, ISAKMP_ATTR_MAKE(0, type)); + SET_ISAKMP_ATTR_LENGTH_VALUE(buf, len); + memcpy(buf + ISAKMP_ATTR_VALUE_OFF, value, len); + return buf + ISAKMP_ATTR_VALUE_OFF + len; } /* @@ -65,51 +65,49 @@ attribute_set_var (u_int8_t *buf, u_int16_t type, u_int8_t *value, * -1 return value. If all goes well return zero. */ int -attribute_map (u_int8_t *buf, size_t sz, - int (*func) (u_int16_t, u_int8_t *, u_int16_t, void *), - void *arg) +attribute_map(u_int8_t * buf, size_t sz, + int (*func) (u_int16_t, u_int8_t *, u_int16_t, void *), + void *arg) { - u_int8_t *attr; - int fmt; - u_int16_t type; - u_int8_t *value; - u_int16_t len; + u_int8_t *attr; + int fmt; + u_int16_t type; + u_int8_t *value; + u_int16_t len; - for (attr = buf; attr < buf + sz; attr = value + len) - { - if (attr + ISAKMP_ATTR_VALUE_OFF > buf + sz) - return -1; - type = GET_ISAKMP_ATTR_TYPE (attr); - fmt = ISAKMP_ATTR_FORMAT (type); - type = ISAKMP_ATTR_TYPE (type); - value - = attr + (fmt ? ISAKMP_ATTR_LENGTH_VALUE_OFF : ISAKMP_ATTR_VALUE_OFF); - len = (fmt ? ISAKMP_ATTR_LENGTH_VALUE_LEN - : GET_ISAKMP_ATTR_LENGTH_VALUE (attr)); - if (value + len > buf + sz) - return -1; - if (func (type, value, len, arg)) - return -1; - } - return 0; + for (attr = buf; attr < buf + sz; attr = value + len) { + if (attr + ISAKMP_ATTR_VALUE_OFF > buf + sz) + return -1; + type = GET_ISAKMP_ATTR_TYPE(attr); + fmt = ISAKMP_ATTR_FORMAT(type); + type = ISAKMP_ATTR_TYPE(type); + value + = attr + (fmt ? ISAKMP_ATTR_LENGTH_VALUE_OFF : ISAKMP_ATTR_VALUE_OFF); + len = (fmt ? ISAKMP_ATTR_LENGTH_VALUE_LEN + : GET_ISAKMP_ATTR_LENGTH_VALUE(attr)); + if (value + len > buf + sz) + return -1; + if (func(type, value, len, arg)) + return -1; + } + return 0; } int -attribute_set_constant (char *section, char *tag, struct constant_map *map, - int attr_class, u_int8_t **attr) +attribute_set_constant(char *section, char *tag, struct constant_map * map, + int attr_class, u_int8_t ** attr) { - char *name; - int value; + char *name; + int value; - name = conf_get_str (section, tag); - if (!name) - { - LOG_DBG ((LOG_MISC, 70, - "attribute_set_constant: no %s in the %s section", tag, - section)); - return -1; - } - value = constant_value (map, name); - *attr = attribute_set_basic (*attr, attr_class, value); - return 0; + name = conf_get_str(section, tag); + if (!name) { + LOG_DBG((LOG_MISC, 70, + "attribute_set_constant: no %s in the %s section", tag, + section)); + return -1; + } + value = constant_value(map, name); + *attr = attribute_set_basic(*attr, attr_class, value); + return 0; } diff --git a/sbin/isakmpd/attribute.h b/sbin/isakmpd/attribute.h index 86ebbad456c..29de52fb769 100644 --- a/sbin/isakmpd/attribute.h +++ b/sbin/isakmpd/attribute.h @@ -1,5 +1,5 @@ -/* $OpenBSD: attribute.h,v 1.4 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: attribute.h,v 1.2 1998/09/29 21:51:07 niklas Exp $ */ +/* $OpenBSD: attribute.h,v 1.5 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: attribute.h,v 1.2 1998/09/29 21:51:07 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -36,13 +36,14 @@ struct constant_map; -extern int attribute_map (u_int8_t *, size_t, - int (*) (u_int16_t, u_int8_t *, u_int16_t, void *), - void *); -extern u_int8_t *attribute_set_basic (u_int8_t *, u_int16_t, u_int16_t); -extern int attribute_set_constant (char *, char *, struct constant_map *, - int, u_int8_t **); -extern u_int8_t *attribute_set_var (u_int8_t *, u_int16_t, u_int8_t *, - u_int16_t); +extern int +attribute_map(u_int8_t *, size_t, + int (*) (u_int16_t, u_int8_t *, u_int16_t, void *), + void *); + extern u_int8_t *attribute_set_basic(u_int8_t *, u_int16_t, u_int16_t); + extern int attribute_set_constant(char *, char *, struct constant_map *, + int, u_int8_t **); + extern u_int8_t *attribute_set_var(u_int8_t *, u_int16_t, u_int8_t *, + u_int16_t); -#endif /* _ATTRIBUTE_H_ */ +#endif /* _ATTRIBUTE_H_ */ diff --git a/sbin/isakmpd/cert.c b/sbin/isakmpd/cert.c index dd77098fc9b..13124ecd8a7 100644 --- a/sbin/isakmpd/cert.c +++ b/sbin/isakmpd/cert.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cert.c,v 1.25 2004/03/31 10:54:46 ho Exp $ */ -/* $EOM: cert.c,v 1.18 2000/09/28 12:53:27 niklas Exp $ */ +/* $OpenBSD: cert.c,v 1.26 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: cert.c,v 1.18 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niels Provos. All rights reserved. @@ -51,65 +51,64 @@ struct cert_handler cert_handler[] = { #ifdef USE_X509 - { - ISAKMP_CERTENC_X509_SIG, - x509_cert_init, x509_crl_init, x509_cert_get, x509_cert_validate, - x509_cert_insert, x509_cert_free, - x509_certreq_validate, x509_certreq_decode, x509_free_aca, - x509_cert_obtain, x509_cert_get_key, x509_cert_get_subjects, - x509_cert_dup, x509_serialize, x509_printable, x509_from_printable - }, + { + ISAKMP_CERTENC_X509_SIG, + x509_cert_init, x509_crl_init, x509_cert_get, x509_cert_validate, + x509_cert_insert, x509_cert_free, + x509_certreq_validate, x509_certreq_decode, x509_free_aca, + x509_cert_obtain, x509_cert_get_key, x509_cert_get_subjects, + x509_cert_dup, x509_serialize, x509_printable, x509_from_printable + }, #endif #ifdef USE_KEYNOTE - { - ISAKMP_CERTENC_KEYNOTE, - keynote_cert_init, NULL, keynote_cert_get, keynote_cert_validate, - keynote_cert_insert, keynote_cert_free, - keynote_certreq_validate, keynote_certreq_decode, keynote_free_aca, - keynote_cert_obtain, keynote_cert_get_key, keynote_cert_get_subjects, - keynote_cert_dup, keynote_serialize, keynote_printable, - keynote_from_printable - }, + { + ISAKMP_CERTENC_KEYNOTE, + keynote_cert_init, NULL, keynote_cert_get, keynote_cert_validate, + keynote_cert_insert, keynote_cert_free, + keynote_certreq_validate, keynote_certreq_decode, keynote_free_aca, + keynote_cert_obtain, keynote_cert_get_key, keynote_cert_get_subjects, + keynote_cert_dup, keynote_serialize, keynote_printable, + keynote_from_printable + }, #endif }; /* Initialize all certificate handlers */ - int -cert_init (void) +cert_init(void) { - size_t i; - int err = 1; + size_t i; + int err = 1; - for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++) - if (cert_handler[i].cert_init && !(*cert_handler[i].cert_init) ()) - err = 0; + for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++) + if (cert_handler[i].cert_init && !(*cert_handler[i].cert_init) ()) + err = 0; - return err; + return err; } int -crl_init (void) +crl_init(void) { - size_t i; - int err = 1; + size_t i; + int err = 1; - for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++) - if (cert_handler[i].crl_init && !(*cert_handler[i].crl_init) ()) - err = 0; + for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++) + if (cert_handler[i].crl_init && !(*cert_handler[i].crl_init) ()) + err = 0; - return err; + return err; } struct cert_handler * -cert_get (u_int16_t id) +cert_get(u_int16_t id) { - size_t i; + size_t i; - for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++) - if (id == cert_handler[i].id) - return &cert_handler[i]; - return 0; + for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++) + if (id == cert_handler[i].id) + return &cert_handler[i]; + return 0; } /* @@ -118,48 +117,43 @@ cert_get (u_int16_t id) * responsible for deallocating. */ struct certreq_aca * -certreq_decode (u_int16_t type, u_int8_t *data, u_int32_t datalen) +certreq_decode(u_int16_t type, u_int8_t *data, u_int32_t datalen) { - struct cert_handler *handler; - struct certreq_aca aca, *ret; - - handler = cert_get (type); - if (!handler) - return 0; - - aca.id = type; - aca.handler = handler; - - if (datalen > 0) - { - aca.data = handler->certreq_decode (data, datalen); - if (!aca.data) - return 0; - } - else - aca.data = 0; - - ret = malloc (sizeof aca); - if (!ret) - { - log_error ("certreq_decode: malloc (%lu) failed", - (unsigned long)sizeof aca); - handler->free_aca (aca.data); - return 0; - } - - memcpy (ret, &aca, sizeof aca); - - return ret; + struct cert_handler *handler; + struct certreq_aca aca, *ret; + + handler = cert_get(type); + if (!handler) + return 0; + + aca.id = type; + aca.handler = handler; + + if (datalen > 0) { + aca.data = handler->certreq_decode(data, datalen); + if (!aca.data) + return 0; + } else + aca.data = 0; + + ret = malloc(sizeof aca); + if (!ret) { + log_error("certreq_decode: malloc (%lu) failed", + (unsigned long) sizeof aca); + handler->free_aca(aca.data); + return 0; + } + memcpy(ret, &aca, sizeof aca); + return ret; } void -cert_free_subjects (int n, u_int8_t **id, u_int32_t *len) +cert_free_subjects(int n, u_int8_t **id, u_int32_t *len) { - int i; + int i; - for (i = 0; i < n; i++) - free (id[i]); - free (id); - free (len); + for (i = 0; i < n; i++) + free(id[i]); + free(id); + free(len); } diff --git a/sbin/isakmpd/cert.h b/sbin/isakmpd/cert.h index dd19f0edb6d..ea9da823eb2 100644 --- a/sbin/isakmpd/cert.h +++ b/sbin/isakmpd/cert.h @@ -1,5 +1,5 @@ -/* $OpenBSD: cert.h,v 1.12 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: cert.h,v 1.8 2000/09/28 12:53:27 niklas Exp $ */ +/* $OpenBSD: cert.h,v 1.13 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: cert.h,v 1.8 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niels Provos. All rights reserved. @@ -55,40 +55,42 @@ */ struct cert_handler { - u_int16_t id; /* ISAKMP Cert Encoding ID */ - int (*cert_init) (void); - int (*crl_init) (void); - void *(*cert_get) (u_int8_t *, u_int32_t); - int (*cert_validate) (void *); - int (*cert_insert) (int, void *); - void (*cert_free) (void *); - int (*certreq_validate) (u_int8_t *, u_int32_t); - void *(*certreq_decode) (u_int8_t *, u_int32_t); - void (*free_aca) (void *); - int (*cert_obtain) (u_int8_t *, size_t, void *, u_int8_t **, u_int32_t *); - int (*cert_get_key) (void *, void *); - int (*cert_get_subjects) (void *, int *, u_int8_t ***, u_int32_t **); - void *(*cert_dup) (void *); - void (*cert_serialize) (void *, u_int8_t **, u_int32_t *); - char *(*cert_printable) (void *); - void *(*cert_from_printable) (char *); + u_int16_t id; /* ISAKMP Cert Encoding ID */ + int (*cert_init) (void); + int (*crl_init) (void); + void *(*cert_get) (u_int8_t *, u_int32_t); + int (*cert_validate) (void *); + int (*cert_insert) (int, void *); + void (*cert_free) (void *); + int (*certreq_validate) (u_int8_t *, u_int32_t); + void *(*certreq_decode) (u_int8_t *, u_int32_t); + void (*free_aca) (void *); + int (*cert_obtain) (u_int8_t *, size_t, void *, + u_int8_t **, u_int32_t *); + int (*cert_get_key) (void *, void *); + int (*cert_get_subjects) (void *, int *, u_int8_t ***, + u_int32_t **); + void *(*cert_dup) (void *); + void (*cert_serialize) (void *, u_int8_t **, u_int32_t *); + char *(*cert_printable) (void *); + void *(*cert_from_printable) (char *); }; /* The acceptable authority of cert request. */ struct certreq_aca { - TAILQ_ENTRY (certreq_aca) link; + TAILQ_ENTRY(certreq_aca) link; - u_int16_t id; - struct cert_handler *handler; + u_int16_t id; + struct cert_handler *handler; - /* If data is a null pointer, everything is acceptable. */ - void *data; + /* If data is a null pointer, everything is acceptable. */ + void *data; }; -struct certreq_aca *certreq_decode (u_int16_t, u_int8_t *, u_int32_t); -void cert_free_subjects (int, u_int8_t **, u_int32_t *); -struct cert_handler *cert_get (u_int16_t); -int cert_init (void); -int crl_init (void); +struct certreq_aca *certreq_decode(u_int16_t, u_int8_t *, u_int32_t); +void cert_free_subjects(int, u_int8_t **, u_int32_t *); +struct cert_handler *cert_get(u_int16_t); +int cert_init(void); +int crl_init(void); -#endif /* _CERT_H_ */ +#endif /* _CERT_H_ */ diff --git a/sbin/isakmpd/conf.c b/sbin/isakmpd/conf.c index bb929315f38..7efd7fa5524 100644 --- a/sbin/isakmpd/conf.c +++ b/sbin/isakmpd/conf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: conf.c,v 1.62 2004/03/19 14:04:43 hshoexer Exp $ */ -/* $EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $ */ +/* $OpenBSD: conf.c,v 1.63 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -53,126 +53,123 @@ #include "monitor.h" #include "util.h" -static char *conf_get_trans_str (int, char *, char *); -static void conf_load_defaults (int); +static char *conf_get_trans_str(int, char *, char *); +static void conf_load_defaults(int); #if 0 -static int conf_find_trans_xf (int, char *); +static int conf_find_trans_xf(int, char *); #endif struct conf_trans { - TAILQ_ENTRY (conf_trans) link; - int trans; - enum conf_op { CONF_SET, CONF_REMOVE, CONF_REMOVE_SECTION } op; - char *section; - char *tag; - char *value; - int override; - int is_default; + TAILQ_ENTRY(conf_trans) link; + int trans; + enum conf_op { + CONF_SET, CONF_REMOVE, CONF_REMOVE_SECTION + } op; + char *section; + char *tag; + char *value; + int override; + int is_default; }; -TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue; +TAILQ_HEAD(conf_trans_head, conf_trans) conf_trans_queue; /* * Radix-64 Encoding. */ -const u_int8_t bin2asc[] - = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const u_int8_t bin2asc[] + = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -const u_int8_t asc2bin[] = + const u_int8_t asc2bin[] = + { + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 255, 255, 255, 255, 255, 255, + 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 255, 255, 255, 255, 255, + 255, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255 + }; + + struct conf_binding { + LIST_ENTRY(conf_binding) link; + char *section; + char *tag; + char *value; + int is_default; + }; + + char *conf_path = CONFIG_FILE; +LIST_HEAD(conf_bindings, conf_binding) conf_bindings[256]; + + static char *conf_addr; + + static __inline__ u_int8_t + conf_hash(char *s) { - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 62, 255, 255, 255, 63, - 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 255, 255, 255, 255, 255, 255, - 255, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 255, 255, 255, 255, 255, - 255, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255 -}; - -struct conf_binding { - LIST_ENTRY (conf_binding) link; - char *section; - char *tag; - char *value; - int is_default; -}; + u_int8_t hash = 0; -char *conf_path = CONFIG_FILE; -LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256]; - -static char *conf_addr; - -static __inline__ u_int8_t -conf_hash (char *s) -{ - u_int8_t hash = 0; - - while (*s) - { - hash = ((hash << 1) | (hash >> 7)) ^ tolower (*s); - s++; - } - return hash; + while (*s) { + hash = ((hash << 1) | (hash >> 7)) ^ tolower(*s); + s++; + } + return hash; } /* * Insert a tag-value combination from LINE (the equal sign is at POS) */ static int -conf_remove_now (char *section, char *tag) +conf_remove_now(char *section, char *tag) { - struct conf_binding *cb, *next; - - for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; cb = next) - { - next = LIST_NEXT (cb, link); - if (strcasecmp (cb->section, section) == 0 - && strcasecmp (cb->tag, tag) == 0) - { - LIST_REMOVE (cb, link); - LOG_DBG ((LOG_MISC, 95, "[%s]:%s->%s removed", section, tag, - cb->value)); - free (cb->section); - free (cb->tag); - free (cb->value); - free (cb); - return 0; + struct conf_binding *cb, *next; + + for (cb = LIST_FIRST(&conf_bindings[conf_hash(section)]); cb; cb = next) { + next = LIST_NEXT(cb, link); + if (strcasecmp(cb->section, section) == 0 + && strcasecmp(cb->tag, tag) == 0) { + LIST_REMOVE(cb, link); + LOG_DBG((LOG_MISC, 95, "[%s]:%s->%s removed", section, tag, + cb->value)); + free(cb->section); + free(cb->tag); + free(cb->value); + free(cb); + return 0; + } } - } - return 1; + return 1; } static int -conf_remove_section_now (char *section) +conf_remove_section_now(char *section) { - struct conf_binding *cb, *next; - int unseen = 1; - - for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; cb = next) - { - next = LIST_NEXT (cb, link); - if (strcasecmp (cb->section, section) == 0) - { - unseen = 0; - LIST_REMOVE (cb, link); - LOG_DBG ((LOG_MISC, 95, "[%s]:%s->%s removed", section, cb->tag, - cb->value)); - free (cb->section); - free (cb->tag); - free (cb->value); - free (cb); + struct conf_binding *cb, *next; + int unseen = 1; + + for (cb = LIST_FIRST(&conf_bindings[conf_hash(section)]); cb; cb = next) { + next = LIST_NEXT(cb, link); + if (strcasecmp(cb->section, section) == 0) { + unseen = 0; + LIST_REMOVE(cb, link); + LOG_DBG((LOG_MISC, 95, "[%s]:%s->%s removed", section, cb->tag, + cb->value)); + free(cb->section); + free(cb->tag); + free(cb->value); + free(cb); + } } - } - return unseen; + return unseen; } /* @@ -180,37 +177,34 @@ conf_remove_section_now (char *section) * into SECTION of our configuration database. */ static int -conf_set_now (char *section, char *tag, char *value, int override, - int is_default) +conf_set_now(char *section, char *tag, char *value, int override, + int is_default) { - struct conf_binding *node = 0; - - if (override) - conf_remove_now (section, tag); - else if (conf_get_str (section, tag)) - { - if (!is_default) - log_print ("conf_set_now: duplicate tag [%s]:%s, ignoring...\n", - section, tag); - return 1; - } - - node = calloc (1, sizeof *node); - if (!node) - { - log_error ("conf_set_now: calloc (1, %lu) failed", (unsigned long)sizeof - * node); - return 1; - } - node->section = strdup (section); - node->tag = strdup (tag); - node->value = strdup (value); - node->is_default = is_default; - - LIST_INSERT_HEAD (&conf_bindings[conf_hash (section)], node, link); - LOG_DBG ((LOG_MISC, 95, "conf_set_now: [%s]:%s->%s", node->section, node->tag, - node->value)); - return 0; + struct conf_binding *node = 0; + + if (override) + conf_remove_now(section, tag); + else if (conf_get_str(section, tag)) { + if (!is_default) + log_print("conf_set_now: duplicate tag [%s]:%s, ignoring...\n", + section, tag); + return 1; + } + node = calloc(1, sizeof *node); + if (!node) { + log_error("conf_set_now: calloc (1, %lu) failed", (unsigned long) sizeof + *node); + return 1; + } + node->section = strdup(section); + node->tag = strdup(tag); + node->value = strdup(value); + node->is_default = is_default; + + LIST_INSERT_HEAD(&conf_bindings[conf_hash(section)], node, link); + LOG_DBG((LOG_MISC, 95, "conf_set_now: [%s]:%s->%s", node->section, node->tag, + node->value)); + return 0; } /* @@ -218,102 +212,92 @@ conf_set_now (char *section, char *tag, char *value, int override, * headers and feed tag-value pairs into our configuration database. */ static void -conf_parse_line (int trans, char *line, size_t sz) +conf_parse_line(int trans, char *line, size_t sz) { - char *val; - size_t i; - int j; - static char *section = 0; - static int ln = 0; - - ln++; - - /* Lines starting with '#' or ';' are comments. */ - if (*line == '#' || *line == ';') - return; - - /* '[section]' parsing... */ - if (*line == '[') - { - for (i = 1; i < sz; i++) - if (line[i] == ']') - break; - if (section) - free (section); - if (i == sz) - { - log_print ("conf_parse_line: %d:" - "non-matched ']', ignoring until next section", ln); - section = 0; - return; - } - section = malloc (i); - if (!section) - { - log_print ("conf_parse_line: %d: malloc (%lu) failed", ln, - (unsigned long)i); - return; + char *val; + size_t i; + int j; + static char *section = 0; + static int ln = 0; + + ln++; + + /* Lines starting with '#' or ';' are comments. */ + if (*line == '#' || *line == ';') + return; + + /* '[section]' parsing... */ + if (*line == '[') { + for (i = 1; i < sz; i++) + if (line[i] == ']') + break; + if (section) + free(section); + if (i == sz) { + log_print("conf_parse_line: %d:" + "non-matched ']', ignoring until next section", ln); + section = 0; + return; + } + section = malloc(i); + if (!section) { + log_print("conf_parse_line: %d: malloc (%lu) failed", ln, + (unsigned long) i); + return; + } + strlcpy(section, line + 1, i); + return; } - strlcpy (section, line + 1, i); - return; - } - - /* Deal with assignments. */ - for (i = 0; i < sz; i++) - if (line[i] == '=') - { - /* If no section, we are ignoring the lines. */ - if (!section) - { - log_print ("conf_parse_line: %d: ignoring line due to no section", - ln); - return; - } - line[strcspn (line, " \t=")] = '\0'; - val = line + i + 1 + strspn (line + i + 1, " \t"); - /* Skip trailing whitespace, if any */ - for (j = sz - (val - line) - 1; j > 0 && isspace (val[j]); j--) - val[j] = '\0'; - /* XXX Perhaps should we not ignore errors? */ - conf_set (trans, section, line, val, 0, 0); - return; - } - - /* Other non-empty lines are weird. */ - i = strspn (line, " \t"); - if (line[i]) - log_print ("conf_parse_line: %d: syntax error", ln); + /* Deal with assignments. */ + for (i = 0; i < sz; i++) + if (line[i] == '=') { + /* If no section, we are ignoring the lines. */ + if (!section) { + log_print("conf_parse_line: %d: ignoring line due to no section", + ln); + return; + } + line[strcspn(line, " \t=")] = '\0'; + val = line + i + 1 + strspn(line + i + 1, " \t"); + /* Skip trailing whitespace, if any */ + for (j = sz - (val - line) - 1; j > 0 && isspace(val[j]); j--) + val[j] = '\0'; + /* XXX Perhaps should we not ignore errors? */ + conf_set(trans, section, line, val, 0, 0); + return; + } + /* Other non-empty lines are weird. */ + i = strspn(line, " \t"); + if (line[i]) + log_print("conf_parse_line: %d: syntax error", ln); - return; + return; } /* Parse the mapped configuration file. */ static void -conf_parse (int trans, char *buf, size_t sz) +conf_parse(int trans, char *buf, size_t sz) { - char *cp = buf; - char *bufend = buf + sz; - char *line; - - line = cp; - while (cp < bufend) - { - if (*cp == '\n') - { - /* Check for escaped newlines. */ - if (cp > buf && *(cp - 1) == '\\') - *(cp - 1) = *cp = ' '; - else - { - *cp = '\0'; - conf_parse_line (trans, line, cp - line); - line = cp + 1; - } + char *cp = buf; + char *bufend = buf + sz; + char *line; + + line = cp; + while (cp < bufend) { + if (*cp == '\n') { + /* Check for escaped newlines. */ + if (cp > buf && *(cp - 1) == '\\') + *(cp - 1) = *cp = ' '; + else { + *cp = '\0'; + conf_parse_line(trans, line, cp - line); + line = cp + 1; + } + } + cp++; } - cp++; - } - if (cp != line) - log_print ("conf_parse: last line non-terminated, ignored."); + if (cp != line) + log_print("conf_parse: last line non-terminated, ignored."); } /* @@ -338,310 +322,328 @@ conf_parse (int trans, char *buf, size_t sz) */ /* Find the value for a section+tag in the transaction list. */ -static char * -conf_get_trans_str (int trans, char *section, char *tag) +static char * +conf_get_trans_str(int trans, char *section, char *tag) { - struct conf_trans *node, *nf = 0; - - for (node = TAILQ_FIRST (&conf_trans_queue); node; - node = TAILQ_NEXT (node, link)) - if (node->trans == trans && strcasecmp (section, node->section) == 0 - && strcasecmp (tag, node->tag) == 0) - { - if (!nf) - nf = node; - else if (node->override) - nf = node; - } - return nf ? nf->value : 0; + struct conf_trans *node, *nf = 0; + + for (node = TAILQ_FIRST(&conf_trans_queue); node; + node = TAILQ_NEXT(node, link)) + if (node->trans == trans && strcasecmp(section, node->section) == 0 + && strcasecmp(tag, node->tag) == 0) { + if (!nf) + nf = node; + else if (node->override) + nf = node; + } + return nf ? nf->value : 0; } #if 0 /* XXX Currently unused. */ static int -conf_find_trans_xf (int phase, char *xf) +conf_find_trans_xf(int phase, char *xf) { - struct conf_trans *node; - char *p; - - /* Find the relevant transforms and suites, if any. */ - for (node = TAILQ_FIRST (&conf_trans_queue); node; - node = TAILQ_NEXT (node, link)) - if ((phase == 1 && strcmp ("Transforms", node->tag) == 0) || - (phase == 2 && strcmp ("Suites", node->tag) == 0)) - { - p = node->value; - while ((p = strstr (p, xf)) != NULL) - if (*(p + strlen (p)) && *(p + strlen (p)) != ',') - p += strlen (p); - else - return 1; - } - return 0; + struct conf_trans *node; + char *p; + + /* Find the relevant transforms and suites, if any. */ + for (node = TAILQ_FIRST(&conf_trans_queue); node; + node = TAILQ_NEXT(node, link)) + if ((phase == 1 && strcmp("Transforms", node->tag) == 0) || + (phase == 2 && strcmp("Suites", node->tag) == 0)) { + p = node->value; + while ((p = strstr(p, xf)) != NULL) + if (*(p + strlen(p)) && *(p + strlen(p)) != ',') + p += strlen(p); + else + return 1; + } + return 0; } #endif static void -conf_load_defaults (int tr) +conf_load_defaults(int tr) { #define CONF_MAX 256 - int enc, auth, hash, group, group_max, proto, mode, pfs; - char sect[CONF_MAX], *dflt; - - char *mm_auth[] = { "PRE_SHARED", "DSS", "RSA_SIG", 0 }; - char *mm_hash[] = { "MD5", "SHA", 0 }; - char *mm_enc[] = { "DES_CBC", "BLOWFISH_CBC", "3DES_CBC", - "CAST_CBC", "AES_CBC", 0 }; - char *dh_group[] = { "MODP_768", "MODP_1024", "MODP_1536", "MODP_2048", 0 }; - char *qm_enc[] = { "DES", "3DES", "CAST", "BLOWFISH", "AES", 0 }; - char *qm_hash[] = { "HMAC_MD5", "HMAC_SHA", "HMAC_RIPEMD", - "HMAC_SHA2_256", "HMAC_SHA2_384", "HMAC_SHA2_512", - "NONE", 0 }; - - /* Abbreviations to make section names a bit shorter. */ - char *mm_auth_p[] = { "", "-DSS", "-RSA_SIG", 0 }; - char *mm_enc_p[] = { "DES", "BLF", "3DES", "CAST", "AES", 0 }; - char *dh_group_p[]= { "-GRP1", "-GRP2", "-GRP5", "-GRP14", "", 0 }; - char *qm_enc_p[] = { "-DES", "-3DES", "-CAST", "-BLF", "-AES", 0 }; - char *qm_hash_p[] = { "-MD5", "-SHA", "-RIPEMD", - "-SHA2-256", "-SHA2-384", "-SHA2-512", - "", 0 }; - - /* Helper #defines, incl abbreviations. */ + int enc, auth, hash, group, group_max, proto, mode, + pfs; + char sect[CONF_MAX], *dflt; + + char *mm_auth[] = {"PRE_SHARED", "DSS", "RSA_SIG", 0}; + char *mm_hash[] = {"MD5", "SHA", 0}; + char *mm_enc[] = {"DES_CBC", "BLOWFISH_CBC", "3DES_CBC", + "CAST_CBC", "AES_CBC", 0}; + char *dh_group[] = {"MODP_768", "MODP_1024", "MODP_1536", "MODP_2048", 0}; + char *qm_enc[] = {"DES", "3DES", "CAST", "BLOWFISH", "AES", 0}; + char *qm_hash[] = {"HMAC_MD5", "HMAC_SHA", "HMAC_RIPEMD", + "HMAC_SHA2_256", "HMAC_SHA2_384", "HMAC_SHA2_512", + "NONE", 0}; + + /* Abbreviations to make section names a bit shorter. */ + char *mm_auth_p[] = {"", "-DSS", "-RSA_SIG", 0}; + char *mm_enc_p[] = {"DES", "BLF", "3DES", "CAST", "AES", 0}; + char *dh_group_p[] = {"-GRP1", "-GRP2", "-GRP5", "-GRP14", "", 0}; + char *qm_enc_p[] = {"-DES", "-3DES", "-CAST", "-BLF", "-AES", 0}; + char *qm_hash_p[] = {"-MD5", "-SHA", "-RIPEMD", + "-SHA2-256", "-SHA2-384", "-SHA2-512", + "", 0}; + + /* Helper #defines, incl abbreviations. */ #define PROTO(x) ((x) ? "AH" : "ESP") #define PFS(x) ((x) ? "-PFS" : "") #define MODE(x) ((x) ? "TRANSPORT" : "TUNNEL") #define MODE_p(x) ((x) ? "-TRP" : "") - group_max = sizeof dh_group / sizeof *dh_group - 1; + group_max = sizeof dh_group / sizeof *dh_group - 1; - /* General and X509 defaults */ - conf_set (tr, "General", "Retransmits", CONF_DFLT_RETRANSMITS, 0, 1); - conf_set (tr, "General", "Exchange-max-time", CONF_DFLT_EXCH_MAX_TIME, 0, 1); - conf_set (tr, "General", "Policy-file", CONF_DFLT_POLICY_FILE, 0, 1); - conf_set (tr, "General", "Pubkey-directory", CONF_DFLT_PUBKEY_DIR, 0, 1); + /* General and X509 defaults */ + conf_set(tr, "General", "Retransmits", CONF_DFLT_RETRANSMITS, 0, 1); + conf_set(tr, "General", "Exchange-max-time", CONF_DFLT_EXCH_MAX_TIME, 0, 1); + conf_set(tr, "General", "Policy-file", CONF_DFLT_POLICY_FILE, 0, 1); + conf_set(tr, "General", "Pubkey-directory", CONF_DFLT_PUBKEY_DIR, 0, 1); #ifdef USE_X509 - conf_set (tr, "X509-certificates", "CA-directory", CONF_DFLT_X509_CA_DIR, 0, - 1); - conf_set (tr, "X509-certificates", "Cert-directory", CONF_DFLT_X509_CERT_DIR, - 0, 1); - conf_set (tr, "X509-certificates", "Private-key", CONF_DFLT_X509_PRIVATE_KEY, - 0, 1); - conf_set (tr, "X509-certificates", "CRL-directory", CONF_DFLT_X509_CRL_DIR, - 0, 1); + conf_set(tr, "X509-certificates", "CA-directory", CONF_DFLT_X509_CA_DIR, 0, + 1); + conf_set(tr, "X509-certificates", "Cert-directory", CONF_DFLT_X509_CERT_DIR, + 0, 1); + conf_set(tr, "X509-certificates", "Private-key", CONF_DFLT_X509_PRIVATE_KEY, + 0, 1); + conf_set(tr, "X509-certificates", "CRL-directory", CONF_DFLT_X509_CRL_DIR, + 0, 1); #endif #ifdef USE_KEYNOTE - conf_set (tr, "KeyNote", "Credential-directory", CONF_DFLT_KEYNOTE_CRED_DIR, - 0, 1); + conf_set(tr, "KeyNote", "Credential-directory", CONF_DFLT_KEYNOTE_CRED_DIR, + 0, 1); #endif - /* Lifetimes. XXX p1/p2 vs main/quick mode may be unclear. */ - dflt = conf_get_trans_str (tr, "General", "Default-phase-1-lifetime"); - conf_set (tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_TYPE", - CONF_DFLT_TYPE_LIFE_MAIN_MODE, 0, 1); - conf_set (tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_DURATION", - (dflt ? dflt : CONF_DFLT_VAL_LIFE_MAIN_MODE), 0, 1); - - dflt = conf_get_trans_str (tr, "General", "Default-phase-2-lifetime"); - conf_set (tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_TYPE", - CONF_DFLT_TYPE_LIFE_QUICK_MODE, 0, 1); - conf_set (tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_DURATION", - (dflt ? dflt : CONF_DFLT_VAL_LIFE_QUICK_MODE), 0, 1); - - /* Default Phase-1 Configuration section */ - conf_set (tr, CONF_DFLT_TAG_PHASE1_CONFIG, "EXCHANGE_TYPE", - CONF_DFLT_PHASE1_EXCH_TYPE, 0, 1); - conf_set (tr, CONF_DFLT_TAG_PHASE1_CONFIG, "Transforms", - CONF_DFLT_PHASE1_TRANSFORMS, 0, 1); - - /* Main modes */ - for (enc = 0; mm_enc[enc]; enc ++) - for (hash = 0; mm_hash[hash]; hash ++) - for (auth = 0; mm_auth[auth]; auth ++) - for (group = 0; dh_group_p[group]; group ++) /* special */ - { - snprintf (sect, sizeof sect, "%s-%s%s%s", mm_enc_p[enc], - mm_hash[hash], dh_group_p[group], mm_auth_p[auth]); + /* Lifetimes. XXX p1/p2 vs main/quick mode may be unclear. */ + dflt = conf_get_trans_str(tr, "General", "Default-phase-1-lifetime"); + conf_set(tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_TYPE", + CONF_DFLT_TYPE_LIFE_MAIN_MODE, 0, 1); + conf_set(tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_DURATION", + (dflt ? dflt : CONF_DFLT_VAL_LIFE_MAIN_MODE), 0, 1); + + dflt = conf_get_trans_str(tr, "General", "Default-phase-2-lifetime"); + conf_set(tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_TYPE", + CONF_DFLT_TYPE_LIFE_QUICK_MODE, 0, 1); + conf_set(tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_DURATION", + (dflt ? dflt : CONF_DFLT_VAL_LIFE_QUICK_MODE), 0, 1); + + /* Default Phase-1 Configuration section */ + conf_set(tr, CONF_DFLT_TAG_PHASE1_CONFIG, "EXCHANGE_TYPE", + CONF_DFLT_PHASE1_EXCH_TYPE, 0, 1); + conf_set(tr, CONF_DFLT_TAG_PHASE1_CONFIG, "Transforms", + CONF_DFLT_PHASE1_TRANSFORMS, 0, 1); + + /* Main modes */ + for (enc = 0; mm_enc[enc]; enc++) + for (hash = 0; mm_hash[hash]; hash++) + for (auth = 0; mm_auth[auth]; auth++) + for (group = 0; dh_group_p[group]; group++) { /* special */ + snprintf(sect, sizeof sect, "%s-%s%s%s", mm_enc_p[enc], + mm_hash[hash], dh_group_p[group], mm_auth_p[auth]); #if 0 - if (!conf_find_trans_xf (1, sect)) - continue; + if (!conf_find_trans_xf(1, sect)) + continue; #endif - LOG_DBG ((LOG_MISC, 90, "conf_load_defaults : main mode %s", - sect)); - - conf_set (tr, sect, "ENCRYPTION_ALGORITHM", mm_enc[enc], 0, 1); - if (strcmp (mm_enc[enc], "BLOWFISH_CBC") == 0) - conf_set (tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, 0, - 1); - - conf_set (tr, sect, "HASH_ALGORITHM", mm_hash[hash], 0, 1); - conf_set (tr, sect, "AUTHENTICATION_METHOD", mm_auth[auth], 0, 1); - - /* XXX Always DH group 2 (MODP_1024) */ - conf_set (tr, sect, "GROUP_DESCRIPTION", - dh_group[group < group_max ? group : 1], 0, 1); - - conf_set (tr, sect, "Life", CONF_DFLT_TAG_LIFE_MAIN_MODE, 0, 1); - } - - /* Setup a default Phase 1 entry */ - conf_set (tr, "Phase 1", "Default", "Default-phase-1", 0, 1); - - conf_set (tr, "Default-phase-1", "Phase", "1", 0, 1); - conf_set (tr, "Default-phase-1", "Configuration", - "Default-phase-1-configuration", 0, 1); - dflt = conf_get_trans_str (tr, "General", "Default-phase-1-ID"); - if (dflt) - conf_set (tr, "Default-phase-1", "ID", dflt, 0, 1); - - /* Quick modes */ - for (enc = 0; qm_enc[enc]; enc ++) - for (proto = 0; proto < 2; proto ++) - for (mode = 0; mode < 2; mode ++) - for (pfs = 0; pfs < 2; pfs ++) - for (hash = 0; qm_hash[hash]; hash ++) - for (group = 0; dh_group_p[group]; group ++) - if ((proto == 1 && strcmp (qm_hash[hash], "NONE") == 0)) /* AH */ - continue; - else - { - char tmp[CONF_MAX]; - - snprintf (tmp, sizeof tmp, "QM-%s%s%s%s%s%s", PROTO (proto), - MODE_p (mode), qm_enc_p[enc], qm_hash_p[hash], - PFS (pfs), dh_group_p[group]); - - strlcpy (sect, tmp, CONF_MAX); - strlcat (sect, "-SUITE", CONF_MAX); + LOG_DBG((LOG_MISC, 90, "conf_load_defaults : main mode %s", + sect)); + + conf_set(tr, sect, "ENCRYPTION_ALGORITHM", mm_enc[enc], 0, 1); + if (strcmp(mm_enc[enc], "BLOWFISH_CBC") == 0) + conf_set(tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, 0, + 1); + + conf_set(tr, sect, "HASH_ALGORITHM", mm_hash[hash], 0, 1); + conf_set(tr, sect, "AUTHENTICATION_METHOD", mm_auth[auth], 0, 1); + + /* XXX Always DH group 2 (MODP_1024) */ + conf_set(tr, sect, "GROUP_DESCRIPTION", + dh_group[group < group_max ? group : 1], 0, 1); + + conf_set(tr, sect, "Life", CONF_DFLT_TAG_LIFE_MAIN_MODE, 0, 1); + } + + /* Setup a default Phase 1 entry */ + conf_set(tr, "Phase 1", "Default", "Default-phase-1", 0, 1); + + conf_set(tr, "Default-phase-1", "Phase", "1", 0, 1); + conf_set(tr, "Default-phase-1", "Configuration", + "Default-phase-1-configuration", 0, 1); + dflt = conf_get_trans_str(tr, "General", "Default-phase-1-ID"); + if (dflt) + conf_set(tr, "Default-phase-1", "ID", dflt, 0, 1); + + /* Quick modes */ + for (enc = 0; qm_enc[enc]; enc++) + for (proto = 0; proto < 2; proto++) + for (mode = 0; mode < 2; mode++) + for (pfs = 0; pfs < 2; pfs++) + for (hash = 0; qm_hash[hash]; hash++) + for (group = 0; dh_group_p[group]; group++) + if ((proto == 1 && strcmp(qm_hash[hash], "NONE") == 0)) /* AH */ + continue; + else { + char tmp[CONF_MAX]; + + snprintf(tmp, sizeof tmp, "QM-%s%s%s%s%s%s", PROTO(proto), + MODE_p(mode), qm_enc_p[enc], qm_hash_p[hash], + PFS(pfs), dh_group_p[group]); + + strlcpy(sect, tmp, CONF_MAX); + strlcat(sect, "-SUITE", CONF_MAX); #if 0 - if (!conf_find_trans_xf (2, sect)) - continue; + if (!conf_find_trans_xf(2, sect)) + continue; #endif - LOG_DBG ((LOG_MISC, 90, "conf_load_defaults : quick mode %s", - sect)); - - conf_set (tr, sect, "Protocols", tmp, 0, 1); - - snprintf (sect, sizeof sect, "IPSEC_%s", PROTO (proto)); - conf_set (tr, tmp, "PROTOCOL_ID", sect, 0, 1); - - strlcpy (sect, tmp, CONF_MAX); - strlcat (sect, "-XF", CONF_MAX); - conf_set (tr, tmp, "Transforms", sect, 0, 1); - - /* XXX For now, defaults contain one xf per protocol. */ - - conf_set (tr, sect, "TRANSFORM_ID", qm_enc[enc], 0, 1); - - if (strcmp (qm_enc[enc], "BLOWFISH") == 0) - conf_set (tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, - 0, 1); - - conf_set (tr, sect, "ENCAPSULATION_MODE", MODE (mode), 0, 1); - - if (strcmp (qm_hash[hash], "NONE")) - { - conf_set (tr, sect, "AUTHENTICATION_ALGORITHM", - qm_hash[hash], 0, 1); - - /* XXX Another shortcut -- to keep length down. */ - if (pfs) - conf_set (tr, sect, "GROUP_DESCRIPTION", - dh_group[group < group_max ? group : 1], 0, - 1); - } - - /* XXX Lifetimes depending on enc/auth strength? */ - conf_set (tr, sect, "Life", CONF_DFLT_TAG_LIFE_QUICK_MODE, 0, - 1); - } - return; + LOG_DBG((LOG_MISC, 90, "conf_load_defaults : quick mode %s", + sect)); + + conf_set(tr, sect, "Protocols", tmp, 0, 1); + + snprintf(sect, sizeof sect, "IPSEC_%s", PROTO(proto)); + conf_set(tr, tmp, "PROTOCOL_ID", sect, 0, 1); + + strlcpy(sect, tmp, CONF_MAX); + strlcat(sect, "-XF", CONF_MAX); + conf_set(tr, tmp, "Transforms", sect, 0, 1); + + /* + * XXX For + * now, + * defaults + * contain + * one xf per + * protocol. + */ + + conf_set(tr, sect, "TRANSFORM_ID", qm_enc[enc], 0, 1); + + if (strcmp(qm_enc[enc], "BLOWFISH") == 0) + conf_set(tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, + 0, 1); + + conf_set(tr, sect, "ENCAPSULATION_MODE", MODE(mode), 0, 1); + + if (strcmp(qm_hash[hash], "NONE")) { + conf_set(tr, sect, "AUTHENTICATION_ALGORITHM", + qm_hash[hash], 0, 1); + + /* + * XXX + * + * Ano + * the + * r + * sho + * rtc + * ut + * -- + * to + * kee + * p + * len + * gth + * + * dow + * n. + */ + if (pfs) + conf_set(tr, sect, "GROUP_DESCRIPTION", + dh_group[group < group_max ? group : 1], 0, + 1); + } + /* + * XXX + * Lifetimes + * depending + * on + * enc/auth + * strength? + */ + conf_set(tr, sect, "Life", CONF_DFLT_TAG_LIFE_QUICK_MODE, 0, + 1); + } + return; } void -conf_init (void) +conf_init(void) { - unsigned int i; + unsigned int i; - for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) - LIST_INIT (&conf_bindings[i]); - TAILQ_INIT (&conf_trans_queue); - conf_reinit (); + for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) + LIST_INIT(&conf_bindings[i]); + TAILQ_INIT(&conf_trans_queue); + conf_reinit(); } /* Open the config file and map it into our address space, then parse it. */ void -conf_reinit (void) +conf_reinit(void) { - struct conf_binding *cb = 0; - int fd, trans; - unsigned int i; - size_t sz; - char *new_conf_addr = 0; - struct stat sb; - - if ((monitor_stat (conf_path, &sb) == 0) || (errno != ENOENT)) - { - if (check_file_secrecy (conf_path, &sz)) - return; - - fd = monitor_open (conf_path, O_RDONLY, 0); - if (fd == -1) - { - log_error ("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path); - return; - } - - new_conf_addr = malloc (sz); - if (!new_conf_addr) - { - log_error ("conf_reinit: malloc (%lu) failed", (unsigned long)sz); - goto fail; + struct conf_binding *cb = 0; + int fd, trans; + unsigned int i; + size_t sz; + char *new_conf_addr = 0; + struct stat sb; + + if ((monitor_stat(conf_path, &sb) == 0) || (errno != ENOENT)) { + if (check_file_secrecy(conf_path, &sz)) + return; + + fd = monitor_open(conf_path, O_RDONLY, 0); + if (fd == -1) { + log_error("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path); + return; + } + new_conf_addr = malloc(sz); + if (!new_conf_addr) { + log_error("conf_reinit: malloc (%lu) failed", (unsigned long) sz); + goto fail; + } + /* XXX I assume short reads won't happen here. */ + if (read(fd, new_conf_addr, sz) != (int) sz) { + log_error("conf_reinit: read (%d, %p, %lu) failed", + fd, new_conf_addr, (unsigned long) sz); + goto fail; + } + close(fd); + + trans = conf_begin(); + + /* XXX Should we not care about errors and rollback? */ + conf_parse(trans, new_conf_addr, sz); + } else + trans = conf_begin(); + + /* Load default configuration values. */ + conf_load_defaults(trans); + + /* Free potential existing configuration. */ + if (conf_addr) { + for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) + for (cb = LIST_FIRST(&conf_bindings[i]); cb; + cb = LIST_FIRST(&conf_bindings[i])) + conf_remove_now(cb->section, cb->tag); + free(conf_addr); } + conf_end(trans, 1); + conf_addr = new_conf_addr; + return; - /* XXX I assume short reads won't happen here. */ - if (read (fd, new_conf_addr, sz) != (int)sz) - { - log_error ("conf_reinit: read (%d, %p, %lu) failed", - fd, new_conf_addr, (unsigned long)sz); - goto fail; - } - close (fd); - - trans = conf_begin (); - - /* XXX Should we not care about errors and rollback? */ - conf_parse (trans, new_conf_addr, sz); - } - else - trans = conf_begin (); - - /* Load default configuration values. */ - conf_load_defaults (trans); - - /* Free potential existing configuration. */ - if (conf_addr) - { - for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) - for (cb = LIST_FIRST (&conf_bindings[i]); cb; - cb = LIST_FIRST (&conf_bindings[i])) - conf_remove_now (cb->section, cb->tag); - free (conf_addr); - } - - conf_end (trans, 1); - conf_addr = new_conf_addr; - return; - - fail: - if (new_conf_addr) - free (new_conf_addr); - close (fd); +fail: + if (new_conf_addr) + free(new_conf_addr); + close(fd); } /* @@ -649,13 +651,13 @@ conf_reinit (void) * if that tag does not exist. */ int -conf_get_num (char *section, char *tag, int def) +conf_get_num(char *section, char *tag, int def) { - char *value = conf_get_str (section, tag); + char *value = conf_get_str(section, tag); - if (value) - return atoi (value); - return def; + if (value) + return atoi(value); + return def; } /* @@ -664,64 +666,62 @@ conf_get_num (char *section, char *tag, int def) * this structure when it is finished with it. */ struct sockaddr * -conf_get_address (char *section, char *tag) +conf_get_address(char *section, char *tag) { - char *value = conf_get_str (section, tag); - struct sockaddr *sa; - - if (!value) - return 0; - if (text2sockaddr (value, 0, &sa) == -1) - return 0; - return sa; + char *value = conf_get_str(section, tag); + struct sockaddr *sa; + + if (!value) + return 0; + if (text2sockaddr(value, 0, &sa) == -1) + return 0; + return sa; } /* Validate X according to the range denoted by TAG in section SECTION. */ int -conf_match_num (char *section, char *tag, int x) +conf_match_num(char *section, char *tag, int x) { - char *value = conf_get_str (section, tag); - int val, min, max, n; - - if (!value) - return 0; - n = sscanf (value, "%d,%d:%d", &val, &min, &max); - switch (n) - { - case 1: - LOG_DBG ((LOG_MISC, 90, "conf_match_num: %s:%s %d==%d?", section, tag, - val, x)); - return x == val; - case 3: - LOG_DBG ((LOG_MISC, 90, "conf_match_num: %s:%s %d<=%d<=%d?", section, - tag, min, x, max)); - return min <= x && max >= x; - default: - log_error ("conf_match_num: section %s tag %s: invalid number spec %s", - section, tag, value); - } - return 0; + char *value = conf_get_str(section, tag); + int val, min, max, n; + + if (!value) + return 0; + n = sscanf(value, "%d,%d:%d", &val, &min, &max); + switch (n) { + case 1: + LOG_DBG((LOG_MISC, 90, "conf_match_num: %s:%s %d==%d?", section, tag, + val, x)); + return x == val; + case 3: + LOG_DBG((LOG_MISC, 90, "conf_match_num: %s:%s %d<=%d<=%d?", section, + tag, min, x, max)); + return min <= x && max >= x; + default: + log_error("conf_match_num: section %s tag %s: invalid number spec %s", + section, tag, value); + } + return 0; } /* Return the string value denoted by TAG in section SECTION. */ -char * -conf_get_str (char *section, char *tag) +char * +conf_get_str(char *section, char *tag) { - struct conf_binding *cb; - - for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; - cb = LIST_NEXT (cb, link)) - if (strcasecmp (section, cb->section) == 0 - && strcasecmp (tag, cb->tag) == 0) - { - LOG_DBG ((LOG_MISC, 95, "conf_get_str: [%s]:%s->%s", section, - tag, cb->value)); - return cb->value; - } - LOG_DBG ((LOG_MISC, 95, - "conf_get_str: configuration value not found [%s]:%s", section, - tag)); - return 0; + struct conf_binding *cb; + + for (cb = LIST_FIRST(&conf_bindings[conf_hash(section)]); cb; + cb = LIST_NEXT(cb, link)) + if (strcasecmp(section, cb->section) == 0 + && strcasecmp(tag, cb->tag) == 0) { + LOG_DBG((LOG_MISC, 95, "conf_get_str: [%s]:%s->%s", section, + tag, cb->value)); + return cb->value; + } + LOG_DBG((LOG_MISC, 95, + "conf_get_str: configuration value not found [%s]:%s", section, + tag)); + return 0; } /* @@ -729,332 +729,312 @@ conf_get_str (char *section, char *tag) * TAG in SECTION. */ struct conf_list * -conf_get_list (char *section, char *tag) +conf_get_list(char *section, char *tag) { - char *liststr = 0, *p, *field, *t; - struct conf_list *list = 0; - struct conf_list_node *node; - - list = malloc (sizeof *list); - if (!list) - goto cleanup; - TAILQ_INIT (&list->fields); - list->cnt = 0; - liststr = conf_get_str (section, tag); - if (!liststr) - goto cleanup; - liststr = strdup (liststr); - if (!liststr) - goto cleanup; - p = liststr; - while ((field = strsep (&p, ",")) != NULL) - { - /* Skip leading whitespace */ - while (isspace (*field)) - field++; - /* Skip trailing whitespace */ - if (p) - for (t = p - 1; t > field && isspace (*t); t--) - *t = '\0'; - if (*field == '\0') - { - log_print ("conf_get_list: empty field, ignoring..."); - continue; + char *liststr = 0, *p, *field, *t; + struct conf_list *list = 0; + struct conf_list_node *node; + + list = malloc(sizeof *list); + if (!list) + goto cleanup; + TAILQ_INIT(&list->fields); + list->cnt = 0; + liststr = conf_get_str(section, tag); + if (!liststr) + goto cleanup; + liststr = strdup(liststr); + if (!liststr) + goto cleanup; + p = liststr; + while ((field = strsep(&p, ",")) != NULL) { + /* Skip leading whitespace */ + while (isspace(*field)) + field++; + /* Skip trailing whitespace */ + if (p) + for (t = p - 1; t > field && isspace(*t); t--) + *t = '\0'; + if (*field == '\0') { + log_print("conf_get_list: empty field, ignoring..."); + continue; + } + list->cnt++; + node = calloc(1, sizeof *node); + if (!node) + goto cleanup; + node->field = strdup(field); + if (!node->field) + goto cleanup; + TAILQ_INSERT_TAIL(&list->fields, node, link); } - list->cnt++; - node = calloc (1, sizeof *node); - if (!node) - goto cleanup; - node->field = strdup (field); - if (!node->field) - goto cleanup; - TAILQ_INSERT_TAIL (&list->fields, node, link); - } - free (liststr); - return list; - - cleanup: - if (list) - conf_free_list (list); - if (liststr) - free (liststr); - return 0; + free(liststr); + return list; + +cleanup: + if (list) + conf_free_list(list); + if (liststr) + free(liststr); + return 0; } struct conf_list * -conf_get_tag_list (char *section) +conf_get_tag_list(char *section) { - struct conf_list *list = 0; - struct conf_list_node *node; - struct conf_binding *cb; - - list = malloc (sizeof *list); - if (!list) - goto cleanup; - TAILQ_INIT (&list->fields); - list->cnt = 0; - for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; - cb = LIST_NEXT (cb, link)) - if (strcasecmp (section, cb->section) == 0) - { - list->cnt++; - node = calloc (1, sizeof *node); - if (!node) - goto cleanup; - node->field = strdup (cb->tag); - if (!node->field) - goto cleanup; - TAILQ_INSERT_TAIL (&list->fields, node, link); - } - return list; - - cleanup: - if (list) - conf_free_list (list); - return 0; + struct conf_list *list = 0; + struct conf_list_node *node; + struct conf_binding *cb; + + list = malloc(sizeof *list); + if (!list) + goto cleanup; + TAILQ_INIT(&list->fields); + list->cnt = 0; + for (cb = LIST_FIRST(&conf_bindings[conf_hash(section)]); cb; + cb = LIST_NEXT(cb, link)) + if (strcasecmp(section, cb->section) == 0) { + list->cnt++; + node = calloc(1, sizeof *node); + if (!node) + goto cleanup; + node->field = strdup(cb->tag); + if (!node->field) + goto cleanup; + TAILQ_INSERT_TAIL(&list->fields, node, link); + } + return list; + +cleanup: + if (list) + conf_free_list(list); + return 0; } /* Decode a PEM encoded buffer. */ int -conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf) +conf_decode_base64(u_int8_t * out, u_int32_t * len, u_char * buf) { - u_int32_t c = 0; - u_int8_t c1, c2, c3, c4; - - while (*buf) - { - if (*buf > 127 || (c1 = asc2bin[*buf]) == 255) - return 0; - buf++; - - if (*buf > 127 || (c2 = asc2bin[*buf]) == 255) - return 0; - buf++; - - if (*buf == '=') - { - c3 = c4 = 0; - c++; - - /* Check last four bit */ - if (c2 & 0xF) - return 0; - - if (strcmp ((char *)buf, "==") == 0) - buf++; - else - return 0; + u_int32_t c = 0; + u_int8_t c1, c2, c3, c4; + + while (*buf) { + if (*buf > 127 || (c1 = asc2bin[*buf]) == 255) + return 0; + buf++; + + if (*buf > 127 || (c2 = asc2bin[*buf]) == 255) + return 0; + buf++; + + if (*buf == '=') { + c3 = c4 = 0; + c++; + + /* Check last four bit */ + if (c2 & 0xF) + return 0; + + if (strcmp((char *) buf, "==") == 0) + buf++; + else + return 0; + } else if (*buf > 127 || (c3 = asc2bin[*buf]) == 255) + return 0; + else { + if (*++buf == '=') { + c4 = 0; + c += 2; + + /* Check last two bit */ + if (c3 & 3) + return 0; + + if (strcmp((char *) buf, "=")) + return 0; + + } else if (*buf > 127 || (c4 = asc2bin[*buf]) == 255) + return 0; + else + c += 3; + } + + buf++; + *out++ = (c1 << 2) | (c2 >> 4); + *out++ = (c2 << 4) | (c3 >> 2); + *out++ = (c3 << 6) | c4; } - else if (*buf > 127 || (c3 = asc2bin[*buf]) == 255) - return 0; - else - { - if (*++buf == '=') - { - c4 = 0; - c += 2; - /* Check last two bit */ - if (c3 & 3) - return 0; - - if (strcmp ((char *)buf, "=")) - return 0; - - } - else if (*buf > 127 || (c4 = asc2bin[*buf]) == 255) - return 0; - else - c += 3; - } - - buf++; - *out++ = (c1 << 2) | (c2 >> 4); - *out++ = (c2 << 4) | (c3 >> 2); - *out++ = (c3 << 6) | c4; - } - - *len = c; - return 1; + *len = c; + return 1; } void -conf_free_list (struct conf_list *list) +conf_free_list(struct conf_list * list) { - struct conf_list_node *node = TAILQ_FIRST (&list->fields); - - while (node) - { - TAILQ_REMOVE (&list->fields, node, link); - if (node->field) - free (node->field); - free (node); - node = TAILQ_FIRST (&list->fields); - } - free (list); + struct conf_list_node *node = TAILQ_FIRST(&list->fields); + + while (node) { + TAILQ_REMOVE(&list->fields, node, link); + if (node->field) + free(node->field); + free(node); + node = TAILQ_FIRST(&list->fields); + } + free(list); } int -conf_begin (void) +conf_begin(void) { - static int seq = 0; + static int seq = 0; - return ++seq; + return ++seq; } static struct conf_trans * -conf_trans_node (int transaction, enum conf_op op) +conf_trans_node(int transaction, enum conf_op op) { - struct conf_trans *node; - - node = calloc (1, sizeof *node); - if (!node) - { - log_error ("conf_trans_node: calloc (1, %lu) failed", - (unsigned long)sizeof *node); - return 0; - } - node->trans = transaction; - node->op = op; - TAILQ_INSERT_TAIL (&conf_trans_queue, node, link); - return node; + struct conf_trans *node; + + node = calloc(1, sizeof *node); + if (!node) { + log_error("conf_trans_node: calloc (1, %lu) failed", + (unsigned long) sizeof *node); + return 0; + } + node->trans = transaction; + node->op = op; + TAILQ_INSERT_TAIL(&conf_trans_queue, node, link); + return node; } /* Queue a set operation. */ int -conf_set (int transaction, char *section, char *tag, char *value, int override, - int is_default) +conf_set(int transaction, char *section, char *tag, char *value, int override, + int is_default) { - struct conf_trans *node; - - node = conf_trans_node (transaction, CONF_SET); - if (!node) - return 1; - node->section = strdup (section); - if (!node->section) - { - log_error ("conf_set: strdup (\"%s\") failed", section); - goto fail; - } - node->tag = strdup (tag); - if (!node->tag) - { - log_error ("conf_set: strdup (\"%s\") failed", tag); - goto fail; - } - node->value = strdup (value); - if (!node->value) - { - log_error ("conf_set: strdup (\"%s\") failed", value); - goto fail; - } - node->override = override; - node->is_default = is_default; - return 0; - - fail: - if (node->tag) - free (node->tag); - if (node->section) - free (node->section); - if (node) - free (node); - return 1; + struct conf_trans *node; + + node = conf_trans_node(transaction, CONF_SET); + if (!node) + return 1; + node->section = strdup(section); + if (!node->section) { + log_error("conf_set: strdup (\"%s\") failed", section); + goto fail; + } + node->tag = strdup(tag); + if (!node->tag) { + log_error("conf_set: strdup (\"%s\") failed", tag); + goto fail; + } + node->value = strdup(value); + if (!node->value) { + log_error("conf_set: strdup (\"%s\") failed", value); + goto fail; + } + node->override = override; + node->is_default = is_default; + return 0; + +fail: + if (node->tag) + free(node->tag); + if (node->section) + free(node->section); + if (node) + free(node); + return 1; } /* Queue a remove operation. */ int -conf_remove (int transaction, char *section, char *tag) +conf_remove(int transaction, char *section, char *tag) { - struct conf_trans *node; - - node = conf_trans_node (transaction, CONF_REMOVE); - if (!node) - goto fail; - node->section = strdup (section); - if (!node->section) - { - log_error ("conf_remove: strdup (\"%s\") failed", section); - goto fail; - } - node->tag = strdup (tag); - if (!node->tag) - { - log_error ("conf_remove: strdup (\"%s\") failed", tag); - goto fail; - } - return 0; - - fail: - if (node->section) - free (node->section); - if (node) - free (node); - return 1; + struct conf_trans *node; + + node = conf_trans_node(transaction, CONF_REMOVE); + if (!node) + goto fail; + node->section = strdup(section); + if (!node->section) { + log_error("conf_remove: strdup (\"%s\") failed", section); + goto fail; + } + node->tag = strdup(tag); + if (!node->tag) { + log_error("conf_remove: strdup (\"%s\") failed", tag); + goto fail; + } + return 0; + +fail: + if (node->section) + free(node->section); + if (node) + free(node); + return 1; } /* Queue a remove section operation. */ int -conf_remove_section (int transaction, char *section) +conf_remove_section(int transaction, char *section) { - struct conf_trans *node; - - node = conf_trans_node (transaction, CONF_REMOVE_SECTION); - if (!node) - goto fail; - node->section = strdup (section); - if (!node->section) - { - log_error ("conf_remove_section: strdup (\"%s\") failed", section); - goto fail; - } - return 0; - - fail: - if (node) - free (node); - return 1; + struct conf_trans *node; + + node = conf_trans_node(transaction, CONF_REMOVE_SECTION); + if (!node) + goto fail; + node->section = strdup(section); + if (!node->section) { + log_error("conf_remove_section: strdup (\"%s\") failed", section); + goto fail; + } + return 0; + +fail: + if (node) + free(node); + return 1; } /* Execute all queued operations for this transaction. Cleanup. */ int -conf_end (int transaction, int commit) +conf_end(int transaction, int commit) { - struct conf_trans *node, *next; - - for (node = TAILQ_FIRST (&conf_trans_queue); node; node = next) - { - next = TAILQ_NEXT (node, link); - if (node->trans == transaction) - { - if (commit) - switch (node->op) - { - case CONF_SET: - conf_set_now (node->section, node->tag, node->value, - node->override, node->is_default); - break; - case CONF_REMOVE: - conf_remove_now (node->section, node->tag); - break; - case CONF_REMOVE_SECTION: - conf_remove_section_now (node->section); - break; - default: - log_print ("conf_end: unknown operation: %d", node->op); - } - TAILQ_REMOVE (&conf_trans_queue, node, link); - if (node->section) - free (node->section); - if (node->tag) - free (node->tag); - if (node->value) - free (node->value); - free (node); + struct conf_trans *node, *next; + + for (node = TAILQ_FIRST(&conf_trans_queue); node; node = next) { + next = TAILQ_NEXT(node, link); + if (node->trans == transaction) { + if (commit) + switch (node->op) { + case CONF_SET: + conf_set_now(node->section, node->tag, node->value, + node->override, node->is_default); + break; + case CONF_REMOVE: + conf_remove_now(node->section, node->tag); + break; + case CONF_REMOVE_SECTION: + conf_remove_section_now(node->section); + break; + default: + log_print("conf_end: unknown operation: %d", node->op); + } + TAILQ_REMOVE(&conf_trans_queue, node, link); + if (node->section) + free(node->section); + if (node->tag) + free(node->tag); + if (node->value) + free(node->value); + free(node); + } } - } - return 0; + return 0; } /* @@ -1062,107 +1042,98 @@ conf_end (int transaction, int commit) * Configuration is "stored in reverse order", so reverse it again. */ struct dumper { - char *s, *v; - struct dumper *next; + char *s, *v; + struct dumper *next; }; static void -conf_report_dump (struct dumper *node) +conf_report_dump(struct dumper * node) { - /* Recursive, cleanup when we're done. */ - - if (node->next) - conf_report_dump (node->next); + /* Recursive, cleanup when we're done. */ - if (node->v) - LOG_DBG ((LOG_REPORT, 0, "%s=\t%s", node->s, node->v)); - else if (node->s) - { - LOG_DBG ((LOG_REPORT, 0, "%s", node->s)); - if (strlen (node->s) > 0) - free (node->s); - } + if (node->next) + conf_report_dump(node->next); - free (node); + if (node->v) + LOG_DBG((LOG_REPORT, 0, "%s=\t%s", node->s, node->v)); + else if (node->s) { + LOG_DBG((LOG_REPORT, 0, "%s", node->s)); + if (strlen(node->s) > 0) + free(node->s); + } + free(node); } void -conf_report (void) +conf_report(void) { - struct conf_binding *cb, *last = 0; - unsigned int i, len; - char *current_section = (char *)0; - struct dumper *dumper, *dnode; - - dumper = dnode = (struct dumper *)calloc (1, sizeof *dumper); - if (!dumper) - goto mem_fail; - - LOG_DBG ((LOG_REPORT, 0, "conf_report: dumping running configuration")); - - for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) - for (cb = LIST_FIRST (&conf_bindings[i]); cb; - cb = LIST_NEXT (cb, link)) - { - if (!cb->is_default) - { - /* Dump this entry. */ - if (!current_section || strcmp (cb->section, current_section)) - { - if (current_section) - { - len = strlen (current_section) + 3; - dnode->s = malloc (len); - if (!dnode->s) - goto mem_fail; - - snprintf (dnode->s, len, "[%s]", current_section); - dnode->next - = (struct dumper *)calloc (1, sizeof (struct dumper)); - dnode = dnode->next; - if (!dnode) - goto mem_fail; - - dnode->s = ""; - dnode->next - = (struct dumper *)calloc (1, sizeof (struct dumper)); - dnode = dnode->next; - if (!dnode) - goto mem_fail; - } - current_section = cb->section; - } - dnode->s = cb->tag; - dnode->v = cb->value; - dnode->next = (struct dumper *)calloc (1, sizeof (struct dumper)); - dnode = dnode->next; - if (!dnode) - goto mem_fail; - last = cb; - } - } - - if (last) - { - len = strlen (last->section) + 3; - dnode->s = malloc (len); - if (!dnode->s) - goto mem_fail; - snprintf (dnode->s, len, "[%s]", last->section); - } - - conf_report_dump (dumper); - - return; - - mem_fail: - log_error ("conf_report: malloc/calloc failed"); - while ((dnode = dumper) != 0) - { - dumper = dumper->next; - if (dnode->s) - free (dnode->s); - free (dnode); - } - return; + struct conf_binding *cb, *last = 0; + unsigned int i, len; + char *current_section = (char *) 0; + struct dumper *dumper, *dnode; + + dumper = dnode = (struct dumper *) calloc(1, sizeof *dumper); + if (!dumper) + goto mem_fail; + + LOG_DBG((LOG_REPORT, 0, "conf_report: dumping running configuration")); + + for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) + for (cb = LIST_FIRST(&conf_bindings[i]); cb; + cb = LIST_NEXT(cb, link)) { + if (!cb->is_default) { + /* Dump this entry. */ + if (!current_section || strcmp(cb->section, current_section)) { + if (current_section) { + len = strlen(current_section) + 3; + dnode->s = malloc(len); + if (!dnode->s) + goto mem_fail; + + snprintf(dnode->s, len, "[%s]", current_section); + dnode->next + = (struct dumper *) calloc(1, sizeof(struct dumper)); + dnode = dnode->next; + if (!dnode) + goto mem_fail; + + dnode->s = ""; + dnode->next + = (struct dumper *) calloc(1, sizeof(struct dumper)); + dnode = dnode->next; + if (!dnode) + goto mem_fail; + } + current_section = cb->section; + } + dnode->s = cb->tag; + dnode->v = cb->value; + dnode->next = (struct dumper *) calloc(1, sizeof(struct dumper)); + dnode = dnode->next; + if (!dnode) + goto mem_fail; + last = cb; + } + } + + if (last) { + len = strlen(last->section) + 3; + dnode->s = malloc(len); + if (!dnode->s) + goto mem_fail; + snprintf(dnode->s, len, "[%s]", last->section); + } + conf_report_dump(dumper); + + return; + +mem_fail: + log_error("conf_report: malloc/calloc failed"); + while ((dnode = dumper) != 0) { + dumper = dumper->next; + if (dnode->s) + free(dnode->s); + free(dnode); + } + return; } diff --git a/sbin/isakmpd/conf.h b/sbin/isakmpd/conf.h index cac8d139141..b45d896ab60 100644 --- a/sbin/isakmpd/conf.h +++ b/sbin/isakmpd/conf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: conf.h,v 1.26 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: conf.h,v 1.13 2000/09/18 00:01:47 ho Exp $ */ +/* $OpenBSD: conf.h,v 1.27 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: conf.h,v 1.13 2000/09/18 00:01:47 ho Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -70,32 +70,32 @@ #define CONF_DFLT_PHASE1_TRANSFORMS "3DES-SHA-RSA_SIG" struct conf_list_node { - TAILQ_ENTRY (conf_list_node) link; - char *field; + TAILQ_ENTRY(conf_list_node) link; + char *field; }; struct conf_list { - size_t cnt; - TAILQ_HEAD (conf_list_fields_head, conf_list_node) fields; + size_t cnt; + TAILQ_HEAD(conf_list_fields_head, conf_list_node) fields; }; -extern char *conf_path; - -extern int conf_begin (void); -extern int conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf); -extern int conf_end (int, int); -extern void conf_free_list (struct conf_list *); -extern struct sockaddr *conf_get_address (char *, char *); -extern struct conf_list *conf_get_list (char *, char *); -extern struct conf_list *conf_get_tag_list (char *); -extern int conf_get_num (char *, char *, int); -extern char *conf_get_str (char *, char *); -extern void conf_init (void); -extern int conf_match_num (char *, char *, int); -extern void conf_reinit (void); -extern int conf_remove (int, char *, char *); -extern int conf_remove_section (int, char *); -extern int conf_set (int, char *, char *, char *, int, int); -extern void conf_report (void); - -#endif /* _CONF_H_ */ +extern char *conf_path; + +extern int conf_begin(void); +extern int conf_decode_base64(u_int8_t * out, u_int32_t * len, u_char * buf); +extern int conf_end(int, int); +extern void conf_free_list(struct conf_list *); +extern struct sockaddr *conf_get_address(char *, char *); +extern struct conf_list *conf_get_list(char *, char *); +extern struct conf_list *conf_get_tag_list(char *); +extern int conf_get_num(char *, char *, int); +extern char *conf_get_str(char *, char *); +extern void conf_init(void); +extern int conf_match_num(char *, char *, int); +extern void conf_reinit(void); +extern int conf_remove(int, char *, char *); +extern int conf_remove_section(int, char *); +extern int conf_set(int, char *, char *, char *, int, int); +extern void conf_report(void); + +#endif /* _CONF_H_ */ diff --git a/sbin/isakmpd/connection.c b/sbin/isakmpd/connection.c index 05236c70df6..d855ed66509 100644 --- a/sbin/isakmpd/connection.c +++ b/sbin/isakmpd/connection.c @@ -1,5 +1,5 @@ -/* $OpenBSD: connection.c,v 1.25 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: connection.c,v 1.28 2000/11/23 12:21:18 niklas Exp $ */ +/* $OpenBSD: connection.c,v 1.26 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: connection.c,v 1.28 2000/11/23 12:21:18 niklas Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -53,143 +53,137 @@ /* How often should we check that connections we require to be up, are up? */ #define CHECK_INTERVAL 60 -static void connection_passive_teardown (char *); +static void connection_passive_teardown(char *); -struct connection -{ - TAILQ_ENTRY (connection) link; - char *name; - struct event *ev; +struct connection { + TAILQ_ENTRY(connection) link; + char *name; + struct event *ev; }; -struct connection_passive -{ - TAILQ_ENTRY (connection_passive) link; - char *name; - u_int8_t *local_id, *remote_id; - size_t local_sz, remote_sz; +struct connection_passive { + TAILQ_ENTRY(connection_passive) link; + char *name; + u_int8_t *local_id, *remote_id; + size_t local_sz, remote_sz; #if 0 - /* XXX Potential additions to 'connection_passive'. */ - char *isakmp_peer; - struct sa *sa; /* XXX "Soft" ref to active sa? */ - struct timeval sa_expiration; /* XXX *sa may expire. */ + /* XXX Potential additions to 'connection_passive'. */ + char *isakmp_peer; + struct sa *sa; /* XXX "Soft" ref to active sa? */ + struct timeval sa_expiration; /* XXX *sa may expire. */ #endif }; -TAILQ_HEAD (connection_head, connection) connections; -TAILQ_HEAD (passive_head, connection_passive) connections_passive; +TAILQ_HEAD(connection_head, connection) connections; +TAILQ_HEAD(passive_head, connection_passive) connections_passive; /* * This is where we setup all the connections we want there right from the * start. */ void -connection_init (void) +connection_init(void) { - struct conf_list *conns, *attrs; - struct conf_list_node *conn, *attr = NULL; - - /* - * Passive connections normally include: all "active" connections that - * are not flagged "Active-Only", plus all connections listed in - * the 'Passive-Connections' list. - */ - - TAILQ_INIT (&connections); - TAILQ_INIT (&connections_passive); - - conns = conf_get_list ("Phase 2", "Connections"); - if (conns) - { - for (conn = TAILQ_FIRST (&conns->fields); conn; - conn = TAILQ_NEXT (conn, link)) - { - if (connection_setup (conn->field)) - log_print ("connection_init: could not setup \"%s\"", conn->field); - - /* XXX Break/abort here if connection_setup failed? */ - - /* - * XXX This code (i.e. the attribute lookup) seems like a - * likely candidate for factoring out into a function of its - * own. - */ - attrs = conf_get_list (conn->field, "Flags"); - if (attrs) - for (attr = TAILQ_FIRST (&attrs->fields); attr; - attr = TAILQ_NEXT (attr, link)) - if (strcasecmp ("active-only", attr->field) == 0) - break; - if (!attrs || (attrs && !attr)) - if (connection_record_passive (conn->field)) - log_print ("connection_init: could not record " - "connection \"%s\"", conn->field); - if (attrs) - conf_free_list (attrs); - + struct conf_list *conns, *attrs; + struct conf_list_node *conn, *attr = NULL; + + /* + * Passive connections normally include: all "active" connections that + * are not flagged "Active-Only", plus all connections listed in + * the 'Passive-Connections' list. + */ + TAILQ_INIT(&connections); + TAILQ_INIT(&connections_passive); + + conns = conf_get_list("Phase 2", "Connections"); + if (conns) { + for (conn = TAILQ_FIRST(&conns->fields); conn; + conn = TAILQ_NEXT(conn, link)) { + if (connection_setup(conn->field)) + log_print("connection_init: could not setup \"%s\"", + conn->field); + + /* XXX Break/abort here if connection_setup failed? */ + + /* + * XXX This code (i.e. the attribute lookup) seems like a + * likely candidate for factoring out into a function of its + * own. + */ + attrs = conf_get_list(conn->field, "Flags"); + if (attrs) + for (attr = TAILQ_FIRST(&attrs->fields); attr; + attr = TAILQ_NEXT(attr, link)) + if (strcasecmp("active-only", attr->field) == 0) + break; + if (!attrs || (attrs && !attr)) + if (connection_record_passive(conn->field)) + log_print("connection_init: could not record " + "connection \"%s\"", conn->field); + if (attrs) + conf_free_list(attrs); + + } + conf_free_list(conns); + } + conns = conf_get_list("Phase 2", "Passive-Connections"); + if (conns) { + for (conn = TAILQ_FIRST(&conns->fields); conn; + conn = TAILQ_NEXT(conn, link)) + if (connection_record_passive(conn->field)) + log_print("connection_init: could not record passive " + "connection \"%s\"", conn->field); + conf_free_list(conns); } - conf_free_list (conns); - } - - conns = conf_get_list ("Phase 2", "Passive-Connections"); - if (conns) - { - for (conn = TAILQ_FIRST (&conns->fields); conn; - conn = TAILQ_NEXT (conn, link)) - if (connection_record_passive (conn->field)) - log_print ("connection_init: could not record passive " - "connection \"%s\"", conn->field); - conf_free_list (conns); - } } /* Check the connection in VCONN and schedule another check later. */ static void -connection_checker (void *vconn) +connection_checker(void *vconn) { - struct timeval now; - struct connection *conn = vconn; - - gettimeofday (&now, 0); - now.tv_sec += conf_get_num ("General", "check-interval", CHECK_INTERVAL); - conn->ev - = timer_add_event ("connection_checker", connection_checker, conn, &now); - if (!conn->ev) - log_print ("connection_checker: could not add timer event"); - sysdep_connection_check (conn->name); + struct timeval now; + struct connection *conn = vconn; + + gettimeofday(&now, 0); + now.tv_sec += conf_get_num("General", "check-interval", CHECK_INTERVAL); + conn->ev = timer_add_event("connection_checker", + connection_checker, conn, &now); + if (!conn->ev) + log_print("connection_checker: could not add timer event"); + sysdep_connection_check(conn->name); } /* Find the connection named NAME. */ static struct connection * -connection_lookup (char *name) +connection_lookup(char *name) { - struct connection *conn; + struct connection *conn; - for (conn = TAILQ_FIRST (&connections); conn; conn = TAILQ_NEXT (conn, link)) - if (strcasecmp (conn->name, name) == 0) - return conn; - return 0; + for (conn = TAILQ_FIRST(&connections); conn; conn = TAILQ_NEXT(conn, link)) + if (strcasecmp(conn->name, name) == 0) + return conn; + return 0; } /* Does the connection named NAME exist? */ int -connection_exist (char *name) +connection_exist(char *name) { - return (connection_lookup (name) != 0); + return (connection_lookup(name) != 0); } /* Find the passive connection named NAME. */ static struct connection_passive * -connection_passive_lookup_by_name (char *name) +connection_passive_lookup_by_name(char *name) { - struct connection_passive *conn; + struct connection_passive *conn; - for (conn = TAILQ_FIRST (&connections_passive); conn; - conn = TAILQ_NEXT (conn, link)) - if (strcasecmp (conn->name, name) == 0) - return conn; - return 0; + for (conn = TAILQ_FIRST(&connections_passive); conn; + conn = TAILQ_NEXT(conn, link)) + if (strcasecmp(conn->name, name) == 0) + return conn; + return 0; } /* @@ -197,67 +191,63 @@ connection_passive_lookup_by_name (char *name) * XXX Rename to ipsec_compare_id, and move to ipsec.c ? */ static int -compare_ids (u_int8_t *id1, u_int8_t *id2, size_t idlen) +compare_ids(u_int8_t *id1, u_int8_t *id2, size_t idlen) { - int id1_type, id2_type; + int id1_type, id2_type; - id1_type = GET_ISAKMP_ID_TYPE (id1); - id2_type = GET_ISAKMP_ID_TYPE (id2); + id1_type = GET_ISAKMP_ID_TYPE(id1); + id2_type = GET_ISAKMP_ID_TYPE(id2); - return id1_type == id2_type - ? memcmp (id1 + ISAKMP_ID_DATA_OFF, id2 + ISAKMP_ID_DATA_OFF, - idlen - ISAKMP_ID_DATA_OFF) : -1; + return id1_type == id2_type ? memcmp(id1 + ISAKMP_ID_DATA_OFF, + id2 + ISAKMP_ID_DATA_OFF, idlen - ISAKMP_ID_DATA_OFF) : -1; } /* Find the connection named with matching IDs. */ char * -connection_passive_lookup_by_ids (u_int8_t *id1, u_int8_t *id2) +connection_passive_lookup_by_ids(u_int8_t *id1, u_int8_t *id2) { - struct connection_passive *conn; - - for (conn = TAILQ_FIRST (&connections_passive); conn; - conn = TAILQ_NEXT (conn, link)) - { - if (!conn->remote_id) - continue; - - /* - * If both IDs match what we have saved, return the name. Don't bother - * in which order they are. - */ - if ((compare_ids (id1, conn->local_id, conn->local_sz) == 0 - && compare_ids (id2, conn->remote_id, conn->remote_sz) == 0) - || (compare_ids (id1, conn->remote_id, conn->remote_sz) == 0 - && compare_ids (id2, conn->local_id, conn->local_sz) == 0)) - { - LOG_DBG ((LOG_MISC, 60, - "connection_passive_lookup_by_ids: returned \"%s\"", - conn->name)); - return conn->name; + struct connection_passive *conn; + + for (conn = TAILQ_FIRST(&connections_passive); conn; + conn = TAILQ_NEXT(conn, link)) { + if (!conn->remote_id) + continue; + + /* + * If both IDs match what we have saved, return the name. Don't bother + * in which order they are. + */ + if ((compare_ids(id1, conn->local_id, conn->local_sz) == 0 && + compare_ids(id2, conn->remote_id, conn->remote_sz) == 0) || + (compare_ids(id1, conn->remote_id, conn->remote_sz) == 0 && + compare_ids(id2, conn->local_id, conn->local_sz) == 0)) { + LOG_DBG((LOG_MISC, 60, + "connection_passive_lookup_by_ids: returned \"%s\"", + conn->name)); + return conn->name; + } } - } - - /* In the road warrior case, we do not know the remote ID. In that - * case we will just match against the local ID. - */ - for (conn = TAILQ_FIRST (&connections_passive); conn; - conn = TAILQ_NEXT (conn, link)) - { - if (!conn->remote_id) - continue; - - if (compare_ids (id1, conn->local_id, conn->local_sz) == 0 - || compare_ids (id2, conn->local_id, conn->local_sz) == 0) - { - LOG_DBG ((LOG_MISC, 60, - "connection passive_lookup_by_ids: returned \"%s\"" - " only matched local id", conn->name)); - return conn->name; + + /* + * In the road warrior case, we do not know the remote ID. In that + * case we will just match against the local ID. + */ + for (conn = TAILQ_FIRST(&connections_passive); conn; + conn = TAILQ_NEXT(conn, link)) { + if (!conn->remote_id) + continue; + + if (compare_ids(id1, conn->local_id, conn->local_sz) == 0 || + compare_ids(id2, conn->local_id, conn->local_sz) == 0) { + LOG_DBG((LOG_MISC, 60, + "connection passive_lookup_by_ids: returned \"%s\"" + " only matched local id", conn->name)); + return conn->name; + } } - } - LOG_DBG ((LOG_MISC, 60, + LOG_DBG((LOG_MISC, 60, "connection_passive_lookup_by_ids: no match")); - return 0; + return 0; } /* @@ -266,210 +256,188 @@ connection_passive_lookup_by_ids (u_int8_t *id1, u_int8_t *id2) * again. */ int -connection_setup (char *name) +connection_setup(char *name) { - struct connection *conn = 0; - struct timeval now; - - /* Check for trials to add duplicate connections. */ - if (connection_lookup (name)) - { - LOG_DBG ((LOG_MISC, 10, "connection_setup: cannot add \"%s\" twice", - name)); - return 0; - } - - conn = calloc (1, sizeof *conn); - if (!conn) - { - log_error ("connection_setup: calloc (1, %lu) failed", - (unsigned long)sizeof *conn); - goto fail; - } - - conn->name = strdup (name); - if (!conn->name) - { - log_error ("connection_setup: strdup (\"%s\") failed", name); - goto fail; - } - - gettimeofday (&now, 0); - conn->ev - = timer_add_event ("connection_checker", connection_checker, conn, &now); - if (!conn->ev) - { - log_print ("connection_setup: could not add timer event"); - goto fail; - } - - TAILQ_INSERT_TAIL (&connections, conn, link); - return 0; - - fail: - if (conn) - { - if (conn->name) - free (conn->name); - free (conn); - } - return -1; + struct connection *conn = 0; + struct timeval now; + + /* Check for trials to add duplicate connections. */ + if (connection_lookup(name)) { + LOG_DBG((LOG_MISC, 10, "connection_setup: cannot add \"%s\" twice", + name)); + return 0; + } + conn = calloc(1, sizeof *conn); + if (!conn) { + log_error("connection_setup: calloc (1, %lu) failed", + (unsigned long) sizeof *conn); + goto fail; + } + conn->name = strdup(name); + if (!conn->name) { + log_error("connection_setup: strdup (\"%s\") failed", name); + goto fail; + } + gettimeofday(&now, 0); + conn->ev = timer_add_event("connection_checker", + connection_checker, conn, &now); + if (!conn->ev) { + log_print("connection_setup: could not add timer event"); + goto fail; + } + TAILQ_INSERT_TAIL(&connections, conn, link); + return 0; + +fail: + if (conn) { + if (conn->name) + free(conn->name); + free(conn); + } + return -1; } int -connection_record_passive (char *name) +connection_record_passive(char *name) { - struct connection_passive *conn; - char *local_id, *remote_id; - - if (connection_passive_lookup_by_name (name)) - { - LOG_DBG ((LOG_MISC, 10, - "connection_record_passive: cannot add \"%s\" twice", - name)); - return 0; - } - - local_id = conf_get_str (name, "Local-ID"); - if (!local_id) - { - log_print ("connection_record_passive: " - "\"Local-ID\" is missing from section [%s]", - name); - return -1; - } - - /* If the remote id lookup fails we defer it to later */ - remote_id = conf_get_str (name, "Remote-ID"); - - conn = calloc (1, sizeof *conn); - if (!conn) - { - log_error ("connection_record_passive: calloc (1, %lu) failed", - (unsigned long)sizeof *conn); - return -1; - } - - conn->name = strdup (name); - if (!conn->name) - { - log_error ("connection_record_passive: strdup (\"%s\") failed", name); - goto fail; - } - - /* XXX IPsec DOI-specific. */ - conn->local_id = ipsec_build_id (local_id, &conn->local_sz); - if (!conn->local_id) - goto fail; - - if (remote_id) - { - conn->remote_id = ipsec_build_id (remote_id, &conn->remote_sz); - if (!conn->remote_id) - goto fail; - } - else - conn->remote_id = 0; - - TAILQ_INSERT_TAIL (&connections_passive, conn, link); - - LOG_DBG ((LOG_MISC, 60, - "connection_record_passive: passive connection \"%s\" " - "added", conn->name)); - return 0; - - fail: - if (conn->local_id) - free (conn->local_id); - if (conn->name) - free (conn->name); - free (conn); - return -1; + struct connection_passive *conn; + char *local_id, *remote_id; + + if (connection_passive_lookup_by_name(name)) { + LOG_DBG((LOG_MISC, 10, + "connection_record_passive: cannot add \"%s\" twice", + name)); + return 0; + } + local_id = conf_get_str(name, "Local-ID"); + if (!local_id) { + log_print("connection_record_passive: " + "\"Local-ID\" is missing from section [%s]", name); + return -1; + } + /* If the remote id lookup fails we defer it to later */ + remote_id = conf_get_str(name, "Remote-ID"); + + conn = calloc(1, sizeof *conn); + if (!conn) { + log_error("connection_record_passive: calloc (1, %lu) failed", + (unsigned long) sizeof *conn); + return -1; + } + conn->name = strdup(name); + if (!conn->name) { + log_error("connection_record_passive: strdup (\"%s\") failed", name); + goto fail; + } + /* XXX IPsec DOI-specific. */ + conn->local_id = ipsec_build_id(local_id, &conn->local_sz); + if (!conn->local_id) + goto fail; + + if (remote_id) { + conn->remote_id = ipsec_build_id(remote_id, &conn->remote_sz); + if (!conn->remote_id) + goto fail; + } else + conn->remote_id = 0; + + TAILQ_INSERT_TAIL(&connections_passive, conn, link); + + LOG_DBG((LOG_MISC, 60, + "connection_record_passive: passive connection \"%s\" added", + conn->name)); + return 0; + +fail: + if (conn->local_id) + free(conn->local_id); + if (conn->name) + free(conn->name); + free(conn); + return -1; } /* Remove the connection named NAME. */ void -connection_teardown (char *name) +connection_teardown(char *name) { - struct connection *conn; + struct connection *conn; - conn = connection_lookup (name); - if (!conn) - return; + conn = connection_lookup(name); + if (!conn) + return; - TAILQ_REMOVE (&connections, conn, link); - timer_remove_event (conn->ev); - free (conn->name); - free (conn); + TAILQ_REMOVE(&connections, conn, link); + timer_remove_event(conn->ev); + free(conn->name); + free(conn); } /* Remove the passive connection named NAME. */ static void -connection_passive_teardown (char *name) +connection_passive_teardown(char *name) { - struct connection_passive *conn; + struct connection_passive *conn; - conn = connection_passive_lookup_by_name (name); - if (!conn) - return; + conn = connection_passive_lookup_by_name(name); + if (!conn) + return; - TAILQ_REMOVE (&connections_passive, conn, link); - free (conn->name); - free (conn->local_id); - free (conn->remote_id); - free (conn); + TAILQ_REMOVE(&connections_passive, conn, link); + free(conn->name); + free(conn->local_id); + free(conn->remote_id); + free(conn); } void -connection_report (void) +connection_report(void) { - struct connection *conn; - struct timeval now; + struct connection *conn; + struct timeval now; #ifdef USE_DEBUG - struct connection_passive *pconn; - struct doi *doi = doi_lookup (ISAKMP_DOI_ISAKMP); + struct connection_passive *pconn; + struct doi *doi = doi_lookup(ISAKMP_DOI_ISAKMP); #endif - gettimeofday (&now, 0); - for (conn = TAILQ_FIRST (&connections); conn; conn = TAILQ_NEXT (conn, link)) - LOG_DBG ((LOG_REPORT, 0, - "connection_report: connection %s next check %ld seconds", - (conn->name ? conn->name : "<unnamed>"), - conn->ev->expiration.tv_sec - now.tv_sec)); + gettimeofday(&now, 0); + for (conn = TAILQ_FIRST(&connections); conn; conn = TAILQ_NEXT(conn, link)) + LOG_DBG((LOG_REPORT, 0, + "connection_report: connection %s next check %ld seconds", + (conn->name ? conn->name : "<unnamed>"), + conn->ev->expiration.tv_sec - now.tv_sec)); #ifdef USE_DEBUG - for (pconn = TAILQ_FIRST (&connections_passive); pconn; - pconn = TAILQ_NEXT (pconn, link)) - LOG_DBG ((LOG_REPORT, 0, - "connection_report: passive connection %s %s", pconn->name, - doi->decode_ids ("local_id: %s, remote_id: %s", - pconn->local_id, pconn->local_sz, - pconn->remote_id, pconn->remote_sz, 1))); + for (pconn = TAILQ_FIRST(&connections_passive); pconn; + pconn = TAILQ_NEXT(pconn, link)) + LOG_DBG((LOG_REPORT, 0, + "connection_report: passive connection %s %s", pconn->name, + doi->decode_ids("local_id: %s, remote_id: %s", + pconn->local_id, pconn->local_sz, + pconn->remote_id, pconn->remote_sz, 1))); #endif } /* Reinitialize all connections (SIGHUP handling). */ void -connection_reinit (void) +connection_reinit(void) { - struct connection *conn, *next; - struct connection_passive *pconn, *pnext; + struct connection *conn, *next; + struct connection_passive *pconn, *pnext; - LOG_DBG ((LOG_MISC, 30, + LOG_DBG((LOG_MISC, 30, "connection_reinit: reinitializing connection list")); - /* Remove all present connections. */ - for (conn = TAILQ_FIRST (&connections); conn; conn = next) - { - next = TAILQ_NEXT (conn, link); - connection_teardown (conn->name); - } - - for (pconn = TAILQ_FIRST (&connections_passive); pconn; pconn = pnext) - { - pnext = TAILQ_NEXT (pconn, link); - connection_passive_teardown (pconn->name); - } - - /* Setup new connections, as the (new) config directs. */ - connection_init (); + /* Remove all present connections. */ + for (conn = TAILQ_FIRST(&connections); conn; conn = next) { + next = TAILQ_NEXT(conn, link); + connection_teardown(conn->name); + } + + for (pconn = TAILQ_FIRST(&connections_passive); pconn; pconn = pnext) { + pnext = TAILQ_NEXT(pconn, link); + connection_passive_teardown(pconn->name); + } + + /* Setup new connections, as the (new) config directs. */ + connection_init(); } diff --git a/sbin/isakmpd/connection.h b/sbin/isakmpd/connection.h index 1e34c732dca..41ee53327e7 100644 --- a/sbin/isakmpd/connection.h +++ b/sbin/isakmpd/connection.h @@ -1,5 +1,5 @@ -/* $OpenBSD: connection.h,v 1.4 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: connection.h,v 1.6 1999/06/07 00:10:48 ho Exp $ */ +/* $OpenBSD: connection.h,v 1.5 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: connection.h,v 1.6 1999/06/07 00:10:48 ho Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -39,13 +39,13 @@ #include <sys/types.h> -extern int connection_exist (char *); -extern void connection_init (void); -extern char *connection_passive_lookup_by_ids (u_int8_t *, u_int8_t *); -extern void connection_reinit (void); -extern void connection_report (void); -extern int connection_setup (char *); -extern int connection_record_passive (char *); -extern void connection_teardown (char *); +extern int connection_exist(char *); +extern void connection_init(void); +extern char *connection_passive_lookup_by_ids(u_int8_t *, u_int8_t *); +extern void connection_reinit(void); +extern void connection_report(void); +extern int connection_setup(char *); +extern int connection_record_passive(char *); +extern void connection_teardown(char *); -#endif /* _CONNECTION_H_ */ +#endif /* _CONNECTION_H_ */ diff --git a/sbin/isakmpd/constants.c b/sbin/isakmpd/constants.c index 0a2883e1831..ec0d0f4b7bd 100644 --- a/sbin/isakmpd/constants.c +++ b/sbin/isakmpd/constants.c @@ -1,5 +1,5 @@ -/* $OpenBSD: constants.c,v 1.8 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: constants.c,v 1.7 1999/04/02 00:57:31 niklas Exp $ */ +/* $OpenBSD: constants.c,v 1.9 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: constants.c,v 1.7 1999/04/02 00:57:31 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -37,65 +37,63 @@ #include "constants.h" int -constant_value (struct constant_map *map, char *name) +constant_value(struct constant_map *map, char *name) { - struct constant_map *entry = map; + struct constant_map *entry = map; - for (entry = map; entry->name; entry++) - if (strcasecmp (entry->name, name) == 0) - return entry->value; - return 0; + for (entry = map; entry->name; entry++) + if (strcasecmp(entry->name, name) == 0) + return entry->value; + return 0; } char * -constant_lookup (struct constant_map *map, int value) +constant_lookup(struct constant_map *map, int value) { - struct constant_map *entry = map; + struct constant_map *entry = map; - for (entry = map; entry->name; entry++) - if (entry->value == value) - return entry->name; - return 0; + for (entry = map; entry->name; entry++) + if (entry->value == value) + return entry->name; + return 0; } struct constant_map * -constant_link_lookup (struct constant_map *map, int value) +constant_link_lookup(struct constant_map *map, int value) { - struct constant_map *entry = map; + struct constant_map *entry = map; - for (entry = map; entry->name; entry++) - if (entry->value == value) - return entry->link; - return 0; + for (entry = map; entry->name; entry++) + if (entry->value == value) + return entry->link; + return 0; } char * -constant_name (struct constant_map *map, int value) +constant_name(struct constant_map *map, int value) { - static char tmp[32]; /* XXX Ugly, I know. */ - char *retval = constant_lookup (map, value); + static char tmp[32];/* XXX Ugly, I know. */ + char *retval = constant_lookup(map, value); - if (!retval) - { - snprintf (tmp, sizeof tmp, "<Unknown %d>", value); - return tmp; - } - return retval; + if (!retval) { + snprintf(tmp, sizeof tmp, "<Unknown %d>", value); + return tmp; + } + return retval; } char * -constant_name_maps (struct constant_map **maps, int value) +constant_name_maps(struct constant_map **maps, int value) { - static char tmp[32]; /* XXX Ugly, I know. */ - char *retval; - struct constant_map **map; + static char tmp[32];/* XXX Ugly, I know. */ + char *retval; + struct constant_map **map; - for (map = maps; *map; map++) - { - retval = constant_lookup (*map, value); - if (retval) - return retval; - } - snprintf (tmp, sizeof tmp, "<Unknown %d>", value); - return tmp; + for (map = maps; *map; map++) { + retval = constant_lookup(*map, value); + if (retval) + return retval; + } + snprintf(tmp, sizeof tmp, "<Unknown %d>", value); + return tmp; } diff --git a/sbin/isakmpd/constants.h b/sbin/isakmpd/constants.h index 91bd0e2e89e..e3dd439e363 100644 --- a/sbin/isakmpd/constants.h +++ b/sbin/isakmpd/constants.h @@ -1,5 +1,5 @@ -/* $OpenBSD: constants.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: constants.h,v 1.5 1998/11/20 07:17:01 niklas Exp $ */ +/* $OpenBSD: constants.h,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: constants.h,v 1.5 1998/11/20 07:17:01 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -33,15 +33,15 @@ #define _CONSTANTS_H_ struct constant_map { - int value; - char *name; - struct constant_map *link; + int value; + char *name; + struct constant_map *link; }; -struct constant_map *constant_link_lookup (struct constant_map *, int); -extern char *constant_lookup (struct constant_map *, int); -extern char *constant_name (struct constant_map *, int); -extern char *constant_name_maps (struct constant_map **, int); -extern int constant_value (struct constant_map *, char *); +struct constant_map *constant_link_lookup(struct constant_map *, int); +extern char *constant_lookup(struct constant_map *, int); +extern char *constant_name(struct constant_map *, int); +extern char *constant_name_maps(struct constant_map **, int); +extern int constant_value(struct constant_map *, char *); -#endif /* _CONSTANTS_H_ */ +#endif /* _CONSTANTS_H_ */ diff --git a/sbin/isakmpd/cookie.c b/sbin/isakmpd/cookie.c index ad9021316a1..56e6ae734b6 100644 --- a/sbin/isakmpd/cookie.c +++ b/sbin/isakmpd/cookie.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cookie.c,v 1.12 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: cookie.c,v 1.21 1999/08/05 15:00:04 niklas Exp $ */ +/* $OpenBSD: cookie.c,v 1.13 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: cookie.c,v 1.21 1999/08/05 15:00:04 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -52,23 +52,23 @@ * EXCHANGE. */ void -cookie_gen (struct transport *t, struct exchange *exchange, u_int8_t *buf, - size_t len) +cookie_gen(struct transport *t, struct exchange *exchange, u_int8_t *buf, + size_t len) { - struct hash* hash = hash_get (HASH_SHA1); - struct sockaddr *name; - u_int8_t tmpsecret[COOKIE_SECRET_SIZE]; + struct hash *hash = hash_get(HASH_SHA1); + u_int8_t tmpsecret[COOKIE_SECRET_SIZE]; + struct sockaddr *name; - hash->Init (hash->ctx); - (*t->vtbl->get_dst) (t, &name); - hash->Update (hash->ctx, (u_int8_t *)name, sysdep_sa_len (name)); - (*t->vtbl->get_src) (t, &name); - hash->Update (hash->ctx, (u_int8_t *)name, sysdep_sa_len (name)); - if (exchange->initiator == 0) - hash->Update (hash->ctx, exchange->cookies + ISAKMP_HDR_ICOOKIE_OFF, - ISAKMP_HDR_ICOOKIE_LEN); - getrandom (tmpsecret, COOKIE_SECRET_SIZE); - hash->Update (hash->ctx, tmpsecret, COOKIE_SECRET_SIZE); - hash->Final (hash->digest, hash->ctx); - memcpy (buf, hash->digest, len); + hash->Init(hash->ctx); + (*t->vtbl->get_dst) (t, &name); + hash->Update(hash->ctx, (u_int8_t *) name, sysdep_sa_len(name)); + (*t->vtbl->get_src) (t, &name); + hash->Update(hash->ctx, (u_int8_t *) name, sysdep_sa_len(name)); + if (exchange->initiator == 0) + hash->Update(hash->ctx, exchange->cookies + ISAKMP_HDR_ICOOKIE_OFF, + ISAKMP_HDR_ICOOKIE_LEN); + getrandom(tmpsecret, COOKIE_SECRET_SIZE); + hash->Update(hash->ctx, tmpsecret, COOKIE_SECRET_SIZE); + hash->Final(hash->digest, hash->ctx); + memcpy(buf, hash->digest, len); } diff --git a/sbin/isakmpd/cookie.h b/sbin/isakmpd/cookie.h index 7fa1ffd05e3..ed5a8ba9768 100644 --- a/sbin/isakmpd/cookie.h +++ b/sbin/isakmpd/cookie.h @@ -1,5 +1,5 @@ -/* $OpenBSD: cookie.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: cookie.h,v 1.5 1998/08/05 09:21:43 niklas Exp $ */ +/* $OpenBSD: cookie.h,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: cookie.h,v 1.5 1998/08/05 09:21:43 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -38,7 +38,8 @@ struct exchange; struct transport; -extern void cookie_gen (struct transport *, struct exchange *, u_int8_t *, - size_t); +extern void +cookie_gen(struct transport *, struct exchange *, u_int8_t *, + size_t); -#endif /* _COOKIE_H_ */ +#endif /* _COOKIE_H_ */ diff --git a/sbin/isakmpd/crypto.c b/sbin/isakmpd/crypto.c index 964cb4e5f55..f53f9dfc194 100644 --- a/sbin/isakmpd/crypto.c +++ b/sbin/isakmpd/crypto.c @@ -1,5 +1,5 @@ -/* $OpenBSD: crypto.c,v 1.19 2004/03/31 10:54:46 ho Exp $ */ -/* $EOM: crypto.c,v 1.32 2000/03/07 20:08:51 niklas Exp $ */ +/* $OpenBSD: crypto.c,v 1.20 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: crypto.c,v 1.32 2000/03/07 20:08:51 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -39,57 +39,57 @@ #include "crypto.h" #include "log.h" -enum cryptoerr des1_init (struct keystate *, u_int8_t *, u_int16_t); -enum cryptoerr des3_init (struct keystate *, u_int8_t *, u_int16_t); -enum cryptoerr blf_init (struct keystate *, u_int8_t *, u_int16_t); -enum cryptoerr cast_init (struct keystate *, u_int8_t *, u_int16_t); -enum cryptoerr aes_init (struct keystate *, u_int8_t *, u_int16_t); -void des1_encrypt (struct keystate *, u_int8_t *, u_int16_t); -void des1_decrypt (struct keystate *, u_int8_t *, u_int16_t); -void des3_encrypt (struct keystate *, u_int8_t *, u_int16_t); -void des3_decrypt (struct keystate *, u_int8_t *, u_int16_t); -void blf_encrypt (struct keystate *, u_int8_t *, u_int16_t); -void blf_decrypt (struct keystate *, u_int8_t *, u_int16_t); -void cast1_encrypt (struct keystate *, u_int8_t *, u_int16_t); -void cast1_decrypt (struct keystate *, u_int8_t *, u_int16_t); -void aes_encrypt (struct keystate *, u_int8_t *, u_int16_t); -void aes_decrypt (struct keystate *, u_int8_t *, u_int16_t); +enum cryptoerr des1_init(struct keystate *, u_int8_t *, u_int16_t); +enum cryptoerr des3_init(struct keystate *, u_int8_t *, u_int16_t); +enum cryptoerr blf_init(struct keystate *, u_int8_t *, u_int16_t); +enum cryptoerr cast_init(struct keystate *, u_int8_t *, u_int16_t); +enum cryptoerr aes_init(struct keystate *, u_int8_t *, u_int16_t); +void des1_encrypt(struct keystate *, u_int8_t *, u_int16_t); +void des1_decrypt(struct keystate *, u_int8_t *, u_int16_t); +void des3_encrypt(struct keystate *, u_int8_t *, u_int16_t); +void des3_decrypt(struct keystate *, u_int8_t *, u_int16_t); +void blf_encrypt(struct keystate *, u_int8_t *, u_int16_t); +void blf_decrypt(struct keystate *, u_int8_t *, u_int16_t); +void cast1_encrypt(struct keystate *, u_int8_t *, u_int16_t); +void cast1_decrypt(struct keystate *, u_int8_t *, u_int16_t); +void aes_encrypt(struct keystate *, u_int8_t *, u_int16_t); +void aes_decrypt(struct keystate *, u_int8_t *, u_int16_t); struct crypto_xf transforms[] = { #ifdef USE_DES - { - DES_CBC, "Data Encryption Standard (CBC-Mode)", 8, 8, BLOCKSIZE, 0, - des1_init, - des1_encrypt, des1_decrypt - }, + { + DES_CBC, "Data Encryption Standard (CBC-Mode)", 8, 8, BLOCKSIZE, 0, + des1_init, + des1_encrypt, des1_decrypt + }, #endif #ifdef USE_TRIPLEDES - { - TRIPLEDES_CBC, "Triple-DES (CBC-Mode)", 24, 24, BLOCKSIZE, 0, - des3_init, - des3_encrypt, des3_decrypt - }, + { + TRIPLEDES_CBC, "Triple-DES (CBC-Mode)", 24, 24, BLOCKSIZE, 0, + des3_init, + des3_encrypt, des3_decrypt + }, #endif #ifdef USE_BLOWFISH - { - BLOWFISH_CBC, "Blowfish (CBC-Mode)", 12, 56, BLOCKSIZE, 0, - blf_init, - blf_encrypt, blf_decrypt - }, + { + BLOWFISH_CBC, "Blowfish (CBC-Mode)", 12, 56, BLOCKSIZE, 0, + blf_init, + blf_encrypt, blf_decrypt + }, #endif #ifdef USE_CAST - { - CAST_CBC, "CAST (CBC-Mode)", 12, 16, BLOCKSIZE, 0, - cast_init, - cast1_encrypt, cast1_decrypt - }, + { + CAST_CBC, "CAST (CBC-Mode)", 12, 16, BLOCKSIZE, 0, + cast_init, + cast1_encrypt, cast1_decrypt + }, #endif #ifdef USE_AES - { - AES_CBC, "AES (CBC-Mode)", 16, 32, AES_BLOCK_SIZE, 0, - aes_init, - aes_encrypt, aes_decrypt - }, + { + AES_CBC, "AES (CBC-Mode)", 16, 32, AES_BLOCK_SIZE, 0, + aes_init, + aes_encrypt, aes_decrypt + }, #endif }; @@ -101,318 +101,303 @@ struct crypto_xf transforms[] = { #endif enum cryptoerr -des1_init (struct keystate *ks, u_int8_t *key, u_int16_t len) +des1_init(struct keystate * ks, u_int8_t * key, u_int16_t len) { - /* des_set_key returns -1 for parity problems, and -2 for weak keys */ - des_set_odd_parity (DC key); - switch (des_set_key (DC key, ks->ks_des[0])) - { - case -2: - return EWEAKKEY; - default: - return EOKAY; - } + /* des_set_key returns -1 for parity problems, and -2 for weak keys */ + des_set_odd_parity(DC key); + switch (des_set_key(DC key, ks->ks_des[0])) { + case -2: + return EWEAKKEY; + default: + return EOKAY; + } } void -des1_encrypt (struct keystate *ks, u_int8_t *d, u_int16_t len) +des1_encrypt(struct keystate * ks, u_int8_t * d, u_int16_t len) { - des_cbc_encrypt (DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_ENCRYPT); + des_cbc_encrypt(DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_ENCRYPT); } void -des1_decrypt (struct keystate *ks, u_int8_t *d, u_int16_t len) +des1_decrypt(struct keystate * ks, u_int8_t * d, u_int16_t len) { - des_cbc_encrypt (DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_DECRYPT); + des_cbc_encrypt(DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_DECRYPT); } #ifdef USE_TRIPLEDES enum cryptoerr -des3_init (struct keystate *ks, u_int8_t *key, u_int16_t len) +des3_init(struct keystate * ks, u_int8_t * key, u_int16_t len) { - des_set_odd_parity (DC key); - des_set_odd_parity (DC (key + 8)); - des_set_odd_parity (DC (key + 16)); + des_set_odd_parity(DC key); + des_set_odd_parity(DC(key + 8)); + des_set_odd_parity(DC(key + 16)); - /* As of the draft Tripe-DES does not check for weak keys */ - des_set_key (DC key, ks->ks_des[0]); - des_set_key (DC (key + 8), ks->ks_des[1]); - des_set_key (DC (key + 16), ks->ks_des[2]); + /* As of the draft Tripe-DES does not check for weak keys */ + des_set_key(DC key, ks->ks_des[0]); + des_set_key(DC(key + 8), ks->ks_des[1]); + des_set_key(DC(key + 16), ks->ks_des[2]); - return EOKAY; + return EOKAY; } void -des3_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +des3_encrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int8_t iv[MAXBLK]; + u_int8_t iv[MAXBLK]; - memcpy (iv, ks->riv, ks->xf->blocksize); - des_ede3_cbc_encrypt (DC data, DC data, len, ks->ks_des[0], ks->ks_des[1], - ks->ks_des[2], DC iv, DES_ENCRYPT); + memcpy(iv, ks->riv, ks->xf->blocksize); + des_ede3_cbc_encrypt(DC data, DC data, len, ks->ks_des[0], ks->ks_des[1], + ks->ks_des[2], DC iv, DES_ENCRYPT); } void -des3_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +des3_decrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int8_t iv[MAXBLK]; + u_int8_t iv[MAXBLK]; - memcpy (iv, ks->riv, ks->xf->blocksize); - des_ede3_cbc_encrypt (DC data, DC data, len, ks->ks_des[0], ks->ks_des[1], - ks->ks_des[2], DC iv, DES_DECRYPT); + memcpy(iv, ks->riv, ks->xf->blocksize); + des_ede3_cbc_encrypt(DC data, DC data, len, ks->ks_des[0], ks->ks_des[1], + ks->ks_des[2], DC iv, DES_DECRYPT); } #undef DC -#endif /* USE_TRIPLEDES */ +#endif /* USE_TRIPLEDES */ #ifdef USE_BLOWFISH enum cryptoerr -blf_init (struct keystate *ks, u_int8_t *key, u_int16_t len) +blf_init(struct keystate * ks, u_int8_t * key, u_int16_t len) { - blf_key (&ks->ks_blf, key, len); + blf_key(&ks->ks_blf, key, len); - return EOKAY; + return EOKAY; } void -blf_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +blf_encrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int16_t i, blocksize = ks->xf->blocksize; - u_int8_t *iv = ks->liv; - u_int32_t xl, xr; - - memcpy (iv, ks->riv, blocksize); - - for (i = 0; i < len; data += blocksize, i += blocksize) - { - XOR64 (data, iv); - xl = GET_32BIT_BIG (data); - xr = GET_32BIT_BIG (data + 4); - Blowfish_encipher (&ks->ks_blf, &xl, &xr); - SET_32BIT_BIG (data, xl); - SET_32BIT_BIG (data + 4, xr); - SET64 (iv, data); - } + u_int16_t i, blocksize = ks->xf->blocksize; + u_int8_t *iv = ks->liv; + u_int32_t xl, xr; + + memcpy(iv, ks->riv, blocksize); + + for (i = 0; i < len; data += blocksize, i += blocksize) { + XOR64(data, iv); + xl = GET_32BIT_BIG(data); + xr = GET_32BIT_BIG(data + 4); + Blowfish_encipher(&ks->ks_blf, &xl, &xr); + SET_32BIT_BIG(data, xl); + SET_32BIT_BIG(data + 4, xr); + SET64(iv, data); + } } void -blf_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +blf_decrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int16_t i, blocksize = ks->xf->blocksize; - u_int32_t xl, xr; - - data += len - blocksize; - for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize) - { - xl = GET_32BIT_BIG (data); - xr = GET_32BIT_BIG (data + 4); - Blowfish_decipher (&ks->ks_blf, &xl, &xr); - SET_32BIT_BIG (data, xl); - SET_32BIT_BIG (data + 4, xr); - XOR64 (data, data - blocksize); - - } - xl = GET_32BIT_BIG (data); - xr = GET_32BIT_BIG (data + 4); - Blowfish_decipher (&ks->ks_blf, &xl, &xr); - SET_32BIT_BIG (data, xl); - SET_32BIT_BIG (data + 4, xr); - XOR64 (data, ks->riv); + u_int16_t i, blocksize = ks->xf->blocksize; + u_int32_t xl, xr; + + data += len - blocksize; + for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize) { + xl = GET_32BIT_BIG(data); + xr = GET_32BIT_BIG(data + 4); + Blowfish_decipher(&ks->ks_blf, &xl, &xr); + SET_32BIT_BIG(data, xl); + SET_32BIT_BIG(data + 4, xr); + XOR64(data, data - blocksize); + + } + xl = GET_32BIT_BIG(data); + xr = GET_32BIT_BIG(data + 4); + Blowfish_decipher(&ks->ks_blf, &xl, &xr); + SET_32BIT_BIG(data, xl); + SET_32BIT_BIG(data + 4, xr); + XOR64(data, ks->riv); } -#endif /* USE_BLOWFISH */ +#endif /* USE_BLOWFISH */ #ifdef USE_CAST enum cryptoerr -cast_init (struct keystate *ks, u_int8_t *key, u_int16_t len) +cast_init(struct keystate * ks, u_int8_t * key, u_int16_t len) { - cast_setkey (&ks->ks_cast, key, len); - return EOKAY; + cast_setkey(&ks->ks_cast, key, len); + return EOKAY; } void -cast1_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +cast1_encrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int16_t i, blocksize = ks->xf->blocksize; - u_int8_t *iv = ks->liv; + u_int16_t i, blocksize = ks->xf->blocksize; + u_int8_t *iv = ks->liv; - memcpy (iv, ks->riv, blocksize); + memcpy(iv, ks->riv, blocksize); - for (i = 0; i < len; data += blocksize, i += blocksize) - { - XOR64 (data, iv); - cast_encrypt (&ks->ks_cast, data, data); - SET64 (iv, data); - } + for (i = 0; i < len; data += blocksize, i += blocksize) { + XOR64(data, iv); + cast_encrypt(&ks->ks_cast, data, data); + SET64(iv, data); + } } void -cast1_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +cast1_decrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int16_t i, blocksize = ks->xf->blocksize; - - data += len - blocksize; - for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize) - { - cast_decrypt (&ks->ks_cast, data, data); - XOR64 (data, data - blocksize); - } - cast_decrypt (&ks->ks_cast, data, data); - XOR64 (data, ks->riv); + u_int16_t i, blocksize = ks->xf->blocksize; + + data += len - blocksize; + for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize) { + cast_decrypt(&ks->ks_cast, data, data); + XOR64(data, data - blocksize); + } + cast_decrypt(&ks->ks_cast, data, data); + XOR64(data, ks->riv); } -#endif /* USE_CAST */ +#endif /* USE_CAST */ #ifdef USE_AES enum cryptoerr -aes_init (struct keystate *ks, u_int8_t *key, u_int16_t len) +aes_init(struct keystate * ks, u_int8_t * key, u_int16_t len) { - AES_set_encrypt_key (key, len << 3, &ks->ks_aes[0]); - AES_set_decrypt_key (key, len << 3, &ks->ks_aes[1]); - return EOKAY; + AES_set_encrypt_key(key, len << 3, &ks->ks_aes[0]); + AES_set_decrypt_key(key, len << 3, &ks->ks_aes[1]); + return EOKAY; } void -aes_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +aes_encrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int8_t iv[MAXBLK]; + u_int8_t iv[MAXBLK]; - memcpy (iv, ks->riv, ks->xf->blocksize); - AES_cbc_encrypt (data, data, len, &ks->ks_aes[0], iv, AES_ENCRYPT); + memcpy(iv, ks->riv, ks->xf->blocksize); + AES_cbc_encrypt(data, data, len, &ks->ks_aes[0], iv, AES_ENCRYPT); } void -aes_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) +aes_decrypt(struct keystate * ks, u_int8_t * data, u_int16_t len) { - u_int8_t iv[MAXBLK]; + u_int8_t iv[MAXBLK]; - memcpy (iv, ks->riv, ks->xf->blocksize); - AES_cbc_encrypt (data, data, len, &ks->ks_aes[1], iv, AES_DECRYPT); + memcpy(iv, ks->riv, ks->xf->blocksize); + AES_cbc_encrypt(data, data, len, &ks->ks_aes[1], iv, AES_DECRYPT); } -#endif /* USE_AES */ +#endif /* USE_AES */ struct crypto_xf * -crypto_get (enum transform id) +crypto_get(enum transform id) { - size_t i; + size_t i; - for (i = 0; i < sizeof transforms / sizeof transforms[0]; i++) - if (id == transforms[i].id) - return &transforms[i]; + for (i = 0; i < sizeof transforms / sizeof transforms[0]; i++) + if (id == transforms[i].id) + return &transforms[i]; - return 0; + return 0; } struct keystate * -crypto_init (struct crypto_xf *xf, u_int8_t *key, u_int16_t len, - enum cryptoerr *err) +crypto_init(struct crypto_xf * xf, u_int8_t * key, u_int16_t len, + enum cryptoerr * err) { - struct keystate *ks; - - if (len < xf->keymin || len > xf->keymax) - { - LOG_DBG ((LOG_CRYPTO, 10, "crypto_init: invalid key length %d", len)); - *err = EKEYLEN; - return 0; - } - - ks = calloc (1, sizeof *ks); - if (!ks) - { - log_error ("crypto_init: calloc (1, %lu) failed", - (unsigned long)sizeof *ks); - *err = ENOCRYPTO; - return 0; - } - - ks->xf = xf; - - /* Setup the IV. */ - ks->riv = ks->iv; - ks->liv = ks->iv2; - - LOG_DBG_BUF ((LOG_CRYPTO, 40, "crypto_init: key", key, len)); - - *err = xf->init (ks, key, len); - if (*err != EOKAY) - { - LOG_DBG ((LOG_CRYPTO, 30, "crypto_init: weak key found for %s", - xf->name)); - free (ks); - return 0; - } - - return ks; + struct keystate *ks; + + if (len < xf->keymin || len > xf->keymax) { + LOG_DBG((LOG_CRYPTO, 10, "crypto_init: invalid key length %d", len)); + *err = EKEYLEN; + return 0; + } + ks = calloc(1, sizeof *ks); + if (!ks) { + log_error("crypto_init: calloc (1, %lu) failed", + (unsigned long) sizeof *ks); + *err = ENOCRYPTO; + return 0; + } + ks->xf = xf; + + /* Setup the IV. */ + ks->riv = ks->iv; + ks->liv = ks->iv2; + + LOG_DBG_BUF((LOG_CRYPTO, 40, "crypto_init: key", key, len)); + + *err = xf->init(ks, key, len); + if (*err != EOKAY) { + LOG_DBG((LOG_CRYPTO, 30, "crypto_init: weak key found for %s", + xf->name)); + free(ks); + return 0; + } + return ks; } void -crypto_update_iv (struct keystate *ks) +crypto_update_iv(struct keystate * ks) { - u_int8_t *tmp; + u_int8_t *tmp; - tmp = ks->riv; - ks->riv = ks->liv; - ks->liv = tmp; + tmp = ks->riv; + ks->riv = ks->liv; + ks->liv = tmp; - LOG_DBG_BUF ((LOG_CRYPTO, 50, "crypto_update_iv: updated IV", ks->riv, - ks->xf->blocksize)); + LOG_DBG_BUF((LOG_CRYPTO, 50, "crypto_update_iv: updated IV", ks->riv, + ks->xf->blocksize)); } void -crypto_init_iv (struct keystate *ks, u_int8_t *buf, size_t len) +crypto_init_iv(struct keystate * ks, u_int8_t * buf, size_t len) { - memcpy (ks->riv, buf, len); + memcpy(ks->riv, buf, len); - LOG_DBG_BUF ((LOG_CRYPTO, 50, "crypto_init_iv: initialized IV", ks->riv, - len)); + LOG_DBG_BUF((LOG_CRYPTO, 50, "crypto_init_iv: initialized IV", ks->riv, + len)); } void -crypto_encrypt (struct keystate *ks, u_int8_t *buf, u_int16_t len) +crypto_encrypt(struct keystate * ks, u_int8_t * buf, u_int16_t len) { - LOG_DBG_BUF ((LOG_CRYPTO, 10, "crypto_encrypt: before encryption", buf, - len)); - ks->xf->encrypt (ks, buf, len); - memcpy (ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize); - LOG_DBG_BUF ((LOG_CRYPTO, 30, "crypto_encrypt: after encryption", buf, - len)); + LOG_DBG_BUF((LOG_CRYPTO, 10, "crypto_encrypt: before encryption", buf, + len)); + ks->xf->encrypt(ks, buf, len); + memcpy(ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize); + LOG_DBG_BUF((LOG_CRYPTO, 30, "crypto_encrypt: after encryption", buf, + len)); } void -crypto_decrypt (struct keystate *ks, u_int8_t *buf, u_int16_t len) +crypto_decrypt(struct keystate * ks, u_int8_t * buf, u_int16_t len) { - LOG_DBG_BUF ((LOG_CRYPTO, 10, "crypto_decrypt: before decryption", buf, - len)); - /* - * XXX There is controversy about the correctness of updating the IV - * like this. - */ - memcpy (ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize); - ks->xf->decrypt (ks, buf, len); - LOG_DBG_BUF ((LOG_CRYPTO, 30, "crypto_decrypt: after decryption", buf, - len)); + LOG_DBG_BUF((LOG_CRYPTO, 10, "crypto_decrypt: before decryption", buf, + len)); + /* + * XXX There is controversy about the correctness of updating the IV + * like this. + */ + memcpy(ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize); + ks->xf->decrypt(ks, buf, len); + LOG_DBG_BUF((LOG_CRYPTO, 30, "crypto_decrypt: after decryption", buf, + len)); } /* Make a copy of the keystate pointed to by OKS. */ struct keystate * -crypto_clone_keystate (struct keystate *oks) +crypto_clone_keystate(struct keystate * oks) { - struct keystate *ks; - - ks = malloc (sizeof *ks); - if (!ks) - { - log_error ("crypto_clone_keystate: malloc (%lu) failed", - (unsigned long)sizeof *ks); - return 0; - } - memcpy (ks, oks, sizeof *ks); - if (oks->riv == oks->iv) - { - ks->riv = ks->iv; - ks->liv = ks->iv2; - } - else - { - ks->riv = ks->iv2; - ks->liv = ks->iv; - } - return ks; + struct keystate *ks; + + ks = malloc(sizeof *ks); + if (!ks) { + log_error("crypto_clone_keystate: malloc (%lu) failed", + (unsigned long) sizeof *ks); + return 0; + } + memcpy(ks, oks, sizeof *ks); + if (oks->riv == oks->iv) { + ks->riv = ks->iv; + ks->liv = ks->iv2; + } else { + ks->riv = ks->iv2; + ks->liv = ks->iv; + } + return ks; } diff --git a/sbin/isakmpd/crypto.h b/sbin/isakmpd/crypto.h index 13c799b3e20..7354e03ad2f 100644 --- a/sbin/isakmpd/crypto.h +++ b/sbin/isakmpd/crypto.h @@ -1,5 +1,5 @@ -/* $OpenBSD: crypto.h,v 1.12 2003/12/22 18:13:58 markus Exp $ */ -/* $EOM: crypto.h,v 1.12 2000/10/15 21:56:41 niklas Exp $ */ +/* $OpenBSD: crypto.h,v 1.13 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: crypto.h,v 1.12 2000/10/15 21:56:41 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -52,7 +52,7 @@ #include <cast.h> #endif -#endif /* __APPLE__ */ +#endif /* __APPLE__ */ #ifdef USE_AES #include <openssl/aes.h> @@ -80,7 +80,7 @@ #define SET64(x,y) SET8(x,y,0); SET8(x,y,1); SET8(x,y,2); SET8(x,y,3); \ SET8(x,y,4); SET8(x,y,5); SET8(x,y,6); SET8(x,y,7); -#endif /* USE_64BIT */ +#endif /* USE_64BIT */ #define SET_32BIT_BIG(x,y) (x)[3]= (y); (x)[2]= (y) >> 8; \ (x)[1] = (y) >> 16; (x)[0]= (y) >> 24; @@ -100,25 +100,25 @@ #endif struct keystate { - struct crypto_xf *xf; /* Back pointer */ - u_int16_t ebytes; /* Number of encrypted bytes */ - u_int16_t dbytes; /* Number of decrypted bytes */ - time_t life; /* Creation time */ - u_int8_t iv[MAXBLK]; /* Next IV to use */ - u_int8_t iv2[MAXBLK]; - u_int8_t *riv, *liv; - union { - des_key_schedule desks[3]; + struct crypto_xf *xf; /* Back pointer */ + u_int16_t ebytes; /* Number of encrypted bytes */ + u_int16_t dbytes; /* Number of decrypted bytes */ + time_t life; /* Creation time */ + u_int8_t iv[MAXBLK]; /* Next IV to use */ + u_int8_t iv2[MAXBLK]; + u_int8_t *riv, *liv; + union { + des_key_schedule desks[3]; #ifdef USE_BLOWFISH - blf_ctx blfks; + blf_ctx blfks; #endif #ifdef USE_CAST - cast_key castks; + cast_key castks; #endif #ifdef USE_AES - AES_KEY aesks[2]; + AES_KEY aesks[2]; #endif - } keydata; + } keydata; }; #define ks_des keydata.desks @@ -136,40 +136,41 @@ struct keystate { * only anyhow, and we already have defines for that in ipsec_doi.h. */ enum transform { - DES_CBC=1, /* This is a MUST */ - IDEA_CBC=2, /* Licensed, DONT use */ - BLOWFISH_CBC=3, - RC5_R16_B64_CBC=4, /* Licensed, DONT use */ - TRIPLEDES_CBC=5, /* This is a SHOULD */ - CAST_CBC=6, - AES_CBC=7 + DES_CBC = 1, /* This is a MUST */ + IDEA_CBC = 2, /* Licensed, DONT use */ + BLOWFISH_CBC = 3, + RC5_R16_B64_CBC = 4, /* Licensed, DONT use */ + TRIPLEDES_CBC = 5, /* This is a SHOULD */ + CAST_CBC = 6, + AES_CBC = 7 }; enum cryptoerr { - EOKAY, /* No error */ - ENOCRYPTO, /* A none crypto related error, see errno */ - EWEAKKEY, /* A weak key was found in key setup */ - EKEYLEN /* The key length was invalid for the cipher */ + EOKAY, /* No error */ + ENOCRYPTO, /* A none crypto related error, see errno */ + EWEAKKEY, /* A weak key was found in key setup */ + EKEYLEN /* The key length was invalid for the cipher */ }; struct crypto_xf { - enum transform id; /* Oakley ID */ - char *name; /* Transform Name */ - u_int16_t keymin, keymax; /* Possible Keying Bytes */ - u_int16_t blocksize; /* Need to keep IV in the state */ - struct keystate *state; /* Key information, can also be passed sep. */ - enum cryptoerr (*init) (struct keystate *, u_int8_t *, u_int16_t); - void (*encrypt) (struct keystate *, u_int8_t *, u_int16_t); - void (*decrypt) (struct keystate *, u_int8_t *, u_int16_t); + enum transform id; /* Oakley ID */ + char *name; /* Transform Name */ + u_int16_t keymin, keymax; /* Possible Keying Bytes */ + u_int16_t blocksize; /* Need to keep IV in the state */ + struct keystate *state; /* Key information, can also be passed sep. */ + enum cryptoerr (*init) (struct keystate *, u_int8_t *, u_int16_t); + void (*encrypt) (struct keystate *, u_int8_t *, u_int16_t); + void (*decrypt) (struct keystate *, u_int8_t *, u_int16_t); }; -extern struct keystate *crypto_clone_keystate (struct keystate *); -extern void crypto_decrypt (struct keystate *, u_int8_t *, u_int16_t); -extern void crypto_encrypt (struct keystate *, u_int8_t *, u_int16_t); -extern struct crypto_xf *crypto_get (enum transform); -extern struct keystate *crypto_init (struct crypto_xf *, u_int8_t *, - u_int16_t, enum cryptoerr *); -extern void crypto_init_iv (struct keystate *, u_int8_t *, size_t); -extern void crypto_update_iv (struct keystate *); - -#endif /* _CRYPTO_H_ */ +extern struct keystate *crypto_clone_keystate(struct keystate *); +extern void crypto_decrypt(struct keystate *, u_int8_t *, u_int16_t); +extern void crypto_encrypt(struct keystate *, u_int8_t *, u_int16_t); +extern struct crypto_xf *crypto_get(enum transform); +extern struct keystate * +crypto_init(struct crypto_xf *, u_int8_t *, + u_int16_t, enum cryptoerr *); +extern void crypto_init_iv(struct keystate *, u_int8_t *, size_t); +extern void crypto_update_iv(struct keystate *); + +#endif /* _CRYPTO_H_ */ diff --git a/sbin/isakmpd/dh.c b/sbin/isakmpd/dh.c index c2ba993cd72..afb41baf2c2 100644 --- a/sbin/isakmpd/dh.c +++ b/sbin/isakmpd/dh.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dh.c,v 1.8 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: dh.c,v 1.5 1999/04/17 23:20:22 niklas Exp $ */ +/* $OpenBSD: dh.c,v 1.9 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: dh.c,v 1.5 1999/04/17 23:20:22 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -43,9 +43,9 @@ */ int -dh_getlen (struct group *group) +dh_getlen(struct group *group) { - return group->getlen (group); + return group->getlen(group); } /* @@ -55,14 +55,14 @@ dh_getlen (struct group *group) * dh_create_exchange should only be called once. */ int -dh_create_exchange (struct group *group, u_int8_t *buf) +dh_create_exchange(struct group *group, u_int8_t *buf) { - if (group->setrandom (group, group->c)) - return -1; - if (group->operation (group, group->a, group->gen, group->c)) - return -1; - group->getraw (group, group->a, buf); - return 0; + if (group->setrandom(group, group->c)) + return -1; + if (group->operation(group, group->a, group->gen, group->c)) + return -1; + group->getraw(group, group->a, buf); + return 0; } /* @@ -71,12 +71,12 @@ dh_create_exchange (struct group *group, u_int8_t *buf) * is done for the value, the application has to do that. */ int -dh_create_shared (struct group *group, u_int8_t *secret, u_int8_t *exchange) +dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) { - if (group->setraw (group, group->b, exchange, group->getlen (group))) - return -1; - if (group->operation (group, group->a, group->b, group->c)) - return -1; - group->getraw (group, group->a, secret); - return 0; + if (group->setraw(group, group->b, exchange, group->getlen(group))) + return -1; + if (group->operation(group, group->a, group->b, group->c)) + return -1; + group->getraw(group, group->a, secret); + return 0; } diff --git a/sbin/isakmpd/dh.h b/sbin/isakmpd/dh.h index 0da058e3c34..96c30d2cfd5 100644 --- a/sbin/isakmpd/dh.h +++ b/sbin/isakmpd/dh.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dh.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: dh.h,v 1.4 1999/04/17 23:20:24 niklas Exp $ */ +/* $OpenBSD: dh.h,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: dh.h,v 1.4 1999/04/17 23:20:24 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -36,8 +36,8 @@ struct group; -int dh_getlen (struct group *); -int dh_create_exchange (struct group *, u_int8_t *); -int dh_create_shared (struct group *, u_int8_t *, u_int8_t *); +int dh_getlen(struct group *); +int dh_create_exchange(struct group *, u_int8_t *); +int dh_create_shared(struct group *, u_int8_t *, u_int8_t *); -#endif /* _DH_H_ */ +#endif /* _DH_H_ */ diff --git a/sbin/isakmpd/dnssec.c b/sbin/isakmpd/dnssec.c index 85dfed006d8..9fc4b0c6e09 100644 --- a/sbin/isakmpd/dnssec.c +++ b/sbin/isakmpd/dnssec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dnssec.c,v 1.17 2003/11/06 16:12:07 ho Exp $ */ +/* $OpenBSD: dnssec.c,v 1.18 2004/04/15 18:39:25 deraadt Exp $ */ /* * Copyright (c) 2001 Håkan Olsson. All rights reserved. @@ -56,260 +56,230 @@ /* adapted from <dns/rdatastruct.h> / RFC 2535 */ struct dns_rdata_key { - u_int16_t flags; - u_int8_t protocol; - u_int8_t algorithm; - u_int16_t datalen; - unsigned char *data; + u_int16_t flags; + u_int8_t protocol; + u_int8_t algorithm; + u_int16_t datalen; + unsigned char *data; }; -void * -dns_get_key (int type, struct message *msg, int *keylen) +void * +dns_get_key(int type, struct message * msg, int *keylen) { - struct exchange *exchange = msg->exchange; - struct rrsetinfo *rr; - struct dns_rdata_key key_rr; - char name[MAXHOSTNAMELEN]; - in_addr_t ip4; - u_int8_t algorithm; - u_int8_t *id, *umark; - size_t id_len; - int ret, i; - - switch (type) - { - case IKE_AUTH_RSA_SIG: - algorithm = DNS_KEYALG_RSA; - break; - - case IKE_AUTH_RSA_ENC: - case IKE_AUTH_RSA_ENC_REV: - /* XXX Not yet. */ - /* algorithm = DNS_KEYALG_RSA; */ - return 0; - - case IKE_AUTH_DSS: - /* XXX Not yet. */ - /* algorithm = DNS_KEYALG_DSS; */ - return 0; - - case IKE_AUTH_PRE_SHARED: - default: - return 0; - } - - id = exchange->initiator ? exchange->id_r : exchange->id_i; - id_len = exchange->initiator ? exchange->id_r_len : exchange->id_i_len; - memset (name, 0, sizeof name); - - if (!id || id_len == 0) - { - log_print ("dns_get_key: ID is missing"); - return 0; - } - - /* Exchanges (and SAs) don't carry the ID in ISAKMP form */ - id -= ISAKMP_GEN_SZ; - id_len += ISAKMP_GEN_SZ - ISAKMP_ID_DATA_OFF; - - switch (GET_ISAKMP_ID_TYPE (id)) - { - case IPSEC_ID_IPV4_ADDR: - /* We want to lookup a KEY RR in the reverse zone. */ - if (id_len < sizeof ip4) - return 0; - memcpy (&ip4, id + ISAKMP_ID_DATA_OFF, sizeof ip4); - snprintf (name, sizeof name, "%d.%d.%d.%d.in-addr.arpa.", ip4 >> 24, - (ip4 >> 16) & 0xFF, (ip4 >> 8) & 0xFF, ip4 & 0xFF); - break; - - case IPSEC_ID_IPV6_ADDR: - /* XXX Not yet. */ - return 0; - break; - - case IPSEC_ID_FQDN: - if ((id_len + 1) >= sizeof name) - return 0; - /* ID is not NULL-terminated. Add trailing dot and terminate. */ - memcpy (name, id + ISAKMP_ID_DATA_OFF, id_len); - *(name + id_len) = '.'; - *(name + id_len + 1) = '\0'; - break; - - case IPSEC_ID_USER_FQDN: - /* - * Some special handling here. We want to convert the ID - * 'user@host.domain' string into 'user._ipsec.host.domain.'. - */ - if ((id_len + sizeof (DNS_UFQDN_SEPARATOR)) >= sizeof name) - return 0; - /* Look for the '@' separator. */ - for (umark = id + ISAKMP_ID_DATA_OFF; (umark - id) < id_len; umark++) - if (*umark == '@') - break; - if (*umark != '@') - { - LOG_DBG ((LOG_MISC, 50, "dns_get_key: bad UFQDN ID")); - return 0; + struct exchange *exchange = msg->exchange; + struct rrsetinfo *rr; + struct dns_rdata_key key_rr; + char name[MAXHOSTNAMELEN]; + in_addr_t ip4; + u_int8_t algorithm, *id, *umark; + size_t id_len; + int ret, i; + + switch (type) { + case IKE_AUTH_RSA_SIG: + algorithm = DNS_KEYALG_RSA; + break; + + case IKE_AUTH_RSA_ENC: + case IKE_AUTH_RSA_ENC_REV: + /* XXX Not yet. */ + /* algorithm = DNS_KEYALG_RSA; */ + return 0; + + case IKE_AUTH_DSS: + /* XXX Not yet. */ + /* algorithm = DNS_KEYALG_DSS; */ + return 0; + + case IKE_AUTH_PRE_SHARED: + default: + return 0; } - *umark++ = '\0'; - /* id is now terminated. 'umark', however, is not. */ - snprintf (name, sizeof name, "%s%s", id + ISAKMP_ID_DATA_OFF, - DNS_UFQDN_SEPARATOR); - memcpy (name + strlen (name), umark, id_len - strlen (id) - 1); - *(name + id_len + sizeof (DNS_UFQDN_SEPARATOR) - 2) = '.'; - *(name + id_len + sizeof (DNS_UFQDN_SEPARATOR) - 1) = '\0'; - break; - - default: - return 0; - } - - LOG_DBG ((LOG_MISC, 50, "dns_get_key: trying KEY RR for %s", name)); - ret = getrrsetbyname (name, C_IN, T_KEY, 0, &rr); - - if (ret) - { - LOG_DBG ((LOG_MISC, 30, "dns_get_key: no DNS responses (error %d)", - ret)); - return 0; - } - - LOG_DBG ((LOG_MISC, 80, - "dns_get_key: rrset class %d type %d ttl %d nrdatas %d nrsigs %d", - rr->rri_rdclass, rr->rri_rdtype, rr->rri_ttl, rr->rri_nrdatas, - rr->rri_nsigs)); - /* We don't accept unvalidated data. */ - if (!(rr->rri_flags & RRSET_VALIDATED)) - { - LOG_DBG ((LOG_MISC, 10, "dns_get_key: got unvalidated response")); - freerrset (rr); - return 0; - } - - /* Sanity. */ - if (rr->rri_nrdatas == 0 || rr->rri_rdtype != T_KEY) - { - LOG_DBG ((LOG_MISC, 30, "dns_get_key: no KEY RRs received")); - freerrset (rr); - return 0; - } - - memset (&key_rr, 0, sizeof key_rr); - - /* - * Find a key with the wanted algorithm, if any. - * XXX If there are several keys present, we currently only find the first. - */ - for (i = 0; i < rr->rri_nrdatas && key_rr.datalen == 0; i++) - { - key_rr.flags = ntohs ((u_int16_t) *rr->rri_rdatas[i].rdi_data); - key_rr.protocol = *(rr->rri_rdatas[i].rdi_data + 2); - key_rr.algorithm = *(rr->rri_rdatas[i].rdi_data + 3); - - if (key_rr.protocol != DNS_KEYPROTO_IPSEC) - { - LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored non-IPsec key")); - continue; - } + id = exchange->initiator ? exchange->id_r : exchange->id_i; + id_len = exchange->initiator ? exchange->id_r_len : exchange->id_i_len; + memset(name, 0, sizeof name); - if (key_rr.algorithm != algorithm) - { - LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored key with other alg")); - continue; + if (!id || id_len == 0) { + log_print("dns_get_key: ID is missing"); + return 0; + } + /* Exchanges (and SAs) don't carry the ID in ISAKMP form */ + id -= ISAKMP_GEN_SZ; + id_len += ISAKMP_GEN_SZ - ISAKMP_ID_DATA_OFF; + + switch (GET_ISAKMP_ID_TYPE(id)) { + case IPSEC_ID_IPV4_ADDR: + /* We want to lookup a KEY RR in the reverse zone. */ + if (id_len < sizeof ip4) + return 0; + memcpy(&ip4, id + ISAKMP_ID_DATA_OFF, sizeof ip4); + snprintf(name, sizeof name, "%d.%d.%d.%d.in-addr.arpa.", ip4 >> 24, + (ip4 >> 16) & 0xFF, (ip4 >> 8) & 0xFF, ip4 & 0xFF); + break; + + case IPSEC_ID_IPV6_ADDR: + /* XXX Not yet. */ + return 0; + break; + + case IPSEC_ID_FQDN: + if ((id_len + 1) >= sizeof name) + return 0; + /* ID is not NULL-terminated. Add trailing dot and terminate. */ + memcpy(name, id + ISAKMP_ID_DATA_OFF, id_len); + *(name + id_len) = '.'; + *(name + id_len + 1) = '\0'; + break; + + case IPSEC_ID_USER_FQDN: + /* + * Some special handling here. We want to convert the ID + * 'user@host.domain' string into 'user._ipsec.host.domain.'. + */ + if ((id_len + sizeof(DNS_UFQDN_SEPARATOR)) >= sizeof name) + return 0; + /* Look for the '@' separator. */ + for (umark = id + ISAKMP_ID_DATA_OFF; (umark - id) < id_len; umark++) + if (*umark == '@') + break; + if (*umark != '@') { + LOG_DBG((LOG_MISC, 50, "dns_get_key: bad UFQDN ID")); + return 0; + } + *umark++ = '\0'; + /* id is now terminated. 'umark', however, is not. */ + snprintf(name, sizeof name, "%s%s", id + ISAKMP_ID_DATA_OFF, + DNS_UFQDN_SEPARATOR); + memcpy(name + strlen(name), umark, id_len - strlen(id) - 1); + *(name + id_len + sizeof(DNS_UFQDN_SEPARATOR) - 2) = '.'; + *(name + id_len + sizeof(DNS_UFQDN_SEPARATOR) - 1) = '\0'; + break; + + default: + return 0; } - key_rr.datalen = rr->rri_rdatas[i].rdi_length - 4; - if (key_rr.datalen <= 0) - { - LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored bad key")); - key_rr.datalen = 0; - continue; + LOG_DBG((LOG_MISC, 50, "dns_get_key: trying KEY RR for %s", name)); + ret = getrrsetbyname(name, C_IN, T_KEY, 0, &rr); + + if (ret) { + LOG_DBG((LOG_MISC, 30, "dns_get_key: no DNS responses (error %d)", + ret)); + return 0; } + LOG_DBG((LOG_MISC, 80, + "dns_get_key: rrset class %d type %d ttl %d nrdatas %d nrsigs %d", + rr->rri_rdclass, rr->rri_rdtype, rr->rri_ttl, rr->rri_nrdatas, + rr->rri_nsigs)); - /* This key seems to fit our requirements... */ - key_rr.data = (char *)malloc (key_rr.datalen); - if (!key_rr.data) - { - log_error ("dns_get_key: malloc (%d) failed", key_rr.datalen); - freerrset (rr); - return 0; + /* We don't accept unvalidated data. */ + if (!(rr->rri_flags & RRSET_VALIDATED)) { + LOG_DBG((LOG_MISC, 10, "dns_get_key: got unvalidated response")); + freerrset(rr); + return 0; + } + /* Sanity. */ + if (rr->rri_nrdatas == 0 || rr->rri_rdtype != T_KEY) { + LOG_DBG((LOG_MISC, 30, "dns_get_key: no KEY RRs received")); + freerrset(rr); + return 0; + } + memset(&key_rr, 0, sizeof key_rr); + + /* + * Find a key with the wanted algorithm, if any. + * XXX If there are several keys present, we currently only find the first. + */ + for (i = 0; i < rr->rri_nrdatas && key_rr.datalen == 0; i++) { + key_rr.flags = ntohs((u_int16_t) * rr->rri_rdatas[i].rdi_data); + key_rr.protocol = *(rr->rri_rdatas[i].rdi_data + 2); + key_rr.algorithm = *(rr->rri_rdatas[i].rdi_data + 3); + + if (key_rr.protocol != DNS_KEYPROTO_IPSEC) { + LOG_DBG((LOG_MISC, 50, "dns_get_key: ignored non-IPsec key")); + continue; + } + if (key_rr.algorithm != algorithm) { + LOG_DBG((LOG_MISC, 50, "dns_get_key: ignored " + "key with other alg")); + continue; + } + key_rr.datalen = rr->rri_rdatas[i].rdi_length - 4; + if (key_rr.datalen <= 0) { + LOG_DBG((LOG_MISC, 50, "dns_get_key: ignored bad key")); + key_rr.datalen = 0; + continue; + } + /* This key seems to fit our requirements... */ + key_rr.data = (char *) malloc(key_rr.datalen); + if (!key_rr.data) { + log_error("dns_get_key: malloc (%d) failed", key_rr.datalen); + freerrset(rr); + return 0; + } + memcpy(key_rr.data, rr->rri_rdatas[i].rdi_data + 4, key_rr.datalen); + *keylen = key_rr.datalen; } - memcpy (key_rr.data, rr->rri_rdatas[i].rdi_data + 4, key_rr.datalen); - *keylen = key_rr.datalen; - } - freerrset (rr); + freerrset(rr); - if (key_rr.datalen) - return key_rr.data; - else - return 0; + if (key_rr.datalen) + return key_rr.data; + return 0; } int -dns_RSA_dns_to_x509 (u_int8_t *key, int keylen, RSA **rsa_key) +dns_RSA_dns_to_x509(u_int8_t * key, int keylen, RSA ** rsa_key) { - RSA *rsa; - int key_offset; - u_int8_t e_len; - - if (!key || keylen <= 0) - { - log_print ("dns_RSA_dns_to_x509: invalid public key"); - return -1; - } - - rsa = RSA_new (); - if (rsa == NULL) - { - log_error ("dns_RSA_dns_to_x509: failed to allocate new RSA struct"); - return -1; - } - - e_len = *key; - key_offset = 1; - - if (e_len == 0) - { - if (keylen < 3) - { - log_print ("dns_RSA_dns_to_x509: invalid public key"); - RSA_free (rsa); - return -1; - } - e_len = *(key + key_offset++) << 8; - e_len += *(key + key_offset++); - } - - if (e_len > (keylen - key_offset)) - { - log_print ("dns_RSA_dns_to_x509: invalid public key"); - RSA_free (rsa); - return -1; - } - - rsa->e = BN_bin2bn (key + key_offset, e_len, NULL); - key_offset += e_len; + RSA *rsa; + int key_offset; + u_int8_t e_len; - /* XXX if (keylen <= key_offset) -> "invalid public key" ? */ + if (!key || keylen <= 0) { + log_print("dns_RSA_dns_to_x509: invalid public key"); + return -1; + } + rsa = RSA_new(); + if (rsa == NULL) { + log_error("dns_RSA_dns_to_x509: failed to allocate new RSA struct"); + return -1; + } + e_len = *key; + key_offset = 1; + + if (e_len == 0) { + if (keylen < 3) { + log_print("dns_RSA_dns_to_x509: invalid public key"); + RSA_free(rsa); + return -1; + } + e_len = *(key + key_offset++) << 8; + e_len += *(key + key_offset++); + } + if (e_len > (keylen - key_offset)) { + log_print("dns_RSA_dns_to_x509: invalid public key"); + RSA_free(rsa); + return -1; + } + rsa->e = BN_bin2bn(key + key_offset, e_len, NULL); + key_offset += e_len; - rsa->n = BN_bin2bn (key + key_offset, keylen - key_offset, NULL); + /* XXX if (keylen <= key_offset) -> "invalid public key" ? */ - *rsa_key = rsa; + rsa->n = BN_bin2bn(key + key_offset, keylen - key_offset, NULL); - LOG_DBG ((LOG_MISC, 30, "dns_RSA_dns_to_x509: got %d bits RSA key", - BN_num_bits (rsa->n))); + *rsa_key = rsa; - return 0; + LOG_DBG((LOG_MISC, 30, "dns_RSA_dns_to_x509: got %d bits RSA key", + BN_num_bits(rsa->n))); + return 0; } #if notyet int -dns_RSA_x509_to_dns (RSA *rsa_key, u_int8_t *key, int *keylen) +dns_RSA_x509_to_dns(RSA * rsa_key, u_int8_t * key, int *keylen) { - return 0; + return 0; } #endif diff --git a/sbin/isakmpd/dnssec.h b/sbin/isakmpd/dnssec.h index 9c579ce0fc2..8eb8d384e86 100644 --- a/sbin/isakmpd/dnssec.h +++ b/sbin/isakmpd/dnssec.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dnssec.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ +/* $OpenBSD: dnssec.h,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ /* * Copyright (c) 2001 Håkan Olsson. All rights reserved. @@ -27,8 +27,8 @@ #include "libcrypto.h" #include "message.h" -void *dns_get_key (int, struct message *, int *); -int dns_RSA_dns_to_x509 (u_int8_t *, int, RSA **); +void *dns_get_key(int, struct message *, int *); +int dns_RSA_dns_to_x509(u_int8_t *, int, RSA **); #ifndef DNS_KEYALG_RSA #define DNS_KEYALG_RSA 1 diff --git a/sbin/isakmpd/doi.c b/sbin/isakmpd/doi.c index d67d493527e..8185d9fada1 100644 --- a/sbin/isakmpd/doi.c +++ b/sbin/isakmpd/doi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: doi.c,v 1.6 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: doi.c,v 1.4 1999/04/02 00:57:36 niklas Exp $ */ +/* $OpenBSD: doi.c,v 1.7 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: doi.c,v 1.4 1999/04/02 00:57:36 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -35,28 +35,27 @@ #include "doi.h" -static LIST_HEAD (doi_list, doi) doi_tab; +static +LIST_HEAD(doi_list, doi) doi_tab; -void -doi_init () + void + doi_init() { - LIST_INIT (&doi_tab); + LIST_INIT(&doi_tab); } -struct doi * -doi_lookup (u_int8_t doi_id) +struct doi * +doi_lookup(u_int8_t doi_id) { - struct doi *doi; + struct doi *doi; - for (doi = LIST_FIRST (&doi_tab); doi && doi->id != doi_id; - doi = LIST_NEXT (doi, link)) - ; - return doi; + for (doi = LIST_FIRST(&doi_tab); doi && doi->id != doi_id; + doi = LIST_NEXT(doi, link)); + return doi; } void -doi_register (struct doi *doi) +doi_register(struct doi * doi) { - LIST_INSERT_HEAD (&doi_tab, doi, link); + LIST_INSERT_HEAD(&doi_tab, doi, link); } - diff --git a/sbin/isakmpd/doi.h b/sbin/isakmpd/doi.h index bf5b4b69b2c..adf7ddeef58 100644 --- a/sbin/isakmpd/doi.h +++ b/sbin/isakmpd/doi.h @@ -1,5 +1,5 @@ -/* $OpenBSD: doi.h,v 1.12 2004/03/10 23:08:48 hshoexer Exp $ */ -/* $EOM: doi.h,v 1.29 2000/07/02 18:47:15 provos Exp $ */ +/* $OpenBSD: doi.h,v 1.13 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: doi.h,v 1.29 2000/07/02 18:47:15 provos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -44,54 +44,54 @@ struct sa; /* XXX This structure needs per-field commenting. */ struct doi { - LIST_ENTRY (doi) link; - u_int8_t id; + LIST_ENTRY(doi) link; + u_int8_t id; - /* Size of DOI-specific exchange data. */ - size_t exchange_size; + /* Size of DOI-specific exchange data. */ + size_t exchange_size; - /* Size of DOI-specific security association data. */ - size_t sa_size; + /* Size of DOI-specific security association data. */ + size_t sa_size; - /* Size of DOI-specific protocol data. */ - size_t proto_size; + /* Size of DOI-specific protocol data. */ + size_t proto_size; #ifdef USE_DEBUG - int (*debug_attribute) (u_int16_t, u_int8_t *, u_int16_t, void *); + int (*debug_attribute) (u_int16_t, u_int8_t *, u_int16_t, void *); #endif - void (*delete_spi) (struct sa *, struct proto *, int); - int16_t *(*exchange_script) (u_int8_t); - void (*finalize_exchange) (struct message *); - void (*free_exchange_data) (void *); - void (*free_proto_data) (void *); - void (*free_sa_data) (void *); - struct keystate *(*get_keystate) (struct message *); - u_int8_t *(*get_spi) (size_t *, u_int8_t, struct message *); - int (*handle_leftover_payload) (struct message *, u_int8_t, - struct payload *); - int (*informational_post_hook) (struct message *); - int (*informational_pre_hook) (struct message *); - int (*is_attribute_incompatible) (u_int16_t, u_int8_t *, u_int16_t, void *); - void (*proto_init) (struct proto *, char *); - void (*setup_situation) (u_int8_t *); - size_t (*situation_size) (void); - u_int8_t (*spi_size) (u_int8_t); - int (*validate_attribute) (u_int16_t, u_int8_t *, u_int16_t, void *); - int (*validate_exchange) (u_int8_t); - int (*validate_id_information) (u_int8_t, u_int8_t *, u_int8_t *, size_t, - struct exchange *); - int (*validate_key_information) (u_int8_t *, size_t); - int (*validate_notification) (u_int16_t); - int (*validate_proto) (u_int8_t); - int (*validate_situation) (u_int8_t *, size_t *, size_t); - int (*validate_transform_id) (u_int8_t, u_int8_t); - int (*initiator) (struct message *msg); - int (*responder) (struct message *msg); - char *(*decode_ids) (char *, u_int8_t *, size_t, u_int8_t *, size_t, int); + void (*delete_spi) (struct sa *, struct proto *, int); + int16_t *(*exchange_script) (u_int8_t); + void (*finalize_exchange) (struct message *); + void (*free_exchange_data) (void *); + void (*free_proto_data) (void *); + void (*free_sa_data) (void *); + struct keystate *(*get_keystate) (struct message *); + u_int8_t *(*get_spi) (size_t *, u_int8_t, struct message *); + int (*handle_leftover_payload) (struct message *, u_int8_t, + struct payload *); + int (*informational_post_hook) (struct message *); + int (*informational_pre_hook) (struct message *); + int (*is_attribute_incompatible) (u_int16_t, u_int8_t *, u_int16_t, void *); + void (*proto_init) (struct proto *, char *); + void (*setup_situation) (u_int8_t *); + size_t(*situation_size) (void); + u_int8_t(*spi_size) (u_int8_t); + int (*validate_attribute) (u_int16_t, u_int8_t *, u_int16_t, void *); + int (*validate_exchange) (u_int8_t); + int (*validate_id_information) (u_int8_t, u_int8_t *, u_int8_t *, size_t, + struct exchange *); + int (*validate_key_information) (u_int8_t *, size_t); + int (*validate_notification) (u_int16_t); + int (*validate_proto) (u_int8_t); + int (*validate_situation) (u_int8_t *, size_t *, size_t); + int (*validate_transform_id) (u_int8_t, u_int8_t); + int (*initiator) (struct message * msg); + int (*responder) (struct message * msg); + char *(*decode_ids) (char *, u_int8_t *, size_t, u_int8_t *, size_t, int); }; -extern void doi_init (void); -extern struct doi *doi_lookup (u_int8_t); -extern void doi_register (struct doi *); +extern void doi_init(void); +extern struct doi *doi_lookup(u_int8_t); +extern void doi_register(struct doi *); -#endif /* _DOI_H_ */ +#endif /* _DOI_H_ */ diff --git a/sbin/isakmpd/exchange.h b/sbin/isakmpd/exchange.h index 333eb864482..d4cd76dd9c6 100644 --- a/sbin/isakmpd/exchange.h +++ b/sbin/isakmpd/exchange.h @@ -1,5 +1,5 @@ -/* $OpenBSD: exchange.h,v 1.24 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: exchange.h,v 1.28 2000/09/28 12:54:28 niklas Exp $ */ +/* $OpenBSD: exchange.h,v 1.25 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: exchange.h,v 1.28 2000/09/28 12:54:28 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -53,149 +53,162 @@ struct transport; struct sa; struct exchange { - /* Link to exchanges with the same hash value. */ - LIST_ENTRY (exchange) link; - - /* A name of the SAs this exchange will result in. XXX non unique? */ - char *name; - - /* A name of the major policy deciding offers and acceptable proposals. */ - char *policy; - - /* - * A function with a polymorphic argument called after the exchange - * has been run to its end, successfully. The 2nd argument is true - * if the finalization hook is called due to the exchange not running - * to its end normally. - */ - void (*finalize) (struct exchange *, void *, int); - void *finalize_arg; - - /* When several SA's are being negotiated we keep them here. */ - TAILQ_HEAD (sa_head, sa) sa_list; - - /* - * The event that will occur when it has taken too long time to try to - * run the exchange and which will trigger auto-destruction. - */ - struct event *death; - - /* - * Both initiator and responder cookies. - * XXX For code clarity we might split this into two fields. - */ - u_int8_t cookies[ISAKMP_HDR_COOKIES_LEN]; - - /* The message ID signifying phase 2 exchanges. */ - u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; - - /* The exchange type we are using. */ - u_int8_t type; - - /* Phase is 1 for ISAKMP SA exchanges, and 2 for application ones. */ - u_int8_t phase; - - /* The "step counter" of the exchange, starting from zero. */ - u_int8_t step; - - /* 1 if we are the initiator, 0 if we are the responder. */ - u_int8_t initiator; - - /* Various flags, look below for descriptions. */ - u_int32_t flags; - - /* The DOI that is to handle DOI-specific issues for this exchange. */ - struct doi *doi; - - /* - * A "program counter" into the script that validate message contents for - * this exchange. - */ - int16_t *exch_pc; - - /* The last message received, used for checking for duplicates. */ - struct message *last_received; - - /* The last message sent, to be acked when something new is received. */ - struct message *last_sent; - - /* - * If some message is queued up for sending, we want to be able to remove - * it from the queue, when the exchange is deleted. - */ - struct message *in_transit; - - /* - * Initiator's & responder's nonces respectively, with lengths. - * XXX Should this be in the DOI-specific parts instead? - */ - u_int8_t *nonce_i; - size_t nonce_i_len; - u_int8_t *nonce_r; - size_t nonce_r_len; - - /* The ID payload contents for the initiator & responder, respectively. */ - u_int8_t *id_i; - size_t id_i_len; - u_int8_t *id_r; - size_t id_r_len; - - /* Policy session identifier, where applicable. */ - int policy_id; - - /* Crypto info needed to encrypt/decrypt packets in this exchange. */ - struct crypto_xf *crypto; - size_t key_length; - struct keystate *keystate; - - /* Used only by KeyNote, to cache the key used to authenticate Phase 1 */ - char *keynote_key; /* printable format */ - - /* - * Received certificate - used to verify signatures on packet, - * stored here for later policy processing. - * - * The rules for the recv_* and sent_* fields are: - * - recv_cert stores the credential (if any) received from the peer; - * the kernel may pass us one, but we ignore it. We pass it to the - * kernel so processes can peek at it. When doing passphrase - * authentication in Phase 1, this is empty. - * - recv_key stores the key (public or private) used by the peer - * to authenticate. Otherwise, same properties as recv_cert except - * that we don't tell the kernel about passphrases (so we don't - * reveal system-wide passphrases). Processes that used passphrase - * authentication already know the passphrase! We ignore it if/when - * received from the kernel (meaningless). - * - sent_cert stores the credential, if any, we used to authenticate - * with the peer. It may be passed to us by the kernel, or we may - * have found it in our certificate storage. In either case, there's - * no point passing it to the kernel, so we don't. - * - sent key stores the private key we used for authentication with - * the peer (private key or passphrase). This may have been received - * from the kernel, or may be a system-wide setting. In either case, - * we don't pass it to the kernel, to avoid revealing such information - * to processes (processes either already know it, or have no business - * knowing it). - */ - int recv_certtype, recv_keytype; - void *recv_cert; /* Certificate received from peer, native format */ - void *recv_key; /* Key peer used to authenticate, native format */ - - /* Likewise, for certificates/keys we use. */ - int sent_certtype, sent_keytype; - void *sent_cert; /* Certificate (to be) sent to peer, native format */ - void *sent_key; /* Key we'll use to authenticate to peer, native format */ - - /* ACQUIRE sequence number. */ - u_int32_t seq; - - /* XXX This is no longer necessary, it is covered by policy. */ - - /* Acceptable authorities for cert requests. */ - TAILQ_HEAD (aca_head, certreq_aca) aca_list; - - /* DOI-specific opaque data. */ - void *data; + /* Link to exchanges with the same hash value. */ + LIST_ENTRY(exchange) link; + + /* A name of the SAs this exchange will result in. XXX non unique? */ + char *name; + + /* + * A name of the major policy deciding offers and acceptable + * proposals. + */ + char *policy; + + /* + * A function with a polymorphic argument called after the exchange + * has been run to its end, successfully. The 2nd argument is true + * if the finalization hook is called due to the exchange not running + * to its end normally. + */ + void (*finalize) (struct exchange *, void *, int); + void *finalize_arg; + + /* When several SA's are being negotiated we keep them here. */ + TAILQ_HEAD(sa_head, sa) sa_list; + + /* + * The event that will occur when it has taken too long time to try to + * run the exchange and which will trigger auto-destruction. + */ + struct event *death; + + /* + * Both initiator and responder cookies. + * XXX For code clarity we might split this into two fields. + */ + u_int8_t cookies[ISAKMP_HDR_COOKIES_LEN]; + + /* The message ID signifying phase 2 exchanges. */ + u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; + + /* The exchange type we are using. */ + u_int8_t type; + + /* Phase is 1 for ISAKMP SA exchanges, and 2 for application ones. */ + u_int8_t phase; + + /* The "step counter" of the exchange, starting from zero. */ + u_int8_t step; + + /* 1 if we are the initiator, 0 if we are the responder. */ + u_int8_t initiator; + + /* Various flags, look below for descriptions. */ + u_int32_t flags; + + /* The DOI that is to handle DOI-specific issues for this exchange. */ + struct doi *doi; + + /* + * A "program counter" into the script that validate message contents for + * this exchange. + */ + int16_t *exch_pc; + + /* The last message received, used for checking for duplicates. */ + struct message *last_received; + + /* The last message sent, to be acked when something new is received. */ + struct message *last_sent; + + /* + * If some message is queued up for sending, we want to be able to remove + * it from the queue, when the exchange is deleted. + */ + struct message *in_transit; + + /* + * Initiator's & responder's nonces respectively, with lengths. + * XXX Should this be in the DOI-specific parts instead? + */ + u_int8_t *nonce_i; + size_t nonce_i_len; + u_int8_t *nonce_r; + size_t nonce_r_len; + + /* + * The ID payload contents for the initiator & responder, + * respectively. + */ + u_int8_t *id_i; + size_t id_i_len; + u_int8_t *id_r; + size_t id_r_len; + + /* Policy session identifier, where applicable. */ + int policy_id; + + /* Crypto info needed to encrypt/decrypt packets in this exchange. */ + struct crypto_xf *crypto; + size_t key_length; + struct keystate *keystate; + + /* + * Used only by KeyNote, to cache the key used to authenticate Phase + * 1 + */ + char *keynote_key; /* printable format */ + + /* + * Received certificate - used to verify signatures on packet, + * stored here for later policy processing. + * + * The rules for the recv_* and sent_* fields are: + * - recv_cert stores the credential (if any) received from the peer; + * the kernel may pass us one, but we ignore it. We pass it to the + * kernel so processes can peek at it. When doing passphrase + * authentication in Phase 1, this is empty. + * - recv_key stores the key (public or private) used by the peer + * to authenticate. Otherwise, same properties as recv_cert except + * that we don't tell the kernel about passphrases (so we don't + * reveal system-wide passphrases). Processes that used passphrase + * authentication already know the passphrase! We ignore it if/when + * received from the kernel (meaningless). + * - sent_cert stores the credential, if any, we used to authenticate + * with the peer. It may be passed to us by the kernel, or we may + * have found it in our certificate storage. In either case, there's + * no point passing it to the kernel, so we don't. + * - sent key stores the private key we used for authentication with + * the peer (private key or passphrase). This may have been received + * from the kernel, or may be a system-wide setting. In either case, + * we don't pass it to the kernel, to avoid revealing such information + * to processes (processes either already know it, or have no business + * knowing it). + */ + int recv_certtype, recv_keytype; + void *recv_cert; /* Certificate received from peer, + * native format */ + void *recv_key; /* Key peer used to authenticate, + * native format */ + + /* Likewise, for certificates/keys we use. */ + int sent_certtype, sent_keytype; + void *sent_cert; /* Certificate (to be) sent to peer, + * native format */ + void *sent_key; /* Key we'll use to authenticate to + * peer, native format */ + + /* ACQUIRE sequence number. */ + u_int32_t seq; + + /* XXX This is no longer necessary, it is covered by policy. */ + + /* Acceptable authorities for cert requests. */ + TAILQ_HEAD(aca_head, certreq_aca) aca_list; + + /* DOI-specific opaque data. */ + void *data; }; /* The flag bits. */ @@ -205,32 +218,33 @@ struct exchange { | EXCHANGE_FLAG_HE_COMMITTED) #define EXCHANGE_FLAG_ENCRYPT 4 -extern int exchange_add_certs (struct message *); -extern void exchange_finalize (struct message *); -extern void exchange_free (struct exchange *); -extern void exchange_free_aca_list (struct exchange *); -extern void exchange_establish (char *name, - void (*) (struct exchange *, void *, int), - void *); -extern void exchange_establish_p1 (struct transport *, u_int8_t, u_int32_t, - char *, void *, - void (*) (struct exchange *, void *, int), - void *); -extern void exchange_establish_p2 (struct sa *, u_int8_t, char *, void *, - void (*) (struct exchange *, void *, int), - void *); -extern int exchange_gen_nonce (struct message *, size_t); -extern void exchange_init (void); -extern struct exchange *exchange_lookup (u_int8_t *, int); -extern struct exchange *exchange_lookup_by_name (char *, int); -extern struct exchange *exchange_lookup_from_icookie (u_int8_t *); -extern void exchange_report (void); -extern void exchange_run (struct message *); -extern int exchange_save_nonce (struct message *); -extern int exchange_save_certreq (struct message *); -extern int16_t *exchange_script (struct exchange *); -extern struct exchange *exchange_setup_p1 (struct message *, u_int32_t); -extern struct exchange *exchange_setup_p2 (struct message *, u_int8_t); -extern void exchange_upgrade_p1 (struct message *); - -#endif /* _EXCHANGE_H_ */ +extern int exchange_add_certs(struct message *); +extern void exchange_finalize(struct message *); +extern void exchange_free(struct exchange *); +extern void exchange_free_aca_list(struct exchange *); +extern void +exchange_establish(char *name, + void (*) (struct exchange *, void *, int), + void *); + extern void exchange_establish_p1(struct transport *, u_int8_t, u_int32_t, + char *, void *, + void (*) (struct exchange *, void *, int), + void *); + extern void exchange_establish_p2(struct sa *, u_int8_t, char *, void *, + void (*) (struct exchange *, void *, int), + void *); + extern int exchange_gen_nonce(struct message *, size_t); + extern void exchange_init(void); + extern struct exchange *exchange_lookup(u_int8_t *, int); + extern struct exchange *exchange_lookup_by_name(char *, int); + extern struct exchange *exchange_lookup_from_icookie(u_int8_t *); + extern void exchange_report(void); + extern void exchange_run(struct message *); + extern int exchange_save_nonce(struct message *); + extern int exchange_save_certreq(struct message *); + extern int16_t *exchange_script(struct exchange *); + extern struct exchange *exchange_setup_p1(struct message *, u_int32_t); + extern struct exchange *exchange_setup_p2(struct message *, u_int8_t); + extern void exchange_upgrade_p1(struct message *); + +#endif /* _EXCHANGE_H_ */ diff --git a/sbin/isakmpd/field.c b/sbin/isakmpd/field.c index 9217487f4ab..2f54a1db74d 100644 --- a/sbin/isakmpd/field.c +++ b/sbin/isakmpd/field.c @@ -1,5 +1,5 @@ -/* $OpenBSD: field.c,v 1.13 2003/11/06 16:12:07 ho Exp $ */ -/* $EOM: field.c,v 1.11 2000/02/20 19:58:37 niklas Exp $ */ +/* $OpenBSD: field.c,v 1.14 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: field.c,v 1.11 2000/02/20 19:58:37 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -40,19 +40,19 @@ #include "log.h" #include "util.h" -static char *field_debug_raw (u_int8_t *, size_t, struct constant_map **); -static char *field_debug_num (u_int8_t *, size_t, struct constant_map **); -static char *field_debug_mask (u_int8_t *, size_t, struct constant_map **); -static char *field_debug_ign (u_int8_t *, size_t, struct constant_map **); -static char *field_debug_cst (u_int8_t *, size_t, struct constant_map **); +static char *field_debug_raw(u_int8_t *, size_t, struct constant_map **); +static char *field_debug_num(u_int8_t *, size_t, struct constant_map **); +static char *field_debug_mask(u_int8_t *, size_t, struct constant_map **); +static char *field_debug_ign(u_int8_t *, size_t, struct constant_map **); +static char *field_debug_cst(u_int8_t *, size_t, struct constant_map **); /* Contents must match the enum in struct field. */ -static char *(*decode_field[]) (u_int8_t *, size_t, struct constant_map **) = { - field_debug_raw, - field_debug_num, - field_debug_mask, - field_debug_ign, - field_debug_cst +static char *(*decode_field[]) (u_int8_t *, size_t, struct constant_map **) = { + field_debug_raw, + field_debug_num, + field_debug_mask, + field_debug_ign, + field_debug_cst }; /* @@ -60,23 +60,22 @@ static char *(*decode_field[]) (u_int8_t *, size_t, struct constant_map **) = { * BUF. MAPS should be zero and is only here because the API requires it. */ static char * -field_debug_raw (u_int8_t *buf, size_t len, struct constant_map **maps) +field_debug_raw(u_int8_t *buf, size_t len, struct constant_map **maps) { - char *retval, *p; - - if (len == 0) - return 0; - retval = malloc (3 + len * 2); - if (!retval) - return 0; - strlcpy (retval, "0x", 3 + len * 2); - p = retval + 2; - for (; len > 0; len--) - { - snprintf (p, 1 + len * 2, "%02x", *buf++); - p += 2; - } - return retval; + char *retval, *p; + + if (len == 0) + return 0; + retval = malloc(3 + len * 2); + if (!retval) + return 0; + strlcpy(retval, "0x", 3 + len * 2); + p = retval + 2; + for (; len > 0; len--) { + snprintf(p, 1 + len * 2, "%02x", *buf++); + p += 2; + } + return retval; } /* @@ -84,23 +83,22 @@ field_debug_raw (u_int8_t *buf, size_t len, struct constant_map **maps) * 32-bit unsigned integer of host byteorder pointed to by VAL. */ static int -extract_val (u_int8_t *buf, size_t len, u_int32_t *val) +extract_val(u_int8_t *buf, size_t len, u_int32_t *val) { - switch (len) - { - case 1: - *val = *buf; - break; - case 2: - *val = decode_16 (buf); - break; - case 4: - *val = decode_32 (buf); - break; - default: - return -1; - } - return 0; + switch (len) { + case 1: + *val = *buf; + break; + case 2: + *val = decode_16(buf); + break; + case 4: + *val = decode_32(buf); + break; + default: + return -1; + } + return 0; } /* @@ -109,17 +107,17 @@ extract_val (u_int8_t *buf, size_t len, u_int32_t *val) * the API requires it. */ static char * -field_debug_num (u_int8_t *buf, size_t len, struct constant_map **maps) +field_debug_num(u_int8_t *buf, size_t len, struct constant_map **maps) { - char *retval; - u_int32_t val; - - if (extract_val (buf, len, &val)) - return 0; - /* 3 decimal digits are enough to represent each byte. */ - retval = malloc (3 * len); - snprintf (retval, 3 * len, "%u", val); - return retval; + char *retval; + u_int32_t val; + + if (extract_val(buf, len, &val)) + return 0; + /* 3 decimal digits are enough to represent each byte. */ + retval = malloc(3 * len); + snprintf(retval, 3 * len, "%u", val); + return retval; } /* @@ -127,42 +125,39 @@ field_debug_num (u_int8_t *buf, size_t len, struct constant_map **maps) * octets long, using the constant maps MAPS. */ static char * -field_debug_mask (u_int8_t *buf, size_t len, struct constant_map **maps) +field_debug_mask(u_int8_t *buf, size_t len, struct constant_map **maps) { - u_int32_t val; - u_int32_t bit; - char *retval, *new_buf, *name; - size_t buf_sz; - - if (extract_val (buf, len, &val)) - return 0; - - /* Size for brackets, two spaces and a NUL terminator. */ - buf_sz = 4; - retval = malloc (buf_sz); - if (!retval) - return 0; - - strlcpy (retval, "[ ", buf_sz); - for (bit = 1; bit; bit <<= 1) - { - if (val & bit) - { - name = constant_name_maps (maps, bit); - buf_sz += strlen (name) + 1; - new_buf = realloc (retval, buf_sz); - if (!new_buf) - { - free (retval); - return 0; - } - retval = new_buf; - strlcat (retval, name, buf_sz); - strlcat (retval, " ", buf_sz); + u_int32_t val; + u_int32_t bit; + char *retval, *new_buf, *name; + size_t buf_sz; + + if (extract_val(buf, len, &val)) + return 0; + + /* Size for brackets, two spaces and a NUL terminator. */ + buf_sz = 4; + retval = malloc(buf_sz); + if (!retval) + return 0; + + strlcpy(retval, "[ ", buf_sz); + for (bit = 1; bit; bit <<= 1) { + if (val & bit) { + name = constant_name_maps(maps, bit); + buf_sz += strlen(name) + 1; + new_buf = realloc(retval, buf_sz); + if (!new_buf) { + free(retval); + return 0; + } + retval = new_buf; + strlcat(retval, name, buf_sz); + strlcat(retval, " ", buf_sz); + } } - } - strlcat (retval, "]", buf_sz); - return retval; + strlcat(retval, "]", buf_sz); + return retval; } /* @@ -170,9 +165,9 @@ field_debug_mask (u_int8_t *buf, size_t len, struct constant_map **maps) * should be zero and is only here because the API requires it. */ static char * -field_debug_ign (u_int8_t *buf, size_t len, struct constant_map **maps) +field_debug_ign(u_int8_t *buf, size_t len, struct constant_map **maps) { - return 0; + return 0; } /* @@ -180,79 +175,77 @@ field_debug_ign (u_int8_t *buf, size_t len, struct constant_map **maps) * octets long, using the constant maps MAPS. */ static char * -field_debug_cst (u_int8_t *buf, size_t len, struct constant_map **maps) +field_debug_cst(u_int8_t *buf, size_t len, struct constant_map **maps) { - u_int32_t val; + u_int32_t val; - if (extract_val (buf, len, &val)) - return 0; + if (extract_val(buf, len, &val)) + return 0; - return strdup (constant_name_maps (maps, val)); + return strdup(constant_name_maps(maps, val)); } /* Pretty-print a field from BUF as described by F. */ void -field_dump_field (struct field *f, u_int8_t *buf) +field_dump_field(struct field *f, u_int8_t *buf) { - char *value; + char *value; - value = decode_field[(int)f->type] (buf + f->offset, f->len, f->maps); - if (value) - { - LOG_DBG ((LOG_MESSAGE, 70, "%s: %s", f->name, value)); - free (value); - } + value = decode_field[(int) f->type] (buf + f->offset, f->len, f->maps); + if (value) { + LOG_DBG((LOG_MESSAGE, 70, "%s: %s", f->name, value)); + free(value); + } } /* Pretty-print all the fields of BUF as described in FIELDS. */ void -field_dump_payload (struct field *fields, u_int8_t *buf) +field_dump_payload(struct field *fields, u_int8_t *buf) { - struct field *field; + struct field *field; - for (field = fields; field->name; field++) - field_dump_field (field, buf); + for (field = fields; field->name; field++) + field_dump_field(field, buf); } /* Return the numeric value of the field F of BUF. */ u_int32_t -field_get_num (struct field *f, u_int8_t *buf) +field_get_num(struct field *f, u_int8_t *buf) { - u_int32_t val; + u_int32_t val; - if (extract_val (buf + f->offset, f->len, &val)) - return 0; - return val; + if (extract_val(buf + f->offset, f->len, &val)) + return 0; + return val; } /* Stash the number VAL into BUF's field F. */ void -field_set_num (struct field *f, u_int8_t *buf, u_int32_t val) +field_set_num(struct field *f, u_int8_t *buf, u_int32_t val) { - switch (f->len) - { - case 1: - buf[f->offset] = val; - break; - case 2: - encode_16 (buf + f->offset, val); - break; - case 4: - encode_32 (buf + f->offset, val); - break; - } + switch (f->len) { + case 1: + buf[f->offset] = val; + break; + case 2: + encode_16(buf + f->offset, val); + break; + case 4: + encode_32(buf + f->offset, val); + break; + } } /* Stash BUF's raw field F into VAL. */ void -field_get_raw (struct field *f, u_int8_t *buf, u_int8_t *val) +field_get_raw(struct field * f, u_int8_t * buf, u_int8_t * val) { - memcpy (val, buf + f->offset, f->len); + memcpy(val, buf + f->offset, f->len); } /* Stash the buffer VAL into BUF's field F. */ void -field_set_raw (struct field *f, u_int8_t *buf, u_int8_t *val) +field_set_raw(struct field * f, u_int8_t * buf, u_int8_t * val) { - memcpy (buf + f->offset, val, f->len); + memcpy(buf + f->offset, val, f->len); } diff --git a/sbin/isakmpd/field.h b/sbin/isakmpd/field.h index cd8933bd2c6..9021ba3693c 100644 --- a/sbin/isakmpd/field.h +++ b/sbin/isakmpd/field.h @@ -1,5 +1,5 @@ -/* $OpenBSD: field.h,v 1.4 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: field.h,v 1.3 1998/08/02 20:25:01 niklas Exp $ */ +/* $OpenBSD: field.h,v 1.5 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: field.h,v 1.3 1998/08/02 20:25:01 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -35,18 +35,20 @@ #include <sys/types.h> struct field { - char *name; - int offset; - size_t len; - enum { raw, num, mask, ign, cst } type; - struct constant_map **maps; + char *name; + int offset; + size_t len; + enum { + raw, num, mask, ign, cst + } type; + struct constant_map **maps; }; -extern void field_dump_field (struct field *, u_int8_t *); -extern void field_dump_payload (struct field *, u_int8_t *); -extern u_int32_t field_get_num (struct field *, u_int8_t *); -extern void field_get_raw (struct field *, u_int8_t *, u_int8_t *); -extern void field_set_num (struct field *, u_int8_t *, u_int32_t); -extern void field_set_raw (struct field *, u_int8_t *, u_int8_t *); +extern void field_dump_field(struct field *, u_int8_t *); +extern void field_dump_payload(struct field *, u_int8_t *); +extern u_int32_t field_get_num(struct field *, u_int8_t *); +extern void field_get_raw(struct field *, u_int8_t *, u_int8_t *); +extern void field_set_num(struct field *, u_int8_t *, u_int32_t); +extern void field_set_raw(struct field *, u_int8_t *, u_int8_t *); -#endif /* _FIELD_H_ */ +#endif /* _FIELD_H_ */ diff --git a/sbin/isakmpd/genconstants.sh b/sbin/isakmpd/genconstants.sh index 10217f25210..8332209f3a4 100644 --- a/sbin/isakmpd/genconstants.sh +++ b/sbin/isakmpd/genconstants.sh @@ -1,4 +1,4 @@ -# $OpenBSD: genconstants.sh,v 1.11 2003/06/03 14:28:16 ho Exp $ +# $OpenBSD: genconstants.sh,v 1.12 2004/04/15 18:39:25 deraadt Exp $ # $EOM: genconstants.sh,v 1.6 1999/04/02 01:15:53 niklas Exp $ # @@ -92,7 +92,7 @@ BEGIN { } /^\./ { - print " { 0, 0 }\n};\n" + print " { 0, 0 }\n};\n" next } @@ -103,7 +103,7 @@ BEGIN { } /^[ ]/ && $1 { - printf (" { %s_%s, \"%s\", %s }, \n", prefix, $1, $1, + printf (" { %s_%s, \"%s\", %s },\n", prefix, $1, $1, ($3 && substr($3,1,1) != "#") ? $3 : 0) next } diff --git a/sbin/isakmpd/genfields.sh b/sbin/isakmpd/genfields.sh index e2d79942624..74909e1f14b 100644 --- a/sbin/isakmpd/genfields.sh +++ b/sbin/isakmpd/genfields.sh @@ -1,4 +1,4 @@ -# $OpenBSD: genfields.sh,v 1.8 2003/06/03 14:28:16 ho Exp $ +# $OpenBSD: genfields.sh,v 1.9 2004/04/15 18:39:25 deraadt Exp $ # $EOM: genfields.sh,v 1.5 1999/04/02 01:15:55 niklas Exp $ # @@ -138,13 +138,13 @@ BEGIN { } /^\./ { - print " { 0, 0, 0, 0, 0 }\n};\n" + print " { 0, 0, 0, 0, 0 }\n};\n" size[prefix] = off for (map in maps) { - printf ("struct constant_map *%s_%s_maps[] = { ", locase(prefix), + printf ("struct constant_map *%s_%s_maps[] = {\n", locase(prefix), locase(map)) - printf ("%s,0 };\n", maps[map]) + printf (" %s, 0\n};\n", maps[map]) } next } @@ -174,7 +174,7 @@ BEGIN { { maps_name = "0" } - printf (" { \"%s\", %d, %d, %s, %s }, \n", $1, off, $3, $2, maps_name) + printf (" { \"%s\", %d, %d, %s, %s },\n", $1, off, $3, $2, maps_name) off += $3 next } diff --git a/sbin/isakmpd/gmp_util.c b/sbin/isakmpd/gmp_util.c index f8a759affe4..2a338d266df 100644 --- a/sbin/isakmpd/gmp_util.c +++ b/sbin/isakmpd/gmp_util.c @@ -1,5 +1,5 @@ -/* $OpenBSD: gmp_util.c,v 1.10 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: gmp_util.c,v 1.7 2000/09/18 00:01:47 ho Exp $ */ +/* $OpenBSD: gmp_util.c,v 1.11 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: gmp_util.c,v 1.7 2000/09/18 00:01:47 ho Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -41,67 +41,65 @@ /* Various utility functions for gmp, used in more than one module */ u_int32_t -mpz_sizeinoctets (math_mp_t a) +mpz_sizeinoctets(math_mp_t a) { #if MP_FLAVOUR == MP_FLAVOUR_GMP - return (7 + mpz_sizeinbase (a, 2)) >> 3; + return (7 + mpz_sizeinbase(a, 2)) >> 3; #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - return BN_num_bytes (a); + return BN_num_bytes(a); #endif } void -mpz_getraw (u_int8_t *raw, math_mp_t v, u_int32_t len) +mpz_getraw(u_int8_t *raw, math_mp_t v, u_int32_t len) { - math_mp_t a; + math_mp_t a; #if MP_FLAVOUR == MP_FLAVOUR_GMP - math_mp_t tmp; + math_mp_t tmp; - /* XXX mpz_get_str (raw, BASE, v); ? */ - mpz_init_set (a, v); - mpz_init (tmp); + /* XXX mpz_get_str (raw, BASE, v); ? */ + mpz_init_set(a, v); + mpz_init(tmp); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - /* XXX bn2bin? */ - a = BN_dup (v); + /* XXX bn2bin? */ + a = BN_dup(v); #endif - while (len-- > 0) + while (len-- > 0) #if MP_FLAVOUR == MP_FLAVOUR_GMP - raw[len] = mpz_fdiv_qr_ui (a, tmp, a, 256); + raw[len] = mpz_fdiv_qr_ui(a, tmp, a, 256); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - raw[len] = BN_div_word (a, 256); + raw[len] = BN_div_word(a, 256); #endif #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_clear (a); - mpz_clear (tmp); + mpz_clear(a); + mpz_clear(tmp); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - BN_clear_free (a); + BN_clear_free(a); #endif } void -mpz_setraw (math_mp_t d, u_int8_t *s, u_int32_t l) +mpz_setraw(math_mp_t d, u_int8_t *s, u_int32_t l) { - u_int32_t i; + u_int32_t i; #if MP_FLAVOUR == MP_FLAVOUR_GMP - /* XXX mpz_set_str (d, s, 0); */ - mpz_set_si (d, 0); + /* XXX mpz_set_str (d, s, 0); */ + mpz_set_si(d, 0); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - /* XXX bin2bn? */ - BN_set_word (d, 0); + /* XXX bin2bn? */ + BN_set_word(d, 0); #endif - for (i = 0; i < l; i++) - { + for (i = 0; i < l; i++) { #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_mul_ui (d, d, 256); - mpz_add_ui (d, d, s[i]); + mpz_mul_ui(d, d, 256); + mpz_add_ui(d, d, s[i]); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - BN_mul_word (d, 256); - BN_add_word (d, s[i]); + BN_mul_word(d, 256); + BN_add_word(d, s[i]); #endif - } + } } - diff --git a/sbin/isakmpd/gmp_util.h b/sbin/isakmpd/gmp_util.h index 44a4e00ad76..826c6cab354 100644 --- a/sbin/isakmpd/gmp_util.h +++ b/sbin/isakmpd/gmp_util.h @@ -1,5 +1,5 @@ -/* $OpenBSD: gmp_util.h,v 1.7 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: gmp_util.h,v 1.4 2000/05/08 13:42:11 ho Exp $ */ +/* $OpenBSD: gmp_util.h,v 1.8 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: gmp_util.h,v 1.4 2000/05/08 13:42:11 ho Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -35,8 +35,8 @@ #include "math_mp.h" -u_int32_t mpz_sizeinoctets (math_mp_t); -void mpz_getraw (u_int8_t *, math_mp_t, u_int32_t); -void mpz_setraw (math_mp_t, u_int8_t *, u_int32_t); +u_int32_t mpz_sizeinoctets(math_mp_t); +void mpz_getraw(u_int8_t *, math_mp_t, u_int32_t); +void mpz_setraw(math_mp_t, u_int8_t *, u_int32_t); -#endif /* _GMP_UTIL_H_ */ +#endif /* _GMP_UTIL_H_ */ diff --git a/sbin/isakmpd/hash.c b/sbin/isakmpd/hash.c index 978857eaba9..bf77af07836 100644 --- a/sbin/isakmpd/hash.c +++ b/sbin/isakmpd/hash.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hash.c,v 1.14 2004/03/31 10:54:46 ho Exp $ */ -/* $EOM: hash.c,v 1.10 1999/04/17 23:20:34 niklas Exp $ */ +/* $OpenBSD: hash.c,v 1.15 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: hash.c,v 1.10 1999/04/17 23:20:34 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -38,20 +38,20 @@ #else #include <md5.h> #include <sha1.h> -#endif /* __APPLE__ */ +#endif /* __APPLE__ */ #include "sysdep.h" #include "hash.h" #include "log.h" -void hmac_init (struct hash *, unsigned char *, unsigned int); -void hmac_final (unsigned char *, struct hash *); +void hmac_init(struct hash *, unsigned char *, unsigned int); +void hmac_final(unsigned char *, struct hash *); /* Temporary hash contexts. */ static union { - MD5_CTX md5ctx; - SHA1_CTX sha1ctx; + MD5_CTX md5ctx; + SHA1_CTX sha1ctx; } Ctx, Ctx2; /* Temporary hash digest. */ @@ -60,32 +60,37 @@ static unsigned char digest[HASH_MAX]; /* Encapsulation of hash functions. */ static struct hash hashes[] = { - { HASH_MD5, 5, MD5_SIZE, (void *)&Ctx.md5ctx, digest, - sizeof (MD5_CTX), (void *)&Ctx2.md5ctx, - (void (*) (void *))MD5Init, - (void (*) (void *, unsigned char *, unsigned int))MD5Update, - (void (*) (unsigned char *, void *))MD5Final, - hmac_init, hmac_final }, - { HASH_SHA1, 6, SHA1_SIZE, (void *)&Ctx.sha1ctx, digest, - sizeof (SHA1_CTX), (void *)&Ctx2.sha1ctx, - (void (*) (void *))SHA1Init, - (void (*) (void *, unsigned char *, unsigned int))SHA1Update, - (void (*) (unsigned char *, void *))SHA1Final, - hmac_init, hmac_final }, + { + HASH_MD5, 5, MD5_SIZE, (void *) &Ctx.md5ctx, digest, + sizeof(MD5_CTX), (void *) &Ctx2.md5ctx, + (void (*) (void *)) MD5Init, + (void (*) (void *, unsigned char *, unsigned int)) MD5Update, + (void (*) (unsigned char *, void *)) MD5Final, + hmac_init, + hmac_final + }, { + HASH_SHA1, 6, SHA1_SIZE, (void *) &Ctx.sha1ctx, digest, + sizeof(SHA1_CTX), (void *) &Ctx2.sha1ctx, + (void (*) (void *)) SHA1Init, + (void (*) (void *, unsigned char *, unsigned int)) SHA1Update, + (void (*) (unsigned char *, void *)) SHA1Final, + hmac_init, + hmac_final + }, }; struct hash * -hash_get (enum hashes hashtype) +hash_get(enum hashes hashtype) { - size_t i; + size_t i; - LOG_DBG ((LOG_CRYPTO, 60, "hash_get: requested algorithm %d", hashtype)); + LOG_DBG((LOG_CRYPTO, 60, "hash_get: requested algorithm %d", hashtype)); - for (i = 0; i < sizeof hashes / sizeof hashes[0]; i++) - if (hashtype == hashes[i].type) - return &hashes[i]; + for (i = 0; i < sizeof hashes / sizeof hashes[0]; i++) + if (hashtype == hashes[i].type) + return &hashes[i]; - return 0; + return 0; } /* @@ -95,38 +100,35 @@ hash_get (enum hashes hashtype) */ void -hmac_init (struct hash *hash, unsigned char *okey, unsigned int len) +hmac_init(struct hash *hash, unsigned char *okey, unsigned int len) { - unsigned int i, blocklen = HMAC_BLOCKLEN; - unsigned char key[HMAC_BLOCKLEN]; + unsigned int i, blocklen = HMAC_BLOCKLEN; + unsigned char key[HMAC_BLOCKLEN]; - memset (key, 0, blocklen); - if (len > blocklen) - { - /* Truncate key down to blocklen */ - hash->Init (hash->ctx); - hash->Update (hash->ctx, okey, len); - hash->Final (key, hash->ctx); - } - else - { - memcpy (key, okey, len); - } + memset(key, 0, blocklen); + if (len > blocklen) { + /* Truncate key down to blocklen */ + hash->Init(hash->ctx); + hash->Update(hash->ctx, okey, len); + hash->Final(key, hash->ctx); + } else { + memcpy(key, okey, len); + } - /* HMAC I and O pad computation */ - for (i = 0; i < blocklen; i++) - key[i] ^= HMAC_IPAD_VAL; + /* HMAC I and O pad computation */ + for (i = 0; i < blocklen; i++) + key[i] ^= HMAC_IPAD_VAL; - hash->Init (hash->ctx); - hash->Update (hash->ctx, key, blocklen); + hash->Init(hash->ctx); + hash->Update(hash->ctx, key, blocklen); - for (i = 0; i < blocklen; i++) - key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); + for (i = 0; i < blocklen; i++) + key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - hash->Init (hash->ctx2); - hash->Update (hash->ctx2, key, blocklen); + hash->Init(hash->ctx2); + hash->Update(hash->ctx2, key, blocklen); - memset (key, 0, blocklen); + memset(key, 0, blocklen); } /* @@ -134,9 +136,9 @@ hmac_init (struct hash *hash, unsigned char *okey, unsigned int len) */ void -hmac_final (unsigned char *dgst, struct hash *hash) +hmac_final(unsigned char *dgst, struct hash *hash) { - hash->Final (dgst, hash->ctx); - hash->Update (hash->ctx2, dgst, hash->hashsize); - hash->Final (dgst, hash->ctx2); + hash->Final(dgst, hash->ctx); + hash->Update(hash->ctx2, dgst, hash->hashsize); + hash->Final(dgst, hash->ctx2); } diff --git a/sbin/isakmpd/hash.h b/sbin/isakmpd/hash.h index 900601ea8c3..3af23508138 100644 --- a/sbin/isakmpd/hash.h +++ b/sbin/isakmpd/hash.h @@ -1,5 +1,5 @@ -/* $OpenBSD: hash.h,v 1.6 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: hash.h,v 1.6 1998/07/25 22:04:36 niklas Exp $ */ +/* $OpenBSD: hash.h,v 1.7 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: hash.h,v 1.6 1998/07/25 22:04:36 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -39,23 +39,23 @@ #define HASH_MAX SHA1_SIZE enum hashes { - HASH_MD5 = 0, - HASH_SHA1 + HASH_MD5 = 0, + HASH_SHA1 }; struct hash { - enum hashes type; - int id; /* ISAKMP/Oakley ID */ - u_int8_t hashsize; /* Size of the hash */ - void *ctx; /* Pointer to a context, for HMAC ictx */ - unsigned char *digest; /* Pointer to a digest */ - int ctxsize; - void *ctx2; /* Pointer to a 2nd context, for HMAC octx */ - void (*Init) (void *); - void (*Update) (void *, unsigned char *, unsigned int); - void (*Final) (unsigned char *, void *); - void (*HMACInit) (struct hash *, unsigned char *, unsigned int); - void (*HMACFinal) (unsigned char *, struct hash *); + enum hashes type; + int id; /* ISAKMP/Oakley ID */ + u_int8_t hashsize; /* Size of the hash */ + void *ctx; /* Pointer to a context, for HMAC ictx */ + unsigned char *digest; /* Pointer to a digest */ + int ctxsize; + void *ctx2; /* Pointer to a 2nd context, for HMAC octx */ + void (*Init) (void *); + void (*Update) (void *, unsigned char *, unsigned int); + void (*Final) (unsigned char *, void *); + void (*HMACInit) (struct hash *, unsigned char *, unsigned int); + void (*HMACFinal) (unsigned char *, struct hash *); }; /* HMAC Hash Encapsulation */ @@ -64,7 +64,7 @@ struct hash { #define HMAC_OPAD_VAL 0x5C #define HMAC_BLOCKLEN 64 -extern struct hash *hash_get (enum hashes); -extern void hmac_init (struct hash *, unsigned char *, unsigned int); +extern struct hash *hash_get(enum hashes); +extern void hmac_init(struct hash *, unsigned char *, unsigned int); -#endif /* _HASH_H_ */ +#endif /* _HASH_H_ */ diff --git a/sbin/isakmpd/if.c b/sbin/isakmpd/if.c index ab6cd66bcc2..52bd4ec1905 100644 --- a/sbin/isakmpd/if.c +++ b/sbin/isakmpd/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.18 2004/04/13 21:48:15 hshoexer Exp $ */ +/* $OpenBSD: if.c,v 1.19 2004/04/15 18:39:25 deraadt Exp $ */ /* $EOM: if.c,v 1.12 1999/10/01 13:45:20 niklas Exp $ */ /* @@ -59,96 +59,89 @@ * Return 0 if successful, -1 otherwise. */ int -siocgifconf (struct ifconf *ifcp) +siocgifconf(struct ifconf *ifcp) { - int s; - int len; - caddr_t buf, new_buf; - - /* Get a socket to ask for the network interface configurations. */ - s = monitor_socket (AF_INET, SOCK_DGRAM, 0); - if (s == -1) - { - log_error ("siocgifconf: socket (AF_INET, SOCK_DGRAM, 0) failed"); - return -1; - } - - len = sizeof (struct ifreq) * INITIAL_IFREQ_COUNT; - buf = 0; - while (1) - { - /* - * Allocate a larger buffer each time around the loop and get the - * network interfaces configurations into it. - */ - new_buf = realloc (buf, len); - if (!new_buf) - { - log_error ("siocgifconf: realloc (%p, %d) failed", buf, len); - goto err; + caddr_t buf, new_buf; + int s, len; + + /* Get a socket to ask for the network interface configurations. */ + s = monitor_socket(AF_INET, SOCK_DGRAM, 0); + if (s == -1) { + log_error("siocgifconf: socket (AF_INET, SOCK_DGRAM, 0) failed"); + return -1; } - ifcp->ifc_len = len; - ifcp->ifc_buf = buf = new_buf; - if (ioctl (s, SIOCGIFCONF, ifcp) == -1) - { - log_error ("siocgifconf: ioctl (%d, SIOCGIFCONF, ...) failed", s); - goto err; + len = sizeof(struct ifreq) * INITIAL_IFREQ_COUNT; + buf = 0; + while (1) { + /* + * Allocate a larger buffer each time around the loop and get the + * network interfaces configurations into it. + */ + new_buf = realloc(buf, len); + if (!new_buf) { + log_error("siocgifconf: realloc (%p, %d) failed", buf, len); + goto err; + } + ifcp->ifc_len = len; + ifcp->ifc_buf = buf = new_buf; + if (ioctl(s, SIOCGIFCONF, ifcp) == -1) { + log_error("siocgifconf: ioctl (%d, SIOCGIFCONF, ...) failed", s); + goto err; + } + /* + * If there is place for another ifreq we can be sure that the buffer + * was big enough, otherwise double the size and try again. + */ + if (len - ifcp->ifc_len >= sizeof(struct ifreq)) + break; + len *= 2; } - - /* - * If there is place for another ifreq we can be sure that the buffer - * was big enough, otherwise double the size and try again. - */ - if (len - ifcp->ifc_len >= sizeof (struct ifreq)) - break; - len *= 2; - } - close (s); - return 0; + close(s); + return 0; err: - if (buf) - free (buf); - ifcp->ifc_len = 0; - ifcp->ifc_buf = 0; - close (s); - return -1; + if (buf) + free(buf); + ifcp->ifc_len = 0; + ifcp->ifc_buf = 0; + close(s); + return -1; } #endif int -if_map (int (*func) (char *, struct sockaddr *, void *), void *arg) +if_map(int (*func)(char *, struct sockaddr *, void *), void *arg) { - int err = 0; + int err = 0; + #ifdef HAVE_GETIFADDRS - struct ifaddrs *ifap, *ifa; + struct ifaddrs *ifap, *ifa; - if (getifaddrs (&ifap) < 0) - return -1; + if (getifaddrs(&ifap) < 0) + return -1; - for (ifa = ifap; ifa; ifa = ifa->ifa_next) - if ((*func) (ifa->ifa_name, ifa->ifa_addr, arg) == -1) - err = -1; - freeifaddrs (ifap); + for (ifa = ifap; ifa; ifa = ifa->ifa_next) + if ((*func) (ifa->ifa_name, ifa->ifa_addr, arg) == -1) + err = -1; + freeifaddrs(ifap); #else - struct ifconf ifc; - struct ifreq *ifrp; - caddr_t limit, p; - size_t len; - - if (siocgifconf (&ifc)) - return -1; - - limit = ifc.ifc_buf + ifc.ifc_len; - for (p = ifc.ifc_buf; p < limit; p += len) - { - ifrp = (struct ifreq *)p; - if ((*func) (ifrp->ifr_name, &ifrp->ifr_addr, arg) == -1) - err = -1; - len = sizeof ifrp->ifr_name - + MAX (sysdep_sa_len (&ifrp->ifr_addr), sizeof ifrp->ifr_addr); - } - free (ifc.ifc_buf); + struct ifconf ifc; + struct ifreq *ifrp; + caddr_t limit, p; + size_t len; + + if (siocgifconf(&ifc)) + return -1; + + limit = ifc.ifc_buf + ifc.ifc_len; + for (p = ifc.ifc_buf; p < limit; p += len) { + ifrp = (struct ifreq *) p; + if ((*func) (ifrp->ifr_name, &ifrp->ifr_addr, arg) == -1) + err = -1; + len = sizeof ifrp->ifr_name + + MAX(sysdep_sa_len(&ifrp->ifr_addr), sizeof ifrp->ifr_addr); + } + free(ifc.ifc_buf); #endif - return err; + return err; } diff --git a/sbin/isakmpd/if.h b/sbin/isakmpd/if.h index 8054dd44b6b..82d574d96dc 100644 --- a/sbin/isakmpd/if.h +++ b/sbin/isakmpd/if.h @@ -1,5 +1,5 @@ -/* $OpenBSD: if.h,v 1.6 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: if.h,v 1.2 1998/07/07 23:35:58 niklas Exp $ */ +/* $OpenBSD: if.h,v 1.7 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: if.h,v 1.2 1998/07/07 23:35:58 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -37,7 +37,7 @@ struct ifreq; struct ifconf; -extern int if_map (int (*) (char *, struct sockaddr *, void *), void *); -extern int siocgifconf (struct ifconf *); +extern int if_map(int (*) (char *, struct sockaddr *, void *), void *); +extern int siocgifconf(struct ifconf *); -#endif /* _IF_H_ */ +#endif /* _IF_H_ */ diff --git a/sbin/isakmpd/ike_aggressive.c b/sbin/isakmpd/ike_aggressive.c index 6dbc34580b6..a7d58fc3b9e 100644 --- a/sbin/isakmpd/ike_aggressive.c +++ b/sbin/isakmpd/ike_aggressive.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_aggressive.c,v 1.5 2003/06/04 07:31:16 ho Exp $ */ -/* $EOM: ike_aggressive.c,v 1.4 2000/01/31 22:33:45 niklas Exp $ */ +/* $OpenBSD: ike_aggressive.c,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_aggressive.c,v 1.4 2000/01/31 22:33:45 niklas Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -59,69 +59,69 @@ #include "transport.h" #include "util.h" -static int initiator_recv_SA_KE_NONCE_ID_AUTH (struct message *); -static int initiator_send_SA_KE_NONCE_ID (struct message *); -static int initiator_send_AUTH (struct message *); -static int responder_recv_SA_KE_NONCE_ID (struct message *); -static int responder_send_SA_KE_NONCE_ID_AUTH (struct message *); +static int initiator_recv_SA_KE_NONCE_ID_AUTH(struct message *); +static int initiator_send_SA_KE_NONCE_ID(struct message *); +static int initiator_send_AUTH(struct message *); +static int responder_recv_SA_KE_NONCE_ID(struct message *); +static int responder_send_SA_KE_NONCE_ID_AUTH(struct message *); -int (*ike_aggressive_initiator[]) (struct message *) = { - initiator_send_SA_KE_NONCE_ID, - initiator_recv_SA_KE_NONCE_ID_AUTH, - initiator_send_AUTH +int (*ike_aggressive_initiator[]) (struct message *) = { + initiator_send_SA_KE_NONCE_ID, + initiator_recv_SA_KE_NONCE_ID_AUTH, + initiator_send_AUTH }; -int (*ike_aggressive_responder[]) (struct message *) = { - responder_recv_SA_KE_NONCE_ID, - responder_send_SA_KE_NONCE_ID_AUTH, - ike_phase_1_recv_AUTH +int (*ike_aggressive_responder[]) (struct message *) = { + responder_recv_SA_KE_NONCE_ID, + responder_send_SA_KE_NONCE_ID_AUTH, + ike_phase_1_recv_AUTH }; /* Offer a set of transforms to the responder in the MSG message. */ static int -initiator_send_SA_KE_NONCE_ID (struct message *msg) +initiator_send_SA_KE_NONCE_ID(struct message * msg) { - if (ike_phase_1_initiator_send_SA (msg)) - return -1; + if (ike_phase_1_initiator_send_SA(msg)) + return -1; - if (ike_phase_1_initiator_send_KE_NONCE (msg)) - return -1; + if (ike_phase_1_initiator_send_KE_NONCE(msg)) + return -1; - return ike_phase_1_send_ID (msg); + return ike_phase_1_send_ID(msg); } /* Figure out what transform the responder chose. */ static int -initiator_recv_SA_KE_NONCE_ID_AUTH (struct message *msg) +initiator_recv_SA_KE_NONCE_ID_AUTH(struct message * msg) { - if (ike_phase_1_initiator_recv_SA (msg)) - return -1; + if (ike_phase_1_initiator_recv_SA(msg)) + return -1; - if (ike_phase_1_initiator_recv_KE_NONCE (msg)) - return -1; + if (ike_phase_1_initiator_recv_KE_NONCE(msg)) + return -1; - return ike_phase_1_recv_ID_AUTH (msg); + return ike_phase_1_recv_ID_AUTH(msg); } static int -initiator_send_AUTH (struct message *msg) +initiator_send_AUTH(struct message * msg) { - msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; - - if (ike_phase_1_send_AUTH (msg)) - return -1; - - /* - * RFC 2407 4.6.3 says that, among others, INITIAL-CONTACT MUST NOT - * be sent in Aggressive Mode. This leaves us with the choice of - * doing it in an informational exchange of its own with no delivery - * guarantee or in the first Quick Mode, or not at all. - * draft-jenkins-ipsec-rekeying-01.txt has some text that requires - * INITIAL-CONTACT in phase 1, thus contradicting what we learned - * above. I will bring this up in the IPsec list. For now we don't - * do INITIAL-CONTACT at all when using aggressive mode. - */ - return 0; + msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; + + if (ike_phase_1_send_AUTH(msg)) + return -1; + + /* + * RFC 2407 4.6.3 says that, among others, INITIAL-CONTACT MUST NOT + * be sent in Aggressive Mode. This leaves us with the choice of + * doing it in an informational exchange of its own with no delivery + * guarantee or in the first Quick Mode, or not at all. + * draft-jenkins-ipsec-rekeying-01.txt has some text that requires + * INITIAL-CONTACT in phase 1, thus contradicting what we learned + * above. I will bring this up in the IPsec list. For now we don't + * do INITIAL-CONTACT at all when using aggressive mode. + */ + return 0; } /* @@ -129,15 +129,15 @@ initiator_send_AUTH (struct message *msg) * handle. Also accept initiator's public DH value, nonce and ID. */ static int -responder_recv_SA_KE_NONCE_ID (struct message *msg) +responder_recv_SA_KE_NONCE_ID(struct message * msg) { - if (ike_phase_1_responder_recv_SA (msg)) - return -1; + if (ike_phase_1_responder_recv_SA(msg)) + return -1; - if (ike_phase_1_recv_ID (msg)) - return -1; + if (ike_phase_1_recv_ID(msg)) + return -1; - return ike_phase_1_recv_KE_NONCE (msg); + return ike_phase_1_recv_KE_NONCE(msg); } /* @@ -145,19 +145,19 @@ responder_recv_SA_KE_NONCE_ID (struct message *msg) * to the initiator. */ static int -responder_send_SA_KE_NONCE_ID_AUTH (struct message *msg) +responder_send_SA_KE_NONCE_ID_AUTH(struct message * msg) { - /* Add the SA payload with the transform that was chosen. */ - if (ike_phase_1_responder_send_SA (msg)) - return -1; + /* Add the SA payload with the transform that was chosen. */ + if (ike_phase_1_responder_send_SA(msg)) + return -1; - /* XXX Should we really just use the initiator's nonce size? */ - if (ike_phase_1_send_KE_NONCE (msg, msg->exchange->nonce_i_len)) - return -1; + /* XXX Should we really just use the initiator's nonce size? */ + if (ike_phase_1_send_KE_NONCE(msg, msg->exchange->nonce_i_len)) + return -1; - if (ike_phase_1_post_exchange_KE_NONCE (msg)) - return -1; + if (ike_phase_1_post_exchange_KE_NONCE(msg)) + return -1; - return ike_phase_1_responder_send_ID_AUTH (msg); - return -1; + return ike_phase_1_responder_send_ID_AUTH(msg); + return -1; } diff --git a/sbin/isakmpd/ike_aggressive.h b/sbin/isakmpd/ike_aggressive.h index 44f3cd0fbb0..4356cdeac57 100644 --- a/sbin/isakmpd/ike_aggressive.h +++ b/sbin/isakmpd/ike_aggressive.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_aggressive.h,v 1.3 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ike_aggressive.h,v 1.1 1999/04/16 21:24:43 niklas Exp $ */ +/* $OpenBSD: ike_aggressive.h,v 1.4 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_aggressive.h,v 1.1 1999/04/16 21:24:43 niklas Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -34,7 +34,7 @@ struct message; -extern int (*ike_aggressive_initiator[]) (struct message *msg); -extern int (*ike_aggressive_responder[]) (struct message *msg); +extern int (*ike_aggressive_initiator[]) (struct message * msg); +extern int (*ike_aggressive_responder[]) (struct message * msg); -#endif /* _IKE_AGGRESSIVE_H_ */ +#endif /* _IKE_AGGRESSIVE_H_ */ diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c index 4133c50e41f..b5901acdf0f 100644 --- a/sbin/isakmpd/ike_auth.c +++ b/sbin/isakmpd/ike_auth.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_auth.c,v 1.85 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */ +/* $OpenBSD: ike_auth.c,v 1.86 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -73,63 +73,63 @@ #endif #ifdef notyet -static u_int8_t *enc_gen_skeyid (struct exchange *, size_t *); +static u_int8_t *enc_gen_skeyid(struct exchange *, size_t *); #endif -static u_int8_t *pre_shared_gen_skeyid (struct exchange *, size_t *); +static u_int8_t *pre_shared_gen_skeyid(struct exchange *, size_t *); -static int pre_shared_decode_hash (struct message *); -static int pre_shared_encode_hash (struct message *); +static int pre_shared_decode_hash(struct message *); +static int pre_shared_encode_hash(struct message *); #if defined (USE_X509) || defined (USE_KEYNOTE) -static u_int8_t *sig_gen_skeyid (struct exchange *, size_t *); -static int rsa_sig_decode_hash (struct message *); -static int rsa_sig_encode_hash (struct message *); +static u_int8_t *sig_gen_skeyid(struct exchange *, size_t *); +static int rsa_sig_decode_hash(struct message *); +static int rsa_sig_encode_hash(struct message *); #endif #if defined (USE_RAWKEY) -static int get_raw_key_from_file (int, u_int8_t *, size_t, RSA **); +static int get_raw_key_from_file(int, u_int8_t *, size_t, RSA **); #endif -static int ike_auth_hash (struct exchange *, u_int8_t *); +static int ike_auth_hash(struct exchange *, u_int8_t *); static struct ike_auth ike_auth[] = { - { - IKE_AUTH_PRE_SHARED, pre_shared_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash - }, + { + IKE_AUTH_PRE_SHARED, pre_shared_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, #ifdef notdef - { - IKE_AUTH_DSS, sig_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash - }, + { + IKE_AUTH_DSS, sig_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, #endif #if defined (USE_X509) || defined (USE_KEYNOTE) - { - IKE_AUTH_RSA_SIG, sig_gen_skeyid, rsa_sig_decode_hash, - rsa_sig_encode_hash - }, + { + IKE_AUTH_RSA_SIG, sig_gen_skeyid, rsa_sig_decode_hash, + rsa_sig_encode_hash + }, #endif #ifdef notdef - { - IKE_AUTH_RSA_ENC, enc_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash - }, - { - IKE_AUTH_RSA_ENC_REV, enc_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash - }, + { + IKE_AUTH_RSA_ENC, enc_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, + { + IKE_AUTH_RSA_ENC_REV, enc_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, #endif }; struct ike_auth * -ike_auth_get (u_int16_t id) +ike_auth_get(u_int16_t id) { - size_t i; + size_t i; - for (i = 0; i < sizeof ike_auth / sizeof ike_auth[0]; i++) - if (id == ike_auth[i].id) - return &ike_auth[i]; - return 0; + for (i = 0; i < sizeof ike_auth / sizeof ike_auth[0]; i++) + if (id == ike_auth[i].id) + return &ike_auth[i]; + return 0; } /* @@ -137,378 +137,337 @@ ike_auth_get (u_int16_t id) * peer denoted by ID. Stash the len in KEYLEN. */ static void * -ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen) +ike_auth_get_key(int type, char *id, char *local_id, size_t *keylen) { - char *key, *buf; + char *key, *buf; #if defined (USE_X509) || defined (USE_KEYNOTE) - char *keyfile; + char *keyfile; #if defined (USE_X509) #if defined (USE_PRIVSEP) - FILE *keyfp; + FILE *keyfp; #else - BIO *keyh; + BIO *keyh; #endif - RSA *rsakey; - size_t fsize; + RSA *rsakey; + size_t fsize; #endif #endif - switch (type) - { - case IKE_AUTH_PRE_SHARED: - /* Get the pre-shared key for our peer. */ - key = conf_get_str (id, "Authentication"); - if (!key && local_id) - key = conf_get_str (local_id, "Authentication"); - - if (!key) - { - log_print ("ike_auth_get_key: " - "no key found for peer \"%s\" or local ID \"%s\"", - id, local_id); - return 0; - } - - /* If the key starts with 0x it is in hex format. */ - if (strncasecmp (key, "0x", 2) == 0) - { - *keylen = (strlen (key) - 1) / 2; - buf = malloc (*keylen); - if (!buf) - { - log_error ("ike_auth_get_key: malloc (%lu) failed", - (unsigned long)*keylen); - return 0; - } - if (hex2raw (key + 2, (unsigned char *)buf, *keylen)) - { - free (buf); - log_print ("ike_auth_get_key: invalid hex key %s", key); - return 0; - } - key = buf; - } - else - { - buf = key; - key = strdup (buf); - if (!key) - { - log_error ("ike_auth_get_key: strdup() failed"); - return 0; - } - *keylen = strlen (key); - } - break; + switch (type) { + case IKE_AUTH_PRE_SHARED: + /* Get the pre-shared key for our peer. */ + key = conf_get_str(id, "Authentication"); + if (!key && local_id) + key = conf_get_str(local_id, "Authentication"); + + if (!key) { + log_print("ike_auth_get_key: " + "no key found for peer \"%s\" or local ID \"%s\"", + id, local_id); + return 0; + } + /* If the key starts with 0x it is in hex format. */ + if (strncasecmp(key, "0x", 2) == 0) { + *keylen = (strlen(key) - 1) / 2; + buf = malloc(*keylen); + if (!buf) { + log_error("ike_auth_get_key: malloc (%lu) failed", + (unsigned long) *keylen); + return 0; + } + if (hex2raw(key + 2, (unsigned char *) buf, *keylen)) { + free(buf); + log_print("ike_auth_get_key: invalid hex key %s", + key); + return 0; + } + key = buf; + } else { + buf = key; + key = strdup(buf); + if (!key) { + log_error("ike_auth_get_key: strdup() failed"); + return 0; + } + *keylen = strlen(key); + } + break; - case IKE_AUTH_RSA_SIG: + case IKE_AUTH_RSA_SIG: #if defined (USE_X509) || defined (USE_KEYNOTE) #if defined (USE_KEYNOTE) - if (local_id && - (keyfile = conf_get_str ("KeyNote", "Credential-directory")) != 0) - { - struct stat sb; - struct keynote_deckey dc; - char *privkeyfile, *buf2; - int fd, pkflen; - size_t size; - - pkflen = strlen (keyfile) + strlen (local_id) + - sizeof PRIVATE_KEY_FILE + sizeof "//" - 1; - privkeyfile = calloc (pkflen, sizeof (char)); - if (!privkeyfile) - { - log_print ("ike_auth_get_key: failed to allocate %d bytes", - pkflen); - return 0; - } - - snprintf (privkeyfile, pkflen, "%s/%s/%s", keyfile, local_id, - PRIVATE_KEY_FILE); - keyfile = privkeyfile; - - if (monitor_stat (keyfile, &sb) < 0) - { - free (keyfile); - goto ignorekeynote; - } - size = (size_t)sb.st_size; - - fd = monitor_open (keyfile, O_RDONLY, 0); - if (fd < 0) - { - log_print ("ike_auth_get_key: failed opening \"%s\"", keyfile); - free (keyfile); - return 0; - } - - buf = calloc (size + 1, sizeof (char)); - if (!buf) - { - log_print ("ike_auth_get_key: failed allocating %lu bytes", - (unsigned long)size + 1); - free (keyfile); - return 0; - } - - if (read (fd, buf, size) != (ssize_t)size) - { - free (buf); - log_print ("ike_auth_get_key: " - "failed reading %lu bytes from \"%s\"", - (unsigned long)size, keyfile); - free (keyfile); - return 0; - } - - close (fd); - - /* Parse private key string */ - buf2 = kn_get_string (buf); - free (buf); - - if (kn_decode_key (&dc, buf2, KEYNOTE_PRIVATE_KEY) == -1) - { - free (buf2); - log_print ("ike_auth_get_key: failed decoding key in \"%s\"", - keyfile); - free (keyfile); - return 0; - } - - free (buf2); - - if (dc.dec_algorithm != KEYNOTE_ALGORITHM_RSA) - { - log_print ("ike_auth_get_key: wrong algorithm type %d in \"%s\"", - dc.dec_algorithm, keyfile); - free (keyfile); - kn_free_key (&dc); - return 0; - } - - free (keyfile); - return dc.dec_key; - } - - ignorekeynote: -#endif /* USE_KEYNOTE */ + if (local_id && + (keyfile = conf_get_str("KeyNote", "Credential-directory")) != 0) { + struct stat sb; + struct keynote_deckey dc; + char *privkeyfile, *buf2; + int fd, pkflen; + size_t size; + + pkflen = strlen(keyfile) + strlen(local_id) + + sizeof PRIVATE_KEY_FILE + sizeof "//" - 1; + privkeyfile = calloc(pkflen, sizeof(char)); + if (!privkeyfile) { + log_print("ike_auth_get_key: failed to allocate %d bytes", + pkflen); + return 0; + } + snprintf(privkeyfile, pkflen, "%s/%s/%s", keyfile, local_id, + PRIVATE_KEY_FILE); + keyfile = privkeyfile; + + if (monitor_stat(keyfile, &sb) < 0) { + free(keyfile); + goto ignorekeynote; + } + size = (size_t) sb.st_size; + + fd = monitor_open(keyfile, O_RDONLY, 0); + if (fd < 0) { + log_print("ike_auth_get_key: failed opening \"%s\"", + keyfile); + free(keyfile); + return 0; + } + buf = calloc(size + 1, sizeof(char)); + if (!buf) { + log_print("ike_auth_get_key: failed allocating %lu bytes", + (unsigned long) size + 1); + free(keyfile); + return 0; + } + if (read(fd, buf, size) != (ssize_t) size) { + free(buf); + log_print("ike_auth_get_key: " + "failed reading %lu bytes from \"%s\"", + (unsigned long) size, keyfile); + free(keyfile); + return 0; + } + close(fd); + + /* Parse private key string */ + buf2 = kn_get_string(buf); + free(buf); + + if (kn_decode_key(&dc, buf2, KEYNOTE_PRIVATE_KEY) == -1) { + free(buf2); + log_print("ike_auth_get_key: failed decoding key in \"%s\"", + keyfile); + free(keyfile); + return 0; + } + free(buf2); + + if (dc.dec_algorithm != KEYNOTE_ALGORITHM_RSA) { + log_print("ike_auth_get_key: wrong algorithm type %d in \"%s\"", + dc.dec_algorithm, keyfile); + free(keyfile); + kn_free_key(&dc); + return 0; + } + free(keyfile); + return dc.dec_key; + } +ignorekeynote: +#endif /* USE_KEYNOTE */ #ifdef USE_X509 - /* Otherwise, try X.509 */ - keyfile = conf_get_str ("X509-certificates", "Private-key"); + /* Otherwise, try X.509 */ + keyfile = conf_get_str("X509-certificates", "Private-key"); - if (check_file_secrecy (keyfile, &fsize)) - return 0; + if (check_file_secrecy(keyfile, &fsize)) + return 0; #if defined (USE_PRIVSEP) - keyfp = monitor_fopen (keyfile, "r"); - if (!keyfp) - { - log_print ("ike_auth_get_key: failed opening \"%s\"", keyfile); - return 0; - } + keyfp = monitor_fopen(keyfile, "r"); + if (!keyfp) { + log_print("ike_auth_get_key: failed opening \"%s\"", keyfile); + return 0; + } #if SSLEAY_VERSION_NUMBER >= 0x00904100L - rsakey = PEM_read_RSAPrivateKey (keyfp, NULL, NULL, NULL); + rsakey = PEM_read_RSAPrivateKey(keyfp, NULL, NULL, NULL); #else - rsakey = PEM_read_RSAPrivateKey (keyfp, NULL, NULL); + rsakey = PEM_read_RSAPrivateKey(keyfp, NULL, NULL); #endif - fclose (keyfp); + fclose(keyfp); #else - keyh = BIO_new (BIO_s_file ()); - if (keyh == NULL) - { - log_print ("ike_auth_get_key: " - "BIO_new (BIO_s_file ()) failed"); - return 0; - } - if (BIO_read_filename (keyh, keyfile) == -1) - { - log_print ("ike_auth_get_key: " - "BIO_read_filename (keyh, \"%s\") failed", - keyfile); - BIO_free (keyh); - return 0; - } - + keyh = BIO_new(BIO_s_file()); + if (keyh == NULL) { + log_print("ike_auth_get_key: " + "BIO_new (BIO_s_file ()) failed"); + return 0; + } + if (BIO_read_filename(keyh, keyfile) == -1) { + log_print("ike_auth_get_key: " + "BIO_read_filename (keyh, \"%s\") failed", + keyfile); + BIO_free(keyh); + return 0; + } #if SSLEAY_VERSION_NUMBER >= 0x00904100L - rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL, NULL); + rsakey = PEM_read_bio_RSAPrivateKey(keyh, NULL, NULL, NULL); #else - rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL); + rsakey = PEM_read_bio_RSAPrivateKey(keyh, NULL, NULL); #endif - BIO_free (keyh); -#endif /* USE_PRIVSEP */ + BIO_free(keyh); +#endif /* USE_PRIVSEP */ - if (!rsakey) - { - log_print ("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed"); - return 0; - } - - return rsakey; + if (!rsakey) { + log_print("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed"); + return 0; + } + return rsakey; #endif /* USE_X509 */ #endif /* USE_X509 || USE_KEYNOTE */ - default: - log_print ("ike_auth_get_key: unknown key type %d", type); - return 0; - } + default: + log_print("ike_auth_get_key: unknown key type %d", type); + return 0; + } - return key; + return key; } static u_int8_t * -pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) +pre_shared_gen_skeyid(struct exchange *exchange, size_t *sz) { - struct prf *prf; - struct ipsec_exch *ie = exchange->data; - u_int8_t *skeyid; - u_int8_t *buf = 0; - unsigned char *key; - size_t keylen; - - /* - * If we're the responder and have the initiator's ID (which is the - * case in Aggressive mode), try to find the preshared key in the - * section of the initiator's Phase 1 ID. This allows us to do - * mobile user support with preshared keys. - */ - if (!exchange->initiator && exchange->id_i) - { - switch (exchange->id_i[0]) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - util_ntoa ((char **)&buf, - exchange->id_i[0] == IPSEC_ID_IPV4_ADDR - ? AF_INET : AF_INET6, - exchange->id_i + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); - if (!buf) - return 0; - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - buf = calloc (exchange->id_i_len - ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + 1, sizeof (char)); - if (!buf) - { - log_print ("pre_shared_gen_skeyid: malloc (%lu) failed", - (unsigned long)exchange->id_i_len - ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + 1); - return 0; - } - memcpy (buf, exchange->id_i + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - exchange->id_i_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); - break; - - /* XXX Support more ID types ? */ - default: - break; + struct prf *prf; + struct ipsec_exch *ie = exchange->data; + u_int8_t *skeyid, *buf = 0; + unsigned char *key; + size_t keylen; + + /* + * If we're the responder and have the initiator's ID (which is the + * case in Aggressive mode), try to find the preshared key in the + * section of the initiator's Phase 1 ID. This allows us to do + * mobile user support with preshared keys. + */ + if (!exchange->initiator && exchange->id_i) { + switch (exchange->id_i[0]) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + util_ntoa((char **) &buf, + exchange->id_i[0] == IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6, + exchange->id_i + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + if (!buf) + return 0; + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + buf = calloc(exchange->id_i_len - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, sizeof(char)); + if (!buf) { + log_print("pre_shared_gen_skeyid: malloc (%lu) failed", + (unsigned long) exchange->id_i_len - + ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); + return 0; + } + memcpy(buf, + exchange->id_i + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + exchange->id_i_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; + + /* XXX Support more ID types ? */ + default: + break; + } + } + /* + * Get the pre-shared key for our peer. This will work even if the key + * has been passed to us through a mechanism like PFKEYv2. + */ + key = ike_auth_get_key(IKE_AUTH_PRE_SHARED, exchange->name, + (char *) buf, &keylen); + if (buf) + free(buf); + + /* Fail if no key could be found. */ + if (!key) + return 0; + + /* Store the secret key for later policy processing. */ + exchange->recv_key = calloc(keylen + 1, sizeof(char)); + exchange->recv_keytype = ISAKMP_KEY_PASSPHRASE; + if (!exchange->recv_key) { + log_error("pre_shared_gen_skeyid: malloc (%lu) failed", + (unsigned long) keylen); + free(key); + return 0; } - } - - /* - * Get the pre-shared key for our peer. This will work even if the key - * has been passed to us through a mechanism like PFKEYv2. - */ - key = ike_auth_get_key (IKE_AUTH_PRE_SHARED, exchange->name, (char *)buf, - &keylen); - if (buf) - free (buf); - - /* Fail if no key could be found. */ - if (!key) - return 0; - - /* Store the secret key for later policy processing. */ - exchange->recv_key = calloc (keylen + 1, sizeof (char)); - exchange->recv_keytype = ISAKMP_KEY_PASSPHRASE; - if (!exchange->recv_key) - { - log_error ("pre_shared_gen_skeyid: malloc (%lu) failed", - (unsigned long)keylen); - free (key); - return 0; - } - memcpy (exchange->recv_key, key, keylen); - exchange->recv_certtype = ISAKMP_CERTENC_NONE; - free (key); - - prf = prf_alloc (ie->prf_type, ie->hash->type, exchange->recv_key, keylen); - if (!prf) - return 0; - - *sz = prf->blocksize; - skeyid = malloc (*sz); - if (!skeyid) - { - log_error ("pre_shared_gen_skeyid: malloc (%lu) failed", - (unsigned long)*sz); - prf_free (prf); - return 0; - } - - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); - prf->Update (prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); - prf->Final (skeyid, prf->prfctx); - prf_free (prf); - - return skeyid; + memcpy(exchange->recv_key, key, keylen); + exchange->recv_certtype = ISAKMP_CERTENC_NONE; + free(key); + + prf = prf_alloc(ie->prf_type, ie->hash->type, exchange->recv_key, keylen); + if (!prf) + return 0; + + *sz = prf->blocksize; + skeyid = malloc(*sz); + if (!skeyid) { + log_error("pre_shared_gen_skeyid: malloc (%lu) failed", + (unsigned long) *sz); + prf_free(prf); + return 0; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); + prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); + prf->Final(skeyid, prf->prfctx); + prf_free(prf); + return skeyid; } #if defined (USE_X509) || defined (USE_KEYNOTE) /* Both DSS & RSA signature authentication use this algorithm. */ static u_int8_t * -sig_gen_skeyid (struct exchange *exchange, size_t *sz) +sig_gen_skeyid(struct exchange *exchange, size_t *sz) { - struct prf *prf; - struct ipsec_exch *ie = exchange->data; - u_int8_t *skeyid; - unsigned char *key; - - key = malloc (exchange->nonce_i_len + exchange->nonce_r_len); - if (!key) - return 0; - memcpy (key, exchange->nonce_i, exchange->nonce_i_len); - memcpy (key + exchange->nonce_i_len, exchange->nonce_r, - exchange->nonce_r_len); - - LOG_DBG ((LOG_NEGOTIATION, 80, "sig_gen_skeyid: PRF type %d, hash %d", + struct prf *prf; + struct ipsec_exch *ie = exchange->data; + u_int8_t *skeyid; + unsigned char *key; + + key = malloc(exchange->nonce_i_len + exchange->nonce_r_len); + if (!key) + return 0; + memcpy(key, exchange->nonce_i, exchange->nonce_i_len); + memcpy(key + exchange->nonce_i_len, exchange->nonce_r, + exchange->nonce_r_len); + + LOG_DBG((LOG_NEGOTIATION, 80, "sig_gen_skeyid: PRF type %d, hash %d", ie->prf_type, ie->hash->type)); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, "sig_gen_skeyid: SKEYID initialized with", - (u_int8_t *)key, - exchange->nonce_i_len + exchange->nonce_r_len)); - - prf = prf_alloc (ie->prf_type, ie->hash->type, key, - exchange->nonce_i_len + exchange->nonce_r_len); - free (key); - if (!prf) - return 0; - - *sz = prf->blocksize; - skeyid = malloc (*sz); - if (!skeyid) - { - log_error ("sig_gen_skeyid: malloc (%lu) failed", - (unsigned long)*sz); - prf_free (prf); - return 0; - } - - LOG_DBG ((LOG_NEGOTIATION, 80, "sig_gen_skeyid: g^xy length %lu", - (unsigned long)ie->g_x_len)); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, "sig_gen_skeyid: SKEYID fed with g^xy", - ie->g_xy, ie->g_x_len)); - - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, ie->g_xy, ie->g_x_len); - prf->Final (skeyid, prf->prfctx); - prf_free (prf); - - return skeyid; + LOG_DBG_BUF((LOG_NEGOTIATION, 80, "sig_gen_skeyid: SKEYID initialized with", + (u_int8_t *) key, exchange->nonce_i_len + exchange->nonce_r_len)); + + prf = prf_alloc(ie->prf_type, ie->hash->type, key, + exchange->nonce_i_len + exchange->nonce_r_len); + free(key); + if (!prf) + return 0; + + *sz = prf->blocksize; + skeyid = malloc(*sz); + if (!skeyid) { + log_error("sig_gen_skeyid: malloc (%lu) failed", + (unsigned long) *sz); + prf_free(prf); + return 0; + } + LOG_DBG((LOG_NEGOTIATION, 80, "sig_gen_skeyid: g^xy length %lu", + (unsigned long) ie->g_x_len)); + LOG_DBG_BUF((LOG_NEGOTIATION, 80, "sig_gen_skeyid: SKEYID fed with g^xy", + ie->g_xy, ie->g_x_len)); + + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, ie->g_xy, ie->g_x_len); + prf->Final(skeyid, prf->prfctx); + prf_free(prf); + return skeyid; } -#endif /* USE_X509 || USE_KEYNOTE */ +#endif /* USE_X509 || USE_KEYNOTE */ #ifdef notdef /* @@ -516,797 +475,688 @@ sig_gen_skeyid (struct exchange *exchange, size_t *sz) * computation. */ static u_int8_t * -enc_gen_skeyid (struct exchange *exchange, size_t *sz) +enc_gen_skeyid(struct exchange *exchange, size_t *sz) { - struct prf *prf; - struct ipsec_exch *ie = exchange->data; - struct hash *hash = ie->hash; - u_int8_t *skeyid; - - hash->Init (hash->ctx); - hash->Update (hash->ctx, exchange->nonce_i, exchange->nonce_i_len); - hash->Update (hash->ctx, exchange->nonce_r, exchange->nonce_r_len); - hash->Final (hash->digest, hash->ctx); - prf = prf_alloc (ie->prf_type, hash->type, hash->digest, *sz); - if (!prf) - return 0; - - *sz = prf->blocksize; - skeyid = malloc (*sz); - if (!skeyid) - { - log_error ("enc_gen_skeyid: malloc (%d) failed", *sz); - prf_free (prf); - return 0; - } - - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); - prf->Final (skeyid, prf->prfctx); - prf_free (prf); - - return skeyid; + struct prf *prf; + struct ipsec_exch *ie = exchange->data; + struct hash *hash = ie->hash; + u_int8_t *skeyid; + + hash->Init(hash->ctx); + hash->Update(hash->ctx, exchange->nonce_i, exchange->nonce_i_len); + hash->Update(hash->ctx, exchange->nonce_r, exchange->nonce_r_len); + hash->Final(hash->digest, hash->ctx); + prf = prf_alloc(ie->prf_type, hash->type, hash->digest, *sz); + if (!prf) + return 0; + + *sz = prf->blocksize; + skeyid = malloc(*sz); + if (!skeyid) { + log_error("enc_gen_skeyid: malloc (%d) failed", *sz); + prf_free(prf); + return 0; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); + prf->Final(skeyid, prf->prfctx); + prf_free(prf); + return skeyid; } -#endif /* notdef */ +#endif /* notdef */ static int -pre_shared_decode_hash (struct message *msg) +pre_shared_decode_hash(struct message *msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct payload *payload; - size_t hashsize = ie->hash->hashsize; - char header[80]; - int initiator = exchange->initiator; - u_int8_t **hash_p; - - /* Choose the right fields to fill-in. */ - hash_p = initiator ? &ie->hash_r : &ie->hash_i; - - payload = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - if (!payload) - { - log_print ("pre_shared_decode_hash: no HASH payload found"); - return -1; - } - - /* Check that the hash is of the correct size. */ - if (GET_ISAKMP_GEN_LENGTH (payload->p) - ISAKMP_GEN_SZ != hashsize) - return -1; - - /* XXX Need this hash be in the SA? */ - *hash_p = malloc (hashsize); - if (!*hash_p) - { - log_error ("pre_shared_decode_hash: malloc (%lu) failed", - (unsigned long)hashsize); - return -1; - } - - memcpy (*hash_p, payload->p + ISAKMP_HASH_DATA_OFF, hashsize); - snprintf (header, sizeof header, "pre_shared_decode_hash: HASH_%c", + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct payload *payload; + size_t hashsize = ie->hash->hashsize; + char header[80]; + int initiator = exchange->initiator; + u_int8_t **hash_p; + + /* Choose the right fields to fill-in. */ + hash_p = initiator ? &ie->hash_r : &ie->hash_i; + + payload = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + if (!payload) { + log_print("pre_shared_decode_hash: no HASH payload found"); + return -1; + } + /* Check that the hash is of the correct size. */ + if (GET_ISAKMP_GEN_LENGTH(payload->p) - ISAKMP_GEN_SZ != hashsize) + return -1; + + /* XXX Need this hash be in the SA? */ + *hash_p = malloc(hashsize); + if (!*hash_p) { + log_error("pre_shared_decode_hash: malloc (%lu) failed", + (unsigned long) hashsize); + return -1; + } + memcpy(*hash_p, payload->p + ISAKMP_HASH_DATA_OFF, hashsize); + snprintf(header, sizeof header, "pre_shared_decode_hash: HASH_%c", initiator ? 'R' : 'I'); - LOG_DBG_BUF ((LOG_MISC, 80, header, *hash_p, hashsize)); + LOG_DBG_BUF((LOG_MISC, 80, header, *hash_p, hashsize)); - payload->flags |= PL_MARK; - - return 0; + payload->flags |= PL_MARK; + return 0; } #if defined (USE_X509) || defined (USE_KEYNOTE) /* Decrypt the HASH in SIG, we already need a parsed ID payload. */ static int -rsa_sig_decode_hash (struct message *msg) +rsa_sig_decode_hash(struct message *msg) { - struct cert_handler *handler; - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct payload *p; - void *cert = 0; - u_int8_t *rawcert = 0; - u_int32_t rawcertlen; - RSA *key = 0; - size_t hashsize = ie->hash->hashsize; - char header[80]; - int len; - int initiator = exchange->initiator; - u_int8_t **hash_p, **id_cert, *id; - u_int32_t *id_cert_len; - size_t id_len; - int found = 0, n, i, id_found; + struct cert_handler *handler; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct payload *p; + void *cert = 0; + u_int8_t *rawcert = 0, **hash_p, **id_cert, *id; + u_int32_t rawcertlen, *id_cert_len; + RSA *key = 0; + size_t hashsize = ie->hash->hashsize, id_len; + char header[80]; + int len, initiator = exchange->initiator; + int found = 0, n, i, id_found; #if defined (USE_DNSSEC) - u_int8_t *rawkey = 0; - u_int32_t rawkeylen; + u_int8_t *rawkey = 0; + u_int32_t rawkeylen; #endif - /* Choose the right fields to fill-in. */ - hash_p = initiator ? &ie->hash_r : &ie->hash_i; - id = initiator ? exchange->id_r : exchange->id_i; - id_len = initiator ? exchange->id_r_len : exchange->id_i_len; - - if (!id || id_len == 0) - { - log_print ("rsa_sig_decode_hash: ID is missing"); - return -1; - } - - /* - * XXX Assume we should use the same kind of certification as the remote... - * moreover, just use the first CERT payload to decide what to use. - */ - p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); - if (!p) - handler = cert_get (ISAKMP_CERTENC_KEYNOTE); - else - handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p)); - if (!handler) - { - log_print ("rsa_sig_decode_hash: cert_get (%d) failed", - p ? GET_ISAKMP_CERT_ENCODING (p->p) : -1); - return -1; - } + /* Choose the right fields to fill-in. */ + hash_p = initiator ? &ie->hash_r : &ie->hash_i; + id = initiator ? exchange->id_r : exchange->id_i; + id_len = initiator ? exchange->id_r_len : exchange->id_i_len; -#if defined (USE_POLICY) || defined (USE_KEYNOTE) - /* - * We need the policy session initialized now, so we can add - * credentials etc. - */ - exchange->policy_id = kn_init (); - if (exchange->policy_id == -1) - { - log_print ("rsa_sig_decode_hash: failed to initialize policy session"); - return -1; - } -#endif /* USE_POLICY || USE_KEYNOTE */ - - /* Obtain a certificate from our certificate storage. */ - if (handler->cert_obtain (id, id_len, 0, &rawcert, &rawcertlen)) - { - if (handler->id == ISAKMP_CERTENC_X509_SIG) - { - cert = handler->cert_get (rawcert, rawcertlen); - if (!cert) - LOG_DBG ((LOG_CRYPTO, 50, - "rsa_sig_decode_hash: certificate malformed")); - else - { - if (!handler->cert_get_key (cert, &key)) - { - log_print ("rsa_sig_decode_hash: " - "decoding certificate failed"); - handler->cert_free (cert); - } - else - { - found++; - LOG_DBG ((LOG_CRYPTO, 40, - "rsa_sig_decode_hash: using cert of type %d", - handler->id)); - exchange->recv_cert = cert; - exchange->recv_certtype = handler->id; -#if defined (USE_POLICY) - x509_generate_kn (exchange->policy_id, cert); -#endif /* USE_POLICY */ - } - } + if (!id || id_len == 0) { + log_print("rsa_sig_decode_hash: ID is missing"); + return -1; } - else if (handler->id == ISAKMP_CERTENC_KEYNOTE) - handler->cert_insert (exchange->policy_id, rawcert); - free (rawcert); - } - - /* - * Walk over potential CERT payloads in this message. - * XXX I believe this is the wrong spot for this. CERTs can appear - * anytime. - */ - for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); p; - p = TAILQ_NEXT (p, link)) - { - p->flags |= PL_MARK; - - /* When we have found a key, just walk over the rest, marking them. */ - if (found) - continue; - - handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p)); - if (!handler) - { - LOG_DBG ((LOG_MISC, 30, - "rsa_sig_decode_hash: no handler for %s CERT encoding", - constant_name (isakmp_certenc_cst, - GET_ISAKMP_CERT_ENCODING (p->p)))); - continue; - } - - cert = handler->cert_get (p->p + ISAKMP_CERT_DATA_OFF, - GET_ISAKMP_GEN_LENGTH (p->p) - - ISAKMP_CERT_DATA_OFF); - if (!cert) - { - log_print ("rsa_sig_decode_hash: can not get data from CERT"); - continue; + /* + * XXX Assume we should use the same kind of certification as the remote... + * moreover, just use the first CERT payload to decide what to use. + */ + p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_CERT]); + if (!p) + handler = cert_get(ISAKMP_CERTENC_KEYNOTE); + else + handler = cert_get(GET_ISAKMP_CERT_ENCODING(p->p)); + if (!handler) { + log_print("rsa_sig_decode_hash: cert_get (%d) failed", + p ? GET_ISAKMP_CERT_ENCODING(p->p) : -1); + return -1; } - - if (!handler->cert_validate (cert)) - { - handler->cert_free (cert); - log_print ("rsa_sig_decode_hash: received CERT can't be validated"); - continue; - } - - if (GET_ISAKMP_CERT_ENCODING (p->p) == ISAKMP_CERTENC_X509_SIG) - { - if (!handler->cert_get_subjects (cert, &n, &id_cert, &id_cert_len)) - { - handler->cert_free (cert); - log_print ("rsa_sig_decode_hash: can not get subject from CERT"); - continue; - } - - id_found = 0; - for (i = 0; i < n; i++) - if (id_cert_len[i] == id_len - && id[0] == id_cert[i][0] - && memcmp (id + 4, id_cert[i] + 4, id_len - 4) == 0) - { - id_found++; - break; - } - if (!id_found) - { - handler->cert_free (cert); - log_print ("rsa_sig_decode_hash: no CERT subject match the ID"); - free (id_cert); - continue; - } - - cert_free_subjects (n, id_cert, id_cert_len); +#if defined (USE_POLICY) || defined (USE_KEYNOTE) + /* + * We need the policy session initialized now, so we can add + * credentials etc. + */ + exchange->policy_id = kn_init(); + if (exchange->policy_id == -1) { + log_print("rsa_sig_decode_hash: failed to initialize policy session"); + return -1; } - - if (!handler->cert_get_key (cert, &key)) - { - handler->cert_free (cert); - log_print ("rsa_sig_decode_hash: decoding payload CERT failed"); - continue; +#endif /* USE_POLICY || USE_KEYNOTE */ + + /* Obtain a certificate from our certificate storage. */ + if (handler->cert_obtain(id, id_len, 0, &rawcert, &rawcertlen)) { + if (handler->id == ISAKMP_CERTENC_X509_SIG) { + cert = handler->cert_get(rawcert, rawcertlen); + if (!cert) + LOG_DBG((LOG_CRYPTO, 50, + "rsa_sig_decode_hash: certificate malformed")); + else { + if (!handler->cert_get_key(cert, &key)) { + log_print("rsa_sig_decode_hash: " + "decoding certificate failed"); + handler->cert_free(cert); + } else { + found++; + LOG_DBG((LOG_CRYPTO, 40, + "rsa_sig_decode_hash: using cert of type %d", + handler->id)); + exchange->recv_cert = cert; + exchange->recv_certtype = handler->id; +#if defined (USE_POLICY) + x509_generate_kn(exchange->policy_id, cert); +#endif /* USE_POLICY */ + } + } + } else if (handler->id == ISAKMP_CERTENC_KEYNOTE) + handler->cert_insert(exchange->policy_id, rawcert); + free(rawcert); } + /* + * Walk over potential CERT payloads in this message. + * XXX I believe this is the wrong spot for this. CERTs can appear + * anytime. + */ + for (p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_CERT]); p; + p = TAILQ_NEXT(p, link)) { + p->flags |= PL_MARK; + + /* + * When we have found a key, just walk over the rest, marking + * them. + */ + if (found) + continue; + + handler = cert_get(GET_ISAKMP_CERT_ENCODING(p->p)); + if (!handler) { + LOG_DBG((LOG_MISC, 30, + "rsa_sig_decode_hash: no handler for %s CERT encoding", + constant_name(isakmp_certenc_cst, + GET_ISAKMP_CERT_ENCODING(p->p)))); + continue; + } + cert = handler->cert_get(p->p + ISAKMP_CERT_DATA_OFF, + GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_CERT_DATA_OFF); + if (!cert) { + log_print("rsa_sig_decode_hash: can not get data from CERT"); + continue; + } + if (!handler->cert_validate(cert)) { + handler->cert_free(cert); + log_print("rsa_sig_decode_hash: received CERT can't be validated"); + continue; + } + if (GET_ISAKMP_CERT_ENCODING(p->p) == ISAKMP_CERTENC_X509_SIG) { + if (!handler->cert_get_subjects(cert, &n, &id_cert, + &id_cert_len)) { + handler->cert_free(cert); + log_print("rsa_sig_decode_hash: can not get subject from CERT"); + continue; + } + id_found = 0; + for (i = 0; i < n; i++) + if (id_cert_len[i] == id_len && + id[0] == id_cert[i][0] && + memcmp(id + 4, id_cert[i] + 4, id_len - 4) == 0) { + id_found++; + break; + } + if (!id_found) { + handler->cert_free(cert); + log_print("rsa_sig_decode_hash: no CERT subject match the ID"); + free(id_cert); + continue; + } + cert_free_subjects(n, id_cert, id_cert_len); + } + if (!handler->cert_get_key(cert, &key)) { + handler->cert_free(cert); + log_print("rsa_sig_decode_hash: decoding payload CERT failed"); + continue; + } + /* We validated the cert, cache it for later use. */ + handler->cert_insert(exchange->policy_id, cert); - /* We validated the cert, cache it for later use. */ - handler->cert_insert (exchange->policy_id, cert); - - exchange->recv_cert = cert; - exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING (p->p); + exchange->recv_cert = cert; + exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING(p->p); #if defined (USE_POLICY) || defined (USE_KEYNOTE) - if (exchange->recv_certtype == ISAKMP_CERTENC_KEYNOTE) - { - struct keynote_deckey dc; - char *pp; - int dclen; - - dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; - dc.dec_key = key; - - pp = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, - KEYNOTE_PUBLIC_KEY); - if (pp == NULL) - { - kn_free_key (&dc); - log_print ("rsa_sig_decode_hash: failed to ASCII-encode key"); - return -1; - } - - dclen = strlen (pp) + sizeof "rsa-hex:"; - exchange->keynote_key = calloc (dclen, sizeof (char)); - if (!exchange->keynote_key) - { - free (pp); - kn_free_key (&dc); - log_print ("rsa_sig_decode_hash: failed to allocate %d bytes", - dclen); - return -1; - } - - snprintf (exchange->keynote_key, dclen, "rsa-hex:%s", pp); - free (pp); - } + if (exchange->recv_certtype == ISAKMP_CERTENC_KEYNOTE) { + struct keynote_deckey dc; + char *pp; + int dclen; + + dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; + dc.dec_key = key; + + pp = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, + KEYNOTE_PUBLIC_KEY); + if (pp == NULL) { + kn_free_key(&dc); + log_print("rsa_sig_decode_hash: failed to ASCII-encode key"); + return -1; + } + dclen = strlen(pp) + sizeof "rsa-hex:"; + exchange->keynote_key = calloc(dclen, sizeof(char)); + if (!exchange->keynote_key) { + free(pp); + kn_free_key(&dc); + log_print("rsa_sig_decode_hash: failed to allocate %d bytes", + dclen); + return -1; + } + snprintf(exchange->keynote_key, dclen, "rsa-hex:%s", pp); + free(pp); + } #endif - found++; - } + found++; + } #if defined (USE_DNSSEC) - /* If no certificate provided a key, try to find a validated DNSSEC KEY. */ - if (!found) - { - rawkey = dns_get_key (IKE_AUTH_RSA_SIG, msg, &rawkeylen); - - /* We need to convert 'void *rawkey' into 'RSA *key'. */ - if (dns_RSA_dns_to_x509 (rawkey, rawkeylen, &key) == 0) - found++; - else - log_print ("rsa_sig_decode_hash: KEY to RSA key conversion failed"); - - if (rawkey) - free (rawkey); - } -#endif /* USE_DNSSEC */ + /* + * If no certificate provided a key, try to find a validated DNSSEC + * KEY. + */ + if (!found) { + rawkey = dns_get_key(IKE_AUTH_RSA_SIG, msg, &rawkeylen); + + /* We need to convert 'void *rawkey' into 'RSA *key'. */ + if (dns_RSA_dns_to_x509(rawkey, rawkeylen, &key) == 0) + found++; + else + log_print("rsa_sig_decode_hash: KEY to RSA key conversion failed"); + + if (rawkey) + free(rawkey); + } +#endif /* USE_DNSSEC */ #if defined (USE_RAWKEY) - /* If we still have not found a key, try to read it from a file. */ - if (!found) - if (get_raw_key_from_file (IKE_AUTH_RSA_SIG, id, id_len, &key) != -1) - found++; + /* If we still have not found a key, try to read it from a file. */ + if (!found) + if (get_raw_key_from_file(IKE_AUTH_RSA_SIG, id, id_len, &key) != -1) + found++; #endif - if (!found) - { - log_print ("rsa_sig_decode_hash: no public key found"); - return -1; - } - - p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SIG]); - if (!p) - { - log_print ("rsa_sig_decode_hash: missing signature payload"); - RSA_free (key); - return -1; - } - - /* Check that the sig is of the correct size. */ - len = GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ; - if (len != RSA_size (key)) - { - RSA_free (key); - log_print ("rsa_sig_decode_hash: " - "SIG payload length does not match public key"); - return -1; - } - - *hash_p = malloc (len); - if (!*hash_p) - { - RSA_free (key); - log_error ("rsa_sig_decode_hash: malloc (%d) failed", len); - return -1; - } - - len = RSA_public_decrypt (len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key, - RSA_PKCS1_PADDING); - if (len == -1) - { - RSA_free (key); - log_print ("rsa_sig_decode_hash: RSA_public_decrypt () failed"); - return -1; - } - - /* Store key for later use */ - exchange->recv_key = key; - exchange->recv_keytype = ISAKMP_KEY_RSA; - - if (len != (int)hashsize) - { - free (*hash_p); - *hash_p = 0; - log_print ("rsa_sig_decode_hash: len %lu != hashsize %lu", - (unsigned long)len, (unsigned long)hashsize); - return -1; - } - - snprintf (header, sizeof header, "rsa_sig_decode_hash: HASH_%c", + if (!found) { + log_print("rsa_sig_decode_hash: no public key found"); + return -1; + } + p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SIG]); + if (!p) { + log_print("rsa_sig_decode_hash: missing signature payload"); + RSA_free(key); + return -1; + } + /* Check that the sig is of the correct size. */ + len = GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_SIG_SZ; + if (len != RSA_size(key)) { + RSA_free(key); + log_print("rsa_sig_decode_hash: " + "SIG payload length does not match public key"); + return -1; + } + *hash_p = malloc(len); + if (!*hash_p) { + RSA_free(key); + log_error("rsa_sig_decode_hash: malloc (%d) failed", len); + return -1; + } + len = RSA_public_decrypt(len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key, + RSA_PKCS1_PADDING); + if (len == -1) { + RSA_free(key); + log_print("rsa_sig_decode_hash: RSA_public_decrypt () failed"); + return -1; + } + /* Store key for later use */ + exchange->recv_key = key; + exchange->recv_keytype = ISAKMP_KEY_RSA; + + if (len != (int) hashsize) { + free(*hash_p); + *hash_p = 0; + log_print("rsa_sig_decode_hash: len %lu != hashsize %lu", + (unsigned long) len, (unsigned long) hashsize); + return -1; + } + snprintf(header, sizeof header, "rsa_sig_decode_hash: HASH_%c", initiator ? 'R' : 'I'); - LOG_DBG_BUF ((LOG_MISC, 80, header, *hash_p, hashsize)); + LOG_DBG_BUF((LOG_MISC, 80, header, *hash_p, hashsize)); - p->flags |= PL_MARK; - - return 0; + p->flags |= PL_MARK; + return 0; } -#endif /* USE_X509 || USE_KEYNOTE */ +#endif /* USE_X509 || USE_KEYNOTE */ static int -pre_shared_encode_hash (struct message *msg) +pre_shared_encode_hash(struct message *msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - size_t hashsize = ie->hash->hashsize; - char header[80]; - int initiator = exchange->initiator; - u_int8_t *buf; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + size_t hashsize = ie->hash->hashsize; + char header[80]; + int initiator = exchange->initiator; + u_int8_t *buf; - buf = ipsec_add_hash_payload (msg, hashsize); - if (!buf) - return -1; + buf = ipsec_add_hash_payload(msg, hashsize); + if (!buf) + return -1; - if (ike_auth_hash (exchange, buf + ISAKMP_HASH_DATA_OFF) == -1) - return -1; + if (ike_auth_hash(exchange, buf + ISAKMP_HASH_DATA_OFF) == -1) + return -1; - snprintf (header, sizeof header, "pre_shared_encode_hash: HASH_%c", + snprintf(header, sizeof header, "pre_shared_encode_hash: HASH_%c", initiator ? 'I' : 'R'); - LOG_DBG_BUF ((LOG_MISC, 80, header, buf + ISAKMP_HASH_DATA_OFF, hashsize)); - return 0; + LOG_DBG_BUF((LOG_MISC, 80, header, buf + ISAKMP_HASH_DATA_OFF, hashsize)); + return 0; } #if defined (USE_X509) || defined (USE_KEYNOTE) /* Encrypt the HASH into a SIG type. */ static int -rsa_sig_encode_hash (struct message *msg) +rsa_sig_encode_hash(struct message *msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - size_t hashsize = ie->hash->hashsize; - struct cert_handler *handler; - char header[80]; - int initiator = exchange->initiator; - u_int8_t *buf, *data, *buf2; - u_int32_t datalen; - u_int8_t *id; - size_t id_len; - int idtype; - int32_t sigsize; - void *sent_key; - - id = initiator ? exchange->id_i : exchange->id_r; - id_len = initiator ? exchange->id_i_len : exchange->id_r_len; - - /* We may have been provided these by the kernel */ - buf = (u_int8_t *)conf_get_str (exchange->name, "Credentials"); - if (buf - && (idtype = conf_get_num (exchange->name, "Credential_Type", -1) != -1)) - { - exchange->sent_certtype = idtype; - handler = cert_get (idtype); - if (!handler) - { - log_print ("rsa_sig_encode_hash: cert_get (%d) failed", idtype); - return -1; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + size_t hashsize = ie->hash->hashsize, id_len; + struct cert_handler *handler; + char header[80]; + int initiator = exchange->initiator, idtype; + u_int8_t *buf, *data, *buf2, *id; + u_int32_t datalen; + int32_t sigsize; + void *sent_key; + + id = initiator ? exchange->id_i : exchange->id_r; + id_len = initiator ? exchange->id_i_len : exchange->id_r_len; + + /* We may have been provided these by the kernel */ + buf = (u_int8_t *) conf_get_str(exchange->name, "Credentials"); + if (buf && + (idtype = conf_get_num(exchange->name, "Credential_Type", -1) != -1)) { + exchange->sent_certtype = idtype; + handler = cert_get(idtype); + if (!handler) { + log_print("rsa_sig_encode_hash: cert_get (%d) failed", idtype); + return -1; + } + exchange->sent_cert = handler->cert_from_printable((char *) buf); + if (!exchange->sent_cert) { + log_print("rsa_sig_encode_hash: failed to retrieve certificate"); + return -1; + } + handler->cert_serialize(exchange->sent_cert, &data, &datalen); + if (!data) { + log_print("rsa_sig_encode_hash: cert serialization failed"); + return -1; + } + goto aftercert; /* Skip all the certificate discovery */ } - - exchange->sent_cert = handler->cert_from_printable ((char *)buf); - if (!exchange->sent_cert) - { - log_print ("rsa_sig_encode_hash: failed to retrieve certificate"); - return -1; + /* XXX This needs to be configurable. */ + idtype = ISAKMP_CERTENC_KEYNOTE; + + /* Find a certificate with subjectAltName = id. */ + handler = cert_get(idtype); + if (!handler) { + idtype = ISAKMP_CERTENC_X509_SIG; + handler = cert_get(idtype); + if (!handler) { + log_print("rsa_sig_encode_hash: cert_get(%d) failed", idtype); + return -1; + } } - - handler->cert_serialize (exchange->sent_cert, &data, &datalen); - if (!data) - { - log_print ("rsa_sig_encode_hash: cert serialization failed"); - return -1; + if (handler->cert_obtain(id, id_len, 0, &data, &datalen) == 0) { + if (idtype == ISAKMP_CERTENC_KEYNOTE) { + idtype = ISAKMP_CERTENC_X509_SIG; + handler = cert_get(idtype); + if (!handler) { + log_print("rsa_sig_encode_hash: cert_get(%d) failed", + idtype); + return -1; + } + if (handler->cert_obtain(id, id_len, 0, &data, &datalen) == 0) { + LOG_DBG((LOG_MISC, 10, + "rsa_sig_encode_hash: no certificate to send")); + goto skipcert; + } + } else { + LOG_DBG((LOG_MISC, 10, + "rsa_sig_encode_hash: no certificate to send")); + goto skipcert; + } } + /* Let's store the certificate we are going to use */ + exchange->sent_certtype = idtype; + exchange->sent_cert = handler->cert_get(data, datalen); + if (!exchange->sent_cert) { + free(data); + log_print("rsa_sig_encode_hash: failed to get certificate from wire " + "encoding"); + return -1; + } +aftercert: + + buf = realloc(data, ISAKMP_CERT_SZ + datalen); + if (!buf) { + log_error("rsa_sig_encode_hash: realloc (%p, %d) failed", data, + ISAKMP_CERT_SZ + datalen); + free(data); + return -1; + } + memmove(buf + ISAKMP_CERT_SZ, buf, datalen); + SET_ISAKMP_CERT_ENCODING(buf, idtype); + if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT, buf, + ISAKMP_CERT_SZ + datalen, 1)) { + free(buf); + return -1; + } +skipcert: + + /* Again, we may have these from the kernel */ + buf = (u_int8_t *) conf_get_str(exchange->name, "PKAuthentication"); + if (buf) { + key_from_printable(ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, (char *) buf, + &data, &datalen); + if (!data) { + log_print("rsa_sig_encode_hash: badly formatted RSA private key"); + return 0; + } + sent_key = key_internalize(ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, + data, datalen); + if (!sent_key) { + log_print("rsa_sig_encode_hash: bad RSA private key from dynamic " + "SA acquisition subsystem"); + return 0; + } + } else { + /* Try through the regular means. */ + switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + util_ntoa((char **) &buf2, + id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ] == + IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6, + id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + if (!buf2) + return 0; + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + buf2 = calloc(id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, + sizeof(char)); + if (!buf2) { + log_print("rsa_sig_encode_hash: malloc (%lu) failed", + (unsigned long) id_len - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1); + return 0; + } + memcpy(buf2, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; + + /* XXX Support more ID types? */ + default: + buf2 = 0; + return 0; + } - goto aftercert; /* Skip all the certificate discovery */ - } - - /* XXX This needs to be configurable. */ - idtype = ISAKMP_CERTENC_KEYNOTE; + sent_key = ike_auth_get_key(IKE_AUTH_RSA_SIG, exchange->name, + (char *) buf2, 0); + free(buf2); - /* Find a certificate with subjectAltName = id. */ - handler = cert_get (idtype); - if (!handler) - { - idtype = ISAKMP_CERTENC_X509_SIG; - handler = cert_get (idtype); - if (!handler) - { - log_print ("rsa_sig_encode_hash: cert_get(%d) failed", idtype); - return -1; + /* Did we find a key? */ + if (!sent_key) { + log_print("rsa_sig_encode_hash: could not get private key"); + return -1; + } } - } - if (handler->cert_obtain (id, id_len, 0, &data, &datalen) == 0) - { - if (idtype == ISAKMP_CERTENC_KEYNOTE) - { - idtype = ISAKMP_CERTENC_X509_SIG; - handler = cert_get (idtype); - if (!handler) - { - log_print ("rsa_sig_encode_hash: cert_get(%d) failed", idtype); - return -1; - } - - if (handler->cert_obtain (id, id_len, 0, &data, &datalen) == 0) - { - LOG_DBG ((LOG_MISC, 10, - "rsa_sig_encode_hash: no certificate to send")); - goto skipcert; - } + /* Enable RSA blinding. */ + if (RSA_blinding_on(sent_key, NULL) != 1) { + log_error("rsa_sig_encode_hash: RSA_blinding_on () failed."); + return -1; } - else - { - LOG_DBG ((LOG_MISC, 10, - "rsa_sig_encode_hash: no certificate to send")); - goto skipcert; + /* XXX hashsize is not necessarily prf->blocksize. */ + buf = malloc(hashsize); + if (!buf) { + log_error("rsa_sig_encode_hash: malloc (%lu) failed", + (unsigned long) hashsize); + return -1; } - } - - /* Let's store the certificate we are going to use */ - exchange->sent_certtype = idtype; - exchange->sent_cert = handler->cert_get (data, datalen); - if (!exchange->sent_cert) - { - free (data); - log_print ("rsa_sig_encode_hash: failed to get certificate from wire " - "encoding"); - return -1; - } - - aftercert: - - buf = realloc (data, ISAKMP_CERT_SZ + datalen); - if (!buf) - { - log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data, - ISAKMP_CERT_SZ + datalen); - free (data); - return -1; - } - memmove (buf + ISAKMP_CERT_SZ, buf, datalen); - SET_ISAKMP_CERT_ENCODING (buf, idtype); - if (message_add_payload (msg, ISAKMP_PAYLOAD_CERT, buf, - ISAKMP_CERT_SZ + datalen, 1)) - { - free (buf); - return -1; - } - - skipcert: - - /* Again, we may have these from the kernel */ - buf = (u_int8_t *)conf_get_str (exchange->name, "PKAuthentication"); - if (buf) - { - key_from_printable (ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, (char *)buf, - &data, &datalen); - if (!data) - { - log_print ("rsa_sig_encode_hash: badly formatted RSA private key"); - return 0; + if (ike_auth_hash(exchange, buf) == -1) { + free(buf); + return -1; } + snprintf(header, sizeof header, "rsa_sig_encode_hash: HASH_%c", + initiator ? 'I' : 'R'); + LOG_DBG_BUF((LOG_MISC, 80, header, buf, hashsize)); - sent_key = key_internalize (ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, data, - datalen); - if (!sent_key) - { - log_print ("rsa_sig_encode_hash: bad RSA private key from dynamic " - "SA acquisition subsystem"); - return 0; + data = malloc(RSA_size(sent_key)); + if (!data) { + log_error("rsa_sig_encode_hash: malloc (%d) failed", + RSA_size(sent_key)); + return -1; } - } - else /* Try through the regular means. */ - { - switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - util_ntoa ((char **)&buf2, - id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ] == IPSEC_ID_IPV4_ADDR - ? AF_INET : AF_INET6, - id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); - if (!buf2) - return 0; - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - buf2 = calloc (id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, - sizeof (char)); - if (!buf2) - { - log_print ("rsa_sig_encode_hash: malloc (%lu) failed", - (unsigned long)id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); - return 0; - } - memcpy (buf2, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); - break; - - /* XXX Support more ID types? */ - default: - buf2 = 0; - return 0; + sigsize = RSA_private_encrypt(hashsize, buf, data, sent_key, + RSA_PKCS1_PADDING); + if (sigsize == -1) { + log_print("rsa_sig_encode_hash: RSA_private_encrypt () failed"); + if (data) + free(data); + free(buf); + RSA_free(sent_key); + return -1; } + datalen = (u_int32_t) sigsize; - sent_key = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name, - (char *)buf2, 0); - free (buf2); + free(buf); - /* Did we find a key? */ - if (!sent_key) - { - log_print ("rsa_sig_encode_hash: could not get private key"); - return -1; + buf = realloc(data, ISAKMP_SIG_SZ + datalen); + if (!buf) { + log_error("rsa_sig_encode_hash: realloc (%p, %d) failed", data, + ISAKMP_SIG_SZ + datalen); + free(data); + return -1; } - } - - /* Enable RSA blinding. */ - if (RSA_blinding_on (sent_key, NULL) != 1) - { - log_error ("rsa_sig_encode_hash: RSA_blinding_on () failed."); - return -1; - } - - /* XXX hashsize is not necessarily prf->blocksize. */ - buf = malloc (hashsize); - if (!buf) - { - log_error ("rsa_sig_encode_hash: malloc (%lu) failed", - (unsigned long)hashsize); - return -1; - } - - if (ike_auth_hash (exchange, buf) == -1) - { - free (buf); - return -1; - } - - snprintf (header, sizeof header, "rsa_sig_encode_hash: HASH_%c", - initiator ? 'I' : 'R'); - LOG_DBG_BUF ((LOG_MISC, 80, header, buf, hashsize)); - - data = malloc (RSA_size (sent_key)); - if (!data) - { - log_error ("rsa_sig_encode_hash: malloc (%d) failed", - RSA_size (sent_key)); - return -1; - } - - sigsize = RSA_private_encrypt (hashsize, buf, data, sent_key, - RSA_PKCS1_PADDING); - if (sigsize == -1) - { - log_print ("rsa_sig_encode_hash: RSA_private_encrypt () failed"); - if (data) - free (data); - free (buf); - RSA_free (sent_key); - return -1; - } - datalen = (u_int32_t)sigsize; - - free (buf); - - buf = realloc (data, ISAKMP_SIG_SZ + datalen); - if (!buf) - { - log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data, - ISAKMP_SIG_SZ + datalen); - free (data); - return -1; - } - memmove (buf + ISAKMP_SIG_SZ, buf, datalen); - - snprintf (header, sizeof header, "rsa_sig_encode_hash: SIG_%c", + memmove(buf + ISAKMP_SIG_SZ, buf, datalen); + + snprintf(header, sizeof header, "rsa_sig_encode_hash: SIG_%c", initiator ? 'I' : 'R'); - LOG_DBG_BUF ((LOG_MISC, 80, header, buf + ISAKMP_SIG_DATA_OFF, datalen)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_SIG, buf, - ISAKMP_SIG_SZ + datalen, 1)) - { - free (buf); - return -1; - } - return 0; + LOG_DBG_BUF((LOG_MISC, 80, header, buf + ISAKMP_SIG_DATA_OFF, datalen)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_SIG, buf, + ISAKMP_SIG_SZ + datalen, 1)) { + free(buf); + return -1; + } + return 0; } -#endif /* USE_X509 || USE_KEYNOTE */ +#endif /* USE_X509 || USE_KEYNOTE */ int -ike_auth_hash (struct exchange *exchange, u_int8_t *buf) +ike_auth_hash(struct exchange *exchange, u_int8_t *buf) { - struct ipsec_exch *ie = exchange->data; - struct prf *prf; - struct hash *hash = ie->hash; - int initiator = exchange->initiator; - u_int8_t *id; - size_t id_len; - - /* Choose the right fields to fill-in. */ - id = initiator ? exchange->id_i : exchange->id_r; - id_len = initiator ? exchange->id_i_len : exchange->id_r_len; - - /* Allocate the prf and start calculating our HASH. */ - prf = prf_alloc (ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); - if (!prf) - return -1; - - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, initiator ? ie->g_xi : ie->g_xr, ie->g_x_len); - prf->Update (prf->prfctx, initiator ? ie->g_xr : ie->g_xi, ie->g_x_len); - prf->Update (prf->prfctx, - exchange->cookies - + (initiator ? ISAKMP_HDR_ICOOKIE_OFF : ISAKMP_HDR_RCOOKIE_OFF), - ISAKMP_HDR_ICOOKIE_LEN); - prf->Update (prf->prfctx, - exchange->cookies - + (initiator ? ISAKMP_HDR_RCOOKIE_OFF : ISAKMP_HDR_ICOOKIE_OFF), - ISAKMP_HDR_ICOOKIE_LEN); - prf->Update (prf->prfctx, ie->sa_i_b, ie->sa_i_b_len); - prf->Update (prf->prfctx, id, id_len); - prf->Final (buf, prf->prfctx); - prf_free (prf); - - return 0; + struct ipsec_exch *ie = exchange->data; + struct prf *prf; + struct hash *hash = ie->hash; + int initiator = exchange->initiator; + u_int8_t *id; + size_t id_len; + + /* Choose the right fields to fill-in. */ + id = initiator ? exchange->id_i : exchange->id_r; + id_len = initiator ? exchange->id_i_len : exchange->id_r_len; + + /* Allocate the prf and start calculating our HASH. */ + prf = prf_alloc(ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); + if (!prf) + return -1; + + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, initiator ? ie->g_xi : ie->g_xr, ie->g_x_len); + prf->Update(prf->prfctx, initiator ? ie->g_xr : ie->g_xi, ie->g_x_len); + prf->Update(prf->prfctx, exchange->cookies + + (initiator ? ISAKMP_HDR_ICOOKIE_OFF : ISAKMP_HDR_RCOOKIE_OFF), + ISAKMP_HDR_ICOOKIE_LEN); + prf->Update(prf->prfctx, exchange->cookies + + (initiator ? ISAKMP_HDR_RCOOKIE_OFF : ISAKMP_HDR_ICOOKIE_OFF), + ISAKMP_HDR_ICOOKIE_LEN); + prf->Update(prf->prfctx, ie->sa_i_b, ie->sa_i_b_len); + prf->Update(prf->prfctx, id, id_len); + prf->Final(buf, prf->prfctx); + prf_free(prf); + return 0; } #if defined (USE_RAWKEY) static int -get_raw_key_from_file (int type, u_int8_t *id, size_t id_len, RSA **rsa) +get_raw_key_from_file(int type, u_int8_t *id, size_t id_len, RSA **rsa) { - char filename[FILENAME_MAX]; - char *fstr; - struct stat st; + char filename[FILENAME_MAX]; + char *fstr; + struct stat st; #if defined (USE_PRIVSEP) - FILE *keyfp; + FILE *keyfp; #else - BIO *bio; + BIO *bio; #endif - if (type != IKE_AUTH_RSA_SIG) /* XXX More types? */ - { - LOG_DBG ((LOG_NEGOTIATION, 20, "get_raw_key_from_file: " - "invalid auth type %d\n", type)); - return -1; - } - - *rsa = 0; - - fstr = conf_get_str ("General", "Pubkey-directory"); - if (!fstr) - fstr = CONF_DFLT_PUBKEY_DIR; - - if (snprintf (filename, sizeof filename, "%s/", fstr) - > (int)sizeof filename - 1) - return -1; - - fstr = ipsec_id_string (id, id_len); - if (!fstr) - { - LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: " - "ipsec_id_string failed")); - return -1; - } - strlcat (filename, fstr, sizeof filename - strlen (filename)); - free (fstr); - - /* If the file does not exist, fail silently. */ - if (monitor_stat (filename, &st) == 0) - { -#if defined (USE_PRIVSEP) - keyfp = monitor_fopen (filename, "r"); - if (!keyfp) - { - log_error ("get_raw_key_from_file: monitor_fopen (\"%s\", \"r\") " - "failed", filename); - return -1; - } - *rsa = PEM_read_RSA_PUBKEY (keyfp, NULL, NULL, NULL); - fclose (keyfp); -#else - bio = BIO_new (BIO_s_file ()); - if (!bio) - { - log_error ("get_raw_key_from_file: could not initialize BIO"); - return -1; + if (type != IKE_AUTH_RSA_SIG) { /* XXX More types? */ + LOG_DBG((LOG_NEGOTIATION, 20, "get_raw_key_from_file: " + "invalid auth type %d\n", type)); + return -1; } - if (BIO_read_filename (bio, filename) <= 0) - { - LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: " - "BIO_read_filename(bio, \"%s\") failed", filename)); - BIO_free (bio); - return -1; + *rsa = 0; + + fstr = conf_get_str("General", "Pubkey-directory"); + if (!fstr) + fstr = CONF_DFLT_PUBKEY_DIR; + + if (snprintf(filename, sizeof filename, "%s/", fstr) > + (int) sizeof filename - 1) + return -1; + + fstr = ipsec_id_string(id, id_len); + if (!fstr) { + LOG_DBG((LOG_NEGOTIATION, 50, "get_raw_key_from_file: " + "ipsec_id_string failed")); + return -1; } - LOG_DBG ((LOG_NEGOTIATION, 80, "get_raw_key_from_file: reading file %s", - filename)); - *rsa = PEM_read_bio_RSA_PUBKEY (bio, NULL, NULL, NULL); - BIO_free (bio); -#endif /* USE_PRIVSEP */ - } - else - LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: file %s not found", - filename)); - - return (*rsa ? 0 : -1); + strlcat(filename, fstr, sizeof filename - strlen(filename)); + free(fstr); + + /* If the file does not exist, fail silently. */ + if (monitor_stat(filename, &st) == 0) { +#if defined (USE_PRIVSEP) + keyfp = monitor_fopen(filename, "r"); + if (!keyfp) { + log_error("get_raw_key_from_file: monitor_fopen (\"%s\", \"r\") " + "failed", filename); + return -1; + } + *rsa = PEM_read_RSA_PUBKEY(keyfp, NULL, NULL, NULL); + fclose(keyfp); +#else + bio = BIO_new(BIO_s_file()); + if (!bio) { + log_error("get_raw_key_from_file: could not initialize BIO"); + return -1; + } + if (BIO_read_filename(bio, filename) <= 0) { + LOG_DBG((LOG_NEGOTIATION, 50, "get_raw_key_from_file: " + "BIO_read_filename(bio, \"%s\") failed", filename)); + BIO_free(bio); + return -1; + } + LOG_DBG((LOG_NEGOTIATION, 80, + "get_raw_key_from_file: reading file %s", filename)); + *rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + BIO_free(bio); +#endif /* USE_PRIVSEP */ + } else + LOG_DBG((LOG_NEGOTIATION, 50, + "get_raw_key_from_file: file %s not found", filename)); + + return (*rsa ? 0 : -1); } -#endif /* USE_RAWKEY */ +#endif /* USE_RAWKEY */ diff --git a/sbin/isakmpd/ike_auth.h b/sbin/isakmpd/ike_auth.h index 968bc19b018..39b09230a37 100644 --- a/sbin/isakmpd/ike_auth.h +++ b/sbin/isakmpd/ike_auth.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_auth.h,v 1.4 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ike_auth.h,v 1.5 1998/08/16 19:55:24 provos Exp $ */ +/* $OpenBSD: ike_auth.h,v 1.5 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_auth.h,v 1.5 1998/08/16 19:55:24 provos Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -37,12 +37,12 @@ struct exchange; struct ike_auth { - u_int16_t id; - u_int8_t *(*gen_skeyid) (struct exchange *, size_t *); - int (*decode_hash) (struct message *); - int (*encode_hash) (struct message *); + u_int16_t id; + u_int8_t *(*gen_skeyid) (struct exchange *, size_t *); + int (*decode_hash) (struct message *); + int (*encode_hash) (struct message *); }; -extern struct ike_auth *ike_auth_get (u_int16_t); +extern struct ike_auth *ike_auth_get(u_int16_t); -#endif /* _IKE_AUTH_H_ */ +#endif /* _IKE_AUTH_H_ */ diff --git a/sbin/isakmpd/ike_main_mode.c b/sbin/isakmpd/ike_main_mode.c index aab8049c655..cff96457079 100644 --- a/sbin/isakmpd/ike_main_mode.c +++ b/sbin/isakmpd/ike_main_mode.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_main_mode.c,v 1.12 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ike_main_mode.c,v 1.77 1999/04/25 22:12:34 niklas Exp $ */ +/* $OpenBSD: ike_main_mode.c,v 1.13 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_main_mode.c,v 1.77 1999/04/25 22:12:34 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -58,68 +58,68 @@ #include "transport.h" #include "util.h" -static int initiator_send_ID_AUTH (struct message *); -static int responder_send_ID_AUTH (struct message *); -static int responder_send_KE_NONCE (struct message *); - -int (*ike_main_mode_initiator[]) (struct message *) = { - ike_phase_1_initiator_send_SA, - ike_phase_1_initiator_recv_SA, - ike_phase_1_initiator_send_KE_NONCE, - ike_phase_1_initiator_recv_KE_NONCE, - initiator_send_ID_AUTH, - ike_phase_1_recv_ID_AUTH +static int initiator_send_ID_AUTH(struct message *); +static int responder_send_ID_AUTH(struct message *); +static int responder_send_KE_NONCE(struct message *); + +int (*ike_main_mode_initiator[]) (struct message *) = { + ike_phase_1_initiator_send_SA, + ike_phase_1_initiator_recv_SA, + ike_phase_1_initiator_send_KE_NONCE, + ike_phase_1_initiator_recv_KE_NONCE, + initiator_send_ID_AUTH, + ike_phase_1_recv_ID_AUTH }; -int (*ike_main_mode_responder[]) (struct message *) = { - ike_phase_1_responder_recv_SA, - ike_phase_1_responder_send_SA, - ike_phase_1_recv_KE_NONCE, - responder_send_KE_NONCE, - ike_phase_1_recv_ID_AUTH, - responder_send_ID_AUTH +int (*ike_main_mode_responder[]) (struct message *) = { + ike_phase_1_responder_recv_SA, + ike_phase_1_responder_send_SA, + ike_phase_1_recv_KE_NONCE, + responder_send_KE_NONCE, + ike_phase_1_recv_ID_AUTH, + responder_send_ID_AUTH }; static int -initiator_send_ID_AUTH (struct message *msg) +initiator_send_ID_AUTH(struct message * msg) { - msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; + msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; - if (ike_phase_1_send_ID (msg)) - return -1; + if (ike_phase_1_send_ID(msg)) + return -1; - if (ike_phase_1_send_AUTH (msg)) - return -1; + if (ike_phase_1_send_AUTH(msg)) + return -1; - return ipsec_initial_contact (msg); + return ipsec_initial_contact(msg); } /* Send our public DH value and a nonce to the initiator. */ int -responder_send_KE_NONCE (struct message *msg) +responder_send_KE_NONCE(struct message * msg) { - /* XXX Should we really just use the initiator's nonce size? */ - if (ike_phase_1_send_KE_NONCE (msg, msg->exchange->nonce_i_len)) - return -1; - - /* - * Calculate DH values & key material in parallel with the message going - * on a roundtrip over the wire. - */ - message_register_post_send (msg, - (void (*) (struct message *)) - ike_phase_1_post_exchange_KE_NONCE); - - return 0; + /* XXX Should we really just use the initiator's nonce size? */ + if (ike_phase_1_send_KE_NONCE(msg, msg->exchange->nonce_i_len)) + return -1; + + /* + * Calculate DH values & key material in parallel with the message going + * on a roundtrip over the wire. + */ + message_register_post_send(msg, + (void (*) (struct message *)) + ike_phase_1_post_exchange_KE_NONCE); + + return 0; } static int -responder_send_ID_AUTH (struct message *msg) +responder_send_ID_AUTH(struct message * msg) { - msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; + msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; - if (ike_phase_1_responder_send_ID_AUTH (msg)) - return -1; + if (ike_phase_1_responder_send_ID_AUTH(msg)) + return -1; - return ipsec_initial_contact (msg); + return ipsec_initial_contact(msg); } diff --git a/sbin/isakmpd/ike_main_mode.h b/sbin/isakmpd/ike_main_mode.h index 72be932325e..0ad9e532f97 100644 --- a/sbin/isakmpd/ike_main_mode.h +++ b/sbin/isakmpd/ike_main_mode.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_main_mode.h,v 1.4 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ike_main_mode.h,v 1.1 1998/07/25 11:22:07 niklas Exp $ */ +/* $OpenBSD: ike_main_mode.h,v 1.5 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_main_mode.h,v 1.1 1998/07/25 11:22:07 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -34,7 +34,7 @@ struct message; -extern int (*ike_main_mode_initiator[]) (struct message *msg); -extern int (*ike_main_mode_responder[]) (struct message *msg); +extern int (*ike_main_mode_initiator[]) (struct message * msg); +extern int (*ike_main_mode_responder[]) (struct message * msg); -#endif /* _IKE_MAIN_MODE_H_ */ +#endif /* _IKE_MAIN_MODE_H_ */ diff --git a/sbin/isakmpd/ike_phase_1.c b/sbin/isakmpd/ike_phase_1.c index eaec3956272..a2c2b953643 100644 --- a/sbin/isakmpd/ike_phase_1.c +++ b/sbin/isakmpd/ike_phase_1.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_phase_1.c,v 1.45 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: ike_phase_1.c,v 1.31 2000/12/11 23:47:56 niklas Exp $ */ +/* $OpenBSD: ike_phase_1.c,v 1.46 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_phase_1.c,v 1.31 2000/12/11 23:47:56 niklas Exp $ */ /* * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -60,402 +60,372 @@ #include "transport.h" #include "util.h" -static int attribute_unacceptable (u_int16_t, u_int8_t *, u_int16_t, void *); -static int ike_phase_1_validate_prop (struct exchange *, struct sa *, - struct sa *); +static int attribute_unacceptable(u_int16_t, u_int8_t *, u_int16_t, void *); +static int ike_phase_1_validate_prop(struct exchange *, struct sa *, + struct sa *); /* Offer a set of transforms to the responder in the MSG message. */ int -ike_phase_1_initiator_send_SA (struct message *msg) +ike_phase_1_initiator_send_SA(struct message *msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - u_int8_t *proposal = 0, *sa_buf = 0, *saved_nextp, *attr; - u_int8_t **transform = 0; - size_t transforms_len = 0, proposal_len, sa_len; - size_t *transform_len = 0; - struct conf_list *conf, *life_conf; - struct conf_list_node *xf, *life; - int value, update_nextp; - size_t i; - struct payload *p; - struct proto *proto; - struct proto_attr *pa; - int group_desc = -1, new_group_desc; - - /* Get the list of transforms. */ - conf = conf_get_list (exchange->policy, "Transforms"); - if (!conf) - return -1; - - transform = calloc (conf->cnt, sizeof *transform); - if (!transform) - { - log_error ("ike_phase_1_initiator_send_SA: calloc (%d, %lu) failed", - conf->cnt, (unsigned long)sizeof *transform); - goto bail_out; - } - - transform_len = calloc (conf->cnt, sizeof *transform_len); - if (!transform_len) - { - log_error ("ike_phase_1_initiator_send_SA: calloc (%d, %lu) failed", - conf->cnt, (unsigned long)sizeof *transform_len); - goto bail_out; - } - - for (xf = TAILQ_FIRST (&conf->fields), i = 0; i < conf->cnt; - i++, xf = TAILQ_NEXT (xf, link)) - { - /* XXX The sizing needs to be dynamic. */ - transform[i] - = malloc (ISAKMP_TRANSFORM_SA_ATTRS_OFF + 16 * ISAKMP_ATTR_VALUE_OFF); - if (!transform[i]) - { - log_error ("ike_phase_1_initiator_send_SA: malloc (%d) failed", - ISAKMP_TRANSFORM_SA_ATTRS_OFF - + 16 * ISAKMP_ATTR_VALUE_OFF); - goto bail_out; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + u_int8_t *proposal = 0, *sa_buf = 0, *saved_nextp, *attr; + u_int8_t **transform = 0; + size_t transforms_len = 0, proposal_len, sa_len; + size_t *transform_len = 0; + struct conf_list *conf, *life_conf; + struct conf_list_node *xf, *life; + int value, update_nextp; + size_t i; + struct payload *p; + struct proto *proto; + struct proto_attr *pa; + int group_desc = -1, new_group_desc; + + /* Get the list of transforms. */ + conf = conf_get_list(exchange->policy, "Transforms"); + if (!conf) + return -1; + + transform = calloc(conf->cnt, sizeof *transform); + if (!transform) { + log_error("ike_phase_1_initiator_send_SA: calloc (%d, %lu) failed", + conf->cnt, (unsigned long) sizeof *transform); + goto bail_out; } - - SET_ISAKMP_TRANSFORM_NO (transform[i], i); - SET_ISAKMP_TRANSFORM_ID (transform[i], IPSEC_TRANSFORM_KEY_IKE); - SET_ISAKMP_TRANSFORM_RESERVED (transform[i], 0); - - attr = transform[i] + ISAKMP_TRANSFORM_SA_ATTRS_OFF; - - if (attribute_set_constant (xf->field, "ENCRYPTION_ALGORITHM", - ike_encrypt_cst, - IKE_ATTR_ENCRYPTION_ALGORITHM, &attr)) - goto bail_out; - - if (attribute_set_constant (xf->field, "HASH_ALGORITHM", ike_hash_cst, - IKE_ATTR_HASH_ALGORITHM, &attr)) - goto bail_out; - - if (attribute_set_constant (xf->field, "AUTHENTICATION_METHOD", - ike_auth_cst, IKE_ATTR_AUTHENTICATION_METHOD, - &attr)) - goto bail_out; - - if (attribute_set_constant (xf->field, "GROUP_DESCRIPTION", - ike_group_desc_cst, - IKE_ATTR_GROUP_DESCRIPTION, &attr)) - { - /* - * If no group description exists, try looking for a user-defined - * one. - */ - if (attribute_set_constant (xf->field, "GROUP_TYPE", ike_group_cst, - IKE_ATTR_GROUP_TYPE, &attr)) - goto bail_out; + transform_len = calloc(conf->cnt, sizeof *transform_len); + if (!transform_len) { + log_error("ike_phase_1_initiator_send_SA: calloc (%d, %lu) failed", + conf->cnt, (unsigned long) sizeof *transform_len); + goto bail_out; + } + for (xf = TAILQ_FIRST(&conf->fields), i = 0; i < conf->cnt; + i++, xf = TAILQ_NEXT(xf, link)) { + /* XXX The sizing needs to be dynamic. */ + transform[i] = malloc(ISAKMP_TRANSFORM_SA_ATTRS_OFF + + 16 * ISAKMP_ATTR_VALUE_OFF); + if (!transform[i]) { + log_error("ike_phase_1_initiator_send_SA: malloc (%d) failed", + ISAKMP_TRANSFORM_SA_ATTRS_OFF + + 16 * ISAKMP_ATTR_VALUE_OFF); + goto bail_out; + } + SET_ISAKMP_TRANSFORM_NO(transform[i], i); + SET_ISAKMP_TRANSFORM_ID(transform[i], IPSEC_TRANSFORM_KEY_IKE); + SET_ISAKMP_TRANSFORM_RESERVED(transform[i], 0); + + attr = transform[i] + ISAKMP_TRANSFORM_SA_ATTRS_OFF; + + if (attribute_set_constant(xf->field, "ENCRYPTION_ALGORITHM", + ike_encrypt_cst, IKE_ATTR_ENCRYPTION_ALGORITHM, &attr)) + goto bail_out; + + if (attribute_set_constant(xf->field, "HASH_ALGORITHM", + ike_hash_cst, IKE_ATTR_HASH_ALGORITHM, &attr)) + goto bail_out; + + if (attribute_set_constant(xf->field, "AUTHENTICATION_METHOD", + ike_auth_cst, IKE_ATTR_AUTHENTICATION_METHOD, &attr)) + goto bail_out; + + if (attribute_set_constant(xf->field, "GROUP_DESCRIPTION", + ike_group_desc_cst, IKE_ATTR_GROUP_DESCRIPTION, &attr)) { + /* + * If no group description exists, try looking for + * a user-defined one. + */ + if (attribute_set_constant(xf->field, "GROUP_TYPE", + ike_group_cst, IKE_ATTR_GROUP_TYPE, &attr)) + goto bail_out; #if 0 - if (attribute_set_bignum (xf->field, "GROUP_PRIME", - IKE_ATTR_GROUP_PRIME, &attr)) - goto bail_out; + if (attribute_set_bignum(xf->field, "GROUP_PRIME", + IKE_ATTR_GROUP_PRIME, &attr)) + goto bail_out; - if (attribute_set_bignum (xf->field, "GROUP_GENERATOR_2", - IKE_ATTR_GROUP_GENERATOR_2, &attr)) - goto bail_out; + if (attribute_set_bignum(xf->field, "GROUP_GENERATOR_2", + IKE_ATTR_GROUP_GENERATOR_2, &attr)) + goto bail_out; - if (attribute_set_bignum (xf->field, "GROUP_GENERATOR_2", - IKE_ATTR_GROUP_GENERATOR_2, &attr)) - goto bail_out; + if (attribute_set_bignum(xf->field, "GROUP_GENERATOR_2", + IKE_ATTR_GROUP_GENERATOR_2, &attr)) + goto bail_out; - if (attribute_set_bignum (xf->field, "GROUP_CURVE_A", - IKE_ATTR_GROUP_CURVE_A, &attr)) - goto bail_out; + if (attribute_set_bignum(xf->field, "GROUP_CURVE_A", + IKE_ATTR_GROUP_CURVE_A, &attr)) + goto bail_out; - if (attribute_set_bignum (xf->field, "GROUP_CURVE_B", - IKE_ATTR_GROUP_CURVE_B, &attr)) - goto bail_out; + if (attribute_set_bignum(xf->field, "GROUP_CURVE_B", + IKE_ATTR_GROUP_CURVE_B, &attr)) + goto bail_out; #endif + } + /* + * Life durations are special, we should be able to specify + * several, one per type. + */ + life_conf = conf_get_list(xf->field, "Life"); + if (life_conf) { + for (life = TAILQ_FIRST(&life_conf->fields); life; + life = TAILQ_NEXT(life, link)) { + attribute_set_constant(life->field, "LIFE_TYPE", + ike_duration_cst, IKE_ATTR_LIFE_TYPE, &attr); + + /* + * XXX Deals with 16 and 32 bit lifetimes + * only + */ + value = conf_get_num(life->field, "LIFE_DURATION", 0); + if (value) { + if (value <= 0xffff) + attr = attribute_set_basic(attr, + IKE_ATTR_LIFE_DURATION, value); + else { + value = htonl(value); + attr = attribute_set_var(attr, + IKE_ATTR_LIFE_DURATION, + (u_int8_t *)&value, + sizeof value); + } + } + } + conf_free_list(life_conf); + } + attribute_set_constant(xf->field, "PRF", ike_prf_cst, + IKE_ATTR_PRF, &attr); + + value = conf_get_num(xf->field, "KEY_LENGTH", 0); + if (value) + attr = attribute_set_basic(attr, IKE_ATTR_KEY_LENGTH, value); + + value = conf_get_num(xf->field, "FIELD_SIZE", 0); + if (value) + attr = attribute_set_basic(attr, IKE_ATTR_FIELD_SIZE, value); + + value = conf_get_num(xf->field, "GROUP_ORDER", 0); + if (value) + attr = attribute_set_basic(attr, IKE_ATTR_GROUP_ORDER, value); + + /* Record the real transform size. */ + transforms_len += transform_len[i] = attr - transform[i]; + + /* XXX I don't like exchange-specific stuff in here. */ + if (exchange->type == ISAKMP_EXCH_AGGRESSIVE) { + /* + * Make sure that if a group description is specified, it is + * specified for all transforms equally. + */ + attr = (u_int8_t *) conf_get_str(xf->field, "GROUP_DESCRIPTION"); + new_group_desc = attr ? constant_value(ike_group_desc_cst, + (char *) attr) : 0; + if (group_desc == -1) + group_desc = new_group_desc; + else if (group_desc != new_group_desc) { + log_print("ike_phase_1_initiator_send_SA: " + "differing group descriptions in a proposal"); + goto bail_out; + } + } + /* + * We need to check that we actually support our + * configuration. + */ + if (attribute_map(transform[i] + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + transform_len[i] - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + exchange->doi->is_attribute_incompatible, msg)) { + log_print("ike_phase_1_initiator_send_SA: " + "section [%s] has unsupported attribute(s)", + xf->field); + goto bail_out; + } } - /* - * Life durations are special, we should be able to specify - * several, one per type. - */ - life_conf = conf_get_list (xf->field, "Life"); - if (life_conf) - { - for (life = TAILQ_FIRST (&life_conf->fields); life; - life = TAILQ_NEXT (life, link)) - { - attribute_set_constant (life->field, "LIFE_TYPE", - ike_duration_cst, IKE_ATTR_LIFE_TYPE, - &attr); - - /* XXX Deals with 16 and 32 bit lifetimes only */ - value = conf_get_num (life->field, "LIFE_DURATION", 0); - if (value) - { - if (value <= 0xffff) - attr = attribute_set_basic (attr, IKE_ATTR_LIFE_DURATION, - value); - else - { - value = htonl (value); - attr = attribute_set_var (attr, IKE_ATTR_LIFE_DURATION, - (u_int8_t *)&value, - sizeof value); - } - } - } - conf_free_list (life_conf); - } + /* XXX I don't like exchange-specific stuff in here. */ + if (exchange->type == ISAKMP_EXCH_AGGRESSIVE) + ie->group = group_get(group_desc); - attribute_set_constant (xf->field, "PRF", ike_prf_cst, IKE_ATTR_PRF, - &attr); - - value = conf_get_num (xf->field, "KEY_LENGTH", 0); - if (value) - attr = attribute_set_basic (attr, IKE_ATTR_KEY_LENGTH, value); - - value = conf_get_num (xf->field, "FIELD_SIZE", 0); - if (value) - attr = attribute_set_basic (attr, IKE_ATTR_FIELD_SIZE, value); - - value = conf_get_num (xf->field, "GROUP_ORDER", 0); - if (value) - attr = attribute_set_basic (attr, IKE_ATTR_GROUP_ORDER, value); - - /* Record the real transform size. */ - transforms_len += transform_len[i] = attr - transform[i]; - - /* XXX I don't like exchange-specific stuff in here. */ - if (exchange->type == ISAKMP_EXCH_AGGRESSIVE) - { - /* - * Make sure that if a group description is specified, it is - * specified for all transforms equally. - */ - attr = (u_int8_t *)conf_get_str (xf->field, "GROUP_DESCRIPTION"); - new_group_desc - = attr ? constant_value (ike_group_desc_cst, (char *)attr) : 0; - if (group_desc == -1) - group_desc = new_group_desc; - else if (group_desc != new_group_desc) - { - log_print ("ike_phase_1_initiator_send_SA: " - "differing group descriptions in a proposal"); - goto bail_out; - } + proposal_len = ISAKMP_PROP_SPI_OFF; + proposal = malloc(proposal_len); + if (!proposal) { + log_error("ike_phase_1_initiator_send_SA: malloc (%lu) failed", + (unsigned long) proposal_len); + goto bail_out; } - - /* We need to check that we actually support our configuration. */ - if (attribute_map (transform[i] + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - transform_len[i] - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - exchange->doi->is_attribute_incompatible, msg)) - { - log_print ("ike_phase_1_initiator_send_SA: " - "section [%s] has unsupported attribute(s)", - xf->field); - goto bail_out; + SET_ISAKMP_PROP_NO(proposal, 1); + SET_ISAKMP_PROP_PROTO(proposal, ISAKMP_PROTO_ISAKMP); + SET_ISAKMP_PROP_SPI_SZ(proposal, 0); + SET_ISAKMP_PROP_NTRANSFORMS(proposal, conf->cnt); + + /* XXX I would like to see this factored out. */ + proto = calloc(1, sizeof *proto); + if (!proto) { + log_error("ike_phase_1_initiator_send_SA: calloc (1, %lu) failed", + (unsigned long) sizeof *proto); + goto bail_out; } - } - - /* XXX I don't like exchange-specific stuff in here. */ - if (exchange->type == ISAKMP_EXCH_AGGRESSIVE) - ie->group = group_get (group_desc); - - proposal_len = ISAKMP_PROP_SPI_OFF; - proposal = malloc (proposal_len); - if (!proposal) - { - log_error ("ike_phase_1_initiator_send_SA: malloc (%lu) failed", - (unsigned long)proposal_len); - goto bail_out; - } - - SET_ISAKMP_PROP_NO (proposal, 1); - SET_ISAKMP_PROP_PROTO (proposal, ISAKMP_PROTO_ISAKMP); - SET_ISAKMP_PROP_SPI_SZ (proposal, 0); - SET_ISAKMP_PROP_NTRANSFORMS (proposal, conf->cnt); - - /* XXX I would like to see this factored out. */ - proto = calloc (1, sizeof *proto); - if (!proto) - { - log_error ("ike_phase_1_initiator_send_SA: calloc (1, %lu) failed", - (unsigned long)sizeof *proto); - goto bail_out; - } - - proto->no = 1; - proto->proto = ISAKMP_PROTO_ISAKMP; - proto->sa = TAILQ_FIRST (&exchange->sa_list); - proto->xf_cnt = conf->cnt; - TAILQ_INIT (&proto->xfs); - for (i = 0; i < proto->xf_cnt; i++) - { - pa = (struct proto_attr *)calloc (1, sizeof *pa); - if (!pa) - goto bail_out; - pa->len = transform_len[i]; - pa->attrs = (u_int8_t *)malloc (pa->len); - if (!pa->attrs) - { - free (pa); - goto bail_out; + proto->no = 1; + proto->proto = ISAKMP_PROTO_ISAKMP; + proto->sa = TAILQ_FIRST(&exchange->sa_list); + proto->xf_cnt = conf->cnt; + TAILQ_INIT(&proto->xfs); + for (i = 0; i < proto->xf_cnt; i++) { + pa = (struct proto_attr *) calloc(1, sizeof *pa); + if (!pa) + goto bail_out; + pa->len = transform_len[i]; + pa->attrs = (u_int8_t *) malloc(pa->len); + if (!pa->attrs) { + free(pa); + goto bail_out; + } + memcpy(pa->attrs, transform[i], pa->len); + TAILQ_INSERT_TAIL(&proto->xfs, pa, next); + } + TAILQ_INSERT_TAIL(&TAILQ_FIRST(&exchange->sa_list)->protos, proto, link); + + sa_len = ISAKMP_SA_SIT_OFF + IPSEC_SIT_SIT_LEN; + sa_buf = malloc(sa_len); + if (!sa_buf) { + log_error("ike_phase_1_initiator_send_SA: malloc (%lu) failed", + (unsigned long) sa_len); + goto bail_out; + } + SET_ISAKMP_SA_DOI(sa_buf, IPSEC_DOI_IPSEC); + SET_IPSEC_SIT_SIT(sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY); + + /* + * Add the payloads. As this is a SA, we need to recompute the + * lengths of the payloads containing others. + */ + if (message_add_payload(msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1)) + goto bail_out; + SET_ISAKMP_GEN_LENGTH(sa_buf, + sa_len + proposal_len + transforms_len); + sa_buf = 0; + + saved_nextp = msg->nextp; + if (message_add_payload(msg, ISAKMP_PAYLOAD_PROPOSAL, proposal, + proposal_len, 0)) + goto bail_out; + SET_ISAKMP_GEN_LENGTH(proposal, proposal_len + transforms_len); + proposal = 0; + + update_nextp = 0; + for (i = 0; i < conf->cnt; i++) { + if (message_add_payload(msg, ISAKMP_PAYLOAD_TRANSFORM, transform[i], + transform_len[i], update_nextp)) + goto bail_out; + update_nextp = 1; + transform[i] = 0; + } + msg->nextp = saved_nextp; + + /* Save SA payload body in ie->sa_i_b, length ie->sa_i_b_len. */ + ie->sa_i_b_len = sa_len + proposal_len + transforms_len - ISAKMP_GEN_SZ; + ie->sa_i_b = malloc(ie->sa_i_b_len); + if (!ie->sa_i_b) { + log_error("ike_phase_1_initiator_send_SA: malloc (%lu) failed", + (unsigned long) ie->sa_i_b_len); + goto bail_out; } - memcpy (pa->attrs, transform[i], pa->len); - TAILQ_INSERT_TAIL (&proto->xfs, pa, next); - } - TAILQ_INSERT_TAIL (&TAILQ_FIRST (&exchange->sa_list)->protos, proto, link); - - sa_len = ISAKMP_SA_SIT_OFF + IPSEC_SIT_SIT_LEN; - sa_buf = malloc (sa_len); - if (!sa_buf) - { - log_error ("ike_phase_1_initiator_send_SA: malloc (%lu) failed", - (unsigned long)sa_len); - goto bail_out; - } - - SET_ISAKMP_SA_DOI (sa_buf, IPSEC_DOI_IPSEC); - SET_IPSEC_SIT_SIT (sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY); - - /* - * Add the payloads. As this is a SA, we need to recompute the - * lengths of the payloads containing others. - */ - if (message_add_payload (msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1)) - goto bail_out; - SET_ISAKMP_GEN_LENGTH (sa_buf, - sa_len + proposal_len + transforms_len); - sa_buf = 0; - - saved_nextp = msg->nextp; - if (message_add_payload (msg, ISAKMP_PAYLOAD_PROPOSAL, proposal, - proposal_len, 0)) - goto bail_out; - SET_ISAKMP_GEN_LENGTH (proposal, proposal_len + transforms_len); - proposal = 0; - - update_nextp = 0; - for (i = 0; i < conf->cnt; i++) - { - if (message_add_payload (msg, ISAKMP_PAYLOAD_TRANSFORM, transform[i], - transform_len[i], update_nextp)) - goto bail_out; - update_nextp = 1; - transform[i] = 0; - } - msg->nextp = saved_nextp; - - /* Save SA payload body in ie->sa_i_b, length ie->sa_i_b_len. */ - ie->sa_i_b_len = sa_len + proposal_len + transforms_len - ISAKMP_GEN_SZ; - ie->sa_i_b = malloc (ie->sa_i_b_len); - if (!ie->sa_i_b) - { - log_error ("ike_phase_1_initiator_send_SA: malloc (%lu) failed", - (unsigned long)ie->sa_i_b_len); - goto bail_out; - } - memcpy (ie->sa_i_b, - TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA])->p + ISAKMP_GEN_SZ, - sa_len - ISAKMP_GEN_SZ); - memcpy (ie->sa_i_b + sa_len - ISAKMP_GEN_SZ, - TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_PROPOSAL])->p, - proposal_len); - transforms_len = 0; - for (i = 0, p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); - i < conf->cnt; i++, p = TAILQ_NEXT (p, link)) - { - memcpy (ie->sa_i_b + sa_len + proposal_len + transforms_len - - ISAKMP_GEN_SZ, - p->p, transform_len[i]); - transforms_len += transform_len[i]; - } - - conf_free_list (conf); - free (transform); - free (transform_len); - return 0; - - bail_out: - if (sa_buf) - free (sa_buf); - if (proposal) - free (proposal); - if (transform) - { - for (i = 0; i < conf->cnt; i++) - if (transform[i]) - free (transform[i]); - free (transform); - } - if (transform_len) - free (transform_len); - conf_free_list (conf); - return -1; + memcpy(ie->sa_i_b, + TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SA])->p + ISAKMP_GEN_SZ, + sa_len - ISAKMP_GEN_SZ); + memcpy(ie->sa_i_b + sa_len - ISAKMP_GEN_SZ, + TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_PROPOSAL])->p, + proposal_len); + transforms_len = 0; + for (i = 0, p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); + i < conf->cnt; i++, p = TAILQ_NEXT(p, link)) { + memcpy(ie->sa_i_b + sa_len + proposal_len + transforms_len - + ISAKMP_GEN_SZ, p->p, transform_len[i]); + transforms_len += transform_len[i]; + } + + conf_free_list(conf); + free(transform); + free(transform_len); + return 0; + +bail_out: + if (sa_buf) + free(sa_buf); + if (proposal) + free(proposal); + if (transform) { + for (i = 0; i < conf->cnt; i++) + if (transform[i]) + free(transform[i]); + free(transform); + } + if (transform_len) + free(transform_len); + conf_free_list(conf); + return -1; } /* Figure out what transform the responder chose. */ int -ike_phase_1_initiator_recv_SA (struct message *msg) +ike_phase_1_initiator_recv_SA(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct sa *sa = TAILQ_FIRST (&exchange->sa_list); - struct ipsec_exch *ie = exchange->data; - struct ipsec_sa *isa = sa->data; - struct payload *sa_p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA]); - struct payload *prop = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_PROPOSAL]); - struct payload *xf = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); - - /* - * IKE requires that only one SA with only one proposal exists and since - * we are getting an answer on our transform offer, only one transform. - */ - if (TAILQ_NEXT (sa_p, link) || TAILQ_NEXT (prop, link) - || TAILQ_NEXT (xf, link)) - { - log_print ("ike_phase_1_initiator_recv_SA: " - "multiple SA, proposal or transform payloads in phase 1"); - /* XXX Is there a better notification type? */ - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - /* Check that the chosen transform matches an offer. */ - if (message_negotiate_sa (msg, ike_phase_1_validate_prop) - || !TAILQ_FIRST (&sa->protos)) - return -1; - - ipsec_decode_transform (msg, sa, TAILQ_FIRST (&sa->protos), xf->p); - - /* XXX I don't like exchange-specific stuff in here. */ - if (exchange->type != ISAKMP_EXCH_AGGRESSIVE) - ie->group = group_get (isa->group_desc); - - /* Mark the SA as handled. */ - sa_p->flags |= PL_MARK; - - return 0; + struct exchange *exchange = msg->exchange; + struct sa *sa = TAILQ_FIRST(&exchange->sa_list); + struct ipsec_exch *ie = exchange->data; + struct ipsec_sa *isa = sa->data; + struct payload *sa_p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SA]); + struct payload *prop = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_PROPOSAL]); + struct payload *xf = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); + + /* + * IKE requires that only one SA with only one proposal exists and since + * we are getting an answer on our transform offer, only one transform. + */ + if (TAILQ_NEXT(sa_p, link) || TAILQ_NEXT(prop, link) || + TAILQ_NEXT(xf, link)) { + log_print("ike_phase_1_initiator_recv_SA: " + "multiple SA, proposal or transform payloads in phase 1"); + /* XXX Is there a better notification type? */ + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + /* Check that the chosen transform matches an offer. */ + if (message_negotiate_sa(msg, ike_phase_1_validate_prop) || + !TAILQ_FIRST(&sa->protos)) + return -1; + + ipsec_decode_transform(msg, sa, TAILQ_FIRST(&sa->protos), xf->p); + + /* XXX I don't like exchange-specific stuff in here. */ + if (exchange->type != ISAKMP_EXCH_AGGRESSIVE) + ie->group = group_get(isa->group_desc); + + /* Mark the SA as handled. */ + sa_p->flags |= PL_MARK; + + return 0; } /* Send our public DH value and a nonce to the responder. */ int -ike_phase_1_initiator_send_KE_NONCE (struct message *msg) +ike_phase_1_initiator_send_KE_NONCE(struct message * msg) { - struct ipsec_exch *ie = msg->exchange->data; + struct ipsec_exch *ie = msg->exchange->data; - ie->g_x_len = dh_getlen (ie->group); + ie->g_x_len = dh_getlen(ie->group); - /* XXX I want a better way to specify the nonce's size. */ - return ike_phase_1_send_KE_NONCE (msg, 16); + /* XXX I want a better way to specify the nonce's size. */ + return ike_phase_1_send_KE_NONCE(msg, 16); } /* Accept responder's public DH value and nonce. */ int -ike_phase_1_initiator_recv_KE_NONCE (struct message *msg) +ike_phase_1_initiator_recv_KE_NONCE(struct message * msg) { - if (ike_phase_1_recv_KE_NONCE (msg)) - return -1; + if (ike_phase_1_recv_KE_NONCE(msg)) + return -1; - return ike_phase_1_post_exchange_KE_NONCE (msg); + return ike_phase_1_post_exchange_KE_NONCE(msg); } /* @@ -463,126 +433,108 @@ ike_phase_1_initiator_recv_KE_NONCE (struct message *msg) * handle. */ int -ike_phase_1_responder_recv_SA (struct message *msg) +ike_phase_1_responder_recv_SA(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct sa *sa = TAILQ_FIRST (&exchange->sa_list); - struct ipsec_sa *isa = sa->data; - struct payload *sa_p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA]); - struct payload *prop = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_PROPOSAL]); - struct ipsec_exch *ie = exchange->data; - - /* Mark the SA as handled. */ - sa_p->flags |= PL_MARK; - - /* IKE requires that only one SA with only one proposal exists. */ - if (TAILQ_NEXT (sa_p, link) || TAILQ_NEXT (prop, link)) - { - log_print ("ike_phase_1_responder_recv_SA: " - "multiple SA or proposal payloads in phase 1"); - /* XXX Is there a better notification type? */ - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - /* Chose a transform from the SA. */ - if (message_negotiate_sa (msg, ike_phase_1_validate_prop) - || !TAILQ_FIRST (&sa->protos)) - return -1; - - /* XXX Move into message_negotiate_sa? */ - ipsec_decode_transform (msg, sa, TAILQ_FIRST (&sa->protos), - TAILQ_FIRST (&sa->protos)->chosen->p); - - ie->group = group_get (isa->group_desc); - - /* - * Check that the mandatory attributes: encryption, hash, authentication - * method and Diffie-Hellman group description, has been supplied. - */ - if (!exchange->crypto || !ie->hash || !ie->ike_auth || !ie->group) - { - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - /* Save the body for later hash computation. */ - ie->sa_i_b_len = GET_ISAKMP_GEN_LENGTH (sa_p->p) - ISAKMP_GEN_SZ; - ie->sa_i_b = malloc (ie->sa_i_b_len); - if (!ie->sa_i_b) - { - /* XXX How to notify peer? */ - log_error ("ike_phase_1_responder_recv_SA: malloc (%lu) failed", - (unsigned long)ie->sa_i_b_len); - return -1; - } - memcpy (ie->sa_i_b, sa_p->p + ISAKMP_GEN_SZ, ie->sa_i_b_len); - - return 0; + struct exchange *exchange = msg->exchange; + struct sa *sa = TAILQ_FIRST(&exchange->sa_list); + struct ipsec_sa *isa = sa->data; + struct payload *sa_p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SA]); + struct payload *prop = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_PROPOSAL]); + struct ipsec_exch *ie = exchange->data; + + /* Mark the SA as handled. */ + sa_p->flags |= PL_MARK; + + /* IKE requires that only one SA with only one proposal exists. */ + if (TAILQ_NEXT(sa_p, link) || TAILQ_NEXT(prop, link)) { + log_print("ike_phase_1_responder_recv_SA: " + "multiple SA or proposal payloads in phase 1"); + /* XXX Is there a better notification type? */ + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + /* Chose a transform from the SA. */ + if (message_negotiate_sa(msg, ike_phase_1_validate_prop) || + !TAILQ_FIRST(&sa->protos)) + return -1; + + /* XXX Move into message_negotiate_sa? */ + ipsec_decode_transform(msg, sa, TAILQ_FIRST(&sa->protos), + TAILQ_FIRST(&sa->protos)->chosen->p); + + ie->group = group_get(isa->group_desc); + + /* + * Check that the mandatory attributes: encryption, hash, authentication + * method and Diffie-Hellman group description, has been supplied. + */ + if (!exchange->crypto || !ie->hash || !ie->ike_auth || !ie->group) { + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + /* Save the body for later hash computation. */ + ie->sa_i_b_len = GET_ISAKMP_GEN_LENGTH(sa_p->p) - ISAKMP_GEN_SZ; + ie->sa_i_b = malloc(ie->sa_i_b_len); + if (!ie->sa_i_b) { + /* XXX How to notify peer? */ + log_error("ike_phase_1_responder_recv_SA: malloc (%lu) failed", + (unsigned long) ie->sa_i_b_len); + return -1; + } + memcpy(ie->sa_i_b, sa_p->p + ISAKMP_GEN_SZ, ie->sa_i_b_len); + return 0; } /* Reply with the transform we chose. */ int -ike_phase_1_responder_send_SA (struct message *msg) +ike_phase_1_responder_send_SA(struct message * msg) { - /* Add the SA payload with the transform that was chosen. */ - return message_add_sa_payload (msg); + /* Add the SA payload with the transform that was chosen. */ + return message_add_sa_payload(msg); } /* Send our public DH value and a nonce to the peer. */ int -ike_phase_1_send_KE_NONCE (struct message *msg, size_t nonce_sz) +ike_phase_1_send_KE_NONCE(struct message * msg, size_t nonce_sz) { - /* Public DH key. */ - if (ipsec_gen_g_x (msg)) - { - /* XXX How to log and notify peer? */ - return -1; - } - - /* Generate a nonce, and add it to the message. */ - if (exchange_gen_nonce (msg, nonce_sz)) - { - /* XXX Log? */ - return -1; - } - - /* Try to add certificates which are acceptable for the CERTREQs */ - if (exchange_add_certs (msg)) - { - /* XXX Log? */ - return -1; - } - - return 0; + /* Public DH key. */ + if (ipsec_gen_g_x(msg)) { + /* XXX How to log and notify peer? */ + return -1; + } + /* Generate a nonce, and add it to the message. */ + if (exchange_gen_nonce(msg, nonce_sz)) { + /* XXX Log? */ + return -1; + } + /* Try to add certificates which are acceptable for the CERTREQs */ + if (exchange_add_certs(msg)) { + /* XXX Log? */ + return -1; + } + return 0; } /* Receive our peer's public DH value and nonce. */ int -ike_phase_1_recv_KE_NONCE (struct message *msg) +ike_phase_1_recv_KE_NONCE(struct message * msg) { - /* Copy out the initiator's DH public value. */ - if (ipsec_save_g_x (msg)) - { - /* XXX How to log and notify peer? */ - return -1; - } - - /* Copy out the initiator's nonce. */ - if (exchange_save_nonce (msg)) - { - /* XXX How to log and notify peer? */ - return -1; - } - - /* Copy out the initiator's cert requests. */ - if (exchange_save_certreq (msg)) - { - /* XXX How to log and notify peer? */ - return -1; - } - - return 0; + /* Copy out the initiator's DH public value. */ + if (ipsec_save_g_x(msg)) { + /* XXX How to log and notify peer? */ + return -1; + } + /* Copy out the initiator's nonce. */ + if (exchange_save_nonce(msg)) { + /* XXX How to log and notify peer? */ + return -1; + } + /* Copy out the initiator's cert requests. */ + if (exchange_save_certreq(msg)) { + /* XXX How to log and notify peer? */ + return -1; + } + return 0; } /* @@ -591,626 +543,568 @@ ike_phase_1_recv_KE_NONCE (struct message *msg) * thus speeding up exchanges. */ int -ike_phase_1_post_exchange_KE_NONCE (struct message *msg) +ike_phase_1_post_exchange_KE_NONCE(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct prf *prf; - struct hash *hash = ie->hash; - enum cryptoerr err; - - /* Compute Diffie-Hellman shared value. */ - ie->g_xy = malloc (ie->g_x_len); - if (!ie->g_xy) - { - /* XXX How to notify peer? */ - log_error ("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", - (unsigned long)ie->g_x_len); - return -1; - } - if (dh_create_shared (ie->group, ie->g_xy, - exchange->initiator ? ie->g_xr : ie->g_xi)) - { - log_print ("ike_phase_1_post_exchange_KE_NONCE: " - "dh_create_shared failed"); - return -1; - } - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, - "ike_phase_1_post_exchange_KE_NONCE: g^xy", ie->g_xy, - ie->g_x_len)); - - /* Compute the SKEYID depending on the authentication method. */ - ie->skeyid = ie->ike_auth->gen_skeyid (exchange, &ie->skeyid_len); - if (!ie->skeyid) - { - /* XXX Log and teardown? */ - return -1; - } - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, - "ike_phase_1_post_exchange_KE_NONCE: SKEYID", ie->skeyid, - ie->skeyid_len)); - - /* SKEYID_d. */ - ie->skeyid_d = malloc (ie->skeyid_len); - if (!ie->skeyid_d) - { - /* XXX How to notify peer? */ - log_error ("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", - (unsigned long)ie->skeyid_len); - return -1; - } - prf = prf_alloc (ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); - if (!prf) - { - /* XXX Log and teardown? */ - return -1; - } - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, ie->g_xy, ie->g_x_len); - prf->Update (prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); - prf->Update (prf->prfctx, (unsigned char *)"\0", 1); - prf->Final (ie->skeyid_d, prf->prfctx); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, - "ike_phase_1_post_exchange_KE_NONCE: SKEYID_d", ie->skeyid_d, - ie->skeyid_len)); - - /* SKEYID_a. */ - ie->skeyid_a = malloc (ie->skeyid_len); - if (!ie->skeyid_a) - { - log_error ("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", - (unsigned long)ie->skeyid_len); - prf_free (prf); - return -1; - } - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, ie->skeyid_d, ie->skeyid_len); - prf->Update (prf->prfctx, ie->g_xy, ie->g_x_len); - prf->Update (prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); - prf->Update (prf->prfctx, (unsigned char *)"\1", 1); - prf->Final (ie->skeyid_a, prf->prfctx); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, - "ike_phase_1_post_exchange_KE_NONCE: SKEYID_a", ie->skeyid_a, - ie->skeyid_len)); - - /* SKEYID_e. */ - ie->skeyid_e = malloc (ie->skeyid_len); - if (!ie->skeyid_e) - { - /* XXX How to notify peer? */ - log_error ("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", - (unsigned long)ie->skeyid_len); - prf_free (prf); - return -1; - } - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, ie->skeyid_a, ie->skeyid_len); - prf->Update (prf->prfctx, ie->g_xy, ie->g_x_len); - prf->Update (prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); - prf->Update (prf->prfctx, (unsigned char *)"\2", 1); - prf->Final (ie->skeyid_e, prf->prfctx); - prf_free (prf); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, - "ike_phase_1_post_exchange_KE_NONCE: SKEYID_e", ie->skeyid_e, - ie->skeyid_len)); - - /* Key length determination. */ - if (!exchange->key_length) - exchange->key_length = exchange->crypto->keymax; - - /* Derive a longer key from skeyid_e */ - if (ie->skeyid_len < exchange->key_length) - { - u_int16_t len, keylen; - u_int8_t *key, *p; - - prf = prf_alloc (ie->prf_type, hash->type, ie->skeyid_e, ie->skeyid_len); - if (!prf) - { - /* XXX - notify peer */ - return -1; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct prf *prf; + struct hash *hash = ie->hash; + enum cryptoerr err; + + /* Compute Diffie-Hellman shared value. */ + ie->g_xy = malloc(ie->g_x_len); + if (!ie->g_xy) { + /* XXX How to notify peer? */ + log_error("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", + (unsigned long) ie->g_x_len); + return -1; } - - /* Make keylen a multiple of prf->blocksize */ - keylen = exchange->key_length; - if (keylen % prf->blocksize) - keylen += prf->blocksize - (keylen % prf->blocksize); - - key = malloc (keylen); - if (!key) - { - /* XXX - Notify peer. */ - log_error ("ike_phase_1_post_exchange_KE_NONCE: malloc (%d) failed", - keylen); - return -1; + if (dh_create_shared(ie->group, ie->g_xy, + exchange->initiator ? ie->g_xr : ie->g_xi)) { + log_print("ike_phase_1_post_exchange_KE_NONCE: " + "dh_create_shared failed"); + return -1; } + LOG_DBG_BUF((LOG_NEGOTIATION, 80, + "ike_phase_1_post_exchange_KE_NONCE: g^xy", ie->g_xy, + ie->g_x_len)); + + /* Compute the SKEYID depending on the authentication method. */ + ie->skeyid = ie->ike_auth->gen_skeyid(exchange, &ie->skeyid_len); + if (!ie->skeyid) { + /* XXX Log and teardown? */ + return -1; + } + LOG_DBG_BUF((LOG_NEGOTIATION, 80, + "ike_phase_1_post_exchange_KE_NONCE: SKEYID", ie->skeyid, + ie->skeyid_len)); + + /* SKEYID_d. */ + ie->skeyid_d = malloc(ie->skeyid_len); + if (!ie->skeyid_d) { + /* XXX How to notify peer? */ + log_error("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", + (unsigned long) ie->skeyid_len); + return -1; + } + prf = prf_alloc(ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); + if (!prf) { + /* XXX Log and teardown? */ + return -1; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, ie->g_xy, ie->g_x_len); + prf->Update(prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); + prf->Update(prf->prfctx, (unsigned char *) "\0", 1); + prf->Final(ie->skeyid_d, prf->prfctx); + LOG_DBG_BUF((LOG_NEGOTIATION, 80, + "ike_phase_1_post_exchange_KE_NONCE: SKEYID_d", ie->skeyid_d, + ie->skeyid_len)); + + /* SKEYID_a. */ + ie->skeyid_a = malloc(ie->skeyid_len); + if (!ie->skeyid_a) { + log_error("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", + (unsigned long) ie->skeyid_len); + prf_free(prf); + return -1; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, ie->skeyid_d, ie->skeyid_len); + prf->Update(prf->prfctx, ie->g_xy, ie->g_x_len); + prf->Update(prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); + prf->Update(prf->prfctx, (unsigned char *) "\1", 1); + prf->Final(ie->skeyid_a, prf->prfctx); + LOG_DBG_BUF((LOG_NEGOTIATION, 80, + "ike_phase_1_post_exchange_KE_NONCE: SKEYID_a", ie->skeyid_a, + ie->skeyid_len)); + + /* SKEYID_e. */ + ie->skeyid_e = malloc(ie->skeyid_len); + if (!ie->skeyid_e) { + /* XXX How to notify peer? */ + log_error("ike_phase_1_post_exchange_KE_NONCE: malloc (%lu) failed", + (unsigned long) ie->skeyid_len); + prf_free(prf); + return -1; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, ie->skeyid_a, ie->skeyid_len); + prf->Update(prf->prfctx, ie->g_xy, ie->g_x_len); + prf->Update(prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); + prf->Update(prf->prfctx, (unsigned char *) "\2", 1); + prf->Final(ie->skeyid_e, prf->prfctx); + prf_free(prf); + LOG_DBG_BUF((LOG_NEGOTIATION, 80, + "ike_phase_1_post_exchange_KE_NONCE: SKEYID_e", ie->skeyid_e, + ie->skeyid_len)); + + /* Key length determination. */ + if (!exchange->key_length) + exchange->key_length = exchange->crypto->keymax; + + /* Derive a longer key from skeyid_e */ + if (ie->skeyid_len < exchange->key_length) { + u_int16_t len, keylen; + u_int8_t *key, *p; + + prf = prf_alloc(ie->prf_type, hash->type, ie->skeyid_e, ie->skeyid_len); + if (!prf) { + /* XXX - notify peer */ + return -1; + } + /* Make keylen a multiple of prf->blocksize */ + keylen = exchange->key_length; + if (keylen % prf->blocksize) + keylen += prf->blocksize - (keylen % prf->blocksize); + + key = malloc(keylen); + if (!key) { + /* XXX - Notify peer. */ + log_error("ike_phase_1_post_exchange_KE_NONCE: malloc (%d) failed", + keylen); + return -1; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, (unsigned char *) "\0", 1); + prf->Final(key, prf->prfctx); + + for (len = prf->blocksize, p = key; len < exchange->key_length; + len += prf->blocksize, p += prf->blocksize) { + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, p, prf->blocksize); + prf->Final(p + prf->blocksize, prf->prfctx); + } + prf_free(prf); + + /* Setup our keystate using the derived encryption key. */ + exchange->keystate = crypto_init(exchange->crypto, key, + exchange->key_length, &err); + + free(key); + } else + /* Setup our keystate using the raw skeyid_e. */ + exchange->keystate = crypto_init(exchange->crypto, ie->skeyid_e, + exchange->key_length, &err); + + /* Special handling for DES weak keys. */ + if (!exchange->keystate && err == EWEAKKEY && + (exchange->key_length << 1) <= ie->skeyid_len) { + log_print("ike_phase_1_post_exchange_KE_NONCE: " + "weak key, trying subseq. skeyid_e"); + exchange->keystate = crypto_init(exchange->crypto, + ie->skeyid_e + exchange->key_length, + exchange->key_length, &err); + } + if (!exchange->keystate) { + log_print("ike_phase_1_post_exchange_KE_NONCE: " + "exchange->crypto->init () failed: %d", err); - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, (unsigned char *)"\0", 1); - prf->Final (key, prf->prfctx); - - for (len = prf->blocksize, p = key; len < exchange->key_length; - len += prf->blocksize, p += prf->blocksize) - { - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, p, prf->blocksize); - prf->Final (p + prf->blocksize, prf->prfctx); + /* + * XXX We really need to know if problems are of transient nature + * or fatal (like failed assertions etc.) + */ + return -1; } - prf_free (prf); - - /* Setup our keystate using the derived encryption key. */ - exchange->keystate - = crypto_init (exchange->crypto, key, exchange->key_length, &err); - - free (key); - } - else - /* Setup our keystate using the raw skeyid_e. */ - exchange->keystate = crypto_init (exchange->crypto, ie->skeyid_e, - exchange->key_length, &err); - - /* Special handling for DES weak keys. */ - if (!exchange->keystate && err == EWEAKKEY - && (exchange->key_length << 1) <= ie->skeyid_len) - { - log_print ("ike_phase_1_post_exchange_KE_NONCE: " - "weak key, trying subseq. skeyid_e"); - exchange->keystate - = crypto_init (exchange->crypto, ie->skeyid_e + exchange->key_length, - exchange->key_length, &err); - } - - if (!exchange->keystate) - { - log_print ("ike_phase_1_post_exchange_KE_NONCE: " - "exchange->crypto->init () failed: %d", err); - - /* - * XXX We really need to know if problems are of transient nature - * or fatal (like failed assertions etc.) - */ - return -1; - } - - /* Setup IV. XXX Only for CBC transforms, no? */ - hash->Init (hash->ctx); - hash->Update (hash->ctx, ie->g_xi, ie->g_x_len); - hash->Update (hash->ctx, ie->g_xr, ie->g_x_len); - hash->Final (hash->digest, hash->ctx); - crypto_init_iv (exchange->keystate, hash->digest, - exchange->crypto->blocksize); - - return 0; + /* Setup IV. XXX Only for CBC transforms, no? */ + hash->Init(hash->ctx); + hash->Update(hash->ctx, ie->g_xi, ie->g_x_len); + hash->Update(hash->ctx, ie->g_xr, ie->g_x_len); + hash->Final(hash->digest, hash->ctx); + crypto_init_iv(exchange->keystate, hash->digest, + exchange->crypto->blocksize); + return 0; } int -ike_phase_1_responder_send_ID_AUTH (struct message *msg) +ike_phase_1_responder_send_ID_AUTH(struct message * msg) { - if (ike_phase_1_send_ID (msg)) - return -1; + if (ike_phase_1_send_ID(msg)) + return -1; - return ike_phase_1_send_AUTH (msg); + return ike_phase_1_send_AUTH(msg); } int -ike_phase_1_send_ID (struct message *msg) +ike_phase_1_send_ID(struct message * msg) { - struct exchange *exchange = msg->exchange; - u_int8_t *buf; - char header[80]; - ssize_t sz; - struct sockaddr *src; - int initiator = exchange->initiator; - u_int8_t **id; - size_t *id_len; - char *my_id = 0; - u_int8_t id_type; - - /* Choose the right fields to fill-in. */ - id = initiator ? &exchange->id_i : &exchange->id_r; - id_len = initiator ? &exchange->id_i_len : &exchange->id_r_len; - - if (exchange->name) - my_id = conf_get_str (exchange->name, "ID"); - - if (!my_id) - my_id = conf_get_str ("General", "Default-phase-1-ID"); - - msg->transport->vtbl->get_src (msg->transport, &src); - sz = my_id ? ipsec_id_size (my_id, &id_type) : sockaddr_addrlen (src); - if (sz == -1) - return -1; - - sz += ISAKMP_ID_DATA_OFF; - buf = malloc (sz); - if (!buf) - { - log_error ("ike_phase_1_send_ID: malloc (%lu) failed", - (unsigned long)sz); - return -1; - } - - SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - if (my_id) - { - SET_ISAKMP_ID_TYPE (buf, id_type); - switch (id_type) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - /* Already in network byteorder. */ - memcpy (buf + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src), - sockaddr_addrlen (src)); - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - case IPSEC_ID_KEY_ID: - memcpy (buf + ISAKMP_ID_DATA_OFF, conf_get_str (my_id, "Name"), - sz - ISAKMP_ID_DATA_OFF); - break; - - default: - log_print ("ike_phase_1_send_ID: unsupported ID type %d", id_type); - free (buf); - return -1; + struct exchange *exchange = msg->exchange; + u_int8_t *buf; + char header[80]; + ssize_t sz; + struct sockaddr *src; + int initiator = exchange->initiator; + u_int8_t **id; + size_t *id_len; + char *my_id = 0; + u_int8_t id_type; + + /* Choose the right fields to fill-in. */ + id = initiator ? &exchange->id_i : &exchange->id_r; + id_len = initiator ? &exchange->id_i_len : &exchange->id_r_len; + + if (exchange->name) + my_id = conf_get_str(exchange->name, "ID"); + + if (!my_id) + my_id = conf_get_str("General", "Default-phase-1-ID"); + + msg->transport->vtbl->get_src(msg->transport, &src); + sz = my_id ? ipsec_id_size(my_id, &id_type) : sockaddr_addrlen(src); + if (sz == -1) + return -1; + + sz += ISAKMP_ID_DATA_OFF; + buf = malloc(sz); + if (!buf) { + log_error("ike_phase_1_send_ID: malloc (%lu) failed", + (unsigned long) sz); + return -1; } - } - else - { - switch (src->sa_family) - { - case AF_INET: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR); - break; - case AF_INET6: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV6_ADDR); - break; + SET_IPSEC_ID_PROTO(buf + ISAKMP_ID_DOI_DATA_OFF, 0); + SET_IPSEC_ID_PORT(buf + ISAKMP_ID_DOI_DATA_OFF, 0); + if (my_id) { + SET_ISAKMP_ID_TYPE(buf, id_type); + switch (id_type) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + /* Already in network byteorder. */ + memcpy(buf + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(src), + sockaddr_addrlen(src)); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + case IPSEC_ID_KEY_ID: + memcpy(buf + ISAKMP_ID_DATA_OFF, conf_get_str(my_id, "Name"), + sz - ISAKMP_ID_DATA_OFF); + break; + + default: + log_print("ike_phase_1_send_ID: unsupported ID type %d", + id_type); + free(buf); + return -1; + } + } else { + switch (src->sa_family) { + case AF_INET: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV4_ADDR); + break; + case AF_INET6: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV6_ADDR); + break; + } + /* Already in network byteorder. */ + memcpy(buf + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(src), + sockaddr_addrlen(src)); + } + + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, buf, sz, 1)) { + free(buf); + return -1; } - /* Already in network byteorder. */ - memcpy (buf + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src), - sockaddr_addrlen (src)); - } - - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, buf, sz, 1)) - { - free (buf); - return -1; - } - *id_len = sz - ISAKMP_GEN_SZ; - *id = malloc (*id_len); - if (!*id) - { - log_error ("ike_phase_1_send_ID: malloc (%lu) failed", - (unsigned long)*id_len); - return -1; - } - memcpy (*id, buf + ISAKMP_GEN_SZ, *id_len); - snprintf (header, sizeof header, "ike_phase_1_send_ID: %s", - constant_name (ipsec_id_cst, GET_ISAKMP_ID_TYPE (buf))); - LOG_DBG_BUF ((LOG_NEGOTIATION, 40, header, buf + ISAKMP_ID_DATA_OFF, - sz - ISAKMP_ID_DATA_OFF)); - - return 0; + *id_len = sz - ISAKMP_GEN_SZ; + *id = malloc(*id_len); + if (!*id) { + log_error("ike_phase_1_send_ID: malloc (%lu) failed", + (unsigned long) *id_len); + return -1; + } + memcpy(*id, buf + ISAKMP_GEN_SZ, *id_len); + snprintf(header, sizeof header, "ike_phase_1_send_ID: %s", + constant_name(ipsec_id_cst, GET_ISAKMP_ID_TYPE(buf))); + LOG_DBG_BUF((LOG_NEGOTIATION, 40, header, buf + ISAKMP_ID_DATA_OFF, + sz - ISAKMP_ID_DATA_OFF)); + return 0; } int -ike_phase_1_send_AUTH (struct message *msg) +ike_phase_1_send_AUTH(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - - if (ie->ike_auth->encode_hash (msg)) - { - /* XXX Log? */ - return -1; - } - - /* - * XXX Many people say the COMMIT flag is just junk, especially in Phase 1. - */ + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + + if (ie->ike_auth->encode_hash(msg)) { + /* XXX Log? */ + return -1; + } + /* + * XXX Many people say the COMMIT flag is just junk, especially in Phase 1. + */ #ifdef notyet - if ((exchange->flags & EXCHANGE_FLAG_COMMITTED) == 0) - exchange->flags |= EXCHANGE_FLAG_I_COMMITTED; + if ((exchange->flags & EXCHANGE_FLAG_COMMITTED) == 0) + exchange->flags |= EXCHANGE_FLAG_I_COMMITTED; #endif - return 0; + return 0; } /* Receive ID and HASH and check that the exchange has been consistent. */ int -ike_phase_1_recv_ID_AUTH (struct message *msg) +ike_phase_1_recv_ID_AUTH(struct message * msg) { - if (ike_phase_1_recv_ID (msg)) - return -1; + if (ike_phase_1_recv_ID(msg)) + return -1; - return ike_phase_1_recv_AUTH (msg); + return ike_phase_1_recv_AUTH(msg); } /* Receive ID. */ int -ike_phase_1_recv_ID (struct message *msg) +ike_phase_1_recv_ID(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct payload *payload; - char header[80], *rs = 0, *rid = 0, *p; - int initiator = exchange->initiator; - u_int8_t **id, id_type; - size_t *id_len; - ssize_t sz; - struct sockaddr *sa; - - payload = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ID]); - - if (exchange->name) - rs = conf_get_str (exchange->name, "Remote-ID"); - - if (rs) - { - sz = ipsec_id_size (rs, &id_type); - if (sz == -1) - { - log_print ("ike_phase_1_recv_ID: could not handle specified " - "Remote-ID [%s]", rs); - return -1; - } - - rid = malloc (sz); - if (!rid) - { - log_error ("ike_phase_1_recv_ID: malloc (%lu) failed", - (unsigned long)sz); - return -1; - } + struct exchange *exchange = msg->exchange; + struct payload *payload; + char header[80], *rs = 0, *rid = 0, *p; + int initiator = exchange->initiator; + u_int8_t **id, id_type; + size_t *id_len; + ssize_t sz; + struct sockaddr *sa; + + payload = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_ID]); + + if (exchange->name) + rs = conf_get_str(exchange->name, "Remote-ID"); + + if (rs) { + sz = ipsec_id_size(rs, &id_type); + if (sz == -1) { + log_print("ike_phase_1_recv_ID: could not handle specified " + "Remote-ID [%s]", rs); + return -1; + } + rid = malloc(sz); + if (!rid) { + log_error("ike_phase_1_recv_ID: malloc (%lu) failed", + (unsigned long) sz); + return -1; + } + switch (id_type) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + p = conf_get_str(rs, "Address"); + if (!p) { + log_print("ike_phase_1_recv_ID: " + "failed to get Address in Remote-ID section [%s]", + rs); + free(rid); + return -1; + } + if (text2sockaddr(p, 0, &sa) == -1) { + log_print("ike_phase_1_recv_ID: failed to parse address %s", p); + free(rid); + return -1; + } + if ((id_type == IPSEC_ID_IPV4_ADDR && + sa->sa_family != AF_INET) || + (id_type == IPSEC_ID_IPV6_ADDR && + sa->sa_family != AF_INET6)) { + log_print("ike_phase_1_recv_ID: " + "address %s not of expected family", p); + free(rid); + free(sa); + return -1; + } + memcpy(rid, sockaddr_addrdata(sa), sockaddr_addrlen(sa)); + free(sa); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + case IPSEC_ID_KEY_ID: + p = conf_get_str(rs, "Name"); + if (!p) { + log_print("ike_phase_1_recv_ID: " + "failed to get Name in Remote-ID section [%s]", rs); + free(rid); + return -1; + } + memcpy(rid, p, sz); + break; + + default: + log_print("ike_phase_1_recv_ID: unsupported ID type %d", + id_type); + free(rid); + return -1; + } - switch (id_type) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - p = conf_get_str (rs, "Address"); - if (!p) - { - log_print ("ike_phase_1_recv_ID: " - "failed to get Address in Remote-ID section [%s]", - rs); - free (rid); - return -1; - } - - if (text2sockaddr (p, 0, &sa) == -1) - { - log_print ("ike_phase_1_recv_ID: failed to parse address %s", p); - free (rid); - return -1; - } - - if ((id_type == IPSEC_ID_IPV4_ADDR && sa->sa_family != AF_INET) - || (id_type == IPSEC_ID_IPV6_ADDR && sa->sa_family != AF_INET6)) - { - log_print ("ike_phase_1_recv_ID: " - "address %s not of expected family", p); - free (rid); - free (sa); - return -1; - } - - memcpy (rid, sockaddr_addrdata (sa), sockaddr_addrlen (sa)); - free (sa); - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - case IPSEC_ID_KEY_ID: - p = conf_get_str (rs, "Name"); - if (!p) - { - log_print ("ike_phase_1_recv_ID: " - "failed to get Name in Remote-ID section [%s]", rs); - free (rid); - return -1; - } - - memcpy (rid, p, sz); - break; - - default: - log_print ("ike_phase_1_recv_ID: unsupported ID type %d", id_type); - free (rid); - return -1; + /* Compare expected/desired and received remote ID */ + if (bcmp(rid, payload->p + ISAKMP_ID_DATA_OFF, sz)) { + free(rid); + log_print("ike_phase_1_recv_ID: " + "received remote ID other than expected %s", p); + return -1; + } + free(rid); } - - /* Compare expected/desired and received remote ID */ - if (bcmp (rid, payload->p + ISAKMP_ID_DATA_OFF, sz)) - { - free (rid); - log_print ("ike_phase_1_recv_ID: " - "received remote ID other than expected %s", p); - return -1; + /* Choose the right fields to fill in */ + id = initiator ? &exchange->id_r : &exchange->id_i; + id_len = initiator ? &exchange->id_r_len : &exchange->id_i_len; + + *id_len = GET_ISAKMP_GEN_LENGTH(payload->p) - ISAKMP_GEN_SZ; + *id = malloc(*id_len); + if (!*id) { + log_error("ike_phase_1_recv_ID: malloc (%lu) failed", + (unsigned long) *id_len); + return -1; } - - free (rid); - } - - /* Choose the right fields to fill in */ - id = initiator ? &exchange->id_r : &exchange->id_i; - id_len = initiator ? &exchange->id_r_len : &exchange->id_i_len; - - *id_len = GET_ISAKMP_GEN_LENGTH (payload->p) - ISAKMP_GEN_SZ; - *id = malloc (*id_len); - if (!*id) - { - log_error ("ike_phase_1_recv_ID: malloc (%lu) failed", - (unsigned long)*id_len); - return -1; - } - memcpy (*id, payload->p + ISAKMP_GEN_SZ, *id_len); - snprintf (header, sizeof header, "ike_phase_1_recv_ID: %s", - constant_name (ipsec_id_cst, GET_ISAKMP_ID_TYPE (payload->p))); - LOG_DBG_BUF ((LOG_NEGOTIATION, 40, header, payload->p + ISAKMP_ID_DATA_OFF, - *id_len + ISAKMP_GEN_SZ - ISAKMP_ID_DATA_OFF)); - payload->flags |= PL_MARK; - - return 0; + memcpy(*id, payload->p + ISAKMP_GEN_SZ, *id_len); + snprintf(header, sizeof header, "ike_phase_1_recv_ID: %s", + constant_name(ipsec_id_cst, GET_ISAKMP_ID_TYPE(payload->p))); + LOG_DBG_BUF((LOG_NEGOTIATION, 40, header, payload->p + ISAKMP_ID_DATA_OFF, + *id_len + ISAKMP_GEN_SZ - ISAKMP_ID_DATA_OFF)); + payload->flags |= PL_MARK; + return 0; } /* Receive HASH and check that the exchange has been consistent. */ int -ike_phase_1_recv_AUTH (struct message *msg) +ike_phase_1_recv_AUTH(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct prf *prf; - struct hash *hash = ie->hash; - char header[80]; - size_t hashsize = hash->hashsize; - int initiator = exchange->initiator; - u_int8_t **hash_p, *id; - size_t id_len; - - /* Choose the right fields to fill in */ - hash_p = initiator ? &ie->hash_r : &ie->hash_i; - id = initiator ? exchange->id_r : exchange->id_i; - id_len = initiator ? exchange->id_r_len : exchange->id_i_len; - - /* The decoded hash will be in ie->hash_r or ie->hash_i */ - if (ie->ike_auth->decode_hash (msg)) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION, 0, 1, 0); - return -1; - } - - /* Allocate the prf and start calculating his HASH. */ - prf = prf_alloc (ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); - if (!prf) - { - /* XXX Log? */ - return -1; - } - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, initiator ? ie->g_xr : ie->g_xi, ie->g_x_len); - prf->Update (prf->prfctx, initiator ? ie->g_xi : ie->g_xr, ie->g_x_len); - prf->Update (prf->prfctx, - exchange->cookies - + (initiator ? ISAKMP_HDR_RCOOKIE_OFF : ISAKMP_HDR_ICOOKIE_OFF), - ISAKMP_HDR_ICOOKIE_LEN); - prf->Update (prf->prfctx, - exchange->cookies - + (initiator ? ISAKMP_HDR_ICOOKIE_OFF : ISAKMP_HDR_RCOOKIE_OFF), - ISAKMP_HDR_ICOOKIE_LEN); - prf->Update (prf->prfctx, ie->sa_i_b, ie->sa_i_b_len); - prf->Update (prf->prfctx, id, id_len); - prf->Final (hash->digest, prf->prfctx); - prf_free (prf); - snprintf (header, sizeof header, "ike_phase_1_recv_AUTH: computed HASH_%c", + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct prf *prf; + struct hash *hash = ie->hash; + char header[80]; + size_t hashsize = hash->hashsize; + int initiator = exchange->initiator; + u_int8_t **hash_p, *id; + size_t id_len; + + /* Choose the right fields to fill in */ + hash_p = initiator ? &ie->hash_r : &ie->hash_i; + id = initiator ? exchange->id_r : exchange->id_i; + id_len = initiator ? exchange->id_r_len : exchange->id_i_len; + + /* The decoded hash will be in ie->hash_r or ie->hash_i */ + if (ie->ike_auth->decode_hash(msg)) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION, 0, 1, 0); + return -1; + } + /* Allocate the prf and start calculating his HASH. */ + prf = prf_alloc(ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); + if (!prf) { + /* XXX Log? */ + return -1; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, initiator ? ie->g_xr : ie->g_xi, ie->g_x_len); + prf->Update(prf->prfctx, initiator ? ie->g_xi : ie->g_xr, ie->g_x_len); + prf->Update(prf->prfctx, exchange->cookies + + (initiator ? ISAKMP_HDR_RCOOKIE_OFF : ISAKMP_HDR_ICOOKIE_OFF), + ISAKMP_HDR_ICOOKIE_LEN); + prf->Update(prf->prfctx, exchange->cookies + + (initiator ? ISAKMP_HDR_ICOOKIE_OFF : ISAKMP_HDR_RCOOKIE_OFF), + ISAKMP_HDR_ICOOKIE_LEN); + prf->Update(prf->prfctx, ie->sa_i_b, ie->sa_i_b_len); + prf->Update(prf->prfctx, id, id_len); + prf->Final(hash->digest, prf->prfctx); + prf_free(prf); + snprintf(header, sizeof header, "ike_phase_1_recv_AUTH: computed HASH_%c", initiator ? 'R' : 'I'); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, header, hash->digest, hashsize)); - - /* Check that the hash we got matches the one we computed. */ - if (memcmp (*hash_p, hash->digest, hashsize) != 0) - { - /* XXX Log? */ - return -1; - } + LOG_DBG_BUF((LOG_NEGOTIATION, 80, header, hash->digest, hashsize)); - return 0; + /* Check that the hash we got matches the one we computed. */ + if (memcmp(*hash_p, hash->digest, hashsize) != 0) { + /* XXX Log? */ + return -1; + } + return 0; } struct attr_node { - LIST_ENTRY (attr_node) link; - u_int16_t type; + LIST_ENTRY(attr_node) link; + u_int16_t type; }; struct validation_state { - struct conf_list_node *xf; - LIST_HEAD (attr_head, attr_node) attrs; - char *life; + struct conf_list_node *xf; + LIST_HEAD(attr_head, attr_node) attrs; + char *life; }; /* Validate a proposal inside SA according to EXCHANGE's policy. */ static int -ike_phase_1_validate_prop (struct exchange *exchange, struct sa *sa, - struct sa *isakmp_sa) +ike_phase_1_validate_prop(struct exchange *exchange, struct sa *sa, + struct sa *isakmp_sa) { - struct conf_list *conf, *tags; - struct conf_list_node *xf, *tag; - struct proto *proto; - struct validation_state vs; - struct attr_node *node, *next_node; - - /* Get the list of transforms. */ - conf = conf_get_list (exchange->policy, "Transforms"); - if (!conf) - return 0; - - for (xf = TAILQ_FIRST (&conf->fields); xf; xf = TAILQ_NEXT (xf, link)) - { - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - /* Mark all attributes in our policy as unseen. */ - LIST_INIT (&vs.attrs); - vs.xf = xf; - vs.life = 0; - if (attribute_map (proto->chosen->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (proto->chosen->p) - - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - attribute_unacceptable, &vs)) - goto try_next; - - /* Sweep over unseen tags in this section. */ - tags = conf_get_tag_list (xf->field); - if (tags) - { - for (tag = TAILQ_FIRST (&tags->fields); tag; - tag = TAILQ_NEXT (tag, link)) - /* - * XXX Should we care about attributes we have, they do not - * provide? - */ - for (node = LIST_FIRST (&vs.attrs); node; - node = next_node) - { - next_node = LIST_NEXT (node, link); - if (node->type - == constant_value (ike_attr_cst, tag->field)) - { - LIST_REMOVE (node, link); - free (node); - } - } - conf_free_list (tags); - } - - /* Are there leftover tags in this section? */ - node = LIST_FIRST (&vs.attrs); - if (node) - goto try_next; - } + struct conf_list *conf, *tags; + struct conf_list_node *xf, *tag; + struct proto *proto; + struct validation_state vs; + struct attr_node *node, *next_node; + + /* Get the list of transforms. */ + conf = conf_get_list(exchange->policy, "Transforms"); + if (!conf) + return 0; + + for (xf = TAILQ_FIRST(&conf->fields); xf; xf = TAILQ_NEXT(xf, link)) { + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + /* Mark all attributes in our policy as unseen. */ + LIST_INIT(&vs.attrs); + vs.xf = xf; + vs.life = 0; + if (attribute_map(proto->chosen->p + + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(proto->chosen->p) - + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + attribute_unacceptable, &vs)) + goto try_next; + + /* Sweep over unseen tags in this section. */ + tags = conf_get_tag_list(xf->field); + if (tags) { + for (tag = TAILQ_FIRST(&tags->fields); tag; + tag = TAILQ_NEXT(tag, link)) + /* + * XXX Should we care about attributes + * we have, they do not provide? + */ + for (node = LIST_FIRST(&vs.attrs); node; + node = next_node) { + next_node = LIST_NEXT(node, link); + if (node->type == + constant_value(ike_attr_cst, + tag->field)) { + LIST_REMOVE(node, link); + free(node); + } + } + conf_free_list(tags); + } + /* Are there leftover tags in this section? */ + node = LIST_FIRST(&vs.attrs); + if (node) + goto try_next; + } - /* All protocols were OK, we succeeded. */ - LOG_DBG ((LOG_NEGOTIATION, 20, "ike_phase_1_validate_prop: success")); - conf_free_list (conf); - if (vs.life) - free (vs.life); - return 1; - - try_next: - /* Are there leftover tags in this section? */ - node = LIST_FIRST (&vs.attrs); - while (node) - { - LIST_REMOVE (node, link); - free (node); - node = LIST_FIRST (&vs.attrs); + /* All protocols were OK, we succeeded. */ + LOG_DBG((LOG_NEGOTIATION, 20, "ike_phase_1_validate_prop: success")); + conf_free_list(conf); + if (vs.life) + free(vs.life); + return 1; + +try_next: + /* Are there leftover tags in this section? */ + node = LIST_FIRST(&vs.attrs); + while (node) { + LIST_REMOVE(node, link); + free(node); + node = LIST_FIRST(&vs.attrs); + } + if (vs.life) + free(vs.life); } - if (vs.life) - free (vs.life); - } - LOG_DBG ((LOG_NEGOTIATION, 20, "ike_phase_1_validate_prop: failure")); - conf_free_list (conf); - return 0; + LOG_DBG((LOG_NEGOTIATION, 20, "ike_phase_1_validate_prop: failure")); + conf_free_list(conf); + return 0; } /* @@ -1219,179 +1113,162 @@ ike_phase_1_validate_prop (struct exchange *exchange, struct sa *sa, * If the attribute is unacceptable to use, return non-zero, otherwise zero. */ static int -attribute_unacceptable (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vvs) +attribute_unacceptable(u_int16_t type, u_int8_t *value, u_int16_t len, + void *vvs) { - struct validation_state *vs = vvs; - struct conf_list *life_conf; - struct conf_list_node *xf = vs->xf, *life; - char *tag = constant_lookup (ike_attr_cst, type); - char *str; - struct constant_map *map; - struct attr_node *node; - int rv; - - if (!tag) - { - LOG_DBG ((LOG_NEGOTIATION, 60, - "attribute_unacceptable: attribute type %d not known", type)); - return 1; - } - - switch (type) - { - case IKE_ATTR_ENCRYPTION_ALGORITHM: - case IKE_ATTR_HASH_ALGORITHM: - case IKE_ATTR_AUTHENTICATION_METHOD: - case IKE_ATTR_GROUP_DESCRIPTION: - case IKE_ATTR_GROUP_TYPE: - case IKE_ATTR_PRF: - str = conf_get_str (xf->field, tag); - if (!str) - { - /* This attribute does not exist in this policy. */ - LOG_DBG ((LOG_NEGOTIATION, 70, - "attribute_unacceptable: attr %s does not exist in %s", - tag, xf->field)); - return 1; + struct validation_state *vs = vvs; + struct conf_list *life_conf; + struct conf_list_node *xf = vs->xf, *life; + char *tag = constant_lookup(ike_attr_cst, type); + char *str; + struct constant_map *map; + struct attr_node *node; + int rv; + + if (!tag) { + LOG_DBG((LOG_NEGOTIATION, 60, + "attribute_unacceptable: attribute type %d not known", type)); + return 1; } - - map = constant_link_lookup (ike_attr_cst, type); - if (!map) - return 1; - - if ((constant_value (map, str) == decode_16 (value)) || - (!strcmp (str, "ANY"))) - { - /* Mark this attribute as seen. */ - node = malloc (sizeof *node); - if (!node) - { - log_error ("attribute_unacceptable: malloc (%lu) failed", - (unsigned long)sizeof *node); - return 1; - } - node->type = type; - LIST_INSERT_HEAD (&vs->attrs, node, link); - return 0; - } - LOG_DBG ((LOG_NEGOTIATION, 70, - "attribute_unacceptable: %s: got %s, expected %s", tag, - constant_name (map, decode_16 (value)), str)); - return 1; - - case IKE_ATTR_GROUP_PRIME: - case IKE_ATTR_GROUP_GENERATOR_1: - case IKE_ATTR_GROUP_GENERATOR_2: - case IKE_ATTR_GROUP_CURVE_A: - case IKE_ATTR_GROUP_CURVE_B: - /* XXX Bignums not handled yet. */ - return 1; - - case IKE_ATTR_LIFE_TYPE: - case IKE_ATTR_LIFE_DURATION: - life_conf = conf_get_list (xf->field, "Life"); - if (life_conf && !strcmp (conf_get_str (xf->field, "Life"), "ANY")) - return 0; - - rv = 1; - if (!life_conf) - { - /* Life attributes given, but not in our policy. */ - LOG_DBG ((LOG_NEGOTIATION, 70, "attribute_unacceptable: " - "received unexpected life attribute")); - return 1; - } - - /* - * Each lifetime type must match, otherwise we turn the proposal down. - * In order to do this we need to find the specific section of our - * policy's "Life" list and match its duration - */ - switch (type) - { - case IKE_ATTR_LIFE_TYPE: - for (life = TAILQ_FIRST (&life_conf->fields); life; - life = TAILQ_NEXT (life, link)) - { - str = conf_get_str (life->field, "LIFE_TYPE"); - if (!str) - { - LOG_DBG ((LOG_NEGOTIATION, 70, "attribute_unacceptable: " - "section [%s] has no LIFE_TYPE", life->field)); - continue; + switch (type) { + case IKE_ATTR_ENCRYPTION_ALGORITHM: + case IKE_ATTR_HASH_ALGORITHM: + case IKE_ATTR_AUTHENTICATION_METHOD: + case IKE_ATTR_GROUP_DESCRIPTION: + case IKE_ATTR_GROUP_TYPE: + case IKE_ATTR_PRF: + str = conf_get_str(xf->field, tag); + if (!str) { + /* This attribute does not exist in this policy. */ + LOG_DBG((LOG_NEGOTIATION, 70, + "attribute_unacceptable: attr %s does not exist in %s", + tag, xf->field)); + return 1; } - - /* - * If this is the type we are looking at, save a pointer - * to this section in vs->life. - */ - if (constant_value (ike_duration_cst, str) == decode_16 (value)) - { - vs->life = strdup (life->field); - rv = 0; - goto bail_out; + map = constant_link_lookup(ike_attr_cst, type); + if (!map) + return 1; + + if ((constant_value(map, str) == decode_16(value)) || + (!strcmp(str, "ANY"))) { + /* Mark this attribute as seen. */ + node = malloc(sizeof *node); + if (!node) { + log_error("attribute_unacceptable: malloc (%lu) failed", + (unsigned long) sizeof *node); + return 1; + } + node->type = type; + LIST_INSERT_HEAD(&vs->attrs, node, link); + return 0; } - } - LOG_DBG ((LOG_NEGOTIATION, 70, - "attribute_unacceptable: unrecognized LIFE_TYPE %d", - decode_16 (value))); - vs->life = 0; - break; + LOG_DBG((LOG_NEGOTIATION, 70, + "attribute_unacceptable: %s: got %s, expected %s", tag, + constant_name(map, decode_16(value)), str)); + return 1; + + case IKE_ATTR_GROUP_PRIME: + case IKE_ATTR_GROUP_GENERATOR_1: + case IKE_ATTR_GROUP_GENERATOR_2: + case IKE_ATTR_GROUP_CURVE_A: + case IKE_ATTR_GROUP_CURVE_B: + /* XXX Bignums not handled yet. */ + return 1; + case IKE_ATTR_LIFE_TYPE: case IKE_ATTR_LIFE_DURATION: - if (!vs->life) - { - LOG_DBG ((LOG_NEGOTIATION, 70, "attribute_unacceptable: " - "LIFE_DURATION without LIFE_TYPE")); - rv = 1; - goto bail_out; - } - - str = conf_get_str (vs->life, "LIFE_DURATION"); - if (str) - { - if (!strcmp (str, "ANY")) - rv = 0; - else - rv = !conf_match_num (vs->life, "LIFE_DURATION", - len == 4 ? decode_32 (value) : - decode_16 (value)); - } - else - { - LOG_DBG ((LOG_NEGOTIATION, 70, "attribute_unacceptable: " - "section [%s] has no LIFE_DURATION", vs->life)); - rv = 1; - } - - free (vs->life); - vs->life = 0; - break; - } + life_conf = conf_get_list(xf->field, "Life"); + if (life_conf && !strcmp(conf_get_str(xf->field, "Life"), "ANY")) + return 0; + + rv = 1; + if (!life_conf) { + /* Life attributes given, but not in our policy. */ + LOG_DBG((LOG_NEGOTIATION, 70, "attribute_unacceptable: " + "received unexpected life attribute")); + return 1; + } + /* + * Each lifetime type must match, otherwise we turn the proposal down. + * In order to do this we need to find the specific section of our + * policy's "Life" list and match its duration + */ + switch (type) { + case IKE_ATTR_LIFE_TYPE: + for (life = TAILQ_FIRST(&life_conf->fields); life; + life = TAILQ_NEXT(life, link)) { + str = conf_get_str(life->field, "LIFE_TYPE"); + if (!str) { + LOG_DBG((LOG_NEGOTIATION, 70, + "attribute_unacceptable: " + "section [%s] has no LIFE_TYPE", + life->field)); + continue; + } + + /* + * If this is the type we are looking at, + * to save a pointer this section in vs->life. + */ + if (constant_value(ike_duration_cst, str) == + decode_16(value)) { + vs->life = strdup(life->field); + rv = 0; + goto bail_out; + } + } + LOG_DBG((LOG_NEGOTIATION, 70, + "attribute_unacceptable: unrecognized LIFE_TYPE %d", + decode_16(value))); + vs->life = 0; + break; + + case IKE_ATTR_LIFE_DURATION: + if (!vs->life) { + LOG_DBG((LOG_NEGOTIATION, 70, "attribute_unacceptable: " + "LIFE_DURATION without LIFE_TYPE")); + rv = 1; + goto bail_out; + } + str = conf_get_str(vs->life, "LIFE_DURATION"); + if (str) { + if (!strcmp(str, "ANY")) + rv = 0; + else + rv = !conf_match_num(vs->life, "LIFE_DURATION", + len == 4 ? decode_32(value) : + decode_16(value)); + } else { + LOG_DBG((LOG_NEGOTIATION, 70, "attribute_unacceptable: " + "section [%s] has no LIFE_DURATION", vs->life)); + rv = 1; + } + + free(vs->life); + vs->life = 0; + break; + } - bail_out: - conf_free_list (life_conf); - return rv; - - case IKE_ATTR_KEY_LENGTH: - case IKE_ATTR_FIELD_SIZE: - case IKE_ATTR_GROUP_ORDER: - if (conf_match_num (xf->field, tag, decode_16 (value))) - { - /* Mark this attribute as seen. */ - node = malloc (sizeof *node); - if (!node) - { - log_error ("attribute_unacceptable: malloc (%lu) failed", - (unsigned long)sizeof *node); - return 1; - } - node->type = type; - LIST_INSERT_HEAD (&vs->attrs, node, link); - return 0; +bail_out: + conf_free_list(life_conf); + return rv; + + case IKE_ATTR_KEY_LENGTH: + case IKE_ATTR_FIELD_SIZE: + case IKE_ATTR_GROUP_ORDER: + if (conf_match_num(xf->field, tag, decode_16(value))) { + /* Mark this attribute as seen. */ + node = malloc(sizeof *node); + if (!node) { + log_error("attribute_unacceptable: malloc (%lu) failed", + (unsigned long) sizeof *node); + return 1; + } + node->type = type; + LIST_INSERT_HEAD(&vs->attrs, node, link); + return 0; + } + return 1; } - return 1; - } - return 1; + return 1; } diff --git a/sbin/isakmpd/ike_phase_1.h b/sbin/isakmpd/ike_phase_1.h index 3a0498abe40..1252664b7e3 100644 --- a/sbin/isakmpd/ike_phase_1.h +++ b/sbin/isakmpd/ike_phase_1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ike_phase_1.h,v 1.3 2003/06/03 14:28:16 ho Exp $ */ +/* $OpenBSD: ike_phase_1.h,v 1.4 2004/04/15 18:39:25 deraadt Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -33,21 +33,21 @@ struct message; -extern int ike_phase_1_initiator_recv_KE_NONCE (struct message *); -extern int ike_phase_1_initiator_recv_SA (struct message *); -extern int ike_phase_1_initiator_send_KE_NONCE (struct message *); -extern int ike_phase_1_initiator_send_SA (struct message *); -extern int ike_phase_1_post_exchange_KE_NONCE (struct message *); -extern int ike_phase_1_recv_AUTH (struct message *); -extern int ike_phase_1_recv_ID (struct message *); -extern int ike_phase_1_recv_ID_AUTH (struct message *); -extern int ike_phase_1_recv_KE_NONCE (struct message *); -extern int ike_phase_1_responder_recv_SA (struct message *); -extern int ike_phase_1_responder_send_SA (struct message *); -extern int ike_phase_1_responder_send_ID_AUTH (struct message *); -extern int ike_phase_1_send_AUTH (struct message *); -extern int ike_phase_1_send_ID (struct message *); -extern int ike_phase_1_send_ID_AUTH (struct message *); -extern int ike_phase_1_send_KE_NONCE (struct message *, size_t); +extern int ike_phase_1_initiator_recv_KE_NONCE(struct message *); +extern int ike_phase_1_initiator_recv_SA(struct message *); +extern int ike_phase_1_initiator_send_KE_NONCE(struct message *); +extern int ike_phase_1_initiator_send_SA(struct message *); +extern int ike_phase_1_post_exchange_KE_NONCE(struct message *); +extern int ike_phase_1_recv_AUTH(struct message *); +extern int ike_phase_1_recv_ID(struct message *); +extern int ike_phase_1_recv_ID_AUTH(struct message *); +extern int ike_phase_1_recv_KE_NONCE(struct message *); +extern int ike_phase_1_responder_recv_SA(struct message *); +extern int ike_phase_1_responder_send_SA(struct message *); +extern int ike_phase_1_responder_send_ID_AUTH(struct message *); +extern int ike_phase_1_send_AUTH(struct message *); +extern int ike_phase_1_send_ID(struct message *); +extern int ike_phase_1_send_ID_AUTH(struct message *); +extern int ike_phase_1_send_KE_NONCE(struct message *, size_t); -#endif /* _IKE_PHASE_1_H_ */ +#endif /* _IKE_PHASE_1_H_ */ diff --git a/sbin/isakmpd/ike_quick_mode.c b/sbin/isakmpd/ike_quick_mode.c index 1b4f2c34e6a..bb92aaf2a0e 100644 --- a/sbin/isakmpd/ike_quick_mode.c +++ b/sbin/isakmpd/ike_quick_mode.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_quick_mode.c,v 1.76 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: ike_quick_mode.c,v 1.139 2001/01/26 10:43:17 niklas Exp $ */ +/* $OpenBSD: ike_quick_mode.c,v 1.77 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_quick_mode.c,v 1.139 2001/01/26 10:43:17 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -65,29 +65,29 @@ #include "x509.h" #endif -static void gen_g_xy (struct message *); -static int initiator_send_HASH_SA_NONCE (struct message *); -static int initiator_recv_HASH_SA_NONCE (struct message *); -static int initiator_send_HASH (struct message *); -static void post_quick_mode (struct message *); -static int responder_recv_HASH_SA_NONCE (struct message *); -static int responder_send_HASH_SA_NONCE (struct message *); -static int responder_recv_HASH (struct message *); +static void gen_g_xy(struct message *); +static int initiator_send_HASH_SA_NONCE(struct message *); +static int initiator_recv_HASH_SA_NONCE(struct message *); +static int initiator_send_HASH(struct message *); +static void post_quick_mode(struct message *); +static int responder_recv_HASH_SA_NONCE(struct message *); +static int responder_send_HASH_SA_NONCE(struct message *); +static int responder_recv_HASH(struct message *); #ifdef USE_POLICY -static int check_policy (struct exchange *, struct sa *, struct sa *); +static int check_policy(struct exchange *, struct sa *, struct sa *); #endif -int (*ike_quick_mode_initiator[]) (struct message *) = { - initiator_send_HASH_SA_NONCE, - initiator_recv_HASH_SA_NONCE, - initiator_send_HASH +int (*ike_quick_mode_initiator[]) (struct message *) = { + initiator_send_HASH_SA_NONCE, + initiator_recv_HASH_SA_NONCE, + initiator_send_HASH }; -int (*ike_quick_mode_responder[]) (struct message *) = { - responder_recv_HASH_SA_NONCE, - responder_send_HASH_SA_NONCE, - responder_recv_HASH +int (*ike_quick_mode_responder[]) (struct message *) = { + responder_recv_HASH_SA_NONCE, + responder_send_HASH_SA_NONCE, + responder_recv_HASH }; #ifdef USE_POLICY @@ -100,1369 +100,1262 @@ int (*ike_quick_mode_responder[]) (struct message *) = { * acceptable. */ static int -check_policy (struct exchange *exchange, struct sa *sa, struct sa *isakmp_sa) +check_policy(struct exchange *exchange, struct sa *sa, struct sa *isakmp_sa) { - char *return_values[RETVALUES_NUM]; - char **principal = 0; - int i, len, result = 0, nprinc = 0; - int *x509_ids = 0, *keynote_ids = 0; - unsigned char hashbuf[20]; /* Set to the largest digest result */ + char *return_values[RETVALUES_NUM]; + char **principal = 0; + int i, len, result = 0, nprinc = 0; + int *x509_ids = 0, *keynote_ids = 0; + unsigned char hashbuf[20]; /* Set to the largest digest result */ #ifdef USE_X509 - struct keynote_deckey dc; - X509_NAME *subject; + struct keynote_deckey dc; + X509_NAME *subject; #endif - /* Initialize if necessary -- e.g., if pre-shared key auth was used */ - if (isakmp_sa->policy_id < 0) - { - if ((isakmp_sa->policy_id = kn_init ()) == -1) - { - log_print ("check_policy: failed to initialize policy session"); - return 0; + /* Initialize if necessary -- e.g., if pre-shared key auth was used */ + if (isakmp_sa->policy_id < 0) { + if ((isakmp_sa->policy_id = kn_init()) == -1) { + log_print("check_policy: failed to initialize policy session"); + return 0; + } } - } - - /* Add the callback that will handle attributes. */ - if (kn_add_action (isakmp_sa->policy_id, ".*", (char *) policy_callback, - ENVIRONMENT_FLAG_FUNC | ENVIRONMENT_FLAG_REGEX) == -1) - { - log_print ("check_policy: " - "kn_add_action (%d, \".*\", %p, FUNC | REGEX) failed", - isakmp_sa->policy_id, policy_callback); - kn_close (isakmp_sa->policy_id); - isakmp_sa->policy_id = -1; - return 0; - } - - if (keynote_policy_asserts_num) - { - keynote_ids = calloc (keynote_policy_asserts_num, sizeof *keynote_ids); - if (!keynote_ids) - { - log_error ("check_policy: calloc (%d, %lu) failed", - keynote_policy_asserts_num, (unsigned long)sizeof *keynote_ids); - return 0; - } - } - - /* Add the policy assertions */ - for (i = 0; i < keynote_policy_asserts_num; i++) - keynote_ids[i] = kn_add_assertion (isakmp_sa->policy_id, - keynote_policy_asserts[i], - strlen (keynote_policy_asserts[i]), - ASSERT_FLAG_LOCAL); - - /* Initialize -- we'll let the callback do all the work. */ - policy_exchange = exchange; - policy_sa = sa; - policy_isakmp_sa = isakmp_sa; - - /* Set the return values; true/false for now at least. */ - return_values[0] = "false"; /* Order of values in array is important. */ - return_values[1] = "true"; - - /* Create a principal (authorizer) for the SA/ID request. */ - switch (isakmp_sa->recv_certtype) - { - case ISAKMP_CERTENC_NONE: - /* - * For shared keys, just duplicate the passphrase with the - * appropriate prefix tag. - */ - nprinc = 3; - principal = calloc (nprinc, sizeof *principal); - if (!principal) - { - log_error ("check_policy: calloc (%d, %lu) failed", nprinc, - (unsigned long)sizeof *principal); - goto policydone; + /* Add the callback that will handle attributes. */ + if (kn_add_action(isakmp_sa->policy_id, ".*", (char *) policy_callback, + ENVIRONMENT_FLAG_FUNC | ENVIRONMENT_FLAG_REGEX) == -1) { + log_print("check_policy: " + "kn_add_action (%d, \".*\", %p, FUNC | REGEX) failed", + isakmp_sa->policy_id, policy_callback); + kn_close(isakmp_sa->policy_id); + isakmp_sa->policy_id = -1; + return 0; } - - len = strlen (isakmp_sa->recv_key) + sizeof "passphrase:"; - principal[0] = calloc (len, sizeof (char)); - if (!principal[0]) - { - log_error ("check_policy: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto policydone; + if (keynote_policy_asserts_num) { + keynote_ids = calloc(keynote_policy_asserts_num, sizeof *keynote_ids); + if (!keynote_ids) { + log_error("check_policy: calloc (%d, %lu) failed", + keynote_policy_asserts_num, + (unsigned long) sizeof *keynote_ids); + return 0; + } } + /* Add the policy assertions */ + for (i = 0; i < keynote_policy_asserts_num; i++) + keynote_ids[i] = kn_add_assertion(isakmp_sa->policy_id, + keynote_policy_asserts[i], + strlen(keynote_policy_asserts[i]), ASSERT_FLAG_LOCAL); + + /* Initialize -- we'll let the callback do all the work. */ + policy_exchange = exchange; + policy_sa = sa; + policy_isakmp_sa = isakmp_sa; + + /* Set the return values; true/false for now at least. */ + return_values[0] = "false"; /* Order of values in array is + * important. */ + return_values[1] = "true"; + + /* Create a principal (authorizer) for the SA/ID request. */ + switch (isakmp_sa->recv_certtype) { + case ISAKMP_CERTENC_NONE: + /* + * For shared keys, just duplicate the passphrase with the + * appropriate prefix tag. + */ + nprinc = 3; + principal = calloc(nprinc, sizeof *principal); + if (!principal) { + log_error("check_policy: calloc (%d, %lu) failed", nprinc, + (unsigned long) sizeof *principal); + goto policydone; + } + len = strlen(isakmp_sa->recv_key) + sizeof "passphrase:"; + principal[0] = calloc(len, sizeof(char)); + if (!principal[0]) { + log_error("check_policy: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto policydone; + } + /* + * XXX Consider changing the magic hash lengths with + * constants. + */ + strlcpy(principal[0], "passphrase:", len); + memcpy(principal[0] + sizeof "passphrase:" - 1, isakmp_sa->recv_key, + strlen(isakmp_sa->recv_key)); + + len = sizeof "passphrase-md5-hex:" + 2 * 16; + principal[1] = calloc(len, sizeof(char)); + if (!principal[1]) { + log_error("check_policy: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto policydone; + } + strlcpy(principal[1], "passphrase-md5-hex:", len); + MD5(isakmp_sa->recv_key, strlen(isakmp_sa->recv_key), hashbuf); + for (i = 0; i < 16; i++) + snprintf(principal[1] + 2 * i + sizeof "passphrase-md5-hex:" - 1, + 3, "%02x", hashbuf[i]); + + len = sizeof "passphrase-sha1-hex:" + 2 * 20; + principal[2] = calloc(len, sizeof(char)); + if (!principal[2]) { + log_error("check_policy: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto policydone; + } + strlcpy(principal[2], "passphrase-sha1-hex:", len); + SHA1(isakmp_sa->recv_key, strlen(isakmp_sa->recv_key), hashbuf); + for (i = 0; i < 20; i++) + snprintf(principal[2] + 2 * i + sizeof "passphrase-sha1-hex:" - 1, + 3, "%02x", hashbuf[i]); + break; + + case ISAKMP_CERTENC_KEYNOTE: +#ifdef USE_KEYNOTE + nprinc = 1; - /* XXX Consider changing the magic hash lengths with constants. */ - strlcpy (principal[0], "passphrase:", len); - memcpy (principal[0] + sizeof "passphrase:" - 1, isakmp_sa->recv_key, - strlen (isakmp_sa->recv_key)); - - len = sizeof "passphrase-md5-hex:" + 2 * 16; - principal[1] = calloc (len, sizeof (char)); - if (!principal[1]) - { - log_error ("check_policy: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto policydone; - } + principal = calloc(nprinc, sizeof *principal); + if (!principal) { + log_error("check_policy: calloc (%d, %lu) failed", nprinc, + (unsigned long) sizeof *principal); + goto policydone; + } + /* Dup the keys */ + principal[0] = strdup(isakmp_sa->keynote_key); + if (!principal[0]) { + log_error("check_policy: calloc (%lu, %lu) failed", + (unsigned long) strlen(isakmp_sa->keynote_key), + (unsigned long) sizeof(char)); + goto policydone; + } +#endif + break; - strlcpy (principal[1], "passphrase-md5-hex:", len); - MD5 (isakmp_sa->recv_key, strlen (isakmp_sa->recv_key), hashbuf); - for (i = 0; i < 16; i++) - snprintf (principal[1] + 2 * i + sizeof "passphrase-md5-hex:" - 1, - 3, "%02x", hashbuf[i]); - - len = sizeof "passphrase-sha1-hex:" + 2 * 20; - principal[2] = calloc (len, sizeof (char)); - if (!principal[2]) - { - log_error ("check_policy: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto policydone; - } + case ISAKMP_CERTENC_X509_SIG: +#ifdef USE_X509 + principal = calloc(2, sizeof *principal); + if (!principal) { + log_error("check_policy: calloc (2, %lu) failed", + (unsigned long) sizeof *principal); + goto policydone; + } + if (isakmp_sa->recv_keytype == ISAKMP_KEY_RSA) + dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; + else { + log_error("check_policy: unknown/unsupported public key algorithm " + "%d", isakmp_sa->recv_keytype); + goto policydone; + } - strlcpy (principal[2], "passphrase-sha1-hex:", len); - SHA1 (isakmp_sa->recv_key, strlen (isakmp_sa->recv_key), hashbuf); - for (i = 0; i < 20; i++) - snprintf (principal[2] + 2 * i + sizeof "passphrase-sha1-hex:" - 1, - 3, "%02x", hashbuf[i]); - break; + dc.dec_key = isakmp_sa->recv_key; + principal[0] = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, + KEYNOTE_PUBLIC_KEY); + if (keynote_errno == ERROR_MEMORY) { + log_print("check_policy: failed to get memory for public key"); + goto policydone; + } + if (!principal[0]) { + log_print("check_policy: failed to allocate memory for principal"); + goto policydone; + } + len = strlen(principal[0]) + sizeof "rsa-hex:"; + principal[1] = calloc(len, sizeof(char)); + if (!principal[1]) { + log_error("check_policy: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto policydone; + } + snprintf(principal[1], len, "rsa-hex:%s", principal[0]); + free(principal[0]); + principal[0] = principal[1]; + principal[1] = 0; + + /* Generate a "DN:" principal. */ + subject = X509_get_subject_name(isakmp_sa->recv_cert); + if (subject) { + principal[1] = calloc(259, sizeof(char)); + if (!principal[1]) { + log_error("check_policy: calloc (259, %lu) failed", + (unsigned long) sizeof(char)); + goto policydone; + } + strlcpy(principal[1], "DN:", 259); + X509_NAME_oneline(subject, principal[1] + 3, 256); + nprinc = 2; + } else { + nprinc = 1; + } + break; +#endif - case ISAKMP_CERTENC_KEYNOTE: -#ifdef USE_KEYNOTE - nprinc = 1; - - principal = calloc (nprinc, sizeof *principal); - if (!principal) - { - log_error ("check_policy: calloc (%d, %lu) failed", nprinc, - (unsigned long)sizeof *principal); - goto policydone; + /* XXX Eventually handle these. */ + case ISAKMP_CERTENC_PKCS: + case ISAKMP_CERTENC_PGP: + case ISAKMP_CERTENC_DNS: + case ISAKMP_CERTENC_X509_KE: + case ISAKMP_CERTENC_KERBEROS: + case ISAKMP_CERTENC_CRL: + case ISAKMP_CERTENC_ARL: + case ISAKMP_CERTENC_SPKI: + case ISAKMP_CERTENC_X509_ATTR: + default: + log_print("check_policy: " + "unknown/unsupported certificate/authentication method %d", + isakmp_sa->recv_certtype); + goto policydone; } - /* Dup the keys */ - principal[0] = strdup (isakmp_sa->keynote_key); - if (!principal[0]) - { - log_error ("check_policy: calloc (%lu, %lu) failed", - (unsigned long)strlen (isakmp_sa->keynote_key), - (unsigned long)sizeof (char)); - goto policydone; + /* + * Add the authorizer (who is requesting the SA/ID); + * this may be a public or a secret key, depending on + * what mode of authentication we used in Phase 1. + */ + for (i = 0; i < nprinc; i++) { + LOG_DBG((LOG_POLICY, 40, "check_policy: adding authorizer [%s]", + principal[i])); + + if (kn_add_authorizer(isakmp_sa->policy_id, principal[i]) == -1) { + int j; + + for (j = 0; j < i; j++) + kn_remove_authorizer(isakmp_sa->policy_id, principal[j]); + log_print("check_policy: kn_add_authorizer failed"); + goto policydone; + } } -#endif - break; - case ISAKMP_CERTENC_X509_SIG: -#ifdef USE_X509 - principal = calloc (2, sizeof *principal); - if (!principal) - { - log_error ("check_policy: calloc (2, %lu) failed", - (unsigned long)sizeof *principal); - goto policydone; - } + /* Ask policy */ + result = kn_do_query(isakmp_sa->policy_id, return_values, RETVALUES_NUM); + LOG_DBG((LOG_POLICY, 40, "check_policy: kn_do_query returned %d", result)); - if (isakmp_sa->recv_keytype == ISAKMP_KEY_RSA) - dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; - else - { - log_error ("check_policy: unknown/unsupported public key algorithm " - "%d", isakmp_sa->recv_keytype); - goto policydone; - } + /* Cleanup environment */ + kn_cleanup_action_environment(isakmp_sa->policy_id); - dc.dec_key = isakmp_sa->recv_key; - principal[0] = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, - KEYNOTE_PUBLIC_KEY); - if (keynote_errno == ERROR_MEMORY) - { - log_print ("check_policy: failed to get memory for public key"); - goto policydone; + /* Remove authorizers from the session */ + for (i = 0; i < nprinc; i++) { + kn_remove_authorizer(isakmp_sa->policy_id, principal[i]); + free(principal[i]); } - if (!principal[0]) - { - log_print ("check_policy: failed to allocate memory for principal"); - goto policydone; - } + free(principal); + principal = 0; + nprinc = 0; - len = strlen (principal[0]) + sizeof "rsa-hex:"; - principal[1] = calloc (len, sizeof (char)); - if (!principal[1]) - { - log_error ("check_policy: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto policydone; + /* Check what policy said. */ + if (result < 0) { + LOG_DBG((LOG_POLICY, 40, "check_policy: proposal refused")); + result = 0; + goto policydone; + } +policydone: + for (i = 0; i < nprinc; i++) + if (principal && principal[i]) + free(principal[i]); + + if (principal) + free(principal); + + /* Remove the policies */ + for (i = 0; i < keynote_policy_asserts_num; i++) { + if (keynote_ids[i] != -1) + kn_remove_assertion(isakmp_sa->policy_id, keynote_ids[i]); } - snprintf (principal[1], len, "rsa-hex:%s", principal[0]); - free (principal[0]); - principal[0] = principal[1]; - principal[1] = 0; + if (keynote_ids) + free(keynote_ids); - /* Generate a "DN:" principal. */ - subject = X509_get_subject_name (isakmp_sa->recv_cert); - if (subject) - { - principal[1] = calloc (259, sizeof (char)); - if (!principal[1]) - { - log_error ("check_policy: calloc (259, %lu) failed", - (unsigned long)sizeof (char)); - goto policydone; - } - strlcpy (principal[1], "DN:", 259); - X509_NAME_oneline (subject, principal[1] + 3, 256); - nprinc = 2; - } else { - nprinc = 1; - } - break; -#endif + if (x509_ids) + free(x509_ids); - /* XXX Eventually handle these. */ - case ISAKMP_CERTENC_PKCS: - case ISAKMP_CERTENC_PGP: - case ISAKMP_CERTENC_DNS: - case ISAKMP_CERTENC_X509_KE: - case ISAKMP_CERTENC_KERBEROS: - case ISAKMP_CERTENC_CRL: - case ISAKMP_CERTENC_ARL: - case ISAKMP_CERTENC_SPKI: - case ISAKMP_CERTENC_X509_ATTR: - default: - log_print ("check_policy: " - "unknown/unsupported certificate/authentication method %d", - isakmp_sa->recv_certtype); - goto policydone; - } - - /* - * Add the authorizer (who is requesting the SA/ID); - * this may be a public or a secret key, depending on - * what mode of authentication we used in Phase 1. - */ - for (i = 0; i < nprinc; i++) - { - LOG_DBG ((LOG_POLICY, 40, "check_policy: adding authorizer [%s]", - principal[i])); - - if (kn_add_authorizer (isakmp_sa->policy_id, principal[i]) == -1) - { - int j; - - for (j = 0; j < i; j++) - kn_remove_authorizer (isakmp_sa->policy_id, principal[j]); - log_print ("check_policy: kn_add_authorizer failed"); - goto policydone; - } - } - - /* Ask policy */ - result = kn_do_query (isakmp_sa->policy_id, return_values, RETVALUES_NUM); - LOG_DBG ((LOG_POLICY, 40, "check_policy: kn_do_query returned %d", result)); - - /* Cleanup environment */ - kn_cleanup_action_environment (isakmp_sa->policy_id); - - /* Remove authorizers from the session */ - for (i = 0; i < nprinc; i++) - { - kn_remove_authorizer (isakmp_sa->policy_id, principal[i]); - free (principal[i]); - } - - free (principal); - principal = 0; - nprinc = 0; - - /* Check what policy said. */ - if (result < 0) - { - LOG_DBG ((LOG_POLICY, 40, "check_policy: proposal refused")); - result = 0; - goto policydone; - } - - policydone: - for (i = 0; i < nprinc; i++) - if (principal && principal[i]) - free (principal[i]); - - if (principal) - free (principal); - - /* Remove the policies */ - for (i = 0; i < keynote_policy_asserts_num; i++) - { - if (keynote_ids[i] != -1) - kn_remove_assertion (isakmp_sa->policy_id, keynote_ids[i]); - } - - if (keynote_ids) - free (keynote_ids); - - if (x509_ids) - free (x509_ids); - - /* - * XXX Currently, check_policy() is only called from message_negotiate_sa(), - * and so this log message reflects this. Change to something better? - */ - if (result == 0) - log_print ("check_policy: negotiated SA failed policy check"); - - /* - * Given that we have only 2 return values from policy (true/false) - * we can just return the query result directly (no pre-processing needed). - */ - return result; + /* + * XXX Currently, check_policy() is only called from message_negotiate_sa(), + * and so this log message reflects this. Change to something better? + */ + if (result == 0) + log_print("check_policy: negotiated SA failed policy check"); + + /* + * Given that we have only 2 return values from policy (true/false) + * we can just return the query result directly (no pre-processing needed). + */ + return result; } -#endif /* USE_POLICY */ +#endif /* USE_POLICY */ /* * Offer several sets of transforms to the responder. * XXX Split this huge function up and look for common code with main mode. */ static int -initiator_send_HASH_SA_NONCE (struct message *msg) +initiator_send_HASH_SA_NONCE(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct doi *doi = exchange->doi; - struct ipsec_exch *ie = exchange->data; - u_int8_t ***transform = 0, ***new_transform; - u_int8_t **proposal = 0, **new_proposal; - u_int8_t *sa_buf = 0, *attr, *saved_nextp_sa, *saved_nextp_prop, *id, *spi; - size_t spi_sz, sz; - size_t proposal_len = 0, proposals_len = 0, sa_len; - size_t **transform_len = 0, **new_transform_len; - size_t *transforms_len = 0, *new_transforms_len; - u_int32_t *transform_cnt = 0, *new_transform_cnt; - u_int32_t suite_no, prop_no, prot_no, xf_no, prop_cnt = 0; - u_int32_t i; - int value, update_nextp, protocol_num, proto_id; - struct proto *proto; - struct conf_list *suite_conf, *prot_conf = 0, *xf_conf = 0, *life_conf; - struct conf_list_node *suite, *prot, *xf, *life; - struct constant_map *id_map; - char *protocol_id, *transform_id; - char *local_id, *remote_id; - int group_desc = -1, new_group_desc; - struct ipsec_sa *isa = msg->isakmp_sa->data; - struct hash *hash = hash_get (isa->hash); - struct sockaddr *src; - struct proto_attr *pa; - - if (!ipsec_add_hash_payload (msg, hash->hashsize)) - return -1; - - /* Get the list of protocol suites. */ - suite_conf = conf_get_list (exchange->policy, "Suites"); - if (!suite_conf) - return -1; - - for (suite = TAILQ_FIRST (&suite_conf->fields), suite_no = prop_no = 0; - suite_no < suite_conf->cnt; - suite_no++, suite = TAILQ_NEXT (suite, link)) - { - /* Now get each protocol in this specific protocol suite. */ - prot_conf = conf_get_list (suite->field, "Protocols"); - if (!prot_conf) - goto bail_out; - - for (prot = TAILQ_FIRST (&prot_conf->fields), prot_no = 0; - prot_no < prot_conf->cnt; - prot_no++, prot = TAILQ_NEXT (prot, link)) - { - /* Make sure we have a proposal/transform vectors. */ - if (prop_no >= prop_cnt) - { - /* This resize algorithm is completely arbitrary. */ - prop_cnt = 2 * prop_cnt + 10; - new_proposal = realloc (proposal, prop_cnt * sizeof *proposal); - if (!new_proposal) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "realloc (%p, %lu) failed", - proposal, - prop_cnt * (unsigned long)sizeof *proposal); - goto bail_out; - } - proposal = new_proposal; - - new_transforms_len = realloc (transforms_len, - prop_cnt * sizeof *transforms_len); - if (!new_transforms_len) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "realloc (%p, %lu) failed", - transforms_len, - prop_cnt * (unsigned long)sizeof *transforms_len); - goto bail_out; - } - transforms_len = new_transforms_len; - - new_transform = realloc (transform, - prop_cnt * sizeof *transform); - if (!new_transform) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "realloc (%p, %lu) failed", - transform, - prop_cnt * (unsigned long)sizeof *transform); - goto bail_out; - } - transform = new_transform; - - new_transform_cnt = realloc (transform_cnt, - prop_cnt * sizeof *transform_cnt); - if (!new_transform_cnt) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "realloc (%p, %lu) failed", - transform_cnt, - prop_cnt * (unsigned long)sizeof *transform_cnt); - goto bail_out; - } - transform_cnt = new_transform_cnt; - - new_transform_len = realloc (transform_len, - prop_cnt * sizeof *transform_len); - if (!new_transform_len) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "realloc (%p, %lu) failed", - transform_len, - prop_cnt * (unsigned long)sizeof *transform_len); - goto bail_out; - } - transform_len = new_transform_len; - } - - protocol_id = conf_get_str (prot->field, "PROTOCOL_ID"); - if (!protocol_id) - goto bail_out; - - proto_id = constant_value (ipsec_proto_cst, protocol_id); - switch (proto_id) - { - case IPSEC_PROTO_IPSEC_AH: - id_map = ipsec_ah_cst; - break; - - case IPSEC_PROTO_IPSEC_ESP: - id_map = ipsec_esp_cst; - break; - - case IPSEC_PROTO_IPCOMP: - id_map = ipsec_ipcomp_cst; - break; - - default: - { - log_print ("initiator_send_HASH_SA_NONCE: invalid PROTCOL_ID: " - "%s", protocol_id); - goto bail_out; - } - } - - /* Now get each transform we offer for this protocol. */ - xf_conf = conf_get_list (prot->field, "Transforms"); - if (!xf_conf) - goto bail_out; - transform_cnt[prop_no] = xf_conf->cnt; - - transform[prop_no] = calloc (transform_cnt[prop_no], - sizeof **transform); - if (!transform[prop_no]) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "calloc (%d, %lu) failed", - transform_cnt[prop_no], - (unsigned long)sizeof **transform); - goto bail_out; - } - - transform_len[prop_no] - = calloc (transform_cnt[prop_no], sizeof **transform_len); - if (!transform_len[prop_no]) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "calloc (%d, %lu) failed", - transform_cnt[prop_no], - (unsigned long)sizeof **transform_len); - goto bail_out; - } - - transforms_len[prop_no] = 0; - for (xf = TAILQ_FIRST (&xf_conf->fields), xf_no = 0; - xf_no < transform_cnt[prop_no]; - xf_no++, xf = TAILQ_NEXT (xf, link)) - { - - /* XXX The sizing needs to be dynamic. */ - transform[prop_no][xf_no] = calloc (ISAKMP_TRANSFORM_SA_ATTRS_OFF - + 9 * ISAKMP_ATTR_VALUE_OFF, - 1); - if (!transform[prop_no][xf_no]) - { - log_error ("initiator_send_HASH_SA_NONCE: " - "calloc (%d, 1) failed", - ISAKMP_TRANSFORM_SA_ATTRS_OFF - + 9 * ISAKMP_ATTR_VALUE_OFF); - goto bail_out; - } + struct exchange *exchange = msg->exchange; + struct doi *doi = exchange->doi; + struct ipsec_exch *ie = exchange->data; + u_int8_t ***transform = 0, ***new_transform; + u_int8_t **proposal = 0, **new_proposal; + u_int8_t *sa_buf = 0, *attr, *saved_nextp_sa, *saved_nextp_prop, + *id, *spi; + size_t spi_sz, sz; + size_t proposal_len = 0, proposals_len = 0, sa_len; + size_t **transform_len = 0, **new_transform_len; + size_t *transforms_len = 0, *new_transforms_len; + u_int32_t *transform_cnt = 0, *new_transform_cnt; + u_int32_t suite_no, prop_no, prot_no, xf_no, prop_cnt = 0; + u_int32_t i; + int value, update_nextp, protocol_num, proto_id; + struct proto *proto; + struct conf_list *suite_conf, *prot_conf = 0, *xf_conf = 0, *life_conf; + struct conf_list_node *suite, *prot, *xf, *life; + struct constant_map *id_map; + char *protocol_id, *transform_id; + char *local_id, *remote_id; + int group_desc = -1, new_group_desc; + struct ipsec_sa *isa = msg->isakmp_sa->data; + struct hash *hash = hash_get(isa->hash); + struct sockaddr *src; + struct proto_attr *pa; + + if (!ipsec_add_hash_payload(msg, hash->hashsize)) + return -1; + + /* Get the list of protocol suites. */ + suite_conf = conf_get_list(exchange->policy, "Suites"); + if (!suite_conf) + return -1; + + for (suite = TAILQ_FIRST(&suite_conf->fields), suite_no = prop_no = 0; + suite_no < suite_conf->cnt; + suite_no++, suite = TAILQ_NEXT(suite, link)) { + /* Now get each protocol in this specific protocol suite. */ + prot_conf = conf_get_list(suite->field, "Protocols"); + if (!prot_conf) + goto bail_out; + + for (prot = TAILQ_FIRST(&prot_conf->fields), prot_no = 0; + prot_no < prot_conf->cnt; + prot_no++, prot = TAILQ_NEXT(prot, link)) { + /* Make sure we have a proposal/transform vectors. */ + if (prop_no >= prop_cnt) { + /* + * This resize algorithm is completely + * arbitrary. + */ + prop_cnt = 2 * prop_cnt + 10; + new_proposal = realloc(proposal, + prop_cnt * sizeof *proposal); + if (!new_proposal) { + log_error("initiator_send_HASH_SA_NONCE: " + "realloc (%p, %lu) failed", + proposal, + prop_cnt * (unsigned long) sizeof *proposal); + goto bail_out; + } + proposal = new_proposal; + + new_transforms_len = realloc(transforms_len, + prop_cnt * sizeof *transforms_len); + if (!new_transforms_len) { + log_error("initiator_send_HASH_SA_NONCE: " + "realloc (%p, %lu) failed", + transforms_len, + prop_cnt * (unsigned long) sizeof *transforms_len); + goto bail_out; + } + transforms_len = new_transforms_len; + + new_transform = realloc(transform, + prop_cnt * sizeof *transform); + if (!new_transform) { + log_error("initiator_send_HASH_SA_NONCE: " + "realloc (%p, %lu) failed", + transform, + prop_cnt * (unsigned long) sizeof *transform); + goto bail_out; + } + transform = new_transform; + + new_transform_cnt = realloc(transform_cnt, + prop_cnt * sizeof *transform_cnt); + if (!new_transform_cnt) { + log_error("initiator_send_HASH_SA_NONCE: " + "realloc (%p, %lu) failed", + transform_cnt, + prop_cnt * (unsigned long) sizeof *transform_cnt); + goto bail_out; + } + transform_cnt = new_transform_cnt; + + new_transform_len = realloc(transform_len, + prop_cnt * sizeof *transform_len); + if (!new_transform_len) { + log_error("initiator_send_HASH_SA_NONCE: " + "realloc (%p, %lu) failed", + transform_len, + prop_cnt * (unsigned long) sizeof *transform_len); + goto bail_out; + } + transform_len = new_transform_len; + } + protocol_id = conf_get_str(prot->field, "PROTOCOL_ID"); + if (!protocol_id) + goto bail_out; + + proto_id = constant_value(ipsec_proto_cst, protocol_id); + switch (proto_id) { + case IPSEC_PROTO_IPSEC_AH: + id_map = ipsec_ah_cst; + break; + + case IPSEC_PROTO_IPSEC_ESP: + id_map = ipsec_esp_cst; + break; + + case IPSEC_PROTO_IPCOMP: + id_map = ipsec_ipcomp_cst; + break; + + default: + { + log_print("initiator_send_HASH_SA_NONCE: invalid PROTCOL_ID: " + "%s", protocol_id); + goto bail_out; + } + } + + /* Now get each transform we offer for this protocol. */ + xf_conf = conf_get_list(prot->field, "Transforms"); + if (!xf_conf) + goto bail_out; + transform_cnt[prop_no] = xf_conf->cnt; + + transform[prop_no] = calloc(transform_cnt[prop_no], + sizeof **transform); + if (!transform[prop_no]) { + log_error("initiator_send_HASH_SA_NONCE: " + "calloc (%d, %lu) failed", + transform_cnt[prop_no], + (unsigned long) sizeof **transform); + goto bail_out; + } + transform_len[prop_no] = calloc(transform_cnt[prop_no], + sizeof **transform_len); + if (!transform_len[prop_no]) { + log_error("initiator_send_HASH_SA_NONCE: " + "calloc (%d, %lu) failed", + transform_cnt[prop_no], + (unsigned long) sizeof **transform_len); + goto bail_out; + } + transforms_len[prop_no] = 0; + for (xf = TAILQ_FIRST(&xf_conf->fields), xf_no = 0; + xf_no < transform_cnt[prop_no]; + xf_no++, xf = TAILQ_NEXT(xf, link)) { + + /* XXX The sizing needs to be dynamic. */ + transform[prop_no][xf_no] = + calloc(ISAKMP_TRANSFORM_SA_ATTRS_OFF + + 9 * ISAKMP_ATTR_VALUE_OFF, 1); + if (!transform[prop_no][xf_no]) { + log_error("initiator_send_HASH_SA_NONCE: " + "calloc (%d, 1) failed", + ISAKMP_TRANSFORM_SA_ATTRS_OFF + + 9 * ISAKMP_ATTR_VALUE_OFF); + goto bail_out; + } + SET_ISAKMP_TRANSFORM_NO(transform[prop_no][xf_no], + xf_no + 1); + + transform_id = conf_get_str(xf->field, "TRANSFORM_ID"); + if (!transform_id) + goto bail_out; + SET_ISAKMP_TRANSFORM_ID(transform[prop_no][xf_no], + constant_value(id_map, transform_id)); + SET_ISAKMP_TRANSFORM_RESERVED(transform[prop_no][xf_no], 0); + + attr = transform[prop_no][xf_no] + ISAKMP_TRANSFORM_SA_ATTRS_OFF; + + /* + * Life durations are special, we should be able to specify + * several, one per type. + */ + life_conf = conf_get_list(xf->field, "Life"); + if (life_conf) { + for (life = TAILQ_FIRST(&life_conf->fields); life; + life = TAILQ_NEXT(life, link)) { + attribute_set_constant(life->field, "LIFE_TYPE", + ipsec_duration_cst, + IPSEC_ATTR_SA_LIFE_TYPE, &attr); + + /* + * XXX Deals with 16 and 32 + * bit lifetimes only + */ + value = conf_get_num(life->field, "LIFE_DURATION", 0); + if (value) { + if (value <= 0xffff) + attr = + attribute_set_basic(attr, + IPSEC_ATTR_SA_LIFE_DURATION, + value); + else { + value = htonl(value); + attr = + attribute_set_var(attr, + IPSEC_ATTR_SA_LIFE_DURATION, + (u_int8_t *) & value, + sizeof value); + } + } + } + conf_free_list(life_conf); + } + attribute_set_constant(xf->field, "ENCAPSULATION_MODE", + ipsec_encap_cst, + IPSEC_ATTR_ENCAPSULATION_MODE, &attr); - SET_ISAKMP_TRANSFORM_NO (transform[prop_no][xf_no], xf_no + 1); + if (proto_id != IPSEC_PROTO_IPCOMP) { + attribute_set_constant(xf->field, + "AUTHENTICATION_ALGORITHM", + ipsec_auth_cst, + IPSEC_ATTR_AUTHENTICATION_ALGORITHM, + &attr); + + attribute_set_constant(xf->field, "GROUP_DESCRIPTION", + ike_group_desc_cst, + IPSEC_ATTR_GROUP_DESCRIPTION, &attr); + + value = conf_get_num(xf->field, "KEY_LENGTH", 0); + if (value) + attr = attribute_set_basic(attr, IPSEC_ATTR_KEY_LENGTH, + value); + + value = conf_get_num(xf->field, "KEY_ROUNDS", 0); + if (value) + attr = attribute_set_basic(attr, IPSEC_ATTR_KEY_ROUNDS, + value); + } else { + value = conf_get_num(xf->field, "COMPRESS_DICTIONARY_SIZE", + 0); + if (value) + attr = attribute_set_basic(attr, + IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE, + value); + + value = conf_get_num(xf->field, + "COMPRESS_PRIVATE_ALGORITHM", 0); + if (value) + attr = attribute_set_basic(attr, + IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM, + value); + } + + value = conf_get_num(xf->field, "ECN_TUNNEL", 0); + if (value) + attr = attribute_set_basic(attr, IPSEC_ATTR_ECN_TUNNEL, + value); + + /* Record the real transform size. */ + transforms_len[prop_no] += (transform_len[prop_no][xf_no] + = attr - transform[prop_no][xf_no]); + + if (proto_id != IPSEC_PROTO_IPCOMP) { + /* + * Make sure that if a group description is specified, it is + * specified for all transforms equally. + */ + attr = (u_int8_t *) conf_get_str(xf->field, + "GROUP_DESCRIPTION"); + new_group_desc + = attr ? constant_value(ike_group_desc_cst, + (char *) attr) : 0; + if (group_desc == -1) + group_desc = new_group_desc; + else if (group_desc != new_group_desc) { + log_print("initiator_send_HASH_SA_NONCE: " + "differing group descriptions in a proposal"); + goto bail_out; + } + } + } + conf_free_list(xf_conf); + xf_conf = 0; + + /* + * Get SPI from application. + * XXX Should we care about unknown constants? + */ + protocol_num = constant_value(ipsec_proto_cst, protocol_id); + spi = doi->get_spi(&spi_sz, protocol_num, msg); + if (spi_sz && !spi) { + log_print("initiator_send_HASH_SA_NONCE: doi->get_spi failed"); + goto bail_out; + } + proposal_len = ISAKMP_PROP_SPI_OFF + spi_sz; + proposals_len += proposal_len + transforms_len[prop_no]; + proposal[prop_no] = malloc(proposal_len); + if (!proposal[prop_no]) { + log_error("initiator_send_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) proposal_len); + goto bail_out; + } + SET_ISAKMP_PROP_NO(proposal[prop_no], suite_no + 1); + SET_ISAKMP_PROP_PROTO(proposal[prop_no], protocol_num); + + /* XXX I would like to see this factored out. */ + proto = calloc(1, sizeof *proto); + if (!proto) { + log_error("initiator_send_HASH_SA_NONCE: calloc (1, %lu) " + "failed", (unsigned long) sizeof *proto); + goto bail_out; + } + if (doi->proto_size) { + proto->data = calloc(1, doi->proto_size); + if (!proto->data) { + log_error("initiator_send_HASH_SA_NONCE: calloc (1, %lu) " + "failed", (unsigned long) doi->proto_size); + goto bail_out; + } + } + proto->no = suite_no + 1; + proto->proto = protocol_num; + proto->sa = TAILQ_FIRST(&exchange->sa_list); + proto->xf_cnt = transform_cnt[prop_no]; + TAILQ_INIT(&proto->xfs); + for (xf_no = 0; xf_no < proto->xf_cnt; xf_no++) { + pa = (struct proto_attr *) calloc(1, sizeof *pa); + if (!pa) + goto bail_out; + pa->len = transform_len[prop_no][xf_no]; + pa->attrs = (u_int8_t *) malloc(pa->len); + if (!pa->attrs) { + free(pa); + goto bail_out; + } + memcpy(pa->attrs, transform[prop_no][xf_no], pa->len); + TAILQ_INSERT_TAIL(&proto->xfs, pa, next); + } + TAILQ_INSERT_TAIL(&TAILQ_FIRST(&exchange->sa_list)->protos, proto, + link); + + /* Setup the incoming SPI. */ + SET_ISAKMP_PROP_SPI_SZ(proposal[prop_no], spi_sz); + memcpy(proposal[prop_no] + ISAKMP_PROP_SPI_OFF, spi, spi_sz); + proto->spi_sz[1] = spi_sz; + proto->spi[1] = spi; + + /* + * Let the DOI get at proto for initializing its own + * data. + */ + if (doi->proto_init) + doi->proto_init(proto, prot->field); + + SET_ISAKMP_PROP_NTRANSFORMS(proposal[prop_no], + transform_cnt[prop_no]); + prop_no++; + } + conf_free_list(prot_conf); + prot_conf = 0; + } - transform_id = conf_get_str (xf->field, "TRANSFORM_ID"); - if (!transform_id) + sa_len = ISAKMP_SA_SIT_OFF + IPSEC_SIT_SIT_LEN; + sa_buf = malloc(sa_len); + if (!sa_buf) { + log_error("initiator_send_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) sa_len); + goto bail_out; + } + SET_ISAKMP_SA_DOI(sa_buf, IPSEC_DOI_IPSEC); + SET_IPSEC_SIT_SIT(sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY); + + /* + * Add the payloads. As this is a SA, we need to recompute the + * lengths of the payloads containing others. We also need to + * reset these payload's "next payload type" field. + */ + if (message_add_payload(msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1)) goto bail_out; - SET_ISAKMP_TRANSFORM_ID (transform[prop_no][xf_no], - constant_value (id_map, transform_id)); - SET_ISAKMP_TRANSFORM_RESERVED (transform[prop_no][xf_no], 0); - - attr = transform[prop_no][xf_no] + ISAKMP_TRANSFORM_SA_ATTRS_OFF; - - /* - * Life durations are special, we should be able to specify - * several, one per type. - */ - life_conf = conf_get_list (xf->field, "Life"); - if (life_conf) - { - for (life = TAILQ_FIRST (&life_conf->fields); life; - life = TAILQ_NEXT (life, link)) - { - attribute_set_constant (life->field, "LIFE_TYPE", - ipsec_duration_cst, - IPSEC_ATTR_SA_LIFE_TYPE, &attr); - - /* XXX Deals with 16 and 32 bit lifetimes only */ - value = conf_get_num (life->field, "LIFE_DURATION", 0); - if (value) - { - if (value <= 0xffff) - attr = - attribute_set_basic (attr, - IPSEC_ATTR_SA_LIFE_DURATION, - value); - else - { - value = htonl (value); - attr = - attribute_set_var (attr, - IPSEC_ATTR_SA_LIFE_DURATION, - (u_int8_t *)&value, - sizeof value); - } - } - } - conf_free_list (life_conf); + SET_ISAKMP_GEN_LENGTH(sa_buf, sa_len + proposals_len); + sa_buf = 0; + + update_nextp = 0; + saved_nextp_sa = msg->nextp; + for (i = 0; i < prop_no; i++) { + if (message_add_payload(msg, ISAKMP_PAYLOAD_PROPOSAL, proposal[i], + proposal_len, update_nextp)) + goto bail_out; + SET_ISAKMP_GEN_LENGTH(proposal[i], proposal_len + transforms_len[i]); + proposal[i] = 0; + + update_nextp = 0; + saved_nextp_prop = msg->nextp; + for (xf_no = 0; xf_no < transform_cnt[i]; xf_no++) { + if (message_add_payload(msg, ISAKMP_PAYLOAD_TRANSFORM, + transform[i][xf_no], + transform_len[i][xf_no], update_nextp)) + goto bail_out; + update_nextp = 1; + transform[i][xf_no] = 0; } + msg->nextp = saved_nextp_prop; + update_nextp = 1; + } + msg->nextp = saved_nextp_sa; - attribute_set_constant (xf->field, "ENCAPSULATION_MODE", - ipsec_encap_cst, - IPSEC_ATTR_ENCAPSULATION_MODE, &attr); - - if (proto_id != IPSEC_PROTO_IPCOMP) - { - attribute_set_constant (xf->field, - "AUTHENTICATION_ALGORITHM", - ipsec_auth_cst, - IPSEC_ATTR_AUTHENTICATION_ALGORITHM, - &attr); - - attribute_set_constant (xf->field, "GROUP_DESCRIPTION", - ike_group_desc_cst, - IPSEC_ATTR_GROUP_DESCRIPTION, &attr); - - value = conf_get_num (xf->field, "KEY_LENGTH", 0); - if (value) - attr = attribute_set_basic (attr, IPSEC_ATTR_KEY_LENGTH, - value); - - value = conf_get_num (xf->field, "KEY_ROUNDS", 0); - if (value) - attr = attribute_set_basic (attr, IPSEC_ATTR_KEY_ROUNDS, - value); - } - else - { - value = conf_get_num (xf->field, "COMPRESS_DICTIONARY_SIZE", - 0); - if (value) - attr = attribute_set_basic (attr, - IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE, - value); - - value = conf_get_num (xf->field, - "COMPRESS_PRIVATE_ALGORITHM", 0); - if (value) - attr = attribute_set_basic (attr, - IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM, - value); - } + /* + * Save SA payload body in ie->sa_i_b, length ie->sa_i_b_len. + */ + ie->sa_i_b = message_copy(msg, ISAKMP_GEN_SZ, &ie->sa_i_b_len); + if (!ie->sa_i_b) + goto bail_out; - value = conf_get_num (xf->field, "ECN_TUNNEL", 0); - if (value) - attr = attribute_set_basic (attr, IPSEC_ATTR_ECN_TUNNEL, - value); - - /* Record the real transform size. */ - transforms_len[prop_no] += (transform_len[prop_no][xf_no] - = attr - transform[prop_no][xf_no]); - - if (proto_id != IPSEC_PROTO_IPCOMP) - { - /* - * Make sure that if a group description is specified, it is - * specified for all transforms equally. - */ - attr = (u_int8_t *)conf_get_str (xf->field, - "GROUP_DESCRIPTION"); - new_group_desc - = attr ? constant_value (ike_group_desc_cst, - (char *)attr) : 0; - if (group_desc == -1) - group_desc = new_group_desc; - else if (group_desc != new_group_desc) - { - log_print ("initiator_send_HASH_SA_NONCE: " - "differing group descriptions in a proposal"); - goto bail_out; - } + /* + * Generate a nonce, and add it to the message. + * XXX I want a better way to specify the nonce's size. + */ + if (exchange_gen_nonce(msg, 16)) + return -1; + + /* Generate optional KEY_EXCH payload. */ + if (group_desc > 0) { + ie->group = group_get(group_desc); + ie->g_x_len = dh_getlen(ie->group); + + if (ipsec_gen_g_x(msg)) { + group_free(ie->group); + ie->group = 0; + return -1; } - } - conf_free_list (xf_conf); - xf_conf = 0; - - /* - * Get SPI from application. - * XXX Should we care about unknown constants? - */ - protocol_num = constant_value (ipsec_proto_cst, protocol_id); - spi = doi->get_spi (&spi_sz, protocol_num, msg); - if (spi_sz && !spi) - { - log_print ("initiator_send_HASH_SA_NONCE: doi->get_spi failed"); - goto bail_out; - } - - proposal_len = ISAKMP_PROP_SPI_OFF + spi_sz; - proposals_len += proposal_len + transforms_len[prop_no]; - proposal[prop_no] = malloc (proposal_len); - if (!proposal[prop_no]) - { - log_error ("initiator_send_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)proposal_len); - goto bail_out; - } - - SET_ISAKMP_PROP_NO (proposal[prop_no], suite_no + 1); - SET_ISAKMP_PROP_PROTO (proposal[prop_no], protocol_num); - - /* XXX I would like to see this factored out. */ - proto = calloc (1, sizeof *proto); - if (!proto) - { - log_error ("initiator_send_HASH_SA_NONCE: calloc (1, %lu) " - "failed", (unsigned long)sizeof *proto); - goto bail_out; - } - - if (doi->proto_size) - { - proto->data = calloc (1, doi->proto_size); - if (!proto->data) - { - log_error ("initiator_send_HASH_SA_NONCE: calloc (1, %lu) " - "failed", (unsigned long)doi->proto_size); - goto bail_out; + } + /* Generate optional client ID payloads. XXX Share with responder. */ + local_id = conf_get_str(exchange->name, "Local-ID"); + remote_id = conf_get_str(exchange->name, "Remote-ID"); + if (local_id && remote_id) { + id = ipsec_build_id(local_id, &sz); + if (!id) + return -1; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic", + id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; } - } - - proto->no = suite_no + 1; - proto->proto = protocol_num; - proto->sa = TAILQ_FIRST (&exchange->sa_list); - proto->xf_cnt = transform_cnt[prop_no]; - TAILQ_INIT (&proto->xfs); - for (xf_no = 0; xf_no < proto->xf_cnt; xf_no++) - { - pa = (struct proto_attr *)calloc (1, sizeof *pa); - if (!pa) - goto bail_out; - pa->len = transform_len[prop_no][xf_no]; - pa->attrs = (u_int8_t *)malloc (pa->len); - if (!pa->attrs) - { - free (pa); - goto bail_out; + id = ipsec_build_id(remote_id, &sz); + if (!id) + return -1; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc", + id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; } - memcpy (pa->attrs, transform[prop_no][xf_no], pa->len); - TAILQ_INSERT_TAIL (&proto->xfs, pa, next); - } - TAILQ_INSERT_TAIL (&TAILQ_FIRST (&exchange->sa_list)->protos, proto, - link); - - /* Setup the incoming SPI. */ - SET_ISAKMP_PROP_SPI_SZ (proposal[prop_no], spi_sz); - memcpy (proposal[prop_no] + ISAKMP_PROP_SPI_OFF, spi, spi_sz); - proto->spi_sz[1] = spi_sz; - proto->spi[1] = spi; - - /* Let the DOI get at proto for initializing its own data. */ - if (doi->proto_init) - doi->proto_init (proto, prot->field); - - SET_ISAKMP_PROP_NTRANSFORMS (proposal[prop_no], - transform_cnt[prop_no]); - prop_no++; - } - conf_free_list (prot_conf); - prot_conf = 0; - } - - sa_len = ISAKMP_SA_SIT_OFF + IPSEC_SIT_SIT_LEN; - sa_buf = malloc (sa_len); - if (!sa_buf) - { - log_error ("initiator_send_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)sa_len); - goto bail_out; - } - SET_ISAKMP_SA_DOI (sa_buf, IPSEC_DOI_IPSEC); - SET_IPSEC_SIT_SIT (sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY); - - /* - * Add the payloads. As this is a SA, we need to recompute the - * lengths of the payloads containing others. We also need to - * reset these payload's "next payload type" field. - */ - if (message_add_payload (msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1)) - goto bail_out; - SET_ISAKMP_GEN_LENGTH (sa_buf, sa_len + proposals_len); - sa_buf = 0; - - update_nextp = 0; - saved_nextp_sa = msg->nextp; - for (i = 0; i < prop_no; i++) - { - if (message_add_payload (msg, ISAKMP_PAYLOAD_PROPOSAL, proposal[i], - proposal_len, update_nextp)) - goto bail_out; - SET_ISAKMP_GEN_LENGTH (proposal[i], proposal_len + transforms_len[i]); - proposal[i] = 0; - - update_nextp = 0; - saved_nextp_prop = msg->nextp; - for (xf_no = 0; xf_no < transform_cnt[i]; xf_no++) - { - if (message_add_payload (msg, ISAKMP_PAYLOAD_TRANSFORM, - transform[i][xf_no], - transform_len[i][xf_no], update_nextp)) - goto bail_out; - update_nextp = 1; - transform[i][xf_no] = 0; - } - msg->nextp = saved_nextp_prop; - update_nextp = 1; - } - msg->nextp = saved_nextp_sa; - - /* - * Save SA payload body in ie->sa_i_b, length ie->sa_i_b_len. - */ - ie->sa_i_b = message_copy (msg, ISAKMP_GEN_SZ, &ie->sa_i_b_len); - if (!ie->sa_i_b) - goto bail_out; - - /* - * Generate a nonce, and add it to the message. - * XXX I want a better way to specify the nonce's size. - */ - if (exchange_gen_nonce (msg, 16)) - return -1; - - /* Generate optional KEY_EXCH payload. */ - if (group_desc > 0) - { - ie->group = group_get (group_desc); - ie->g_x_len = dh_getlen (ie->group); - - if (ipsec_gen_g_x (msg)) - { - group_free (ie->group); - ie->group = 0; - return -1; - } - } - - /* Generate optional client ID payloads. XXX Share with responder. */ - local_id = conf_get_str (exchange->name, "Local-ID"); - remote_id = conf_get_str (exchange->name, "Remote-ID"); - if (local_id && remote_id) - { - id = ipsec_build_id (local_id, &sz); - if (!id) - return -1; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic", - id, sz)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) - { - free (id); - return -1; - } - - id = ipsec_build_id (remote_id, &sz); - if (!id) - return -1; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc", - id, sz)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) - { - free (id); - return -1; } - } - /* XXX I do not judge these as errors, are they? */ - else if (local_id) - log_print ("initiator_send_HASH_SA_NONCE: " - "Local-ID given without Remote-ID for \"%s\"", - exchange->name); - else if (remote_id) - /* This code supports the "road warrior" case, where the initiator doesn't - * have a fixed IP address, but wants to specify a particular remote - * network to talk to. - * -- Adrian Close <adrian@esec.com.au> - */ - { - log_print ("initiator_send_HASH_SA_NONCE: " - "Remote-ID given without Local-ID for \"%s\"", - exchange->name); - - /* If we're here, then we are the initiator, so use initiator - address for local ID */ - msg->transport->vtbl->get_src (msg->transport, &src); - sz = ISAKMP_ID_SZ + sockaddr_addrlen (src); - - id = calloc (sz, sizeof (char)); - if (!id) + /* XXX I do not judge these as errors, are they? */ + else if (local_id) + log_print("initiator_send_HASH_SA_NONCE: " + "Local-ID given without Remote-ID for \"%s\"", + exchange->name); + else if (remote_id) + /* + * This code supports the "road warrior" case, where the + * initiator doesn't have a fixed IP address, but wants to + * specify a particular remote network to talk to. -- Adrian + * Close <adrian@esec.com.au> + */ { - log_error ("initiator_send_HASH_SA_NONCE: calloc (%lu, %lu) failed", - (unsigned long)sz, (unsigned long)sizeof (char)); - return -1; + log_print("initiator_send_HASH_SA_NONCE: " + "Remote-ID given without Local-ID for \"%s\"", + exchange->name); + + /* + * If we're here, then we are the initiator, so use initiator + * address for local ID + */ + msg->transport->vtbl->get_src(msg->transport, &src); + sz = ISAKMP_ID_SZ + sockaddr_addrlen(src); + + id = calloc(sz, sizeof(char)); + if (!id) { + log_error("initiator_send_HASH_SA_NONCE: calloc (%lu, %lu) failed", + (unsigned long) sz, (unsigned long) sizeof(char)); + return -1; + } + switch (src->sa_family) { + case AF_INET6: + SET_ISAKMP_ID_TYPE(id, IPSEC_ID_IPV6_ADDR); + break; + case AF_INET: + SET_ISAKMP_ID_TYPE(id, IPSEC_ID_IPV4_ADDR); + break; + default: + log_error("initiator_send_HASH_SA_NONCE: unknown sa_family %d", + src->sa_family); + free(id); + return -1; + } + memcpy(id + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(src), + sockaddr_addrlen(src)); + + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic", + id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; + } + /* Send supplied remote_id */ + id = ipsec_build_id(remote_id, &sz); + if (!id) + return -1; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc", + id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; + } } + if (ipsec_fill_in_hash(msg)) + goto bail_out; - switch (src->sa_family) - { - case AF_INET6: - SET_ISAKMP_ID_TYPE (id, IPSEC_ID_IPV6_ADDR); - break; - case AF_INET: - SET_ISAKMP_ID_TYPE (id, IPSEC_ID_IPV4_ADDR); - break; - default: - log_error ("initiator_send_HASH_SA_NONCE: unknown sa_family %d", - src->sa_family); - free (id); - return -1; + conf_free_list(suite_conf); + for (i = 0; i < prop_no; i++) { + free(transform[i]); + free(transform_len[i]); } - memcpy (id + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src), - sockaddr_addrlen (src)); - - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDic", - id, sz)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) - { - free (id); - return -1; + free(proposal); + free(transform); + free(transforms_len); + free(transform_len); + free(transform_cnt); + return 0; + +bail_out: + if (sa_buf) + free(sa_buf); + if (proposal) { + for (i = 0; i < prop_no; i++) { + if (proposal[i]) + free(proposal[i]); + if (transform[i]) { + for (xf_no = 0; xf_no < transform_cnt[i]; xf_no++) + if (transform[i][xf_no]) + free(transform[i][xf_no]); + free(transform[i]); + } + if (transform_len[i]) + free(transform_len[i]); + } + free(proposal); + free(transforms_len); + free(transform); + free(transform_len); + free(transform_cnt); } - - /* Send supplied remote_id */ - id = ipsec_build_id (remote_id, &sz); - if (!id) + if (xf_conf) + conf_free_list(xf_conf); + if (prot_conf) + conf_free_list(prot_conf); + conf_free_list(suite_conf); return -1; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH_SA_NONCE: IDrc", - id, sz)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) - { - free (id); - return -1; - } - } - - if (ipsec_fill_in_hash (msg)) - goto bail_out; - - conf_free_list (suite_conf); - for (i = 0; i < prop_no; i++) - { - free (transform[i]); - free (transform_len[i]); - } - free (proposal); - free (transform); - free (transforms_len); - free (transform_len); - free (transform_cnt); - return 0; - - bail_out: - if (sa_buf) - free (sa_buf); - if (proposal) - { - for (i = 0; i < prop_no; i++) - { - if (proposal[i]) - free (proposal[i]); - if (transform[i]) - { - for (xf_no = 0; xf_no < transform_cnt[i]; xf_no++) - if (transform[i][xf_no]) - free (transform[i][xf_no]); - free (transform[i]); - } - if (transform_len[i]) - free (transform_len[i]); - } - free (proposal); - free (transforms_len); - free (transform); - free (transform_len); - free (transform_cnt); - } - if (xf_conf) - conf_free_list (xf_conf); - if (prot_conf) - conf_free_list (prot_conf); - conf_free_list (suite_conf); - return -1; } /* Figure out what transform the responder chose. */ static int -initiator_recv_HASH_SA_NONCE (struct message *msg) +initiator_recv_HASH_SA_NONCE(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct sa *sa; - struct proto *proto, *next_proto; - struct payload *sa_p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA]); - struct payload *xf, *idp; - struct payload *hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - struct payload *kep = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]); - struct prf *prf; - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct hash *hash = hash_get (isa->hash); - size_t hashsize = hash->hashsize; - u_int8_t *rest; - size_t rest_len; - struct sockaddr *src, *dst; - - /* Allocate the prf and start calculating our HASH(1). XXX Share? */ - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: SKEYID_a", - (u_int8_t *)isa->skeyid_a, isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); - if (!prf) - return -1; - - prf->Init (prf->prfctx); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "initiator_recv_HASH_SA_NONCE: message_id", - exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: NONCE_I_b", - exchange->nonce_i, exchange->nonce_i_len)); - prf->Update (prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); - rest = hashp->p + GET_ISAKMP_GEN_LENGTH (hashp->p); - rest_len = (GET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base) - - (rest - (u_int8_t*)msg->iov[0].iov_base)); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "initiator_recv_HASH_SA_NONCE: payloads after HASH(2)", rest, - rest_len)); - prf->Update (prf->prfctx, rest, rest_len); - prf->Final (hash->digest, prf->prfctx); - prf_free (prf); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, - "initiator_recv_HASH_SA_NONCE: computed HASH(2)", - hash->digest, hashsize)); - if (memcmp (hashp->p + ISAKMP_HASH_DATA_OFF, hash->digest, hashsize) != 0) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); - return -1; - } - /* Mark the HASH as handled. */ - hashp->flags |= PL_MARK; - - /* - * As we are getting an answer on our transform offer, only one transform - * should be given. - * - * XXX Currently we only support negotiating one SA per quick mode run. - */ - if (TAILQ_NEXT (sa_p, link)) - { - log_print ("initiator_recv_HASH_SA_NONCE: " - "multiple SA payloads in quick mode not supported yet"); - return -1; - } - - sa = TAILQ_FIRST (&exchange->sa_list); - - /* This is here for the policy check */ - if (kep) - ie->pfs = 1; - - /* Handle optional client ID payloads. */ - idp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ID]); - if (idp) - { - /* If IDci is there, IDcr must be too. */ - if (!TAILQ_NEXT (idp, link)) - { - /* XXX Is this a good notify type? */ - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct sa *sa; + struct proto *proto, *next_proto; + struct payload *sa_p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SA]); + struct payload *xf, *idp; + struct payload *hashp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + struct payload *kep = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]); + struct prf *prf; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct hash *hash = hash_get(isa->hash); + size_t hashsize = hash->hashsize; + u_int8_t *rest; + size_t rest_len; + struct sockaddr *src, *dst; + + /* Allocate the prf and start calculating our HASH(1). XXX Share? */ + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: SKEYID_a", + (u_int8_t *) isa->skeyid_a, isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); + if (!prf) + return -1; + + prf->Init(prf->prfctx); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "initiator_recv_HASH_SA_NONCE: message_id", + exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_recv_HASH_SA_NONCE: NONCE_I_b", + exchange->nonce_i, exchange->nonce_i_len)); + prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); + rest = hashp->p + GET_ISAKMP_GEN_LENGTH(hashp->p); + rest_len = (GET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base) + - (rest - (u_int8_t *) msg->iov[0].iov_base)); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "initiator_recv_HASH_SA_NONCE: payloads after HASH(2)", rest, + rest_len)); + prf->Update(prf->prfctx, rest, rest_len); + prf->Final(hash->digest, prf->prfctx); + prf_free(prf); + LOG_DBG_BUF((LOG_NEGOTIATION, 80, + "initiator_recv_HASH_SA_NONCE: computed HASH(2)", + hash->digest, hashsize)); + if (memcmp(hashp->p + ISAKMP_HASH_DATA_OFF, hash->digest, hashsize) != 0) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + return -1; } - - /* XXX We should really compare, not override. */ - ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH (idp->p); - ie->id_ci = malloc (ie->id_ci_sz); - if (!ie->id_ci) - { - log_error ("initiator_recv_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)ie->id_ci_sz); - return -1; - } - memcpy (ie->id_ci, idp->p, ie->id_ci_sz); - idp->flags |= PL_MARK; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "initiator_recv_HASH_SA_NONCE: IDci", - ie->id_ci + ISAKMP_GEN_SZ, ie->id_ci_sz - - ISAKMP_GEN_SZ)); - - idp = TAILQ_NEXT (idp, link); - ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH (idp->p); - ie->id_cr = malloc (ie->id_cr_sz); - if (!ie->id_cr) - { - log_error ("initiator_recv_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)ie->id_cr_sz); - return -1; - } - memcpy (ie->id_cr, idp->p, ie->id_cr_sz); - idp->flags |= PL_MARK; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "initiator_recv_HASH_SA_NONCE: IDcr", - ie->id_cr + ISAKMP_GEN_SZ, ie->id_cr_sz - - ISAKMP_GEN_SZ)); - } - else - { - /* - * If client identifiers are not present in the exchange, - * we fake them. RFC 2409 states: - * The identities of the SAs negotiated in Quick Mode are - * implicitly assumed to be the IP addresses of the ISAKMP - * peers, without any constraints on the protocol or port - * numbers allowed, unless client identifiers are specified - * in Quick Mode. - * - * -- Michael Paddon (mwp@aba.net.au) - */ - - ie->flags = IPSEC_EXCH_FLAG_NO_ID; - - /* Get initiator and responder addresses. */ - msg->transport->vtbl->get_src (msg->transport, &src); - msg->transport->vtbl->get_dst (msg->transport, &dst); - ie->id_ci_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen (src); - ie->id_cr_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen (dst); - ie->id_ci = calloc (ie->id_ci_sz, sizeof (char)); - ie->id_cr = calloc (ie->id_cr_sz, sizeof (char)); - - if (!ie->id_ci || !ie->id_cr) - { - log_error ("initiator_recv_HASH_SA_NONCE: calloc (%lu, %lu) failed", - (unsigned long)ie->id_cr_sz, (unsigned long)sizeof (char)); - if (ie->id_ci) - { - free (ie->id_ci); - ie->id_ci = 0; - } - if (ie->id_cr) - { - free (ie->id_cr); - ie->id_cr = 0; - } - return -1; + /* Mark the HASH as handled. */ + hashp->flags |= PL_MARK; + + /* + * As we are getting an answer on our transform offer, only one transform + * should be given. + * + * XXX Currently we only support negotiating one SA per quick mode run. + */ + if (TAILQ_NEXT(sa_p, link)) { + log_print("initiator_recv_HASH_SA_NONCE: " + "multiple SA payloads in quick mode not supported yet"); + return -1; } - - if (src->sa_family != dst->sa_family) - { - log_error ("initiator_recv_HASH_SA_NONCE: sa_family mismatch"); - free (ie->id_ci); - ie->id_ci = 0; - free (ie->id_cr); - ie->id_cr = 0; - return -1; + sa = TAILQ_FIRST(&exchange->sa_list); + + /* This is here for the policy check */ + if (kep) + ie->pfs = 1; + + /* Handle optional client ID payloads. */ + idp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_ID]); + if (idp) { + /* If IDci is there, IDcr must be too. */ + if (!TAILQ_NEXT(idp, link)) { + /* XXX Is this a good notify type? */ + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + /* XXX We should really compare, not override. */ + ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH(idp->p); + ie->id_ci = malloc(ie->id_ci_sz); + if (!ie->id_ci) { + log_error("initiator_recv_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) ie->id_ci_sz); + return -1; + } + memcpy(ie->id_ci, idp->p, ie->id_ci_sz); + idp->flags |= PL_MARK; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "initiator_recv_HASH_SA_NONCE: IDci", + ie->id_ci + ISAKMP_GEN_SZ, ie->id_ci_sz + - ISAKMP_GEN_SZ)); + + idp = TAILQ_NEXT(idp, link); + ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH(idp->p); + ie->id_cr = malloc(ie->id_cr_sz); + if (!ie->id_cr) { + log_error("initiator_recv_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) ie->id_cr_sz); + return -1; + } + memcpy(ie->id_cr, idp->p, ie->id_cr_sz); + idp->flags |= PL_MARK; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "initiator_recv_HASH_SA_NONCE: IDcr", + ie->id_cr + ISAKMP_GEN_SZ, ie->id_cr_sz + - ISAKMP_GEN_SZ)); + } else { + /* + * If client identifiers are not present in the exchange, + * we fake them. RFC 2409 states: + * The identities of the SAs negotiated in Quick Mode are + * implicitly assumed to be the IP addresses of the ISAKMP + * peers, without any constraints on the protocol or port + * numbers allowed, unless client identifiers are specified + * in Quick Mode. + * + * -- Michael Paddon (mwp@aba.net.au) + */ + + ie->flags = IPSEC_EXCH_FLAG_NO_ID; + + /* Get initiator and responder addresses. */ + msg->transport->vtbl->get_src(msg->transport, &src); + msg->transport->vtbl->get_dst(msg->transport, &dst); + ie->id_ci_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen(src); + ie->id_cr_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen(dst); + ie->id_ci = calloc(ie->id_ci_sz, sizeof(char)); + ie->id_cr = calloc(ie->id_cr_sz, sizeof(char)); + + if (!ie->id_ci || !ie->id_cr) { + log_error("initiator_recv_HASH_SA_NONCE: calloc (%lu, %lu) failed", + (unsigned long) ie->id_cr_sz, (unsigned long) sizeof(char)); + if (ie->id_ci) { + free(ie->id_ci); + ie->id_ci = 0; + } + if (ie->id_cr) { + free(ie->id_cr); + ie->id_cr = 0; + } + return -1; + } + if (src->sa_family != dst->sa_family) { + log_error("initiator_recv_HASH_SA_NONCE: sa_family mismatch"); + free(ie->id_ci); + ie->id_ci = 0; + free(ie->id_cr); + ie->id_cr = 0; + return -1; + } + switch (src->sa_family) { + case AF_INET: + SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV4_ADDR); + SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV4_ADDR); + break; + + case AF_INET6: + SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV6_ADDR); + SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV6_ADDR); + break; + + default: + log_error("initiator_recv_HASH_SA_NONCE: unknown sa_family %d", + src->sa_family); + free(ie->id_ci); + ie->id_ci = 0; + free(ie->id_cr); + ie->id_cr = 0; + return -1; + } + memcpy(ie->id_ci + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(src), + sockaddr_addrlen(src)); + memcpy(ie->id_cr + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(dst), + sockaddr_addrlen(dst)); } - switch (src->sa_family) - { - case AF_INET: - SET_ISAKMP_ID_TYPE (ie->id_ci, IPSEC_ID_IPV4_ADDR); - SET_ISAKMP_ID_TYPE (ie->id_cr, IPSEC_ID_IPV4_ADDR); - break; + /* Build the protection suite in our SA. */ + for (xf = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); xf; + xf = TAILQ_NEXT(xf, link)) { - case AF_INET6: - SET_ISAKMP_ID_TYPE (ie->id_ci, IPSEC_ID_IPV6_ADDR); - SET_ISAKMP_ID_TYPE (ie->id_cr, IPSEC_ID_IPV6_ADDR); - break; + /* + * XXX We could check that the proposal each transform belongs to + * is unique. + */ - default: - log_error ("initiator_recv_HASH_SA_NONCE: unknown sa_family %d", - src->sa_family); - free (ie->id_ci); - ie->id_ci = 0; - free (ie->id_cr); - ie->id_cr = 0; - return -1; - } - memcpy (ie->id_ci + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src), - sockaddr_addrlen (src)); - memcpy (ie->id_cr + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (dst), - sockaddr_addrlen (dst)); - } - - /* Build the protection suite in our SA. */ - for (xf = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); xf; - xf = TAILQ_NEXT (xf, link)) - { - - /* - * XXX We could check that the proposal each transform belongs to - * is unique. - */ - - if (sa_add_transform (sa, xf, exchange->initiator, &proto)) - return -1; + if (sa_add_transform(sa, xf, exchange->initiator, &proto)) + return -1; - /* XXX Check that the chosen transform matches an offer. */ + /* XXX Check that the chosen transform matches an offer. */ - ipsec_decode_transform (msg, sa, proto, xf->p); - } + ipsec_decode_transform(msg, sa, proto, xf->p); + } - /* Now remove offers that we don't need anymore. */ - for (proto = TAILQ_FIRST (&sa->protos); proto; proto = next_proto) - { - next_proto = TAILQ_NEXT (proto, link); - if (!proto->chosen) - proto_free (proto); - } + /* Now remove offers that we don't need anymore. */ + for (proto = TAILQ_FIRST(&sa->protos); proto; proto = next_proto) { + next_proto = TAILQ_NEXT(proto, link); + if (!proto->chosen) + proto_free(proto); + } #ifdef USE_POLICY - if (!check_policy (exchange, sa, msg->isakmp_sa)) - { - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - log_print ("initiator_recv_HASH_SA_NONCE: policy check failed"); - return -1; - } + if (!check_policy(exchange, sa, msg->isakmp_sa)) { + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + log_print("initiator_recv_HASH_SA_NONCE: policy check failed"); + return -1; + } #endif - /* Mark the SA as handled. */ - sa_p->flags |= PL_MARK; + /* Mark the SA as handled. */ + sa_p->flags |= PL_MARK; - isa = sa->data; - if ((isa->group_desc && (!ie->group || ie->group->id != isa->group_desc)) - || (!isa->group_desc && ie->group)) - { - log_print ("initiator_recv_HASH_SA_NONCE: disagreement on PFS"); - return -1; - } - - /* Copy out the initiator's nonce. */ - if (exchange_save_nonce (msg)) - return -1; + isa = sa->data; + if ((isa->group_desc && (!ie->group || ie->group->id != isa->group_desc)) + || (!isa->group_desc && ie->group)) { + log_print("initiator_recv_HASH_SA_NONCE: disagreement on PFS"); + return -1; + } + /* Copy out the initiator's nonce. */ + if (exchange_save_nonce(msg)) + return -1; - /* Handle the optional KEY_EXCH payload. */ - if (kep && ipsec_save_g_x (msg)) - return -1; + /* Handle the optional KEY_EXCH payload. */ + if (kep && ipsec_save_g_x(msg)) + return -1; - return 0; + return 0; } static int -initiator_send_HASH (struct message *msg) +initiator_send_HASH(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct prf *prf; - u_int8_t *buf; - struct hash *hash = hash_get (isa->hash); - size_t hashsize = hash->hashsize; - - /* We want a HASH payload to start with. XXX Share with ike_main_mode.c? */ - buf = malloc (ISAKMP_HASH_SZ + hashsize); - if (!buf) - { - log_error ("initiator_send_HASH: malloc (%lu) failed", - ISAKMP_HASH_SZ + (unsigned long)hashsize); - return -1; - } - if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf, - ISAKMP_HASH_SZ + hashsize, 1)) - { - free (buf); - return -1; - } - - /* Allocate the prf and start calculating our HASH(3). XXX Share? */ - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH: SKEYID_a", - isa->skeyid_a, isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); - if (!prf) - return -1; - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, (unsigned char *)"\0", 1); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH: message_id", - exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_I_b", - exchange->nonce_i, exchange->nonce_i_len)); - prf->Update (prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_R_b", - exchange->nonce_r, exchange->nonce_r_len)); - prf->Update (prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); - prf->Final (buf + ISAKMP_GEN_SZ, prf->prfctx); - prf_free (prf); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "initiator_send_HASH: HASH(3)", - buf + ISAKMP_GEN_SZ, hashsize)); - - if (ie->group) - message_register_post_send (msg, gen_g_xy); - - message_register_post_send (msg, post_quick_mode); - - return 0; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct prf *prf; + u_int8_t *buf; + struct hash *hash = hash_get(isa->hash); + size_t hashsize = hash->hashsize; + + /* + * We want a HASH payload to start with. XXX Share with + * ike_main_mode.c? + */ + buf = malloc(ISAKMP_HASH_SZ + hashsize); + if (!buf) { + log_error("initiator_send_HASH: malloc (%lu) failed", + ISAKMP_HASH_SZ + (unsigned long) hashsize); + return -1; + } + if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH, buf, + ISAKMP_HASH_SZ + hashsize, 1)) { + free(buf); + return -1; + } + /* Allocate the prf and start calculating our HASH(3). XXX Share? */ + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: SKEYID_a", + isa->skeyid_a, isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); + if (!prf) + return -1; + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, (unsigned char *) "\0", 1); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: message_id", + exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_I_b", + exchange->nonce_i, exchange->nonce_i_len)); + prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: NONCE_R_b", + exchange->nonce_r, exchange->nonce_r_len)); + prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); + prf->Final(buf + ISAKMP_GEN_SZ, prf->prfctx); + prf_free(prf); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "initiator_send_HASH: HASH(3)", + buf + ISAKMP_GEN_SZ, hashsize)); + + if (ie->group) + message_register_post_send(msg, gen_g_xy); + + message_register_post_send(msg, post_quick_mode); + + return 0; } static void -post_quick_mode (struct message *msg) +post_quick_mode(struct message * msg) { - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct prf *prf; - struct sa *sa; - struct proto *proto; - struct ipsec_proto *iproto; - u_int8_t *keymat; - int i; - - /* - * Loop over all SA negotiations and do both an in- and an outgoing SA - * per protocol. - */ - for (sa = TAILQ_FIRST (&exchange->sa_list); sa; sa = TAILQ_NEXT (sa, next)) - { - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - if (proto->proto == IPSEC_PROTO_IPCOMP) - continue; - - iproto = proto->data; - - /* - * There are two SAs for each SA negotiation, incoming and outcoing. - */ - for (i = 0; i < 2; i++) - { - prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_d, - isa->skeyid_len); - if (!prf) - { - /* XXX What to do? */ - continue; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct prf *prf; + struct sa *sa; + struct proto *proto; + struct ipsec_proto *iproto; + u_int8_t *keymat; + int i; + + /* + * Loop over all SA negotiations and do both an in- and an outgoing SA + * per protocol. + */ + for (sa = TAILQ_FIRST(&exchange->sa_list); sa; sa = TAILQ_NEXT(sa, next)) { + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + if (proto->proto == IPSEC_PROTO_IPCOMP) + continue; + + iproto = proto->data; + + /* + * There are two SAs for each SA negotiation, incoming and outcoing. + */ + for (i = 0; i < 2; i++) { + prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_d, + isa->skeyid_len); + if (!prf) { + /* XXX What to do? */ + continue; + } + ie->keymat_len = ipsec_keymat_length(proto); + + /* + * We need to roundup the length of the key material buffer + * to a multiple of the PRF's blocksize as it is generated + * in chunks of that blocksize. + */ + iproto->keymat[i] + = malloc(((ie->keymat_len + prf->blocksize - 1) + / prf->blocksize) * prf->blocksize); + if (!iproto->keymat[i]) { + log_error("post_quick_mode: malloc (%lu) failed", + (((unsigned long) ie->keymat_len + + prf->blocksize - 1) / prf->blocksize) * + prf->blocksize); + /* XXX What more to do? */ + free(prf); + continue; + } + for (keymat = iproto->keymat[i]; + keymat < iproto->keymat[i] + ie->keymat_len; + keymat += prf->blocksize) { + prf->Init(prf->prfctx); + + if (keymat != iproto->keymat[i]) { + /* + * Hash in last round's + * KEYMAT. + */ + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "post_quick_mode: last KEYMAT", + keymat - prf->blocksize, + prf->blocksize)); + prf->Update(prf->prfctx, keymat - prf->blocksize, + prf->blocksize); + } + /* If PFS is used hash in g^xy. */ + if (ie->g_xy) { + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "post_quick_mode: g^xy", ie->g_xy, + ie->g_x_len)); + prf->Update(prf->prfctx, ie->g_xy, ie->g_x_len); + } + LOG_DBG((LOG_NEGOTIATION, 90, + "post_quick_mode: suite %d proto %d", proto->no, + proto->proto)); + prf->Update(prf->prfctx, &proto->proto, 1); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "post_quick_mode: SPI", + proto->spi[i], proto->spi_sz[i])); + prf->Update(prf->prfctx, proto->spi[i], proto->spi_sz[i]); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "post_quick_mode: Ni_b", + exchange->nonce_i, exchange->nonce_i_len)); + prf->Update(prf->prfctx, exchange->nonce_i, + exchange->nonce_i_len); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "post_quick_mode: Nr_b", + exchange->nonce_r, exchange->nonce_r_len)); + prf->Update(prf->prfctx, exchange->nonce_r, + exchange->nonce_r_len); + prf->Final(keymat, prf->prfctx); + } + prf_free(prf); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "post_quick_mode: KEYMAT", + iproto->keymat[i], ie->keymat_len)); + } } - - ie->keymat_len = ipsec_keymat_length (proto); - - /* - * We need to roundup the length of the key material buffer - * to a multiple of the PRF's blocksize as it is generated - * in chunks of that blocksize. - */ - iproto->keymat[i] - = malloc (((ie->keymat_len + prf->blocksize - 1) - / prf->blocksize) * prf->blocksize); - if (!iproto->keymat[i]) - { - log_error ("post_quick_mode: malloc (%lu) failed", - (((unsigned long)ie->keymat_len + - prf->blocksize - 1) / prf->blocksize) * - prf->blocksize); - /* XXX What more to do? */ - free (prf); - continue; - } - - for (keymat = iproto->keymat[i]; - keymat < iproto->keymat[i] + ie->keymat_len; - keymat += prf->blocksize) - { - prf->Init (prf->prfctx); - - if (keymat != iproto->keymat[i]) - { - /* Hash in last round's KEYMAT. */ - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "post_quick_mode: last KEYMAT", - keymat - prf->blocksize, - prf->blocksize)); - prf->Update (prf->prfctx, keymat - prf->blocksize, - prf->blocksize); - } - - /* If PFS is used hash in g^xy. */ - if (ie->g_xy) - { - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "post_quick_mode: g^xy", ie->g_xy, - ie->g_x_len)); - prf->Update (prf->prfctx, ie->g_xy, ie->g_x_len); - } - LOG_DBG ((LOG_NEGOTIATION, 90, - "post_quick_mode: suite %d proto %d", proto->no, - proto->proto)); - prf->Update (prf->prfctx, &proto->proto, 1); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "post_quick_mode: SPI", - proto->spi[i], proto->spi_sz[i])); - prf->Update (prf->prfctx, proto->spi[i], proto->spi_sz[i]); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "post_quick_mode: Ni_b", - exchange->nonce_i, exchange->nonce_i_len)); - prf->Update (prf->prfctx, exchange->nonce_i, - exchange->nonce_i_len); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "post_quick_mode: Nr_b", - exchange->nonce_r, exchange->nonce_r_len)); - prf->Update (prf->prfctx, exchange->nonce_r, - exchange->nonce_r_len); - prf->Final (keymat, prf->prfctx); - } - prf_free (prf); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "post_quick_mode: KEYMAT", - iproto->keymat[i], ie->keymat_len)); - } } - } - log_verbose ("isakmpd: quick mode done: %s", - !msg->isakmp_sa || !msg->isakmp_sa->transport - ? "<no transport>" - : msg->isakmp_sa->transport->vtbl->decode_ids - (msg->isakmp_sa ->transport)); + log_verbose("isakmpd: quick mode done: %s", + !msg->isakmp_sa || !msg->isakmp_sa->transport + ? "<no transport>" + : msg->isakmp_sa->transport->vtbl->decode_ids + (msg->isakmp_sa->transport)); } /* @@ -1471,533 +1364,497 @@ post_quick_mode (struct message *msg) * XXX Describe in more detail. */ static int -responder_recv_HASH_SA_NONCE (struct message *msg) +responder_recv_HASH_SA_NONCE(struct message * msg) { - struct payload *hashp, *kep, *idp; - struct sa *sa; - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct prf *prf; - u_int8_t *hash, *my_hash = 0; - size_t hash_len; - u_int8_t *pkt = msg->iov[0].iov_base; - u_int8_t group_desc = 0; - int retval = -1; - struct proto *proto; - struct sockaddr *src, *dst; - char *name; - - hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - hash = hashp->p; - hashp->flags |= PL_MARK; - - /* The HASH payload should be the first one. */ - if (hash != pkt + ISAKMP_HDR_SZ) - { - /* XXX Is there a better notification type? */ - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - goto cleanup; - } - hash_len = GET_ISAKMP_GEN_LENGTH (hash); - my_hash = malloc (hash_len - ISAKMP_GEN_SZ); - if (!my_hash) - { - log_error ("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)hash_len - ISAKMP_GEN_SZ); - goto cleanup; - } - - /* - * Check the payload's integrity. - * XXX Share with ipsec_fill_in_hash? - */ - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: SKEYID_a", - isa->skeyid_a, isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); - if (!prf) - goto cleanup; - prf->Init (prf->prfctx); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_recv_HASH_SA_NONCE: message_id", - exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_recv_HASH_SA_NONCE: message after HASH", - hash + hash_len, - msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len)); - prf->Update (prf->prfctx, hash + hash_len, - msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len); - prf->Final (my_hash, prf->prfctx); - prf_free (prf); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_recv_HASH_SA_NONCE: computed HASH(1)", my_hash, - hash_len - ISAKMP_GEN_SZ)); - if (memcmp (hash + ISAKMP_GEN_SZ, my_hash, hash_len - ISAKMP_GEN_SZ) != 0) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); - goto cleanup; - } - free (my_hash); - my_hash = 0; - - kep = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]); - if (kep) - ie->pfs = 1; - - /* Handle optional client ID payloads. */ - idp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ID]); - if (idp) - { - /* If IDci is there, IDcr must be too. */ - if (!TAILQ_NEXT (idp, link)) - { - /* XXX Is this a good notify type? */ - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - goto cleanup; - } - - ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH (idp->p); - ie->id_ci = malloc (ie->id_ci_sz); - if (!ie->id_ci) - { - log_error ("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)ie->id_ci_sz); - goto cleanup; + struct payload *hashp, *kep, *idp; + struct sa *sa; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct prf *prf; + u_int8_t *hash, *my_hash = 0; + size_t hash_len; + u_int8_t *pkt = msg->iov[0].iov_base; + u_int8_t group_desc = 0; + int retval = -1; + struct proto *proto; + struct sockaddr *src, *dst; + char *name; + + hashp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + hash = hashp->p; + hashp->flags |= PL_MARK; + + /* The HASH payload should be the first one. */ + if (hash != pkt + ISAKMP_HDR_SZ) { + /* XXX Is there a better notification type? */ + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + goto cleanup; } - memcpy (ie->id_ci, idp->p, ie->id_ci_sz); - idp->flags |= PL_MARK; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_recv_HASH_SA_NONCE: IDci", - ie->id_ci + ISAKMP_GEN_SZ, ie->id_ci_sz - - ISAKMP_GEN_SZ)); - - idp = TAILQ_NEXT (idp, link); - ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH (idp->p); - ie->id_cr = malloc (ie->id_cr_sz); - if (!ie->id_cr) - { - log_error ("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)ie->id_cr_sz); - goto cleanup; + hash_len = GET_ISAKMP_GEN_LENGTH(hash); + my_hash = malloc(hash_len - ISAKMP_GEN_SZ); + if (!my_hash) { + log_error("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) hash_len - ISAKMP_GEN_SZ); + goto cleanup; } - memcpy (ie->id_cr, idp->p, ie->id_cr_sz); - idp->flags |= PL_MARK; - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_recv_HASH_SA_NONCE: IDcr", - ie->id_cr + ISAKMP_GEN_SZ, ie->id_cr_sz - - ISAKMP_GEN_SZ)); - } - else - { - /* - * If client identifiers are not present in the exchange, - * we fake them. RFC 2409 states: - * The identities of the SAs negotiated in Quick Mode are - * implicitly assumed to be the IP addresses of the ISAKMP - * peers, without any constraints on the protocol or port - * numbers allowed, unless client identifiers are specified - * in Quick Mode. - * - * -- Michael Paddon (mwp@aba.net.au) - */ - - ie->flags = IPSEC_EXCH_FLAG_NO_ID; - - /* Get initiator and responder addresses. */ - msg->transport->vtbl->get_src (msg->transport, &src); - msg->transport->vtbl->get_dst (msg->transport, &dst); - ie->id_ci_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen (src); - ie->id_cr_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen (dst); - ie->id_ci = calloc (ie->id_ci_sz, sizeof (char)); - ie->id_cr = calloc (ie->id_cr_sz, sizeof (char)); - - if (!ie->id_ci || !ie->id_cr) - { - log_error ("responder_recv_HASH_SA_NONCE: calloc (%lu, %lu) failed", - (unsigned long)ie->id_ci_sz, (unsigned long)sizeof (char)); - goto cleanup; + /* + * Check the payload's integrity. + * XXX Share with ipsec_fill_in_hash? + */ + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH_SA_NONCE: SKEYID_a", + isa->skeyid_a, isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); + if (!prf) + goto cleanup; + prf->Init(prf->prfctx); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_recv_HASH_SA_NONCE: message_id", + exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_recv_HASH_SA_NONCE: message after HASH", + hash + hash_len, + msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len)); + prf->Update(prf->prfctx, hash + hash_len, + msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len); + prf->Final(my_hash, prf->prfctx); + prf_free(prf); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_recv_HASH_SA_NONCE: computed HASH(1)", my_hash, + hash_len - ISAKMP_GEN_SZ)); + if (memcmp(hash + ISAKMP_GEN_SZ, my_hash, hash_len - ISAKMP_GEN_SZ) != 0) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + goto cleanup; } + free(my_hash); + my_hash = 0; + + kep = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]); + if (kep) + ie->pfs = 1; + + /* Handle optional client ID payloads. */ + idp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_ID]); + if (idp) { + /* If IDci is there, IDcr must be too. */ + if (!TAILQ_NEXT(idp, link)) { + /* XXX Is this a good notify type? */ + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + goto cleanup; + } + ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH(idp->p); + ie->id_ci = malloc(ie->id_ci_sz); + if (!ie->id_ci) { + log_error("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) ie->id_ci_sz); + goto cleanup; + } + memcpy(ie->id_ci, idp->p, ie->id_ci_sz); + idp->flags |= PL_MARK; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_recv_HASH_SA_NONCE: IDci", + ie->id_ci + ISAKMP_GEN_SZ, ie->id_ci_sz + - ISAKMP_GEN_SZ)); + + idp = TAILQ_NEXT(idp, link); + ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH(idp->p); + ie->id_cr = malloc(ie->id_cr_sz); + if (!ie->id_cr) { + log_error("responder_recv_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) ie->id_cr_sz); + goto cleanup; + } + memcpy(ie->id_cr, idp->p, ie->id_cr_sz); + idp->flags |= PL_MARK; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_recv_HASH_SA_NONCE: IDcr", + ie->id_cr + ISAKMP_GEN_SZ, ie->id_cr_sz + - ISAKMP_GEN_SZ)); + } else { + /* + * If client identifiers are not present in the exchange, + * we fake them. RFC 2409 states: + * The identities of the SAs negotiated in Quick Mode are + * implicitly assumed to be the IP addresses of the ISAKMP + * peers, without any constraints on the protocol or port + * numbers allowed, unless client identifiers are specified + * in Quick Mode. + * + * -- Michael Paddon (mwp@aba.net.au) + */ + + ie->flags = IPSEC_EXCH_FLAG_NO_ID; + + /* Get initiator and responder addresses. */ + msg->transport->vtbl->get_src(msg->transport, &src); + msg->transport->vtbl->get_dst(msg->transport, &dst); + ie->id_ci_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen(src); + ie->id_cr_sz = ISAKMP_ID_DATA_OFF + sockaddr_addrlen(dst); + ie->id_ci = calloc(ie->id_ci_sz, sizeof(char)); + ie->id_cr = calloc(ie->id_cr_sz, sizeof(char)); + + if (!ie->id_ci || !ie->id_cr) { + log_error("responder_recv_HASH_SA_NONCE: calloc (%lu, %lu) failed", + (unsigned long) ie->id_ci_sz, (unsigned long) sizeof(char)); + goto cleanup; + } + if (src->sa_family != dst->sa_family) { + log_error("initiator_recv_HASH_SA_NONCE: sa_family mismatch"); + goto cleanup; + } + switch (src->sa_family) { + case AF_INET: + SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV4_ADDR); + SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV4_ADDR); + break; + + case AF_INET6: + SET_ISAKMP_ID_TYPE(ie->id_ci, IPSEC_ID_IPV6_ADDR); + SET_ISAKMP_ID_TYPE(ie->id_cr, IPSEC_ID_IPV6_ADDR); + break; + + default: + log_error("initiator_recv_HASH_SA_NONCE: unknown sa_family %d", + src->sa_family); + goto cleanup; + } - if (src->sa_family != dst->sa_family) - { - log_error ("initiator_recv_HASH_SA_NONCE: sa_family mismatch"); - goto cleanup; - } - - switch (src->sa_family) - { - case AF_INET: - SET_ISAKMP_ID_TYPE (ie->id_ci, IPSEC_ID_IPV4_ADDR); - SET_ISAKMP_ID_TYPE (ie->id_cr, IPSEC_ID_IPV4_ADDR); - break; - - case AF_INET6: - SET_ISAKMP_ID_TYPE (ie->id_ci, IPSEC_ID_IPV6_ADDR); - SET_ISAKMP_ID_TYPE (ie->id_cr, IPSEC_ID_IPV6_ADDR); - break; - - default: - log_error ("initiator_recv_HASH_SA_NONCE: unknown sa_family %d", - src->sa_family); - goto cleanup; + memcpy(ie->id_cr + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(src), + sockaddr_addrlen(src)); + memcpy(ie->id_ci + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(dst), + sockaddr_addrlen(dst)); } - memcpy (ie->id_cr + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src), - sockaddr_addrlen (src)); - memcpy (ie->id_ci + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (dst), - sockaddr_addrlen (dst)); - } - #ifdef USE_POLICY #ifdef USE_KEYNOTE - if (message_negotiate_sa (msg, check_policy)) - goto cleanup; + if (message_negotiate_sa(msg, check_policy)) + goto cleanup; #else - if (message_negotiate_sa (msg, 0)) - goto cleanup; + if (message_negotiate_sa(msg, 0)) + goto cleanup; #endif #else - if (message_negotiate_sa (msg, 0)) - goto cleanup; -#endif /* USE_POLICY */ - - for (sa = TAILQ_FIRST (&exchange->sa_list); sa; sa = TAILQ_NEXT (sa, next)) - { - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - /* XXX we need to have some attributes per proto, not all per SA. */ - ipsec_decode_transform (msg, sa, proto, proto->chosen->p); - if (proto->proto == IPSEC_PROTO_IPSEC_AH - && !((struct ipsec_proto *)proto->data)->auth) - { - log_print ("responder_recv_HASH_SA_NONCE: " - "AH proposed without an algorithm attribute"); - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - goto next_sa; - } - } + if (message_negotiate_sa(msg, 0)) + goto cleanup; +#endif /* USE_POLICY */ + + for (sa = TAILQ_FIRST(&exchange->sa_list); sa; sa = TAILQ_NEXT(sa, next)) { + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + /* + * XXX we need to have some attributes per proto, not + * all per SA. + */ + ipsec_decode_transform(msg, sa, proto, proto->chosen->p); + if (proto->proto == IPSEC_PROTO_IPSEC_AH + && !((struct ipsec_proto *) proto->data)->auth) { + log_print("responder_recv_HASH_SA_NONCE: " + "AH proposed without an algorithm attribute"); + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + goto next_sa; + } + } - isa = sa->data; + isa = sa->data; + + /* + * The group description is mandatory if we got a KEY_EXCH + * payload. + */ + if (kep) { + if (!isa->group_desc) { + log_print("responder_recv_HASH_SA_NONCE: " + "KEY_EXCH payload without a group desc. attribute"); + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + continue; + } + /* Also, all SAs must have equal groups. */ + if (!group_desc) + group_desc = isa->group_desc; + else if (group_desc != isa->group_desc) { + log_print("responder_recv_HASH_SA_NONCE: " + "differing group descriptions in one QM"); + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + continue; + } + } + /* At least one SA was accepted. */ + retval = 0; - /* The group description is mandatory if we got a KEY_EXCH payload. */ - if (kep) - { - if (!isa->group_desc) - { - log_print ("responder_recv_HASH_SA_NONCE: " - "KEY_EXCH payload without a group desc. attribute"); - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - continue; - } - - /* Also, all SAs must have equal groups. */ - if (!group_desc) - group_desc = isa->group_desc; - else if (group_desc != isa->group_desc) - { - log_print ("responder_recv_HASH_SA_NONCE: " - "differing group descriptions in one QM"); - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - continue; - } +next_sa: + ; /* XXX gcc3 wants this. */ } - /* At least one SA was accepted. */ - retval = 0; - - next_sa: - ; /* XXX gcc3 wants this. */ - } - - if (kep) - { - ie->group = group_get (group_desc); - if (!ie->group) - { - /* - * XXX If the error was due to an out-of-range group description - * we should notify our peer, but this should probably be done - * by the attribute validation. Is it? - */ - goto cleanup; + if (kep) { + ie->group = group_get(group_desc); + if (!ie->group) { + /* + * XXX If the error was due to an out-of-range group description + * we should notify our peer, but this should probably be done + * by the attribute validation. Is it? + */ + goto cleanup; + } } - } - - /* Copy out the initiator's nonce. */ - if (exchange_save_nonce (msg)) - goto cleanup; - - /* Handle the optional KEY_EXCH payload. */ - if (kep && ipsec_save_g_x (msg)) - goto cleanup; - - /* - * Try to find and set the connection name on the exchange. - */ - - /* - * Check for accepted identities as well as lookup the connection - * name and set it on the exchange. - */ - name = connection_passive_lookup_by_ids (ie->id_ci, ie->id_cr); - if (name) - { - exchange->name = strdup (name); - if (!exchange->name) - { - log_error ("responder_recv_HASH_SA_NONCE: strdup (\"%s\") failed", - name); - goto cleanup; + /* Copy out the initiator's nonce. */ + if (exchange_save_nonce(msg)) + goto cleanup; + + /* Handle the optional KEY_EXCH payload. */ + if (kep && ipsec_save_g_x(msg)) + goto cleanup; + + /* + * Try to find and set the connection name on the exchange. + */ + + /* + * Check for accepted identities as well as lookup the connection + * name and set it on the exchange. + */ + name = connection_passive_lookup_by_ids(ie->id_ci, ie->id_cr); + if (name) { + exchange->name = strdup(name); + if (!exchange->name) { + log_error("responder_recv_HASH_SA_NONCE: strdup (\"%s\") failed", + name); + goto cleanup; + } } - } #if !defined (USE_POLICY) && !defined (USE_KEYNOTE) - else - { - /* - * This code is no longer necessary, as policy determines acceptance - * of IDs/SAs. (angelos@openbsd.org) - * - * XXX Keep it if not USE_POLICY for now, though. - */ - - /* XXX Notify peer and log. */ - goto cleanup; - } -#endif /* !USE_POLICY && !USE_KEYNOTE */ - - return retval; + else { + /* + * This code is no longer necessary, as policy determines acceptance + * of IDs/SAs. (angelos@openbsd.org) + * + * XXX Keep it if not USE_POLICY for now, though. + */ + + /* XXX Notify peer and log. */ + goto cleanup; + } +#endif /* !USE_POLICY && !USE_KEYNOTE */ + + return retval; cleanup: - /* Remove all potential protocols that have been added to the SAs. */ - for (sa = TAILQ_FIRST (&exchange->sa_list); sa; sa = TAILQ_NEXT (sa, next)) - while ((proto = TAILQ_FIRST (&sa->protos)) != 0) - proto_free (proto); - if (my_hash) - free (my_hash); - if (ie->id_ci) - { - free (ie->id_ci); - ie->id_ci = 0; - } - if (ie->id_cr) - { - free (ie->id_cr); - ie->id_cr = 0; - } - return -1; + /* Remove all potential protocols that have been added to the SAs. */ + for (sa = TAILQ_FIRST(&exchange->sa_list); sa; sa = TAILQ_NEXT(sa, next)) + while ((proto = TAILQ_FIRST(&sa->protos)) != 0) + proto_free(proto); + if (my_hash) + free(my_hash); + if (ie->id_ci) { + free(ie->id_ci); + ie->id_ci = 0; + } + if (ie->id_cr) { + free(ie->id_cr); + ie->id_cr = 0; + } + return -1; } /* Reply with the transform we chose. */ static int -responder_send_HASH_SA_NONCE (struct message *msg) +responder_send_HASH_SA_NONCE(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct prf *prf; - struct hash *hash = hash_get (isa->hash); - size_t hashsize = hash->hashsize; - size_t nonce_sz = exchange->nonce_i_len; - u_int8_t *buf; - int initiator = exchange->initiator; - char header[80]; - u_int32_t i; - u_int8_t *id; - size_t sz; - - /* We want a HASH payload to start with. XXX Share with ike_main_mode.c? */ - buf = malloc (ISAKMP_HASH_SZ + hashsize); - if (!buf) - { - log_error ("responder_send_HASH_SA_NONCE: malloc (%lu) failed", - ISAKMP_HASH_SZ + (unsigned long)hashsize); - return -1; - } - if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf, - ISAKMP_HASH_SZ + hashsize, 1)) - { - free (buf); - return -1; - } - - /* Add the SA payload(s) with the transform(s) that was/were chosen. */ - if (message_add_sa_payload (msg)) - return -1; - - /* Generate a nonce, and add it to the message. */ - if (exchange_gen_nonce (msg, nonce_sz)) - return -1; - - /* Generate optional KEY_EXCH payload. This is known as PFS. */ - if (ie->group && ipsec_gen_g_x (msg)) - return -1; - - /* If the initiator client ID's were acceptable, just mirror them back. */ - if (!(ie->flags & IPSEC_EXCH_FLAG_NO_ID)) - { - sz = ie->id_ci_sz; - id = malloc (sz); - if (!id) - { - log_error ("responder_send_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)sz); - return -1; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct prf *prf; + struct hash *hash = hash_get(isa->hash); + size_t hashsize = hash->hashsize; + size_t nonce_sz = exchange->nonce_i_len; + u_int8_t *buf; + int initiator = exchange->initiator; + char header[80]; + u_int32_t i; + u_int8_t *id; + size_t sz; + + /* + * We want a HASH payload to start with. XXX Share with + * ike_main_mode.c? + */ + buf = malloc(ISAKMP_HASH_SZ + hashsize); + if (!buf) { + log_error("responder_send_HASH_SA_NONCE: malloc (%lu) failed", + ISAKMP_HASH_SZ + (unsigned long) hashsize); + return -1; } - memcpy (id, ie->id_ci, sz); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDic", - id, sz)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) - { - free (id); - return -1; + if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH, buf, + ISAKMP_HASH_SZ + hashsize, 1)) { + free(buf); + return -1; } - - sz = ie->id_cr_sz; - id = malloc (sz); - if (!id) - { - log_error ("responder_send_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)sz); - return -1; + /* Add the SA payload(s) with the transform(s) that was/were chosen. */ + if (message_add_sa_payload(msg)) + return -1; + + /* Generate a nonce, and add it to the message. */ + if (exchange_gen_nonce(msg, nonce_sz)) + return -1; + + /* Generate optional KEY_EXCH payload. This is known as PFS. */ + if (ie->group && ipsec_gen_g_x(msg)) + return -1; + + /* + * If the initiator client ID's were acceptable, just mirror them + * back. + */ + if (!(ie->flags & IPSEC_EXCH_FLAG_NO_ID)) { + sz = ie->id_ci_sz; + id = malloc(sz); + if (!id) { + log_error("responder_send_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) sz); + return -1; + } + memcpy(id, ie->id_ci, sz); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDic", + id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; + } + sz = ie->id_cr_sz; + id = malloc(sz); + if (!id) { + log_error("responder_send_HASH_SA_NONCE: malloc (%lu) failed", + (unsigned long) sz); + return -1; + } + memcpy(id, ie->id_cr, sz); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDrc", + id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; + } } - memcpy (id, ie->id_cr, sz); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: IDrc", - id, sz)); - if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) - { - free (id); - return -1; + /* Allocate the prf and start calculating our HASH(2). XXX Share? */ + LOG_DBG((LOG_NEGOTIATION, 90, "responder_recv_HASH: isakmp_sa %p isa %p", + isakmp_sa, isa)); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: SKEYID_a", + isa->skeyid_a, isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); + if (!prf) + return -1; + prf->Init(prf->prfctx); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_send_HASH_SA_NONCE: message_id", + exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: NONCE_I_b", + exchange->nonce_i, exchange->nonce_i_len)); + prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); + + /* Loop over all payloads after HASH(2). */ + for (i = 2; i < msg->iovlen; i++) { + /* XXX Misleading payload type printouts. */ + snprintf(header, sizeof header, + "responder_send_HASH_SA_NONCE: payload %d after HASH(2)", + i - 1); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, header, msg->iov[i].iov_base, + msg->iov[i].iov_len)); + prf->Update(prf->prfctx, msg->iov[i].iov_base, msg->iov[i].iov_len); } - } - - /* Allocate the prf and start calculating our HASH(2). XXX Share? */ - LOG_DBG ((LOG_NEGOTIATION, 90, "responder_recv_HASH: isakmp_sa %p isa %p", - isakmp_sa, isa)); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: SKEYID_a", - isa->skeyid_a, isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); - if (!prf) - return -1; - prf->Init (prf->prfctx); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_send_HASH_SA_NONCE: message_id", - exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_send_HASH_SA_NONCE: NONCE_I_b", - exchange->nonce_i, exchange->nonce_i_len)); - prf->Update (prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); - - /* Loop over all payloads after HASH(2). */ - for (i = 2; i < msg->iovlen; i++) - { - /* XXX Misleading payload type printouts. */ - snprintf (header, sizeof header, - "responder_send_HASH_SA_NONCE: payload %d after HASH(2)", - i - 1); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, header, msg->iov[i].iov_base, - msg->iov[i].iov_len)); - prf->Update (prf->prfctx, msg->iov[i].iov_base, msg->iov[i].iov_len); - } - prf->Final (buf + ISAKMP_HASH_DATA_OFF, prf->prfctx); - prf_free (prf); - snprintf (header, sizeof header, "responder_send_HASH_SA_NONCE: HASH_%c", - initiator ? 'I' : 'R'); - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, header, buf + ISAKMP_HASH_DATA_OFF, - hashsize)); - - if (ie->group) - message_register_post_send (msg, gen_g_xy); - - return 0; + prf->Final(buf + ISAKMP_HASH_DATA_OFF, prf->prfctx); + prf_free(prf); + snprintf(header, sizeof header, "responder_send_HASH_SA_NONCE: HASH_%c", + initiator ? 'I' : 'R'); + LOG_DBG_BUF((LOG_NEGOTIATION, 80, header, buf + ISAKMP_HASH_DATA_OFF, + hashsize)); + + if (ie->group) + message_register_post_send(msg, gen_g_xy); + + return 0; } static void -gen_g_xy (struct message *msg) +gen_g_xy(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - - /* Compute Diffie-Hellman shared value. */ - ie->g_xy = malloc (ie->g_x_len); - if (!ie->g_xy) - { - log_error ("gen_g_xy: malloc (%lu) failed", (unsigned long)ie->g_x_len); - return; - } - if (dh_create_shared (ie->group, ie->g_xy, - exchange->initiator ? ie->g_xr : ie->g_xi)) - { - log_print ("gen_g_xy: dh_create_shared failed"); - return; - } - LOG_DBG_BUF ((LOG_NEGOTIATION, 80, "gen_g_xy: g^xy", ie->g_xy, ie->g_x_len)); + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + + /* Compute Diffie-Hellman shared value. */ + ie->g_xy = malloc(ie->g_x_len); + if (!ie->g_xy) { + log_error("gen_g_xy: malloc (%lu) failed", (unsigned long) ie->g_x_len); + return; + } + if (dh_create_shared(ie->group, ie->g_xy, + exchange->initiator ? ie->g_xr : ie->g_xi)) { + log_print("gen_g_xy: dh_create_shared failed"); + return; + } + LOG_DBG_BUF((LOG_NEGOTIATION, 80, "gen_g_xy: g^xy", ie->g_xy, ie->g_x_len)); } static int -responder_recv_HASH (struct message *msg) +responder_recv_HASH(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct prf *prf; - u_int8_t *hash, *my_hash = 0; - size_t hash_len; - struct payload *hashp; - - /* Find HASH(3) and create our own hash, just as big. */ - hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - hash = hashp->p; - hashp->flags |= PL_MARK; - hash_len = GET_ISAKMP_GEN_LENGTH (hash); - my_hash = malloc (hash_len - ISAKMP_GEN_SZ); - if (!my_hash) - { - log_error ("responder_recv_HASH: malloc (%lu) failed", - (unsigned long)hash_len - ISAKMP_GEN_SZ); - goto cleanup; - } - - /* Allocate the prf and start calculating our HASH(3). XXX Share? */ - LOG_DBG ((LOG_NEGOTIATION, 90, "responder_recv_HASH: isakmp_sa %p isa %p", - isakmp_sa, isa)); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_recv_HASH: SKEYID_a", - isa->skeyid_a, isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); - if (!prf) - goto cleanup; - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, (unsigned char *)"\0", 1); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_recv_HASH: message_id", - exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_I_b", - exchange->nonce_i, exchange->nonce_i_len)); - prf->Update (prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_R_b", - exchange->nonce_r, exchange->nonce_r_len)); - prf->Update (prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); - prf->Final (my_hash, prf->prfctx); - prf_free (prf); - LOG_DBG_BUF ((LOG_NEGOTIATION, 90, - "responder_recv_HASH: computed HASH(3)", my_hash, - hash_len - ISAKMP_GEN_SZ)); - if (memcmp (hash + ISAKMP_GEN_SZ, my_hash, hash_len - ISAKMP_GEN_SZ) != 0) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); - goto cleanup; - } - free (my_hash); - - post_quick_mode (msg); - - return 0; - - cleanup: - if (my_hash) - free (my_hash); - return -1; + struct exchange *exchange = msg->exchange; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct prf *prf; + u_int8_t *hash, *my_hash = 0; + size_t hash_len; + struct payload *hashp; + + /* Find HASH(3) and create our own hash, just as big. */ + hashp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + hash = hashp->p; + hashp->flags |= PL_MARK; + hash_len = GET_ISAKMP_GEN_LENGTH(hash); + my_hash = malloc(hash_len - ISAKMP_GEN_SZ); + if (!my_hash) { + log_error("responder_recv_HASH: malloc (%lu) failed", + (unsigned long) hash_len - ISAKMP_GEN_SZ); + goto cleanup; + } + /* Allocate the prf and start calculating our HASH(3). XXX Share? */ + LOG_DBG((LOG_NEGOTIATION, 90, "responder_recv_HASH: isakmp_sa %p isa %p", + isakmp_sa, isa)); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: SKEYID_a", + isa->skeyid_a, isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); + if (!prf) + goto cleanup; + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, (unsigned char *) "\0", 1); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: message_id", + exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_I_b", + exchange->nonce_i, exchange->nonce_i_len)); + prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, "responder_recv_HASH: NONCE_R_b", + exchange->nonce_r, exchange->nonce_r_len)); + prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); + prf->Final(my_hash, prf->prfctx); + prf_free(prf); + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "responder_recv_HASH: computed HASH(3)", my_hash, + hash_len - ISAKMP_GEN_SZ)); + if (memcmp(hash + ISAKMP_GEN_SZ, my_hash, hash_len - ISAKMP_GEN_SZ) != 0) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + goto cleanup; + } + free(my_hash); + + post_quick_mode(msg); + + return 0; + +cleanup: + if (my_hash) + free(my_hash); + return -1; } diff --git a/sbin/isakmpd/ike_quick_mode.h b/sbin/isakmpd/ike_quick_mode.h index afe1709d83d..32b1523ef01 100644 --- a/sbin/isakmpd/ike_quick_mode.h +++ b/sbin/isakmpd/ike_quick_mode.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_quick_mode.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ike_quick_mode.h,v 1.1 1998/08/02 20:22:44 niklas Exp $ */ +/* $OpenBSD: ike_quick_mode.h,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ike_quick_mode.h,v 1.1 1998/08/02 20:22:44 niklas Exp $ */ /* * Copyright (c) 1998, 2001 Niklas Hallqvist. All rights reserved. @@ -34,7 +34,7 @@ struct message; -extern int (*ike_quick_mode_initiator[]) (struct message *); -extern int (*ike_quick_mode_responder[]) (struct message *); +extern int (*ike_quick_mode_initiator[]) (struct message *); +extern int (*ike_quick_mode_responder[]) (struct message *); -#endif /* _IKE_QUICK_MODE_H_ */ +#endif /* _IKE_QUICK_MODE_H_ */ diff --git a/sbin/isakmpd/init.c b/sbin/isakmpd/init.c index dcf1c69122a..929bf07d3e5 100644 --- a/sbin/isakmpd/init.c +++ b/sbin/isakmpd/init.c @@ -1,5 +1,5 @@ -/* $OpenBSD: init.c,v 1.28 2004/04/08 10:05:54 hshoexer Exp $ */ -/* $EOM: init.c,v 1.25 2000/03/30 14:27:24 ho Exp $ */ +/* $OpenBSD: init.c,v 1.29 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: init.c,v 1.25 2000/03/30 14:27:24 ho Exp $ */ /* * Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -59,85 +59,85 @@ #endif void -init (void) +init(void) { - app_init (); - doi_init (); - exchange_init (); - group_init (); - ipsec_init (); - isakmp_doi_init (); - libcrypto_init (); + app_init(); + doi_init(); + exchange_init(); + group_init(); + ipsec_init(); + isakmp_doi_init(); + libcrypto_init(); - timer_init (); + timer_init(); - /* The following group are depending on timer_init having run. */ - conf_init (); - connection_init (); + /* The following group are depending on timer_init having run. */ + conf_init(); + connection_init(); - /* This depends on conf_init, thus check as soon as possible. */ - log_reinit (); + /* This depends on conf_init, thus check as soon as possible. */ + log_reinit(); #ifdef USE_POLICY - /* policy_init depends on conf_init having run. */ - policy_init (); + /* policy_init depends on conf_init having run. */ + policy_init(); #endif - /* Depends on conf_init and policy_init having run */ - cert_init (); - crl_init (); + /* Depends on conf_init and policy_init having run */ + cert_init(); + crl_init(); - sa_init (); - transport_init (); - udp_init (); - ui_init (); + sa_init(); + transport_init(); + udp_init(); + ui_init(); } /* Reinitialize, either after a SIGHUP reception or by FIFO UI cmd. */ void -reinit (void) +reinit(void) { - log_print ("isakmpd: reinitializing daemon"); + log_print("isakmpd: reinitializing daemon"); - /* - * XXX Remove all(/some?) pending exchange timers? - they may not be - * possible to complete after we've re-read the config file. - * User-initiated SIGHUP's maybe "authorizes" a wait until - * next connection-check. - * XXX This means we discard exchange->last_msg, is this really ok? - */ + /* + * XXX Remove all(/some?) pending exchange timers? - they may not be + * possible to complete after we've re-read the config file. + * User-initiated SIGHUP's maybe "authorizes" a wait until + * next connection-check. + * XXX This means we discard exchange->last_msg, is this really ok? + */ - /* Reinitialize PRNG if we are in deterministic mode. */ - if (regrand) - srandom (seed); + /* Reinitialize PRNG if we are in deterministic mode. */ + if (regrand) + srandom(seed); - /* Reread config file. */ - conf_reinit (); + /* Reread config file. */ + conf_reinit(); - log_reinit (); + log_reinit(); #ifdef USE_POLICY - /* Reread the policies. */ - policy_init (); + /* Reread the policies. */ + policy_init(); #endif - /* Reinitialize certificates */ - cert_init (); - crl_init (); + /* Reinitialize certificates */ + cert_init(); + crl_init(); - /* Reinitialize our connection list. */ - connection_reinit (); + /* Reinitialize our connection list. */ + connection_reinit(); - /* - * Rescan interfaces. - */ - transport_reinit (); + /* + * Rescan interfaces. + */ + transport_reinit(); - /* - * XXX "These" (non-existent) reinitializations should not be done. - * cookie_reinit (); - * ui_reinit (); - */ + /* + * XXX "These" (non-existent) reinitializations should not be done. + * cookie_reinit (); + * ui_reinit (); + */ - sa_reinit (); + sa_reinit(); } diff --git a/sbin/isakmpd/init.h b/sbin/isakmpd/init.h index 5f653b0825c..cbcd46ab963 100644 --- a/sbin/isakmpd/init.h +++ b/sbin/isakmpd/init.h @@ -1,5 +1,5 @@ -/* $OpenBSD: init.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: init.h,v 1.2 1998/07/07 23:36:00 niklas Exp $ */ +/* $OpenBSD: init.h,v 1.6 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: init.h,v 1.2 1998/07/07 23:36:00 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -32,7 +32,7 @@ #ifndef _INIT_H_ #define _INIT_H_ -extern void init (void); -extern void reinit (void); +extern void init(void); +extern void reinit(void); -#endif /* _INIT_H_ */ +#endif /* _INIT_H_ */ diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c index 189c5a8fb31..d570759467b 100644 --- a/sbin/isakmpd/ipsec.c +++ b/sbin/isakmpd/ipsec.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ipsec.c,v 1.88 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */ +/* $OpenBSD: ipsec.c,v 1.89 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -78,115 +78,117 @@ #define DEFAULT_REPLAY_WINDOW 16 struct ipsec_decode_arg { - struct message *msg; - struct sa *sa; - struct proto *proto; + struct message *msg; + struct sa *sa; + struct proto *proto; }; /* These variables hold the contacted peers ADT state. */ struct contact { - struct sockaddr *addr; - socklen_t len; -} *contacts = 0; -int contact_cnt = 0, contact_limit = 0; - -static int addr_cmp (const void *, const void *); -static int ipsec_add_contact (struct message *msg); -static int ipsec_contacted (struct message *msg); + struct sockaddr *addr; + socklen_t len; +} *contacts = 0; +int contact_cnt = 0, contact_limit = 0; + +static int addr_cmp(const void *, const void *); +static int ipsec_add_contact(struct message * msg); +static int ipsec_contacted(struct message * msg); #ifdef USE_DEBUG -static int ipsec_debug_attribute (u_int16_t, u_int8_t *, u_int16_t, void *); +static int ipsec_debug_attribute(u_int16_t, u_int8_t *, u_int16_t, void *); #endif -static void ipsec_delete_spi (struct sa *, struct proto *, int); -static int16_t *ipsec_exchange_script (u_int8_t); -static void ipsec_finalize_exchange (struct message *); -static void ipsec_free_exchange_data (void *); -static void ipsec_free_proto_data (void *); -static void ipsec_free_sa_data (void *); -static struct keystate *ipsec_get_keystate (struct message *); -static u_int8_t *ipsec_get_spi (size_t *, u_int8_t, struct message *); -static int ipsec_handle_leftover_payload (struct message *, u_int8_t, - struct payload *); -static int ipsec_informational_post_hook (struct message *); -static int ipsec_informational_pre_hook (struct message *); -static int ipsec_initiator (struct message *); -static void ipsec_proto_init (struct proto *, char *); -static int ipsec_responder (struct message *); -static void ipsec_setup_situation (u_int8_t *); -static int ipsec_set_network (u_int8_t *, u_int8_t *, struct ipsec_sa *); -static size_t ipsec_situation_size (void); -static u_int8_t ipsec_spi_size (u_int8_t); -static int ipsec_validate_attribute (u_int16_t, u_int8_t *, u_int16_t, void *); -static int ipsec_validate_exchange (u_int8_t); -static int ipsec_validate_id_information (u_int8_t, u_int8_t *, u_int8_t *, - size_t, struct exchange *); -static int ipsec_validate_key_information (u_int8_t *, size_t); -static int ipsec_validate_notification (u_int16_t); -static int ipsec_validate_proto (u_int8_t); -static int ipsec_validate_situation (u_int8_t *, size_t *, size_t); -static int ipsec_validate_transform_id (u_int8_t, u_int8_t); +static void ipsec_delete_spi(struct sa *, struct proto *, int); +static int16_t *ipsec_exchange_script(u_int8_t); +static void ipsec_finalize_exchange(struct message *); +static void ipsec_free_exchange_data(void *); +static void ipsec_free_proto_data(void *); +static void ipsec_free_sa_data(void *); +static struct keystate *ipsec_get_keystate(struct message *); +static u_int8_t *ipsec_get_spi(size_t *, u_int8_t, struct message *); +static int +ipsec_handle_leftover_payload(struct message *, u_int8_t, + struct payload *); +static int ipsec_informational_post_hook(struct message *); +static int ipsec_informational_pre_hook(struct message *); +static int ipsec_initiator(struct message *); +static void ipsec_proto_init(struct proto *, char *); +static int ipsec_responder(struct message *); +static void ipsec_setup_situation(u_int8_t *); +static int ipsec_set_network(u_int8_t *, u_int8_t *, struct ipsec_sa *); +static size_t ipsec_situation_size(void); +static u_int8_t ipsec_spi_size(u_int8_t); +static int ipsec_validate_attribute(u_int16_t, u_int8_t *, u_int16_t, void *); +static int ipsec_validate_exchange(u_int8_t); +static int +ipsec_validate_id_information(u_int8_t, u_int8_t *, u_int8_t *, + size_t, struct exchange *); +static int ipsec_validate_key_information(u_int8_t *, size_t); +static int ipsec_validate_notification(u_int16_t); +static int ipsec_validate_proto(u_int8_t); +static int ipsec_validate_situation(u_int8_t *, size_t *, size_t); +static int ipsec_validate_transform_id(u_int8_t, u_int8_t); static struct doi ipsec_doi = { - { 0 }, IPSEC_DOI_IPSEC, - sizeof (struct ipsec_exch), sizeof (struct ipsec_sa), - sizeof (struct ipsec_proto), + {0}, IPSEC_DOI_IPSEC, + sizeof(struct ipsec_exch), sizeof(struct ipsec_sa), + sizeof(struct ipsec_proto), #ifdef USE_DEBUG - ipsec_debug_attribute, + ipsec_debug_attribute, #endif - ipsec_delete_spi, - ipsec_exchange_script, - ipsec_finalize_exchange, - ipsec_free_exchange_data, - ipsec_free_proto_data, - ipsec_free_sa_data, - ipsec_get_keystate, - ipsec_get_spi, - ipsec_handle_leftover_payload, - ipsec_informational_post_hook, - ipsec_informational_pre_hook, - ipsec_is_attribute_incompatible, - ipsec_proto_init, - ipsec_setup_situation, - ipsec_situation_size, - ipsec_spi_size, - ipsec_validate_attribute, - ipsec_validate_exchange, - ipsec_validate_id_information, - ipsec_validate_key_information, - ipsec_validate_notification, - ipsec_validate_proto, - ipsec_validate_situation, - ipsec_validate_transform_id, - ipsec_initiator, - ipsec_responder, - ipsec_decode_ids + ipsec_delete_spi, + ipsec_exchange_script, + ipsec_finalize_exchange, + ipsec_free_exchange_data, + ipsec_free_proto_data, + ipsec_free_sa_data, + ipsec_get_keystate, + ipsec_get_spi, + ipsec_handle_leftover_payload, + ipsec_informational_post_hook, + ipsec_informational_pre_hook, + ipsec_is_attribute_incompatible, + ipsec_proto_init, + ipsec_setup_situation, + ipsec_situation_size, + ipsec_spi_size, + ipsec_validate_attribute, + ipsec_validate_exchange, + ipsec_validate_id_information, + ipsec_validate_key_information, + ipsec_validate_notification, + ipsec_validate_proto, + ipsec_validate_situation, + ipsec_validate_transform_id, + ipsec_initiator, + ipsec_responder, + ipsec_decode_ids }; -int16_t script_quick_mode[] = { - ISAKMP_PAYLOAD_HASH, /* Initiator -> responder. */ - ISAKMP_PAYLOAD_SA, - ISAKMP_PAYLOAD_NONCE, - EXCHANGE_SCRIPT_SWITCH, - ISAKMP_PAYLOAD_HASH, /* Responder -> initiator. */ - ISAKMP_PAYLOAD_SA, - ISAKMP_PAYLOAD_NONCE, - EXCHANGE_SCRIPT_SWITCH, - ISAKMP_PAYLOAD_HASH, /* Initiator -> responder. */ - EXCHANGE_SCRIPT_END +int16_t script_quick_mode[] = { + ISAKMP_PAYLOAD_HASH, /* Initiator -> responder. */ + ISAKMP_PAYLOAD_SA, + ISAKMP_PAYLOAD_NONCE, + EXCHANGE_SCRIPT_SWITCH, + ISAKMP_PAYLOAD_HASH, /* Responder -> initiator. */ + ISAKMP_PAYLOAD_SA, + ISAKMP_PAYLOAD_NONCE, + EXCHANGE_SCRIPT_SWITCH, + ISAKMP_PAYLOAD_HASH, /* Initiator -> responder. */ + EXCHANGE_SCRIPT_END }; -int16_t script_new_group_mode[] = { - ISAKMP_PAYLOAD_HASH, /* Initiator -> responder. */ - ISAKMP_PAYLOAD_SA, - EXCHANGE_SCRIPT_SWITCH, - ISAKMP_PAYLOAD_HASH, /* Responder -> initiator. */ - ISAKMP_PAYLOAD_SA, - EXCHANGE_SCRIPT_END +int16_t script_new_group_mode[] = { + ISAKMP_PAYLOAD_HASH, /* Initiator -> responder. */ + ISAKMP_PAYLOAD_SA, + EXCHANGE_SCRIPT_SWITCH, + ISAKMP_PAYLOAD_HASH, /* Responder -> initiator. */ + ISAKMP_PAYLOAD_SA, + EXCHANGE_SCRIPT_END }; struct dst_spi_proto_arg { - struct sockaddr *dst; - u_int32_t spi; - u_int8_t proto; + struct sockaddr *dst; + u_int32_t spi; + u_int8_t proto; }; /* @@ -195,49 +197,47 @@ struct dst_spi_proto_arg { * if "proto" arg is 0, match any proto */ static int -ipsec_sa_check (struct sa *sa, void *v_arg) +ipsec_sa_check(struct sa *sa, void *v_arg) { - struct dst_spi_proto_arg *arg = v_arg; - struct proto *proto; - struct sockaddr *dst, *src; - int incoming; - - if (sa->phase != 2 || !(sa->flags & SA_FLAG_READY)) - return 0; - - sa->transport->vtbl->get_dst (sa->transport, &dst); - if (memcmp (sockaddr_addrdata (dst), sockaddr_addrdata (arg->dst), - sockaddr_addrlen (dst)) == 0) - incoming = 0; - else - { - sa->transport->vtbl->get_src (sa->transport, &src); - if (memcmp (sockaddr_addrdata (src), sockaddr_addrdata (arg->dst), - sockaddr_addrlen (src)) == 0) - incoming = 1; - else + struct dst_spi_proto_arg *arg = v_arg; + struct proto *proto; + struct sockaddr *dst, *src; + int incoming; + + if (sa->phase != 2 || !(sa->flags & SA_FLAG_READY)) + return 0; + + sa->transport->vtbl->get_dst(sa->transport, &dst); + if (memcmp(sockaddr_addrdata(dst), sockaddr_addrdata(arg->dst), + sockaddr_addrlen(dst)) == 0) + incoming = 0; + else { + sa->transport->vtbl->get_src(sa->transport, &src); + if (memcmp(sockaddr_addrdata(src), sockaddr_addrdata(arg->dst), + sockaddr_addrlen(src)) == 0) + incoming = 1; + else + return 0; + } + + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) + if ((arg->proto == 0 || proto->proto == arg->proto) && + memcmp(proto->spi[incoming], &arg->spi, sizeof arg->spi) == 0) + return 1; return 0; - } - - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - if ((arg->proto == 0 || proto->proto == arg->proto) - && memcmp (proto->spi[incoming], &arg->spi, sizeof arg->spi) == 0) - return 1; - return 0; } /* Find an SA with a "name" of DST, SPI & PROTO. */ -struct sa * -ipsec_sa_lookup (struct sockaddr *dst, u_int32_t spi, u_int8_t proto) +struct sa * +ipsec_sa_lookup(struct sockaddr * dst, u_int32_t spi, u_int8_t proto) { - struct dst_spi_proto_arg arg; + struct dst_spi_proto_arg arg; - arg.dst = dst; - arg.spi = spi; - arg.proto = proto; - - return sa_find (ipsec_sa_check, &arg); + arg.dst = dst; + arg.spi = spi; + arg.proto = proto; + return sa_find(ipsec_sa_check, &arg); } /* @@ -246,32 +246,32 @@ ipsec_sa_lookup (struct sockaddr *dst, u_int32_t spi, u_int8_t proto) * XXX At some point other selectors will matter here too. */ static int -ipsec_sa_check_flow (struct sa *sa, void *v_arg) +ipsec_sa_check_flow(struct sa * sa, void *v_arg) { - struct sa *sa2 = v_arg; - struct ipsec_sa *isa = sa->data, *isa2 = sa2->data; - - if (sa == sa2 || sa->phase != 2 - || (sa->flags & (SA_FLAG_READY | SA_FLAG_REPLACED)) != SA_FLAG_READY) - return 0; - - if (isa->tproto != isa2->tproto || isa->sport != isa2->sport - || isa->dport != isa2->dport) - return 0; - - return isa->src_net->sa_family == isa2->src_net->sa_family - && memcmp (sockaddr_addrdata (isa->src_net), - sockaddr_addrdata (isa2->src_net), - sockaddr_addrlen (isa->src_net)) == 0 - && memcmp (sockaddr_addrdata (isa->src_mask), - sockaddr_addrdata (isa2->src_mask), - sockaddr_addrlen (isa->src_mask)) == 0 - && memcmp (sockaddr_addrdata (isa->dst_net), - sockaddr_addrdata (isa2->dst_net), - sockaddr_addrlen (isa->dst_net)) == 0 - && memcmp (sockaddr_addrdata (isa->dst_mask), - sockaddr_addrdata (isa2->dst_mask), - sockaddr_addrlen (isa->dst_mask)) == 0; + struct sa *sa2 = v_arg; + struct ipsec_sa *isa = sa->data, *isa2 = sa2->data; + + if (sa == sa2 || sa->phase != 2 || + (sa->flags & (SA_FLAG_READY | SA_FLAG_REPLACED)) != SA_FLAG_READY) + return 0; + + if (isa->tproto != isa2->tproto || isa->sport != isa2->sport || + isa->dport != isa2->dport) + return 0; + + return isa->src_net->sa_family == isa2->src_net->sa_family && + memcmp(sockaddr_addrdata(isa->src_net), + sockaddr_addrdata(isa2->src_net), + sockaddr_addrlen(isa->src_net)) == 0 && + memcmp(sockaddr_addrdata(isa->src_mask), + sockaddr_addrdata(isa2->src_mask), + sockaddr_addrlen(isa->src_mask)) == 0 && + memcmp(sockaddr_addrdata(isa->dst_net), + sockaddr_addrdata(isa2->dst_net), + sockaddr_addrlen(isa->dst_net)) == 0 && + memcmp(sockaddr_addrdata(isa->dst_mask), + sockaddr_addrdata(isa2->dst_mask), + sockaddr_addrlen(isa->dst_mask)) == 0; } /* @@ -279,672 +279,663 @@ ipsec_sa_check_flow (struct sa *sa, void *v_arg) * the final message. */ static void -ipsec_finalize_exchange (struct message *msg) +ipsec_finalize_exchange(struct message * msg) { - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa; - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct sa *sa = 0, *old_sa; - struct proto *proto, *last_proto = 0; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct sa *sa = 0, *old_sa; + struct proto *proto, *last_proto = 0; #ifdef USE_DEBUG - char *addr1, *addr2, *mask1, *mask2; + char *addr1, *addr2, *mask1, *mask2; #endif - switch (exchange->phase) - { - case 1: - switch (exchange->type) - { - case ISAKMP_EXCH_ID_PROT: - case ISAKMP_EXCH_AGGRESSIVE: - isa = isakmp_sa->data; - isa->hash = ie->hash->type; - isa->prf_type = ie->prf_type; - isa->skeyid_len = ie->skeyid_len; - isa->skeyid_d = ie->skeyid_d; - isa->skeyid_a = ie->skeyid_a; - /* Prevents early free of SKEYID_*. */ - ie->skeyid_a = ie->skeyid_d = 0; - - /* If a lifetime was negotiated setup the expiration timers. */ - if (isakmp_sa->seconds) - sa_setup_expirations (isakmp_sa); - break; - } - break; - - case 2: - switch (exchange->type) - { - case IKE_EXCH_QUICK_MODE: - /* - * Tell the application(s) about the SPIs and key material. - */ - for (sa = TAILQ_FIRST (&exchange->sa_list); sa; - sa = TAILQ_NEXT (sa, next)) - { - isa = sa->data; - - if (exchange->initiator) - { - /* Initiator is source, responder is destination. */ - if (ipsec_set_network (ie->id_ci, ie->id_cr, isa)) - { - log_print ("ipsec_finalize_exchange: " - "ipsec_set_network failed"); - return; - } - } - else - { - /* Responder is source, initiator is destination. */ - if (ipsec_set_network (ie->id_cr, ie->id_ci, isa)) - { - log_print ("ipsec_finalize_exchange: " - "ipsec_set_network failed"); - return; - } - } - - for (proto = TAILQ_FIRST (&sa->protos), last_proto = 0; proto; - proto = TAILQ_NEXT (proto, link)) - { - if (sysdep_ipsec_set_spi (sa, proto, 0, isakmp_sa) - || (last_proto - && sysdep_ipsec_group_spis (sa, last_proto, proto, - 0)) - || sysdep_ipsec_set_spi (sa, proto, 1, isakmp_sa) - || (last_proto - && sysdep_ipsec_group_spis (sa, last_proto, proto, - 1))) - /* XXX Tear down this exchange. */ - return; - last_proto = proto; + switch (exchange->phase) { + case 1: + switch (exchange->type) { + case ISAKMP_EXCH_ID_PROT: + case ISAKMP_EXCH_AGGRESSIVE: + isa = isakmp_sa->data; + isa->hash = ie->hash->type; + isa->prf_type = ie->prf_type; + isa->skeyid_len = ie->skeyid_len; + isa->skeyid_d = ie->skeyid_d; + isa->skeyid_a = ie->skeyid_a; + /* Prevents early free of SKEYID_*. */ + ie->skeyid_a = ie->skeyid_d = 0; + + /* + * If a lifetime was negotiated setup the expiration + * timers. + */ + if (isakmp_sa->seconds) + sa_setup_expirations(isakmp_sa); + break; } + break; + + case 2: + switch (exchange->type) { + case IKE_EXCH_QUICK_MODE: + /* + * Tell the application(s) about the SPIs and key material. + */ + for (sa = TAILQ_FIRST(&exchange->sa_list); sa; + sa = TAILQ_NEXT(sa, next)) { + isa = sa->data; + + if (exchange->initiator) { + /* + * Initiator is source, responder is + * destination. + */ + if (ipsec_set_network(ie->id_ci, + ie->id_cr, isa)) { + log_print("ipsec_finalize_exchange: " + "ipsec_set_network failed"); + return; + } + } else { + /* + * Responder is source, initiator is + * destination. + */ + if (ipsec_set_network(ie->id_cr, ie->id_ci, + isa)) { + log_print("ipsec_finalize_exchange: " + "ipsec_set_network failed"); + return; + } + } + + for (proto = TAILQ_FIRST(&sa->protos), + last_proto = 0; proto; + proto = TAILQ_NEXT(proto, link)) { + if (sysdep_ipsec_set_spi(sa, proto, + 0, isakmp_sa) || + (last_proto && sysdep_ipsec_group_spis(sa, + last_proto, proto, 0)) || + sysdep_ipsec_set_spi(sa, proto, + 1, isakmp_sa) || + (last_proto && sysdep_ipsec_group_spis(sa, + last_proto, proto, 1))) + /* + * XXX Tear down this + * exchange. + */ + return; + last_proto = proto; + } #ifdef USE_DEBUG - if (sockaddr2text (isa->src_net, &addr1, 0)) - addr1 = 0; - if (sockaddr2text (isa->src_mask, &mask1, 0)) - mask1 = 0; - if (sockaddr2text (isa->dst_net, &addr2, 0)) - addr2 = 0; - if (sockaddr2text (isa->dst_mask, &mask2, 0)) - mask2 = 0; - - LOG_DBG ((LOG_EXCHANGE, 50, - "ipsec_finalize_exchange: " - "src %s %s dst %s %s tproto %u sport %u dport %u", - addr1 ? addr1 : "<??\?>" , mask1 ? mask1 : "<??\?>", - addr2 ? addr2 : "<??\?>" , mask2 ? mask2 : "<??\?>", - isa->tproto, ntohs (isa->sport), ntohs (isa->dport))); - - if (addr1) - free (addr1); - if (mask1) - free (mask1); - if (addr2) - free (addr2); - if (mask2) - free (mask2); - -#endif /* USE_DEBUG */ - - /* - * If this is not an SA acquired by the kernel, it needs - * to have a SPD entry (a.k.a. flow) set up. - */ - if (!(sa->flags & SA_FLAG_ONDEMAND) - && sysdep_ipsec_enable_sa (sa, isakmp_sa)) - /* XXX Tear down this exchange. */ - return; - - /* Mark elder SAs with the same flow information as replaced. */ - while ((old_sa = sa_find (ipsec_sa_check_flow, sa)) != 0) - sa_mark_replaced (old_sa); - } - break; + if (sockaddr2text(isa->src_net, &addr1, 0)) + addr1 = 0; + if (sockaddr2text(isa->src_mask, &mask1, 0)) + mask1 = 0; + if (sockaddr2text(isa->dst_net, &addr2, 0)) + addr2 = 0; + if (sockaddr2text(isa->dst_mask, &mask2, 0)) + mask2 = 0; + + LOG_DBG((LOG_EXCHANGE, 50, + "ipsec_finalize_exchange: " + "src %s %s dst %s %s tproto %u sport %u dport %u", + addr1 ? addr1 : "<??\?>", mask1 ? mask1 : "<??\?>", + addr2 ? addr2 : "<??\?>", mask2 ? mask2 : "<??\?>", + isa->tproto, ntohs(isa->sport), ntohs(isa->dport))); + + if (addr1) + free(addr1); + if (mask1) + free(mask1); + if (addr2) + free(addr2); + if (mask2) + free(mask2); + +#endif /* USE_DEBUG */ + + /* + * If this is not an SA acquired by the kernel, it needs + * to have a SPD entry (a.k.a. flow) set up. + */ + if (!(sa->flags & SA_FLAG_ONDEMAND) && + sysdep_ipsec_enable_sa(sa, isakmp_sa)) + /* XXX Tear down this exchange. */ + return; + + /* + * Mark elder SAs with the same flow + * information as replaced. + */ + while ((old_sa = sa_find(ipsec_sa_check_flow, sa)) != 0) + sa_mark_replaced(old_sa); + } + break; + } } - } } /* Set the client addresses in ISA from SRC_ID and DST_ID. */ static int -ipsec_set_network (u_int8_t *src_id, u_int8_t *dst_id, struct ipsec_sa *isa) +ipsec_set_network(u_int8_t *src_id, u_int8_t *dst_id, struct ipsec_sa *isa) { - int id; - - /* Set source address/mask. */ - id = GET_ISAKMP_ID_TYPE (src_id); - switch (id) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV4_ADDR_SUBNET: - isa->src_net = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); - if (!isa->src_net) - goto memfail; - isa->src_net->sa_family = AF_INET; + int id; + + /* Set source address/mask. */ + id = GET_ISAKMP_ID_TYPE(src_id); + switch (id) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV4_ADDR_SUBNET: + isa->src_net = (struct sockaddr *) calloc(1, + sizeof(struct sockaddr_in)); + if (!isa->src_net) + goto memfail; + isa->src_net->sa_family = AF_INET; #ifndef USE_OLD_SOCKADDR - isa->src_net->sa_len = sizeof (struct sockaddr_in); + isa->src_net->sa_len = sizeof(struct sockaddr_in); #endif - isa->src_mask = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); - if (!isa->src_mask) - goto memfail; - isa->src_mask->sa_family = AF_INET; + isa->src_mask = (struct sockaddr *) calloc(1, + sizeof(struct sockaddr_in)); + if (!isa->src_mask) + goto memfail; + isa->src_mask->sa_family = AF_INET; #ifndef USE_OLD_SOCKADDR - isa->src_mask->sa_len = sizeof (struct sockaddr_in); + isa->src_mask->sa_len = sizeof(struct sockaddr_in); #endif - break; - - case IPSEC_ID_IPV6_ADDR: - case IPSEC_ID_IPV6_ADDR_SUBNET: - isa->src_net = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); - if (!isa->src_net) - goto memfail; - isa->src_net->sa_family = AF_INET6; + break; + + case IPSEC_ID_IPV6_ADDR: + case IPSEC_ID_IPV6_ADDR_SUBNET: + isa->src_net = (struct sockaddr *) calloc(1, + sizeof(struct sockaddr_in6)); + if (!isa->src_net) + goto memfail; + isa->src_net->sa_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - isa->src_net->sa_len = sizeof (struct sockaddr_in6); + isa->src_net->sa_len = sizeof(struct sockaddr_in6); #endif - isa->src_mask = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); - if (!isa->src_mask) - goto memfail; - isa->src_mask->sa_family = AF_INET6; + isa->src_mask = (struct sockaddr *) calloc(1, + sizeof(struct sockaddr_in6)); + if (!isa->src_mask) + goto memfail; + isa->src_mask->sa_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - isa->src_mask->sa_len = sizeof (struct sockaddr_in6); + isa->src_mask->sa_len = sizeof(struct sockaddr_in6); #endif - break; - - case IPSEC_ID_IPV4_RANGE: - case IPSEC_ID_IPV6_RANGE: - case IPSEC_ID_DER_ASN1_DN: - case IPSEC_ID_DER_ASN1_GN: - case IPSEC_ID_KEY_ID: - default: - log_print ("ipsec_set_network: ID type %d (%s) not supported", - id, constant_name (ipsec_id_cst, id)); - return -1; - } - - /* Net */ - memcpy (sockaddr_addrdata (isa->src_net), src_id + ISAKMP_ID_DATA_OFF, - sockaddr_addrlen (isa->src_net)); - - /* Mask */ - switch (id) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - memset (sockaddr_addrdata (isa->src_mask), 0xff, - sockaddr_addrlen (isa->src_mask)); - break; - case IPSEC_ID_IPV4_ADDR_SUBNET: - case IPSEC_ID_IPV6_ADDR_SUBNET: - memcpy (sockaddr_addrdata (isa->src_mask), src_id + ISAKMP_ID_DATA_OFF + - sockaddr_addrlen (isa->src_net), - sockaddr_addrlen (isa->src_mask)); - break; - } - - memcpy (&isa->sport, src_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, - IPSEC_ID_PORT_LEN); - - /* Set destination address. */ - id = GET_ISAKMP_ID_TYPE (dst_id); - switch (id) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV4_ADDR_SUBNET: - isa->dst_net = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); - if (!isa->dst_net) - goto memfail; - isa->dst_net->sa_family = AF_INET; + break; + + case IPSEC_ID_IPV4_RANGE: + case IPSEC_ID_IPV6_RANGE: + case IPSEC_ID_DER_ASN1_DN: + case IPSEC_ID_DER_ASN1_GN: + case IPSEC_ID_KEY_ID: + default: + log_print("ipsec_set_network: ID type %d (%s) not supported", + id, constant_name(ipsec_id_cst, id)); + return -1; + } + + /* Net */ + memcpy(sockaddr_addrdata(isa->src_net), src_id + ISAKMP_ID_DATA_OFF, + sockaddr_addrlen(isa->src_net)); + + /* Mask */ + switch (id) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + memset(sockaddr_addrdata(isa->src_mask), 0xff, + sockaddr_addrlen(isa->src_mask)); + break; + case IPSEC_ID_IPV4_ADDR_SUBNET: + case IPSEC_ID_IPV6_ADDR_SUBNET: + memcpy(sockaddr_addrdata(isa->src_mask), src_id + ISAKMP_ID_DATA_OFF + + sockaddr_addrlen(isa->src_net), sockaddr_addrlen(isa->src_mask)); + break; + } + + memcpy(&isa->sport, src_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, + IPSEC_ID_PORT_LEN); + + /* Set destination address. */ + id = GET_ISAKMP_ID_TYPE(dst_id); + switch (id) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV4_ADDR_SUBNET: + isa->dst_net = + (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in)); + if (!isa->dst_net) + goto memfail; + isa->dst_net->sa_family = AF_INET; #ifndef USE_OLD_SOCKADDR - isa->dst_net->sa_len = sizeof (struct sockaddr_in); + isa->dst_net->sa_len = sizeof(struct sockaddr_in); #endif - isa->dst_mask = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); - if (!isa->dst_mask) - goto memfail; - isa->dst_mask->sa_family = AF_INET; + isa->dst_mask = + (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in)); + if (!isa->dst_mask) + goto memfail; + isa->dst_mask->sa_family = AF_INET; #ifndef USE_OLD_SOCKADDR - isa->dst_mask->sa_len = sizeof (struct sockaddr_in); + isa->dst_mask->sa_len = sizeof(struct sockaddr_in); #endif - break; - - case IPSEC_ID_IPV6_ADDR: - case IPSEC_ID_IPV6_ADDR_SUBNET: - isa->dst_net = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); - if (!isa->dst_net) - goto memfail; - isa->dst_net->sa_family = AF_INET6; + break; + + case IPSEC_ID_IPV6_ADDR: + case IPSEC_ID_IPV6_ADDR_SUBNET: + isa->dst_net = + (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in6)); + if (!isa->dst_net) + goto memfail; + isa->dst_net->sa_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - isa->dst_net->sa_len = sizeof (struct sockaddr_in6); + isa->dst_net->sa_len = sizeof(struct sockaddr_in6); #endif - isa->dst_mask = - (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); - if (!isa->dst_mask) - goto memfail; - isa->dst_mask->sa_family = AF_INET6; + isa->dst_mask = + (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in6)); + if (!isa->dst_mask) + goto memfail; + isa->dst_mask->sa_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - isa->dst_mask->sa_len = sizeof (struct sockaddr_in6); + isa->dst_mask->sa_len = sizeof(struct sockaddr_in6); #endif - break; - } - - /* Net */ - memcpy (sockaddr_addrdata (isa->dst_net), dst_id + ISAKMP_ID_DATA_OFF, - sockaddr_addrlen (isa->dst_net)); - - /* Mask */ - switch (id) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - memset (sockaddr_addrdata (isa->dst_mask), 0xff, - sockaddr_addrlen (isa->dst_mask)); - break; - case IPSEC_ID_IPV4_ADDR_SUBNET: - case IPSEC_ID_IPV6_ADDR_SUBNET: - memcpy (sockaddr_addrdata (isa->dst_mask), dst_id + ISAKMP_ID_DATA_OFF + - sockaddr_addrlen (isa->dst_net), - sockaddr_addrlen (isa->dst_mask)); - break; - } - - memcpy (&isa->tproto, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, - IPSEC_ID_PROTO_LEN); - memcpy (&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, - IPSEC_ID_PORT_LEN); - return 0; - - memfail: - log_error ("ipsec_set_network: calloc () failed"); - return -1; + break; + } + + /* Net */ + memcpy(sockaddr_addrdata(isa->dst_net), dst_id + ISAKMP_ID_DATA_OFF, + sockaddr_addrlen(isa->dst_net)); + + /* Mask */ + switch (id) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + memset(sockaddr_addrdata(isa->dst_mask), 0xff, + sockaddr_addrlen(isa->dst_mask)); + break; + case IPSEC_ID_IPV4_ADDR_SUBNET: + case IPSEC_ID_IPV6_ADDR_SUBNET: + memcpy(sockaddr_addrdata(isa->dst_mask), dst_id + ISAKMP_ID_DATA_OFF + + sockaddr_addrlen(isa->dst_net), + sockaddr_addrlen(isa->dst_mask)); + break; + } + + memcpy(&isa->tproto, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, + IPSEC_ID_PROTO_LEN); + memcpy(&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, + IPSEC_ID_PORT_LEN); + return 0; + +memfail: + log_error("ipsec_set_network: calloc () failed"); + return -1; } /* Free the DOI-specific exchange data pointed to by VIE. */ static void -ipsec_free_exchange_data (void *vie) +ipsec_free_exchange_data(void *vie) { - struct ipsec_exch *ie = vie; + struct ipsec_exch *ie = vie; #ifdef USE_ISAKMP_CFG - struct isakmp_cfg_attr *attr; + struct isakmp_cfg_attr *attr; #endif - if (ie->sa_i_b) - free (ie->sa_i_b); - if (ie->id_ci) - free (ie->id_ci); - if (ie->id_cr) - free (ie->id_cr); - if (ie->g_xi) - free (ie->g_xi); - if (ie->g_xr) - free (ie->g_xr); - if (ie->g_xy) - free (ie->g_xy); - if (ie->skeyid) - free (ie->skeyid); - if (ie->skeyid_d) - free (ie->skeyid_d); - if (ie->skeyid_a) - free (ie->skeyid_a); - if (ie->skeyid_e) - free (ie->skeyid_e); - if (ie->hash_i) - free (ie->hash_i); - if (ie->hash_r) - free (ie->hash_r); - if (ie->group) - group_free (ie->group); + if (ie->sa_i_b) + free(ie->sa_i_b); + if (ie->id_ci) + free(ie->id_ci); + if (ie->id_cr) + free(ie->id_cr); + if (ie->g_xi) + free(ie->g_xi); + if (ie->g_xr) + free(ie->g_xr); + if (ie->g_xy) + free(ie->g_xy); + if (ie->skeyid) + free(ie->skeyid); + if (ie->skeyid_d) + free(ie->skeyid_d); + if (ie->skeyid_a) + free(ie->skeyid_a); + if (ie->skeyid_e) + free(ie->skeyid_e); + if (ie->hash_i) + free(ie->hash_i); + if (ie->hash_r) + free(ie->hash_r); + if (ie->group) + group_free(ie->group); #ifdef USE_ISAKMP_CFG - for (attr = LIST_FIRST (&ie->attrs); attr; attr = LIST_FIRST (&ie->attrs)) - { - LIST_REMOVE (attr, link); - if (attr->length) - free (attr->value); - free (attr); - } + for (attr = LIST_FIRST(&ie->attrs); attr; attr = LIST_FIRST(&ie->attrs)) { + LIST_REMOVE(attr, link); + if (attr->length) + free(attr->value); + free(attr); + } #endif } /* Free the DOI-specific SA data pointed to by VISA. */ static void -ipsec_free_sa_data (void *visa) +ipsec_free_sa_data(void *visa) { - struct ipsec_sa *isa = visa; - - if (isa->src_net) - free (isa->src_net); - if (isa->src_mask) - free (isa->src_mask); - if (isa->dst_net) - free (isa->dst_net); - if (isa->dst_mask) - free (isa->dst_mask); - if (isa->skeyid_a) - free (isa->skeyid_a); - if (isa->skeyid_d) - free (isa->skeyid_d); + struct ipsec_sa *isa = visa; + + if (isa->src_net) + free(isa->src_net); + if (isa->src_mask) + free(isa->src_mask); + if (isa->dst_net) + free(isa->dst_net); + if (isa->dst_mask) + free(isa->dst_mask); + if (isa->skeyid_a) + free(isa->skeyid_a); + if (isa->skeyid_d) + free(isa->skeyid_d); } /* Free the DOI-specific protocol data of an SA pointed to by VIPROTO. */ static void -ipsec_free_proto_data (void *viproto) +ipsec_free_proto_data(void *viproto) { - struct ipsec_proto *iproto = viproto; - int i; + struct ipsec_proto *iproto = viproto; + int i; - for (i = 0; i < 2; i++) - if (iproto->keymat[i]) - free (iproto->keymat[i]); + for (i = 0; i < 2; i++) + if (iproto->keymat[i]) + free(iproto->keymat[i]); } /* Return exchange script based on TYPE. */ static int16_t * -ipsec_exchange_script (u_int8_t type) +ipsec_exchange_script(u_int8_t type) { - switch (type) - { + switch (type) { #ifdef USE_ISAKMP_CFG - case ISAKMP_EXCH_TRANSACTION: - return script_transaction; + case ISAKMP_EXCH_TRANSACTION: + return script_transaction; #endif - case IKE_EXCH_QUICK_MODE: - return script_quick_mode; - case IKE_EXCH_NEW_GROUP_MODE: - return script_new_group_mode; - } - return 0; + case IKE_EXCH_QUICK_MODE: + return script_quick_mode; + case IKE_EXCH_NEW_GROUP_MODE: + return script_new_group_mode; + } + return 0; } /* Initialize this DOI, requires doi_init to already have been called. */ void -ipsec_init (void) +ipsec_init(void) { - doi_register (&ipsec_doi); + doi_register(&ipsec_doi); } /* Given a message MSG, return a suitable IV (or rather keystate). */ static struct keystate * -ipsec_get_keystate (struct message *msg) +ipsec_get_keystate(struct message * msg) { - struct keystate *ks; - struct hash *hash; - - /* If we have already have an IV, use it. */ - if (msg->exchange && msg->exchange->keystate) - { - ks = malloc (sizeof *ks); - if (!ks) - { - log_error ("ipsec_get_keystate: malloc (%lu) failed", - (unsigned long)sizeof *ks); - return 0; + struct keystate *ks; + struct hash *hash; + + /* If we have already have an IV, use it. */ + if (msg->exchange && msg->exchange->keystate) { + ks = malloc(sizeof *ks); + if (!ks) { + log_error("ipsec_get_keystate: malloc (%lu) failed", + (unsigned long) sizeof *ks); + return 0; + } + memcpy(ks, msg->exchange->keystate, sizeof *ks); + return ks; } - memcpy (ks, msg->exchange->keystate, sizeof *ks); - return ks; - } - - /* - * For phase 2 when no SA yet is setup we need to hash the IV used by - * the ISAKMP SA concatenated with the message ID, and use that as an - * IV for further cryptographic operations. - */ - if (!msg->isakmp_sa->keystate) - { - log_print ("ipsec_get_keystate: no keystate in ISAKMP SA %p", - msg->isakmp_sa); - return 0; - } - ks = crypto_clone_keystate (msg->isakmp_sa->keystate); - if (!ks) - return 0; - - hash = hash_get (((struct ipsec_sa *)msg->isakmp_sa->data)->hash); - hash->Init (hash->ctx); - LOG_DBG_BUF ((LOG_CRYPTO, 80, "ipsec_get_keystate: final phase 1 IV", - ks->riv, ks->xf->blocksize)); - hash->Update (hash->ctx, ks->riv, ks->xf->blocksize); - LOG_DBG_BUF ((LOG_CRYPTO, 80, "ipsec_get_keystate: message ID", - ((u_int8_t *)msg->iov[0].iov_base) - + ISAKMP_HDR_MESSAGE_ID_OFF, - ISAKMP_HDR_MESSAGE_ID_LEN)); - hash->Update (hash->ctx, - ((u_int8_t *)msg->iov[0].iov_base) + ISAKMP_HDR_MESSAGE_ID_OFF, - ISAKMP_HDR_MESSAGE_ID_LEN); - hash->Final (hash->digest, hash->ctx); - crypto_init_iv (ks, hash->digest, ks->xf->blocksize); - LOG_DBG_BUF ((LOG_CRYPTO, 80, "ipsec_get_keystate: phase 2 IV", - hash->digest, ks->xf->blocksize)); - return ks; + /* + * For phase 2 when no SA yet is setup we need to hash the IV used by + * the ISAKMP SA concatenated with the message ID, and use that as an + * IV for further cryptographic operations. + */ + if (!msg->isakmp_sa->keystate) { + log_print("ipsec_get_keystate: no keystate in ISAKMP SA %p", + msg->isakmp_sa); + return 0; + } + ks = crypto_clone_keystate(msg->isakmp_sa->keystate); + if (!ks) + return 0; + + hash = hash_get(((struct ipsec_sa *) msg->isakmp_sa->data)->hash); + hash->Init(hash->ctx); + LOG_DBG_BUF((LOG_CRYPTO, 80, "ipsec_get_keystate: final phase 1 IV", + ks->riv, ks->xf->blocksize)); + hash->Update(hash->ctx, ks->riv, ks->xf->blocksize); + LOG_DBG_BUF((LOG_CRYPTO, 80, "ipsec_get_keystate: message ID", + ((u_int8_t *) msg->iov[0].iov_base) + + ISAKMP_HDR_MESSAGE_ID_OFF, + ISAKMP_HDR_MESSAGE_ID_LEN)); + hash->Update(hash->ctx, + ((u_int8_t *) msg->iov[0].iov_base) + ISAKMP_HDR_MESSAGE_ID_OFF, + ISAKMP_HDR_MESSAGE_ID_LEN); + hash->Final(hash->digest, hash->ctx); + crypto_init_iv(ks, hash->digest, ks->xf->blocksize); + LOG_DBG_BUF((LOG_CRYPTO, 80, "ipsec_get_keystate: phase 2 IV", + hash->digest, ks->xf->blocksize)); + return ks; } static void -ipsec_setup_situation (u_int8_t *buf) +ipsec_setup_situation(u_int8_t * buf) { - SET_IPSEC_SIT_SIT (buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY); + SET_IPSEC_SIT_SIT(buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY); } -static size_t -ipsec_situation_size (void) +static size_t +ipsec_situation_size(void) { - return IPSEC_SIT_SIT_LEN; + return IPSEC_SIT_SIT_LEN; } -static u_int8_t -ipsec_spi_size (u_int8_t proto) +static u_int8_t +ipsec_spi_size(u_int8_t proto) { - return IPSEC_SPI_SIZE; + return IPSEC_SPI_SIZE; } static int -ipsec_validate_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vmsg) +ipsec_validate_attribute(u_int16_t type, u_int8_t * value, u_int16_t len, + void *vmsg) { - struct message *msg = vmsg; - - if ((msg->exchange->phase == 1 - && (type < IKE_ATTR_ENCRYPTION_ALGORITHM - || type > IKE_ATTR_GROUP_ORDER)) - || (msg->exchange->phase == 2 - && (type < IPSEC_ATTR_SA_LIFE_TYPE - || type > IPSEC_ATTR_ECN_TUNNEL))) - return -1; - return 0; + struct message *msg = vmsg; + + if ((msg->exchange->phase == 1 + && (type < IKE_ATTR_ENCRYPTION_ALGORITHM + || type > IKE_ATTR_GROUP_ORDER)) + || (msg->exchange->phase == 2 + && (type < IPSEC_ATTR_SA_LIFE_TYPE + || type > IPSEC_ATTR_ECN_TUNNEL))) + return -1; + return 0; } static int -ipsec_validate_exchange (u_int8_t exch) +ipsec_validate_exchange(u_int8_t exch) { - return exch != IKE_EXCH_QUICK_MODE && exch != IKE_EXCH_NEW_GROUP_MODE; + return exch != IKE_EXCH_QUICK_MODE && exch != IKE_EXCH_NEW_GROUP_MODE; } static int -ipsec_validate_id_information (u_int8_t type, u_int8_t *extra, u_int8_t *buf, - size_t sz, struct exchange *exchange) +ipsec_validate_id_information(u_int8_t type, u_int8_t * extra, u_int8_t * buf, + size_t sz, struct exchange * exchange) { - u_int8_t proto = GET_IPSEC_ID_PROTO (extra); - u_int16_t port = GET_IPSEC_ID_PORT (extra); - - LOG_DBG ((LOG_MESSAGE, 40, - "ipsec_validate_id_information: proto %d port %d type %d", - proto, port, type)); - if (type < IPSEC_ID_IPV4_ADDR || type > IPSEC_ID_KEY_ID) - return -1; - - switch (type) - { - case IPSEC_ID_IPV4_ADDR: - LOG_DBG_BUF ((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv4", - buf, sizeof (struct in_addr))); - break; - - case IPSEC_ID_IPV6_ADDR: - LOG_DBG_BUF ((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv6", - buf, sizeof (struct in6_addr))); - break; - - case IPSEC_ID_IPV4_ADDR_SUBNET: - LOG_DBG_BUF ((LOG_MESSAGE, 40, - "ipsec_validate_id_information: IPv4 network/netmask", - buf, 2 * sizeof (struct in_addr))); - break; - - case IPSEC_ID_IPV6_ADDR_SUBNET: - LOG_DBG_BUF ((LOG_MESSAGE, 40, - "ipsec_validate_id_information: IPv6 network/netmask", - buf, 2 * sizeof (struct in6_addr))); - break; - - default: - break; - } - - if (exchange->phase == 1 - && (proto != IPPROTO_UDP || port != UDP_DEFAULT_PORT) - && (proto != 0 || port != 0)) - { -/* XXX SSH's ISAKMP tester fails this test (proto 17 - port 0). */ + u_int8_t proto = GET_IPSEC_ID_PROTO(extra); + u_int16_t port = GET_IPSEC_ID_PORT(extra); + + LOG_DBG((LOG_MESSAGE, 40, + "ipsec_validate_id_information: proto %d port %d type %d", + proto, port, type)); + if (type < IPSEC_ID_IPV4_ADDR || type > IPSEC_ID_KEY_ID) + return -1; + + switch (type) { + case IPSEC_ID_IPV4_ADDR: + LOG_DBG_BUF((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv4", + buf, sizeof(struct in_addr))); + break; + + case IPSEC_ID_IPV6_ADDR: + LOG_DBG_BUF((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv6", + buf, sizeof(struct in6_addr))); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + LOG_DBG_BUF((LOG_MESSAGE, 40, + "ipsec_validate_id_information: IPv4 network/netmask", + buf, 2 * sizeof(struct in_addr))); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + LOG_DBG_BUF((LOG_MESSAGE, 40, + "ipsec_validate_id_information: IPv6 network/netmask", + buf, 2 * sizeof(struct in6_addr))); + break; + + default: + break; + } + + if (exchange->phase == 1 + && (proto != IPPROTO_UDP || port != UDP_DEFAULT_PORT) + && (proto != 0 || port != 0)) { + /* + * XXX SSH's ISAKMP tester fails this test (proto 17 - port + * 0). + */ #ifdef notyet - return -1; + return -1; #else - log_print ("ipsec_validate_id_information: " - "dubious ID information accepted"); + log_print("ipsec_validate_id_information: " + "dubious ID information accepted"); #endif - } - - /* XXX More checks? */ + } + /* XXX More checks? */ - return 0; + return 0; } static int -ipsec_validate_key_information (u_int8_t *buf, size_t sz) +ipsec_validate_key_information(u_int8_t * buf, size_t sz) { - /* XXX Not implemented yet. */ - return 0; + /* XXX Not implemented yet. */ + return 0; } static int -ipsec_validate_notification (u_int16_t type) +ipsec_validate_notification(u_int16_t type) { - return type < IPSEC_NOTIFY_RESPONDER_LIFETIME - || type > IPSEC_NOTIFY_INITIAL_CONTACT ? -1 : 0; + return type < IPSEC_NOTIFY_RESPONDER_LIFETIME + || type > IPSEC_NOTIFY_INITIAL_CONTACT ? -1 : 0; } static int -ipsec_validate_proto (u_int8_t proto) +ipsec_validate_proto(u_int8_t proto) { - return proto < IPSEC_PROTO_IPSEC_AH || proto > IPSEC_PROTO_IPCOMP ? -1 : 0; + return proto < IPSEC_PROTO_IPSEC_AH || proto > IPSEC_PROTO_IPCOMP ? -1 : 0; } static int -ipsec_validate_situation (u_int8_t *buf, size_t *sz, size_t len) +ipsec_validate_situation(u_int8_t * buf, size_t * sz, size_t len) { - if (len < IPSEC_SIT_SIT_OFF + IPSEC_SIT_SIT_LEN) - { - log_print ("ipsec_validate_situation: payload too short: %u", - (unsigned int)len); - return -1; - } - - /* Currently only "identity only" situations are supported. */ - if (GET_IPSEC_SIT_SIT (buf) != IPSEC_SIT_IDENTITY_ONLY) - return 1; + if (len < IPSEC_SIT_SIT_OFF + IPSEC_SIT_SIT_LEN) { + log_print("ipsec_validate_situation: payload too short: %u", + (unsigned int) len); + return -1; + } + /* Currently only "identity only" situations are supported. */ + if (GET_IPSEC_SIT_SIT(buf) != IPSEC_SIT_IDENTITY_ONLY) + return 1; - *sz = IPSEC_SIT_SIT_LEN; + *sz = IPSEC_SIT_SIT_LEN; - return 0; + return 0; } static int -ipsec_validate_transform_id (u_int8_t proto, u_int8_t transform_id) +ipsec_validate_transform_id(u_int8_t proto, u_int8_t transform_id) { - switch (proto) - { - /* - * As no unexpected protocols can occur, we just tie the default case - * to the first case, in orer to silence a GCC warning. - */ - default: - case ISAKMP_PROTO_ISAKMP: - return transform_id != IPSEC_TRANSFORM_KEY_IKE; - case IPSEC_PROTO_IPSEC_AH: - return - transform_id < IPSEC_AH_MD5 || transform_id > IPSEC_AH_DES ? -1 : 0; - case IPSEC_PROTO_IPSEC_ESP: - return transform_id < IPSEC_ESP_DES_IV64 - || (transform_id > IPSEC_ESP_AES_128_CTR - && transform_id < IPSEC_ESP_AES_MARS) - || transform_id > IPSEC_ESP_AES_TWOFISH ? -1 : 0; - case IPSEC_PROTO_IPCOMP: - return transform_id < IPSEC_IPCOMP_OUI - || transform_id > IPSEC_IPCOMP_V42BIS ? -1 : 0; - } + switch (proto) { + /* + * As no unexpected protocols can occur, we just tie the default case + * to the first case, in orer to silence a GCC warning. + */ + default: + case ISAKMP_PROTO_ISAKMP: + return transform_id != IPSEC_TRANSFORM_KEY_IKE; + case IPSEC_PROTO_IPSEC_AH: + return + transform_id < IPSEC_AH_MD5 || transform_id > IPSEC_AH_DES ? -1 : 0; + case IPSEC_PROTO_IPSEC_ESP: + return transform_id < IPSEC_ESP_DES_IV64 + || (transform_id > IPSEC_ESP_AES_128_CTR + && transform_id < IPSEC_ESP_AES_MARS) + || transform_id > IPSEC_ESP_AES_TWOFISH ? -1 : 0; + case IPSEC_PROTO_IPCOMP: + return transform_id < IPSEC_IPCOMP_OUI + || transform_id > IPSEC_IPCOMP_V42BIS ? -1 : 0; + } } static int -ipsec_initiator (struct message *msg) +ipsec_initiator(struct message * msg) { - struct exchange *exchange = msg->exchange; - int (**script) (struct message *) = 0; - - /* Check that the SA is coherent with the IKE rules. */ - if (exchange->type != ISAKMP_EXCH_TRANSACTION - && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT - && exchange->type != ISAKMP_EXCH_AGGRESSIVE - && exchange->type != ISAKMP_EXCH_INFO) - || (exchange->phase == 2 && exchange->type != IKE_EXCH_QUICK_MODE - && exchange->type != ISAKMP_EXCH_INFO))) - { - log_print ("ipsec_initiator: unsupported exchange type %d in phase %d", - exchange->type, exchange->phase); - return -1; - } - - switch (exchange->type) - { - case ISAKMP_EXCH_ID_PROT: - script = ike_main_mode_initiator; - break; + struct exchange *exchange = msg->exchange; + int (**script) (struct message *) = 0; + + /* Check that the SA is coherent with the IKE rules. */ + if (exchange->type != ISAKMP_EXCH_TRANSACTION + && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT + && exchange->type != ISAKMP_EXCH_AGGRESSIVE + && exchange->type != ISAKMP_EXCH_INFO) + || (exchange->phase == 2 && exchange->type != IKE_EXCH_QUICK_MODE + && exchange->type != ISAKMP_EXCH_INFO))) { + log_print("ipsec_initiator: unsupported exchange type %d in phase %d", + exchange->type, exchange->phase); + return -1; + } + switch (exchange->type) { + case ISAKMP_EXCH_ID_PROT: + script = ike_main_mode_initiator; + break; #ifdef USE_AGGRESSIVE - case ISAKMP_EXCH_AGGRESSIVE: - script = ike_aggressive_initiator; - break; + case ISAKMP_EXCH_AGGRESSIVE: + script = ike_aggressive_initiator; + break; #endif #ifdef USE_ISAKMP_CFG - case ISAKMP_EXCH_TRANSACTION: - script = isakmp_cfg_initiator; - break; + case ISAKMP_EXCH_TRANSACTION: + script = isakmp_cfg_initiator; + break; #endif - case ISAKMP_EXCH_INFO: - return message_send_info (msg); - case IKE_EXCH_QUICK_MODE: - script = ike_quick_mode_initiator; - break; - default: - log_print ("ipsec_initiator: unsupported exchange type %d", - exchange->type); - return -1; - } - - /* Run the script code for this step. */ - if (script) - return script[exchange->step] (msg); - - return 0; + case ISAKMP_EXCH_INFO: + return message_send_info(msg); + case IKE_EXCH_QUICK_MODE: + script = ike_quick_mode_initiator; + break; + default: + log_print("ipsec_initiator: unsupported exchange type %d", + exchange->type); + return -1; + } + + /* Run the script code for this step. */ + if (script) + return script[exchange->step] (msg); + + return 0; } /* @@ -954,148 +945,138 @@ ipsec_initiator (struct message *msg) * or 4-octet otherwise. */ static void -ipsec_delete_spi_list (struct sockaddr *addr, u_int8_t proto, - u_int8_t *spis, int nspis, char *type) +ipsec_delete_spi_list(struct sockaddr * addr, u_int8_t proto, + u_int8_t * spis, int nspis, char *type) { - struct sa *sa; - int i; - - for (i = 0; i < nspis; i++) - { - if (proto == ISAKMP_PROTO_ISAKMP) - { - u_int8_t *spi = spis + i * ISAKMP_HDR_COOKIES_LEN; - - /* - * This really shouldn't happen in IPSEC DOI - * code, but Cisco VPN 3000 sends ISAKMP DELETE's - * this way. - */ - sa = sa_lookup_isakmp_sa (addr, spi); - } - else - { - u_int32_t spi = ((u_int32_t *)spis)[i]; - - sa = ipsec_sa_lookup (addr, spi, proto); - } - - if (sa == NULL) - { - LOG_DBG ((LOG_SA, 30, "ipsec_delete_spi_list: " - "could not locate SA (SPI %08x, proto %u)", - ((u_int32_t *)spis)[i], proto)); - continue; - } + struct sa *sa; + int i; + + for (i = 0; i < nspis; i++) { + if (proto == ISAKMP_PROTO_ISAKMP) { + u_int8_t *spi = spis + i * ISAKMP_HDR_COOKIES_LEN; + + /* + * This really shouldn't happen in IPSEC DOI + * code, but Cisco VPN 3000 sends ISAKMP DELETE's + * this way. + */ + sa = sa_lookup_isakmp_sa(addr, spi); + } else { + u_int32_t spi = ((u_int32_t *) spis)[i]; + + sa = ipsec_sa_lookup(addr, spi, proto); + } - /* Delete the SA and search for the next */ - LOG_DBG ((LOG_SA, 30, "ipsec_delete_spi_list: " - "%s made us delete SA %p (%d references) for proto %d", - type, sa, sa->refcnt, proto)); + if (sa == NULL) { + LOG_DBG((LOG_SA, 30, "ipsec_delete_spi_list: " + "could not locate SA (SPI %08x, proto %u)", + ((u_int32_t *) spis)[i], proto)); + continue; + } + /* Delete the SA and search for the next */ + LOG_DBG((LOG_SA, 30, "ipsec_delete_spi_list: " + "%s made us delete SA %p (%d references) for proto %d", + type, sa, sa->refcnt, proto)); - sa_free (sa); - } + sa_free(sa); + } } static int -ipsec_responder (struct message *msg) +ipsec_responder(struct message * msg) { - struct exchange *exchange = msg->exchange; - int (**script) (struct message *) = 0; - struct payload *p; - u_int16_t type; - - /* Check that a new exchange is coherent with the IKE rules. */ - if (exchange->step == 0 && exchange->type != ISAKMP_EXCH_TRANSACTION - && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT - && exchange->type != ISAKMP_EXCH_AGGRESSIVE - && exchange->type != ISAKMP_EXCH_INFO) - || (exchange->phase == 2 && exchange->type == ISAKMP_EXCH_ID_PROT))) - { - message_drop (msg, ISAKMP_NOTIFY_UNSUPPORTED_EXCHANGE_TYPE, 0, 1, 0); - return -1; - } - - LOG_DBG ((LOG_MISC, 30, - "ipsec_responder: phase %d exchange %d step %d", exchange->phase, - exchange->type, exchange->step)); - switch (exchange->type) - { - case ISAKMP_EXCH_ID_PROT: - script = ike_main_mode_responder; - break; + struct exchange *exchange = msg->exchange; + int (**script) (struct message *) = 0; + struct payload *p; + u_int16_t type; + + /* Check that a new exchange is coherent with the IKE rules. */ + if (exchange->step == 0 && exchange->type != ISAKMP_EXCH_TRANSACTION + && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT + && exchange->type != ISAKMP_EXCH_AGGRESSIVE + && exchange->type != ISAKMP_EXCH_INFO) + || (exchange->phase == 2 && exchange->type == ISAKMP_EXCH_ID_PROT))) { + message_drop(msg, ISAKMP_NOTIFY_UNSUPPORTED_EXCHANGE_TYPE, 0, 1, 0); + return -1; + } + LOG_DBG((LOG_MISC, 30, + "ipsec_responder: phase %d exchange %d step %d", exchange->phase, + exchange->type, exchange->step)); + switch (exchange->type) { + case ISAKMP_EXCH_ID_PROT: + script = ike_main_mode_responder; + break; #ifdef USE_AGGRESSIVE - case ISAKMP_EXCH_AGGRESSIVE: - script = ike_aggressive_responder; - break; + case ISAKMP_EXCH_AGGRESSIVE: + script = ike_aggressive_responder; + break; #endif #ifdef USE_ISAKMP_CFG - case ISAKMP_EXCH_TRANSACTION: - script = isakmp_cfg_responder; - break; + case ISAKMP_EXCH_TRANSACTION: + script = isakmp_cfg_responder; + break; #endif - case ISAKMP_EXCH_INFO: - for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_NOTIFY]); p; - p = TAILQ_NEXT (p, link)) - { - type = GET_ISAKMP_NOTIFY_MSG_TYPE (p->p); - LOG_DBG ((LOG_EXCHANGE, 10, - "ipsec_responder: got NOTIFY of type %s", - constant_name (isakmp_notify_cst, type))); + case ISAKMP_EXCH_INFO: + for (p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_NOTIFY]); p; + p = TAILQ_NEXT(p, link)) { + type = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p); + LOG_DBG((LOG_EXCHANGE, 10, + "ipsec_responder: got NOTIFY of type %s", + constant_name(isakmp_notify_cst, type))); - p->flags |= PL_MARK; + p->flags |= PL_MARK; + } + + /* + * If any DELETEs are in here, let the logic of leftover payloads deal + * with them. + */ + + return 0; + + case IKE_EXCH_QUICK_MODE: + script = ike_quick_mode_responder; + break; + + default: + message_drop(msg, ISAKMP_NOTIFY_UNSUPPORTED_EXCHANGE_TYPE, 0, 1, 0); + return -1; } - /* - * If any DELETEs are in here, let the logic of leftover payloads deal - * with them. - */ - - return 0; - - case IKE_EXCH_QUICK_MODE: - script = ike_quick_mode_responder; - break; - - default: - message_drop (msg, ISAKMP_NOTIFY_UNSUPPORTED_EXCHANGE_TYPE, 0, 1, 0); - return -1; - } - - /* Run the script code for this step. */ - if (script) - return script[exchange->step] (msg); - - /* - * XXX So far we don't accept any proposals for exchanges we don't support. - */ - if (TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA])) - { - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - return -1; - } - return 0; + /* Run the script code for this step. */ + if (script) + return script[exchange->step] (msg); + + /* + * XXX So far we don't accept any proposals for exchanges we don't support. + */ + if (TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SA])) { + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + return -1; + } + return 0; } -static enum hashes from_ike_hash (u_int16_t hash) +static enum hashes +from_ike_hash(u_int16_t hash) { - switch (hash) - { - case IKE_HASH_MD5: - return HASH_MD5; - case IKE_HASH_SHA: - return HASH_SHA1; - } - return -1; + switch (hash) { + case IKE_HASH_MD5: + return HASH_MD5; + case IKE_HASH_SHA: + return HASH_SHA1; + } + return -1; } -static enum transform from_ike_crypto (u_int16_t crypto) +static enum transform +from_ike_crypto(u_int16_t crypto) { - /* Coincidentally this is the null operation :-) */ - return crypto; + /* Coincidentally this is the null operation :-) */ + return crypto; } /* @@ -1104,92 +1085,90 @@ static enum transform from_ike_crypto (u_int16_t crypto) * VMSG is a pointer to the current message. */ int -ipsec_is_attribute_incompatible (u_int16_t type, u_int8_t *value, - u_int16_t len, void *vmsg) +ipsec_is_attribute_incompatible(u_int16_t type, u_int8_t * value, + u_int16_t len, void *vmsg) { - struct message *msg = vmsg; - - if (msg->exchange->phase == 1) - { - switch (type) - { - case IKE_ATTR_ENCRYPTION_ALGORITHM: - return !crypto_get (from_ike_crypto (decode_16 (value))); - case IKE_ATTR_HASH_ALGORITHM: - return !hash_get (from_ike_hash (decode_16 (value))); - case IKE_ATTR_AUTHENTICATION_METHOD: - return !ike_auth_get (decode_16 (value)); - case IKE_ATTR_GROUP_DESCRIPTION: - return (decode_16 (value) < IKE_GROUP_DESC_MODP_768 - || decode_16 (value) > IKE_GROUP_DESC_MODP_1536) - && (decode_16 (value) < IKE_GROUP_DESC_MODP_2048 - || decode_16 (value) > IKE_GROUP_DESC_MODP_8192); - case IKE_ATTR_GROUP_TYPE: - return 1; - case IKE_ATTR_GROUP_PRIME: - return 1; - case IKE_ATTR_GROUP_GENERATOR_1: - return 1; - case IKE_ATTR_GROUP_GENERATOR_2: - return 1; - case IKE_ATTR_GROUP_CURVE_A: - return 1; - case IKE_ATTR_GROUP_CURVE_B: - return 1; - case IKE_ATTR_LIFE_TYPE: - return decode_16 (value) < IKE_DURATION_SECONDS - || decode_16 (value) > IKE_DURATION_KILOBYTES; - case IKE_ATTR_LIFE_DURATION: - return len != 2 && len != 4; - case IKE_ATTR_PRF: - return 1; - case IKE_ATTR_KEY_LENGTH: - /* - * Our crypto routines only allows key-lengths which are multiples - * of an octet. - */ - return decode_16 (value) % 8 != 0; - case IKE_ATTR_FIELD_SIZE: - return 1; - case IKE_ATTR_GROUP_ORDER: - return 1; - } - } - else - { - switch (type) - { - case IPSEC_ATTR_SA_LIFE_TYPE: - return decode_16 (value) < IPSEC_DURATION_SECONDS - || decode_16 (value) > IPSEC_DURATION_KILOBYTES; - case IPSEC_ATTR_SA_LIFE_DURATION: - return len != 2 && len != 4; - case IPSEC_ATTR_GROUP_DESCRIPTION: - return (decode_16 (value) < IKE_GROUP_DESC_MODP_768 - || decode_16 (value) > IKE_GROUP_DESC_MODP_1536) - && (decode_16 (value) < IKE_GROUP_DESC_MODP_2048 - || IKE_GROUP_DESC_MODP_8192 < decode_16 (value)); - case IPSEC_ATTR_ENCAPSULATION_MODE: - return decode_16 (value) < IPSEC_ENCAP_TUNNEL - || decode_16 (value) > IPSEC_ENCAP_TRANSPORT; - case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: - return decode_16 (value) < IPSEC_AUTH_HMAC_MD5 - || decode_16 (value) > IPSEC_AUTH_HMAC_RIPEMD; - case IPSEC_ATTR_KEY_LENGTH: - /* XXX Blowfish needs '0'. Others appear to disregard this attr? */ - return 0; - case IPSEC_ATTR_KEY_ROUNDS: - return 1; - case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: - return 1; - case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: - return 1; - case IPSEC_ATTR_ECN_TUNNEL: - return 1; + struct message *msg = vmsg; + + if (msg->exchange->phase == 1) { + switch (type) { + case IKE_ATTR_ENCRYPTION_ALGORITHM: + return !crypto_get(from_ike_crypto(decode_16(value))); + case IKE_ATTR_HASH_ALGORITHM: + return !hash_get(from_ike_hash(decode_16(value))); + case IKE_ATTR_AUTHENTICATION_METHOD: + return !ike_auth_get(decode_16(value)); + case IKE_ATTR_GROUP_DESCRIPTION: + return (decode_16(value) < IKE_GROUP_DESC_MODP_768 + || decode_16(value) > IKE_GROUP_DESC_MODP_1536) + && (decode_16(value) < IKE_GROUP_DESC_MODP_2048 + || decode_16(value) > IKE_GROUP_DESC_MODP_8192); + case IKE_ATTR_GROUP_TYPE: + return 1; + case IKE_ATTR_GROUP_PRIME: + return 1; + case IKE_ATTR_GROUP_GENERATOR_1: + return 1; + case IKE_ATTR_GROUP_GENERATOR_2: + return 1; + case IKE_ATTR_GROUP_CURVE_A: + return 1; + case IKE_ATTR_GROUP_CURVE_B: + return 1; + case IKE_ATTR_LIFE_TYPE: + return decode_16(value) < IKE_DURATION_SECONDS + || decode_16(value) > IKE_DURATION_KILOBYTES; + case IKE_ATTR_LIFE_DURATION: + return len != 2 && len != 4; + case IKE_ATTR_PRF: + return 1; + case IKE_ATTR_KEY_LENGTH: + /* + * Our crypto routines only allows key-lengths which are multiples + * of an octet. + */ + return decode_16(value) % 8 != 0; + case IKE_ATTR_FIELD_SIZE: + return 1; + case IKE_ATTR_GROUP_ORDER: + return 1; + } + } else { + switch (type) { + case IPSEC_ATTR_SA_LIFE_TYPE: + return decode_16(value) < IPSEC_DURATION_SECONDS + || decode_16(value) > IPSEC_DURATION_KILOBYTES; + case IPSEC_ATTR_SA_LIFE_DURATION: + return len != 2 && len != 4; + case IPSEC_ATTR_GROUP_DESCRIPTION: + return (decode_16(value) < IKE_GROUP_DESC_MODP_768 + || decode_16(value) > IKE_GROUP_DESC_MODP_1536) + && (decode_16(value) < IKE_GROUP_DESC_MODP_2048 + || IKE_GROUP_DESC_MODP_8192 < decode_16(value)); + case IPSEC_ATTR_ENCAPSULATION_MODE: + return decode_16(value) < IPSEC_ENCAP_TUNNEL + || decode_16(value) > IPSEC_ENCAP_TRANSPORT; + case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: + return decode_16(value) < IPSEC_AUTH_HMAC_MD5 + || decode_16(value) > IPSEC_AUTH_HMAC_RIPEMD; + case IPSEC_ATTR_KEY_LENGTH: + /* + * XXX Blowfish needs '0'. Others appear to disregard + * this attr? + */ + return 0; + case IPSEC_ATTR_KEY_ROUNDS: + return 1; + case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: + return 1; + case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: + return 1; + case IPSEC_ATTR_ECN_TUNNEL: + return 1; + } } - } - /* XXX Silence gcc. */ - return 1; + /* XXX Silence gcc. */ + return 1; } #ifdef USE_DEBUG @@ -1198,25 +1177,25 @@ ipsec_is_attribute_incompatible (u_int16_t type, u_int8_t *value, * in human-readable form. VMSG is a pointer to the current message. */ int -ipsec_debug_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vmsg) +ipsec_debug_attribute(u_int16_t type, u_int8_t * value, u_int16_t len, + void *vmsg) { - struct message *msg = vmsg; - char val[20]; - - /* XXX Transient solution. */ - if (len == 2) - snprintf (val, sizeof val, "%d", decode_16 (value)); - else if (len == 4) - snprintf (val, sizeof val, "%d", decode_32 (value)); - else - snprintf (val, sizeof val, "unrepresentable"); - - LOG_DBG ((LOG_MESSAGE, 50, "Attribute %s value %s", - constant_name (msg->exchange->phase == 1 - ? ike_attr_cst : ipsec_attr_cst, type), - val)); - return 0; + struct message *msg = vmsg; + char val[20]; + + /* XXX Transient solution. */ + if (len == 2) + snprintf(val, sizeof val, "%d", decode_16(value)); + else if (len == 4) + snprintf(val, sizeof val, "%d", decode_32(value)); + else + snprintf(val, sizeof val, "unrepresentable"); + + LOG_DBG((LOG_MESSAGE, 50, "Attribute %s value %s", + constant_name(msg->exchange->phase == 1 + ? ike_attr_cst : ipsec_attr_cst, type), + val)); + return 0; } #endif @@ -1226,163 +1205,155 @@ ipsec_debug_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, * current message, SA and protocol. */ int -ipsec_decode_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vida) +ipsec_decode_attribute(u_int16_t type, u_int8_t * value, u_int16_t len, + void *vida) { - struct ipsec_decode_arg *ida = vida; - struct message *msg = ida->msg; - struct sa *sa = ida->sa; - struct ipsec_sa *isa = sa->data; - struct proto *proto = ida->proto; - struct ipsec_proto *iproto = proto->data; - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - static int lifetype = 0; - - if (exchange->phase == 1) - { - switch (type) - { - case IKE_ATTR_ENCRYPTION_ALGORITHM: - /* XXX Errors possible? */ - exchange->crypto = crypto_get (from_ike_crypto (decode_16 (value))); - break; - case IKE_ATTR_HASH_ALGORITHM: - /* XXX Errors possible? */ - ie->hash = hash_get (from_ike_hash (decode_16 (value))); - break; - case IKE_ATTR_AUTHENTICATION_METHOD: - /* XXX Errors possible? */ - ie->ike_auth = ike_auth_get (decode_16 (value)); - break; - case IKE_ATTR_GROUP_DESCRIPTION: - isa->group_desc = decode_16 (value); - break; - case IKE_ATTR_GROUP_TYPE: - break; - case IKE_ATTR_GROUP_PRIME: - break; - case IKE_ATTR_GROUP_GENERATOR_1: - break; - case IKE_ATTR_GROUP_GENERATOR_2: - break; - case IKE_ATTR_GROUP_CURVE_A: - break; - case IKE_ATTR_GROUP_CURVE_B: - break; - case IKE_ATTR_LIFE_TYPE: - lifetype = decode_16 (value); - return 0; - case IKE_ATTR_LIFE_DURATION: - switch (lifetype) - { - case IKE_DURATION_SECONDS: - switch (len) - { - case 2: - sa->seconds = decode_16 (value); - break; - case 4: - sa->seconds = decode_32 (value); - break; - default: - log_print ("ipsec_decode_attribute: unreasonable lifetime"); + struct ipsec_decode_arg *ida = vida; + struct message *msg = ida->msg; + struct sa *sa = ida->sa; + struct ipsec_sa *isa = sa->data; + struct proto *proto = ida->proto; + struct ipsec_proto *iproto = proto->data; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + static int lifetype = 0; + + if (exchange->phase == 1) { + switch (type) { + case IKE_ATTR_ENCRYPTION_ALGORITHM: + /* XXX Errors possible? */ + exchange->crypto = crypto_get(from_ike_crypto(decode_16(value))); + break; + case IKE_ATTR_HASH_ALGORITHM: + /* XXX Errors possible? */ + ie->hash = hash_get(from_ike_hash(decode_16(value))); + break; + case IKE_ATTR_AUTHENTICATION_METHOD: + /* XXX Errors possible? */ + ie->ike_auth = ike_auth_get(decode_16(value)); + break; + case IKE_ATTR_GROUP_DESCRIPTION: + isa->group_desc = decode_16(value); + break; + case IKE_ATTR_GROUP_TYPE: + break; + case IKE_ATTR_GROUP_PRIME: + break; + case IKE_ATTR_GROUP_GENERATOR_1: + break; + case IKE_ATTR_GROUP_GENERATOR_2: + break; + case IKE_ATTR_GROUP_CURVE_A: + break; + case IKE_ATTR_GROUP_CURVE_B: + break; + case IKE_ATTR_LIFE_TYPE: + lifetype = decode_16(value); + return 0; + case IKE_ATTR_LIFE_DURATION: + switch (lifetype) { + case IKE_DURATION_SECONDS: + switch (len) { + case 2: + sa->seconds = decode_16(value); + break; + case 4: + sa->seconds = decode_32(value); + break; + default: + log_print("ipsec_decode_attribute: unreasonable lifetime"); + } + break; + case IKE_DURATION_KILOBYTES: + switch (len) { + case 2: + sa->kilobytes = decode_16(value); + break; + case 4: + sa->kilobytes = decode_32(value); + break; + default: + log_print("ipsec_decode_attribute: unreasonable lifetime"); + } + break; + default: + log_print("ipsec_decode_attribute: unknown lifetime type"); + } + break; + case IKE_ATTR_PRF: + break; + case IKE_ATTR_KEY_LENGTH: + exchange->key_length = decode_16(value) / 8; + break; + case IKE_ATTR_FIELD_SIZE: + break; + case IKE_ATTR_GROUP_ORDER: + break; } - break; - case IKE_DURATION_KILOBYTES: - switch (len) - { - case 2: - sa->kilobytes = decode_16 (value); - break; - case 4: - sa->kilobytes = decode_32 (value); - break; - default: - log_print ("ipsec_decode_attribute: unreasonable lifetime"); + } else { + switch (type) { + case IPSEC_ATTR_SA_LIFE_TYPE: + lifetype = decode_16(value); + return 0; + case IPSEC_ATTR_SA_LIFE_DURATION: + switch (lifetype) { + case IPSEC_DURATION_SECONDS: + switch (len) { + case 2: + sa->seconds = decode_16(value); + break; + case 4: + sa->seconds = decode_32(value); + break; + default: + log_print("ipsec_decode_attribute: unreasonable lifetime"); + } + break; + case IPSEC_DURATION_KILOBYTES: + switch (len) { + case 2: + sa->kilobytes = decode_16(value); + break; + case 4: + sa->kilobytes = decode_32(value); + break; + default: + log_print("ipsec_decode_attribute: unreasonable lifetime"); + } + break; + default: + log_print("ipsec_decode_attribute: unknown lifetime type"); + } + break; + case IPSEC_ATTR_GROUP_DESCRIPTION: + isa->group_desc = decode_16(value); + break; + case IPSEC_ATTR_ENCAPSULATION_MODE: + /* + * XXX Multiple protocols must have same + * encapsulation mode, no? + */ + iproto->encap_mode = decode_16(value); + break; + case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: + iproto->auth = decode_16(value); + break; + case IPSEC_ATTR_KEY_LENGTH: + iproto->keylen = decode_16(value); + break; + case IPSEC_ATTR_KEY_ROUNDS: + iproto->keyrounds = decode_16(value); + break; + case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: + break; + case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: + break; + case IPSEC_ATTR_ECN_TUNNEL: + break; } - break; - default: - log_print ("ipsec_decode_attribute: unknown lifetime type"); - } - break; - case IKE_ATTR_PRF: - break; - case IKE_ATTR_KEY_LENGTH: - exchange->key_length = decode_16 (value) / 8; - break; - case IKE_ATTR_FIELD_SIZE: - break; - case IKE_ATTR_GROUP_ORDER: - break; } - } - else - { - switch (type) - { - case IPSEC_ATTR_SA_LIFE_TYPE: - lifetype = decode_16 (value); - return 0; - case IPSEC_ATTR_SA_LIFE_DURATION: - switch (lifetype) - { - case IPSEC_DURATION_SECONDS: - switch (len) - { - case 2: - sa->seconds = decode_16 (value); - break; - case 4: - sa->seconds = decode_32 (value); - break; - default: - log_print ("ipsec_decode_attribute: unreasonable lifetime"); - } - break; - case IPSEC_DURATION_KILOBYTES: - switch (len) - { - case 2: - sa->kilobytes = decode_16 (value); - break; - case 4: - sa->kilobytes = decode_32 (value); - break; - default: - log_print ("ipsec_decode_attribute: unreasonable lifetime"); - } - break; - default: - log_print ("ipsec_decode_attribute: unknown lifetime type"); - } - break; - case IPSEC_ATTR_GROUP_DESCRIPTION: - isa->group_desc = decode_16 (value); - break; - case IPSEC_ATTR_ENCAPSULATION_MODE: - /* XXX Multiple protocols must have same encapsulation mode, no? */ - iproto->encap_mode = decode_16 (value); - break; - case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: - iproto->auth = decode_16 (value); - break; - case IPSEC_ATTR_KEY_LENGTH: - iproto->keylen = decode_16 (value); - break; - case IPSEC_ATTR_KEY_ROUNDS: - iproto->keyrounds = decode_16 (value); - break; - case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: - break; - case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: - break; - case IPSEC_ATTR_ECN_TUNNEL: - break; - } - } - lifetype = 0; - return 0; + lifetype = 0; + return 0; } /* @@ -1391,34 +1362,34 @@ ipsec_decode_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, * processed. */ void -ipsec_decode_transform (struct message *msg, struct sa *sa, - struct proto *proto, u_int8_t *buf) +ipsec_decode_transform(struct message * msg, struct sa * sa, + struct proto * proto, u_int8_t * buf) { - struct ipsec_exch *ie = msg->exchange->data; - struct ipsec_decode_arg ida; - - LOG_DBG ((LOG_MISC, 20, "ipsec_decode_transform: transform %d chosen", - GET_ISAKMP_TRANSFORM_NO (buf))); - - ida.msg = msg; - ida.sa = sa; - ida.proto = proto; - - /* The default IKE lifetime is 8 hours. */ - if (sa->phase == 1) - sa->seconds = 28800; - - /* Extract the attributes and stuff them into the SA. */ - attribute_map (buf + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (buf) - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - ipsec_decode_attribute, &ida); - - /* - * If no pseudo-random function was negotiated, it's HMAC. - * XXX As PRF_HMAC currently is zero, this is a no-op. - */ - if (!ie->prf_type) - ie->prf_type = PRF_HMAC; + struct ipsec_exch *ie = msg->exchange->data; + struct ipsec_decode_arg ida; + + LOG_DBG((LOG_MISC, 20, "ipsec_decode_transform: transform %d chosen", + GET_ISAKMP_TRANSFORM_NO(buf))); + + ida.msg = msg; + ida.sa = sa; + ida.proto = proto; + + /* The default IKE lifetime is 8 hours. */ + if (sa->phase == 1) + sa->seconds = 28800; + + /* Extract the attributes and stuff them into the SA. */ + attribute_map(buf + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(buf) - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + ipsec_decode_attribute, &ida); + + /* + * If no pseudo-random function was negotiated, it's HMAC. + * XXX As PRF_HMAC currently is zero, this is a no-op. + */ + if (!ie->prf_type) + ie->prf_type = PRF_HMAC; } /* @@ -1426,12 +1397,12 @@ ipsec_decode_transform (struct message *msg, struct sa *sa, * of the IKE security association SA. */ static void -ipsec_delete_spi (struct sa *sa, struct proto *proto, int incoming) +ipsec_delete_spi(struct sa * sa, struct proto * proto, int incoming) { - if (sa->phase == 1) - return; - /* XXX Error handling? Is it interesting? */ - sysdep_ipsec_delete_spi (sa, proto, incoming); + if (sa->phase == 1) + return; + /* XXX Error handling? Is it interesting? */ + sysdep_ipsec_delete_spi(sa, proto, incoming); } /* @@ -1439,80 +1410,72 @@ ipsec_delete_spi (struct sa *sa, struct proto *proto, int incoming) * PEER is non-zero when the value is our peer's, and zero when it is ours. */ static int -ipsec_g_x (struct message *msg, int peer, u_int8_t *buf) +ipsec_g_x(struct message * msg, int peer, u_int8_t * buf) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - u_int8_t **g_x; - int initiator = exchange->initiator ^ peer; - char header[32]; - - g_x = initiator ? &ie->g_xi : &ie->g_xr; - *g_x = malloc (ie->g_x_len); - if (!*g_x) - { - log_error ("ipsec_g_x: malloc (%lu) failed", (unsigned long)ie->g_x_len); - return -1; - } - memcpy (*g_x, buf, ie->g_x_len); - snprintf (header, sizeof header, "ipsec_g_x: g^x%c", initiator ? 'i' : 'r'); - LOG_DBG_BUF ((LOG_MISC, 80, header, *g_x, ie->g_x_len)); - return 0; + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + u_int8_t **g_x; + int initiator = exchange->initiator ^ peer; + char header[32]; + + g_x = initiator ? &ie->g_xi : &ie->g_xr; + *g_x = malloc(ie->g_x_len); + if (!*g_x) { + log_error("ipsec_g_x: malloc (%lu) failed", (unsigned long) ie->g_x_len); + return -1; + } + memcpy(*g_x, buf, ie->g_x_len); + snprintf(header, sizeof header, "ipsec_g_x: g^x%c", initiator ? 'i' : 'r'); + LOG_DBG_BUF((LOG_MISC, 80, header, *g_x, ie->g_x_len)); + return 0; } /* Generate our DH value. */ int -ipsec_gen_g_x (struct message *msg) +ipsec_gen_g_x(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - u_int8_t *buf; - - buf = malloc (ISAKMP_KE_SZ + ie->g_x_len); - if (!buf) - { - log_error ("ipsec_gen_g_x: malloc (%lu) failed", - ISAKMP_KE_SZ + (unsigned long)ie->g_x_len); - return -1; - } - - if (message_add_payload (msg, ISAKMP_PAYLOAD_KEY_EXCH, buf, - ISAKMP_KE_SZ + ie->g_x_len, 1)) - { - free (buf); - return -1; - } - - if (dh_create_exchange (ie->group, buf + ISAKMP_KE_DATA_OFF)) - { - log_print ("ipsec_gen_g_x: dh_create_exchange failed"); - free (buf); - return -1; - } - return ipsec_g_x (msg, 0, buf + ISAKMP_KE_DATA_OFF); + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + u_int8_t *buf; + + buf = malloc(ISAKMP_KE_SZ + ie->g_x_len); + if (!buf) { + log_error("ipsec_gen_g_x: malloc (%lu) failed", + ISAKMP_KE_SZ + (unsigned long) ie->g_x_len); + return -1; + } + if (message_add_payload(msg, ISAKMP_PAYLOAD_KEY_EXCH, buf, + ISAKMP_KE_SZ + ie->g_x_len, 1)) { + free(buf); + return -1; + } + if (dh_create_exchange(ie->group, buf + ISAKMP_KE_DATA_OFF)) { + log_print("ipsec_gen_g_x: dh_create_exchange failed"); + free(buf); + return -1; + } + return ipsec_g_x(msg, 0, buf + ISAKMP_KE_DATA_OFF); } /* Save the peer's DH value. */ int -ipsec_save_g_x (struct message *msg) +ipsec_save_g_x(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct ipsec_exch *ie = exchange->data; - struct payload *kep; - - kep = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]); - kep->flags |= PL_MARK; - ie->g_x_len = GET_ISAKMP_GEN_LENGTH (kep->p) - ISAKMP_KE_DATA_OFF; - - /* Check that the given length matches the group's expectancy. */ - if (ie->g_x_len != (size_t)dh_getlen (ie->group)) - { - /* XXX Is this a good notify type? */ - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - return ipsec_g_x (msg, 1, kep->p + ISAKMP_KE_DATA_OFF); + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct payload *kep; + + kep = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]); + kep->flags |= PL_MARK; + ie->g_x_len = GET_ISAKMP_GEN_LENGTH(kep->p) - ISAKMP_KE_DATA_OFF; + + /* Check that the given length matches the group's expectancy. */ + if (ie->g_x_len != (size_t) dh_getlen(ie->group)) { + /* XXX Is this a good notify type? */ + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + return ipsec_g_x(msg, 1, kep->p + ISAKMP_KE_DATA_OFF); } /* @@ -1520,24 +1483,21 @@ ipsec_save_g_x (struct message *msg) * size where SZ points. NB! A zero return is OK if *SZ is zero. */ static u_int8_t * -ipsec_get_spi (size_t *sz, u_int8_t proto, struct message *msg) +ipsec_get_spi(size_t * sz, u_int8_t proto, struct message * msg) { - struct sockaddr *dst, *src; - struct transport *transport = msg->transport; - - if (msg->exchange->phase == 1) - { - *sz = 0; - return 0; - } - else - { - /* We are the destination in the SA we want a SPI for. */ - transport->vtbl->get_src (transport, &dst); - /* The peer is the source. */ - transport->vtbl->get_dst (transport, &src); - return sysdep_ipsec_get_spi (sz, proto, src, dst, msg->exchange->seq); - } + struct sockaddr *dst, *src; + struct transport *transport = msg->transport; + + if (msg->exchange->phase == 1) { + *sz = 0; + return 0; + } else { + /* We are the destination in the SA we want a SPI for. */ + transport->vtbl->get_src(transport, &dst); + /* The peer is the source. */ + transport->vtbl->get_dst(transport, &src); + return sysdep_ipsec_get_spi(sz, proto, src, dst, msg->exchange->seq); + } } /* @@ -1547,215 +1507,196 @@ ipsec_get_spi (size_t *sz, u_int8_t proto, struct message *msg) * 0. */ int -ipsec_handle_leftover_payload (struct message *msg, u_int8_t type, - struct payload *payload) +ipsec_handle_leftover_payload(struct message * msg, u_int8_t type, + struct payload * payload) { - u_int32_t spisz, nspis; - struct sockaddr *dst; - int reenter = 0; - u_int8_t *spis, proto; - struct sa *sa; - - switch (type) - { - case ISAKMP_PAYLOAD_DELETE: - proto = GET_ISAKMP_DELETE_PROTO (payload->p); - nspis = GET_ISAKMP_DELETE_NSPIS (payload->p); - spisz = GET_ISAKMP_DELETE_SPI_SZ (payload->p); - - if (nspis == 0) - { - LOG_DBG ((LOG_SA, 60, "ipsec_handle_leftover_payload: message " - "specified zero SPIs, ignoring")); - return -1; - } - - /* verify proper SPI size */ - if ((proto == ISAKMP_PROTO_ISAKMP && spisz != ISAKMP_HDR_COOKIES_LEN) - || (proto != ISAKMP_PROTO_ISAKMP && spisz != sizeof (u_int32_t))) - { - log_print ("ipsec_handle_leftover_payload: " - "invalid SPI size %d for proto %d in DELETE payload", - spisz, proto); - return -1; - } - - spis = (u_int8_t *)malloc (nspis * spisz); - if (!spis) - { - log_error ("ipsec_handle_leftover_payload: malloc (%d) failed", - nspis * spisz); - return -1; - } - - /* extract SPI and get dst address */ - memcpy (spis, payload->p + ISAKMP_DELETE_SPI_OFF, nspis * spisz); - msg->transport->vtbl->get_dst (msg->transport, &dst); - - ipsec_delete_spi_list (dst, proto, spis, nspis, "DELETE"); - - free (spis); - payload->flags |= PL_MARK; - return 0; - - case ISAKMP_PAYLOAD_NOTIFY: - switch (GET_ISAKMP_NOTIFY_MSG_TYPE (payload->p)) - { - case IPSEC_NOTIFY_INITIAL_CONTACT: - /* - * Permit INITIAL-CONTACT if - * - this is not an AGGRESSIVE mode exchange - * - it is protected by an ISAKMP SA - * - * XXX Instead of the first condition above, we could permit this - * XXX only for phase 2. In the last packet of main-mode, this - * XXX payload, while encrypted, is not part of the hash digest. - * XXX As we currently send our own INITIAL-CONTACTs at this point, - * XXX this too would need to be changed. - */ - if (msg->exchange->type == ISAKMP_EXCH_AGGRESSIVE) - { - log_print ("ipsec_handle_leftover_payload: got INITIAL-CONTACT " - "in AGGRESSIVE mode"); - return -1; - } - - if ((msg->exchange->flags & EXCHANGE_FLAG_ENCRYPT) == 0) - { - log_print ("ipsec_handle_leftover_payload: got INITIAL-CONTACT " - "without ISAKMP SA"); - return -1; - } - - /* - * Find out who is sending this and then delete every SA that is - * ready. Exchanges will timeout themselves and then the - * non-ready SAs will disappear too. - */ - msg->transport->vtbl->get_dst (msg->transport, &dst); - while ((sa = sa_lookup_by_peer (dst, sysdep_sa_len (dst))) != 0) - { - /* - * Don't delete the current SA -- we received the notification - * over it, so it's obviously still active. We temporarily need - * to remove the SA from the list to avoid an endless loop, - * but keep a reference so it won't disappear meanwhile. - */ - if (sa == msg->isakmp_sa) - { - sa_reference (sa); - sa_remove (sa); - reenter = 1; - continue; + u_int32_t spisz, nspis; + struct sockaddr *dst; + int reenter = 0; + u_int8_t *spis, proto; + struct sa *sa; + + switch (type) { + case ISAKMP_PAYLOAD_DELETE: + proto = GET_ISAKMP_DELETE_PROTO(payload->p); + nspis = GET_ISAKMP_DELETE_NSPIS(payload->p); + spisz = GET_ISAKMP_DELETE_SPI_SZ(payload->p); + + if (nspis == 0) { + LOG_DBG((LOG_SA, 60, "ipsec_handle_leftover_payload: message " + "specified zero SPIs, ignoring")); + return -1; + } + /* verify proper SPI size */ + if ((proto == ISAKMP_PROTO_ISAKMP && spisz != ISAKMP_HDR_COOKIES_LEN) + || (proto != ISAKMP_PROTO_ISAKMP && spisz != sizeof(u_int32_t))) { + log_print("ipsec_handle_leftover_payload: " + "invalid SPI size %d for proto %d in DELETE payload", + spisz, proto); + return -1; + } + spis = (u_int8_t *) malloc(nspis * spisz); + if (!spis) { + log_error("ipsec_handle_leftover_payload: malloc (%d) failed", + nspis * spisz); + return -1; + } + /* extract SPI and get dst address */ + memcpy(spis, payload->p + ISAKMP_DELETE_SPI_OFF, nspis * spisz); + msg->transport->vtbl->get_dst(msg->transport, &dst); + + ipsec_delete_spi_list(dst, proto, spis, nspis, "DELETE"); + + free(spis); + payload->flags |= PL_MARK; + return 0; + + case ISAKMP_PAYLOAD_NOTIFY: + switch (GET_ISAKMP_NOTIFY_MSG_TYPE(payload->p)) { + case IPSEC_NOTIFY_INITIAL_CONTACT: + /* + * Permit INITIAL-CONTACT if + * - this is not an AGGRESSIVE mode exchange + * - it is protected by an ISAKMP SA + * + * XXX Instead of the first condition above, we could permit this + * XXX only for phase 2. In the last packet of main-mode, this + * XXX payload, while encrypted, is not part of the hash digest. + * XXX As we currently send our own INITIAL-CONTACTs at this point, + * XXX this too would need to be changed. + */ + if (msg->exchange->type == ISAKMP_EXCH_AGGRESSIVE) { + log_print("ipsec_handle_leftover_payload: got INITIAL-CONTACT " + "in AGGRESSIVE mode"); + return -1; + } + if ((msg->exchange->flags & EXCHANGE_FLAG_ENCRYPT) == 0) { + log_print("ipsec_handle_leftover_payload: got INITIAL-CONTACT " + "without ISAKMP SA"); + return -1; + } + /* + * Find out who is sending this and then delete every SA that is + * ready. Exchanges will timeout themselves and then the + * non-ready SAs will disappear too. + */ + msg->transport->vtbl->get_dst(msg->transport, &dst); + while ((sa = sa_lookup_by_peer(dst, sysdep_sa_len(dst))) != 0) { + /* + * Don't delete the current SA -- we received the + * notification over it, so it's obviously still + * active. We temporarily need to remove the SA + * from the list to avoid an endless loop, but + * keep a reference so it won't disappear meanwhile. + */ + if (sa == msg->isakmp_sa) { + sa_reference(sa); + sa_remove(sa); + reenter = 1; + continue; + } + LOG_DBG((LOG_SA, 30, + "ipsec_handle_leftover_payload: " + "INITIAL-CONTACT made us delete SA %p", + sa)); + sa_delete(sa, 0); + } + + if (reenter) { + sa_enter(msg->isakmp_sa); + sa_release(msg->isakmp_sa); + } + payload->flags |= PL_MARK; + return 0; } - - LOG_DBG ((LOG_SA, 30, - "ipsec_handle_leftover_payload: " - "INITIAL-CONTACT made us delete SA %p", - sa)); - sa_delete (sa, 0); - } - - if (reenter) - { - sa_enter (msg->isakmp_sa); - sa_release (msg->isakmp_sa); - } - payload->flags |= PL_MARK; - return 0; } - } - return -1; + return -1; } /* Return the encryption keylength in octets of the ESP protocol PROTO. */ int -ipsec_esp_enckeylength (struct proto *proto) +ipsec_esp_enckeylength(struct proto * proto) { - struct ipsec_proto *iproto = proto->data; - - /* Compute the keylength to use. */ - switch (proto->id) - { - case IPSEC_ESP_DES: - case IPSEC_ESP_DES_IV32: - case IPSEC_ESP_DES_IV64: - return 8; - case IPSEC_ESP_3DES: - return 24; - case IPSEC_ESP_CAST: - if (!iproto->keylen) - return 16; - return iproto->keylen / 8; - case IPSEC_ESP_AES: - case IPSEC_ESP_AES_128_CTR: - if (!iproto->keylen) - return 16; - /* Fallthrough */ - default: - return iproto->keylen / 8; - } + struct ipsec_proto *iproto = proto->data; + + /* Compute the keylength to use. */ + switch (proto->id) { + case IPSEC_ESP_DES: + case IPSEC_ESP_DES_IV32: + case IPSEC_ESP_DES_IV64: + return 8; + case IPSEC_ESP_3DES: + return 24; + case IPSEC_ESP_CAST: + if (!iproto->keylen) + return 16; + return iproto->keylen / 8; + case IPSEC_ESP_AES: + case IPSEC_ESP_AES_128_CTR: + if (!iproto->keylen) + return 16; + /* Fallthrough */ + default: + return iproto->keylen / 8; + } } /* Return the authentication keylength in octets of the ESP protocol PROTO. */ int -ipsec_esp_authkeylength (struct proto *proto) +ipsec_esp_authkeylength(struct proto * proto) { - struct ipsec_proto *iproto = proto->data; - - switch (iproto->auth) - { - case IPSEC_AUTH_HMAC_MD5: - return 16; - case IPSEC_AUTH_HMAC_SHA: - case IPSEC_AUTH_HMAC_RIPEMD: - return 20; - case IPSEC_AUTH_HMAC_SHA2_256: - return 32; - case IPSEC_AUTH_HMAC_SHA2_384: - return 48; - case IPSEC_AUTH_HMAC_SHA2_512: - return 64; - default: - return 0; - } + struct ipsec_proto *iproto = proto->data; + + switch (iproto->auth) { + case IPSEC_AUTH_HMAC_MD5: + return 16; + case IPSEC_AUTH_HMAC_SHA: + case IPSEC_AUTH_HMAC_RIPEMD: + return 20; + case IPSEC_AUTH_HMAC_SHA2_256: + return 32; + case IPSEC_AUTH_HMAC_SHA2_384: + return 48; + case IPSEC_AUTH_HMAC_SHA2_512: + return 64; + default: + return 0; + } } /* Return the authentication keylength in octets of the AH protocol PROTO. */ int -ipsec_ah_keylength (struct proto *proto) +ipsec_ah_keylength(struct proto * proto) { - switch (proto->id) - { - case IPSEC_AH_MD5: - return 16; - case IPSEC_AH_SHA: - case IPSEC_AH_RIPEMD: - return 20; - case IPSEC_AH_SHA2_256: - return 32; - case IPSEC_AH_SHA2_384: - return 48; - case IPSEC_AH_SHA2_512: - return 64; - default: - return -1; - } + switch (proto->id) { + case IPSEC_AH_MD5: + return 16; + case IPSEC_AH_SHA: + case IPSEC_AH_RIPEMD: + return 20; + case IPSEC_AH_SHA2_256: + return 32; + case IPSEC_AH_SHA2_384: + return 48; + case IPSEC_AH_SHA2_512: + return 64; + default: + return -1; + } } /* Return the total keymaterial length of the protocol PROTO. */ int -ipsec_keymat_length (struct proto *proto) +ipsec_keymat_length(struct proto * proto) { - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_ESP: - return ipsec_esp_enckeylength (proto) + ipsec_esp_authkeylength (proto); - case IPSEC_PROTO_IPSEC_AH: - return ipsec_ah_keylength (proto); - default: - return -1; - } + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_ESP: + return ipsec_esp_enckeylength(proto) + ipsec_esp_authkeylength(proto); + case IPSEC_PROTO_IPSEC_AH: + return ipsec_ah_keylength(proto); + default: + return -1; + } } /* @@ -1765,112 +1706,97 @@ ipsec_keymat_length (struct proto *proto) * Return 0 on success and -1 on failure. */ int -ipsec_get_id (char *section, int *id, struct sockaddr **addr, - struct sockaddr **mask, u_int8_t *tproto, u_int16_t *port) +ipsec_get_id(char *section, int *id, struct sockaddr ** addr, + struct sockaddr ** mask, u_int8_t * tproto, u_int16_t * port) { - char *type, *address, *netmask; - - type = conf_get_str (section, "ID-type"); - if (!type) - { - log_print ("ipsec_get_id: section %s has no \"ID-type\" tag", section); - return -1; - } - - *id = constant_value (ipsec_id_cst, type); - switch (*id) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - address = conf_get_str (section, "Address"); - if (!address) - { - log_print ("ipsec_get_id: section %s has no \"Address\" tag", - section); - return -1; - } + char *type, *address, *netmask; - if (text2sockaddr (address, NULL, addr)) - { - log_print ("ipsec_get_id: invalid address %s in section %s", address, - section); - return -1; + type = conf_get_str(section, "ID-type"); + if (!type) { + log_print("ipsec_get_id: section %s has no \"ID-type\" tag", section); + return -1; } - - *tproto = conf_get_num (section, "Protocol", 0); - if (*tproto) - *port = conf_get_num (section, "Port", 0); - break; + *id = constant_value(ipsec_id_cst, type); + switch (*id) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + address = conf_get_str(section, "Address"); + if (!address) { + log_print("ipsec_get_id: section %s has no \"Address\" tag", + section); + return -1; + } + if (text2sockaddr(address, NULL, addr)) { + log_print("ipsec_get_id: invalid address %s in section %s", address, + section); + return -1; + } + *tproto = conf_get_num(section, "Protocol", 0); + if (*tproto) + *port = conf_get_num(section, "Port", 0); + break; #ifdef notyet - case IPSEC_ID_FQDN: - return -1; + case IPSEC_ID_FQDN: + return -1; - case IPSEC_ID_USER_FQDN: - return -1; + case IPSEC_ID_USER_FQDN: + return -1; #endif - case IPSEC_ID_IPV4_ADDR_SUBNET: - case IPSEC_ID_IPV6_ADDR_SUBNET: - address = conf_get_str (section, "Network"); - if (!address) - { - log_print ("ipsec_get_id: section %s has no \"Network\" tag", - section); - return -1; - } - - if (text2sockaddr (address, NULL, addr)) - { - log_print ("ipsec_get_id: invalid section %s network %s", section, - address); - return -1; - } - - netmask = conf_get_str (section, "Netmask"); - if (!netmask) - { - log_print ("ipsec_get_id: section %s has no \"Netmask\" tag", - section); - return -1; - } - - if (text2sockaddr (netmask, NULL, mask)) - { - log_print ("ipsec_id_build: invalid section %s network %s", section, - netmask); - return -1; - } - - *tproto = conf_get_num (section, "Protocol", 0); - if (*tproto) - *port = conf_get_num (section, "Port", 0); - break; + case IPSEC_ID_IPV4_ADDR_SUBNET: + case IPSEC_ID_IPV6_ADDR_SUBNET: + address = conf_get_str(section, "Network"); + if (!address) { + log_print("ipsec_get_id: section %s has no \"Network\" tag", + section); + return -1; + } + if (text2sockaddr(address, NULL, addr)) { + log_print("ipsec_get_id: invalid section %s network %s", section, + address); + return -1; + } + netmask = conf_get_str(section, "Netmask"); + if (!netmask) { + log_print("ipsec_get_id: section %s has no \"Netmask\" tag", + section); + return -1; + } + if (text2sockaddr(netmask, NULL, mask)) { + log_print("ipsec_id_build: invalid section %s network %s", section, + netmask); + return -1; + } + *tproto = conf_get_num(section, "Protocol", 0); + if (*tproto) + *port = conf_get_num(section, "Port", 0); + break; #ifdef notyet - case IPSEC_ID_IPV4_RANGE: - return -1; + case IPSEC_ID_IPV4_RANGE: + return -1; - case IPSEC_ID_IPV6_RANGE: - return -1; + case IPSEC_ID_IPV6_RANGE: + return -1; - case IPSEC_ID_DER_ASN1_DN: - return -1; + case IPSEC_ID_DER_ASN1_DN: + return -1; - case IPSEC_ID_DER_ASN1_GN: - return -1; + case IPSEC_ID_DER_ASN1_GN: + return -1; - case IPSEC_ID_KEY_ID: - return -1; + case IPSEC_ID_KEY_ID: + return -1; #endif - default: - log_print ("ipsec_get_id: unknown ID type \"%s\" in section %s", type, - section); - return -1; - } + default: + log_print("ipsec_get_id: unknown ID type \"%s\" in section %s", type, + section); + return -1; + } - return 0; + return 0; } /* @@ -1878,102 +1804,99 @@ ipsec_get_id (char *section, int *id, struct sockaddr **addr, * we cannot fit the information in the supplied buffer. */ static void -ipsec_decode_id (char *buf, size_t size, u_int8_t *id, size_t id_len, - int isakmpform) +ipsec_decode_id(char *buf, size_t size, u_int8_t * id, size_t id_len, + int isakmpform) { - int id_type; - char *addr = 0, *mask = 0; - u_int32_t *idp; - - if (id) - { - if (!isakmpform) - { - /* Exchanges and SAs dont carry the IDs in ISAKMP form. */ - id -= ISAKMP_GEN_SZ; - id_len += ISAKMP_GEN_SZ; - } - - id_type = GET_ISAKMP_ID_TYPE (id); - idp = (u_int32_t *)(id + ISAKMP_ID_DATA_OFF); - switch (id_type) - { - case IPSEC_ID_IPV4_ADDR: - util_ntoa (&addr, AF_INET, id + ISAKMP_ID_DATA_OFF); - snprintf (buf, size, "%08x: %s", - decode_32 (id + ISAKMP_ID_DATA_OFF), addr); - break; - - case IPSEC_ID_IPV4_ADDR_SUBNET: - util_ntoa (&addr, AF_INET, id + ISAKMP_ID_DATA_OFF); - util_ntoa (&mask, AF_INET, id + ISAKMP_ID_DATA_OFF + 4); - snprintf (buf, size, "%08x/%08x: %s/%s", - decode_32 (id + ISAKMP_ID_DATA_OFF), - decode_32 (id + ISAKMP_ID_DATA_OFF + 4), addr, mask); - break; - - case IPSEC_ID_IPV6_ADDR: - util_ntoa (&addr, AF_INET6, id + ISAKMP_ID_DATA_OFF); - snprintf (buf, size, "%08x%08x%08x%08x: %s", *idp, *(idp + 1), - *(idp + 2), *(idp + 3), addr); - break; - - case IPSEC_ID_IPV6_ADDR_SUBNET: - util_ntoa (&addr, AF_INET6, id + ISAKMP_ID_DATA_OFF); - util_ntoa (&addr, AF_INET6, id + ISAKMP_ID_DATA_OFF + - sizeof (struct in6_addr)); - snprintf (buf, size, "%08x%08x%08x%08x/%08x%08x%08x%08x: %s/%s", - *idp, *(idp + 1), *(idp + 2), *(idp + 3), *(idp + 4), - *(idp + 5), *(idp + 6), *(idp + 7), addr, mask); - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - /* String is not NUL terminated, be careful */ - id_len -= ISAKMP_ID_DATA_OFF; - id_len = MIN (id_len, size - 1); - memcpy (buf, id + ISAKMP_ID_DATA_OFF, id_len); - buf[id_len] = '\0'; - break; + int id_type; + char *addr = 0, *mask = 0; + u_int32_t *idp; + + if (id) { + if (!isakmpform) { + /* + * Exchanges and SAs dont carry the IDs in ISAKMP + * form. + */ + id -= ISAKMP_GEN_SZ; + id_len += ISAKMP_GEN_SZ; + } + id_type = GET_ISAKMP_ID_TYPE(id); + idp = (u_int32_t *) (id + ISAKMP_ID_DATA_OFF); + switch (id_type) { + case IPSEC_ID_IPV4_ADDR: + util_ntoa(&addr, AF_INET, id + ISAKMP_ID_DATA_OFF); + snprintf(buf, size, "%08x: %s", + decode_32(id + ISAKMP_ID_DATA_OFF), addr); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + util_ntoa(&addr, AF_INET, id + ISAKMP_ID_DATA_OFF); + util_ntoa(&mask, AF_INET, id + ISAKMP_ID_DATA_OFF + 4); + snprintf(buf, size, "%08x/%08x: %s/%s", + decode_32(id + ISAKMP_ID_DATA_OFF), + decode_32(id + ISAKMP_ID_DATA_OFF + 4), addr, mask); + break; + + case IPSEC_ID_IPV6_ADDR: + util_ntoa(&addr, AF_INET6, id + ISAKMP_ID_DATA_OFF); + snprintf(buf, size, "%08x%08x%08x%08x: %s", *idp, *(idp + 1), + *(idp + 2), *(idp + 3), addr); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + util_ntoa(&addr, AF_INET6, id + ISAKMP_ID_DATA_OFF); + util_ntoa(&addr, AF_INET6, id + ISAKMP_ID_DATA_OFF + + sizeof(struct in6_addr)); + snprintf(buf, size, "%08x%08x%08x%08x/%08x%08x%08x%08x: %s/%s", + *idp, *(idp + 1), *(idp + 2), *(idp + 3), *(idp + 4), + *(idp + 5), *(idp + 6), *(idp + 7), addr, mask); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + /* String is not NUL terminated, be careful */ + id_len -= ISAKMP_ID_DATA_OFF; + id_len = MIN(id_len, size - 1); + memcpy(buf, id + ISAKMP_ID_DATA_OFF, id_len); + buf[id_len] = '\0'; + break; #ifdef USE_X509 - case IPSEC_ID_DER_ASN1_DN: - addr = x509_DN_string (id + ISAKMP_ID_DATA_OFF, - id_len - ISAKMP_ID_DATA_OFF); - if (!addr) - { - snprintf (buf, size, "unparsable ASN1 DN ID"); - return; - } - strlcpy (buf, addr, size); - break; + case IPSEC_ID_DER_ASN1_DN: + addr = x509_DN_string(id + ISAKMP_ID_DATA_OFF, + id_len - ISAKMP_ID_DATA_OFF); + if (!addr) { + snprintf(buf, size, "unparsable ASN1 DN ID"); + return; + } + strlcpy(buf, addr, size); + break; #endif - default: - snprintf (buf, size, "<id type unknown: %x>", id_type); - break; - } - } - else - snprintf (buf, size, "<no ipsec id>"); - if (addr) - free (addr); - if (mask) - free (mask); + default: + snprintf(buf, size, "<id type unknown: %x>", id_type); + break; + } + } else + snprintf(buf, size, "<no ipsec id>"); + if (addr) + free(addr); + if (mask) + free(mask); } -char * -ipsec_decode_ids (char *fmt, u_int8_t *id1, size_t id1_len, - u_int8_t *id2, size_t id2_len, int isakmpform) +char * +ipsec_decode_ids(char *fmt, u_int8_t * id1, size_t id1_len, + u_int8_t * id2, size_t id2_len, int isakmpform) { - static char result[1024]; - char s_id1[256], s_id2[256]; + static char result[1024]; + char s_id1[256], s_id2[256]; - ipsec_decode_id (s_id1, sizeof s_id1, id1, id1_len, isakmpform); - ipsec_decode_id (s_id2, sizeof s_id2, id2, id2_len, isakmpform); + ipsec_decode_id(s_id1, sizeof s_id1, id1, id1_len, isakmpform); + ipsec_decode_id(s_id2, sizeof s_id2, id2, id2_len, isakmpform); - snprintf (result, sizeof result, fmt, s_id1, s_id2); - return result; + snprintf(result, sizeof result, fmt, s_id1, s_id2); + return result; } /* @@ -1981,75 +1904,69 @@ ipsec_decode_ids (char *fmt, u_int8_t *id1, size_t id1_len, * ISAKMP ID payload. Ths payload size should be stashed in SZ. * The caller is responsible for freeing the payload. */ -u_int8_t * -ipsec_build_id (char *section, size_t *sz) +u_int8_t * +ipsec_build_id(char *section, size_t * sz) { - struct sockaddr *addr, *mask; - u_int8_t *p; - int id, subnet = 0; - u_int8_t tproto = 0; - u_int16_t port = 0; - - if (ipsec_get_id (section, &id, &addr, &mask, &tproto, &port)) - return 0; - - if (id == IPSEC_ID_IPV4_ADDR_SUBNET || id == IPSEC_ID_IPV6_ADDR_SUBNET) - subnet = 1; - - *sz = ISAKMP_ID_SZ + sockaddr_addrlen (addr); - if (subnet) - *sz += sockaddr_addrlen (mask); - - p = malloc (*sz); - if (!p) - { - log_print ("ipsec_build_id: malloc(%lu) failed", (unsigned long)*sz); - return 0; - } - - SET_ISAKMP_ID_TYPE (p, id); - SET_ISAKMP_ID_DOI_DATA (p, (unsigned char *)"\000\000\000"); - - memcpy (p + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (addr), - sockaddr_addrlen (addr)); - if (subnet) - memcpy (p + ISAKMP_ID_DATA_OFF + sockaddr_addrlen (addr), - sockaddr_addrdata (mask), sockaddr_addrlen (mask)); - - SET_IPSEC_ID_PROTO (p + ISAKMP_ID_DOI_DATA_OFF, tproto); - SET_IPSEC_ID_PORT (p + ISAKMP_ID_DOI_DATA_OFF, port); - - return p; + struct sockaddr *addr, *mask; + u_int8_t *p; + int id, subnet = 0; + u_int8_t tproto = 0; + u_int16_t port = 0; + + if (ipsec_get_id(section, &id, &addr, &mask, &tproto, &port)) + return 0; + + if (id == IPSEC_ID_IPV4_ADDR_SUBNET || id == IPSEC_ID_IPV6_ADDR_SUBNET) + subnet = 1; + + *sz = ISAKMP_ID_SZ + sockaddr_addrlen(addr); + if (subnet) + *sz += sockaddr_addrlen(mask); + + p = malloc(*sz); + if (!p) { + log_print("ipsec_build_id: malloc(%lu) failed", (unsigned long) *sz); + return 0; + } + SET_ISAKMP_ID_TYPE(p, id); + SET_ISAKMP_ID_DOI_DATA(p, (unsigned char *) "\000\000\000"); + + memcpy(p + ISAKMP_ID_DATA_OFF, sockaddr_addrdata(addr), + sockaddr_addrlen(addr)); + if (subnet) + memcpy(p + ISAKMP_ID_DATA_OFF + sockaddr_addrlen(addr), + sockaddr_addrdata(mask), sockaddr_addrlen(mask)); + + SET_IPSEC_ID_PROTO(p + ISAKMP_ID_DOI_DATA_OFF, tproto); + SET_IPSEC_ID_PORT(p + ISAKMP_ID_DOI_DATA_OFF, port); + + return p; } /* * copy an ISAKMPD id */ int -ipsec_clone_id (u_int8_t **did, size_t *did_len, u_int8_t *id, size_t id_len) +ipsec_clone_id(u_int8_t ** did, size_t * did_len, u_int8_t * id, size_t id_len) { - if (*did) - free (*did); - - if (!id_len || !id) - { - *did = 0; - *did_len = 0; - return 0; - } - - *did = malloc (id_len); - if (!*did) - { - *did_len = 0; - log_error ("ipsec_clone_id: malloc(%lu) failed", (unsigned long)id_len); - return -1; - } - - *did_len = id_len; - memcpy (*did, id, id_len); - - return 0; + if (*did) + free(*did); + + if (!id_len || !id) { + *did = 0; + *did_len = 0; + return 0; + } + *did = malloc(id_len); + if (!*did) { + *did_len = 0; + log_error("ipsec_clone_id: malloc(%lu) failed", (unsigned long) id_len); + return -1; + } + *did_len = id_len; + memcpy(*did, id, id_len); + + return 0; } /* @@ -2058,13 +1975,13 @@ ipsec_clone_id (u_int8_t **did, size_t *did_len, u_int8_t *id, size_t id_len) * XXX I want to fix this later. */ void -ipsec_proto_init (struct proto *proto, char *section) +ipsec_proto_init(struct proto * proto, char *section) { - struct ipsec_proto *iproto = proto->data; + struct ipsec_proto *iproto = proto->data; - if (proto->sa->phase == 2 && section) - iproto->replay_window - = conf_get_num (section, "ReplayWindow", DEFAULT_REPLAY_WINDOW); + if (proto->sa->phase == 2 && section) + iproto->replay_window + = conf_get_num(section, "ReplayWindow", DEFAULT_REPLAY_WINDOW); } /* @@ -2072,34 +1989,31 @@ ipsec_proto_init (struct proto *proto, char *section) * the first contact we have made to our peer. */ int -ipsec_initial_contact (struct message *msg) +ipsec_initial_contact(struct message * msg) { - u_int8_t *buf; - - if (ipsec_contacted (msg)) - return 0; - - buf = malloc (ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN); - if (!buf) - { - log_error ("ike_phase_1_initial_contact: malloc (%d) failed", - ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN); - return -1; - } - SET_ISAKMP_NOTIFY_DOI (buf, IPSEC_DOI_IPSEC); - SET_ISAKMP_NOTIFY_PROTO (buf, ISAKMP_PROTO_ISAKMP); - SET_ISAKMP_NOTIFY_SPI_SZ (buf, ISAKMP_HDR_COOKIES_LEN); - SET_ISAKMP_NOTIFY_MSG_TYPE (buf, IPSEC_NOTIFY_INITIAL_CONTACT); - memcpy (buf + ISAKMP_NOTIFY_SPI_OFF, msg->isakmp_sa->cookies, - ISAKMP_HDR_COOKIES_LEN); - if (message_add_payload (msg, ISAKMP_PAYLOAD_NOTIFY, buf, - ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN, 1)) - { - free (buf); - return -1; - } - - return ipsec_add_contact (msg); + u_int8_t *buf; + + if (ipsec_contacted(msg)) + return 0; + + buf = malloc(ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN); + if (!buf) { + log_error("ike_phase_1_initial_contact: malloc (%d) failed", + ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN); + return -1; + } + SET_ISAKMP_NOTIFY_DOI(buf, IPSEC_DOI_IPSEC); + SET_ISAKMP_NOTIFY_PROTO(buf, ISAKMP_PROTO_ISAKMP); + SET_ISAKMP_NOTIFY_SPI_SZ(buf, ISAKMP_HDR_COOKIES_LEN); + SET_ISAKMP_NOTIFY_MSG_TYPE(buf, IPSEC_NOTIFY_INITIAL_CONTACT); + memcpy(buf + ISAKMP_NOTIFY_SPI_OFF, msg->isakmp_sa->cookies, + ISAKMP_HDR_COOKIES_LEN); + if (message_add_payload(msg, ISAKMP_PAYLOAD_NOTIFY, buf, + ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN, 1)) { + free(buf); + return -1; + } + return ipsec_add_contact(msg); } /* @@ -2107,13 +2021,13 @@ ipsec_initial_contact (struct message *msg) * *A < *B, 0 if they are equal, and positive if *A is the largest of them. */ static int -addr_cmp (const void *a, const void *b) +addr_cmp(const void *a, const void *b) { - const struct contact *x = a, *y = b; - int minlen = MIN (x->len, y->len); - int rv = memcmp (x->addr, y->addr, minlen); + const struct contact *x = a, *y = b; + int minlen = MIN(x->len, y->len); + int rv = memcmp(x->addr, y->addr, minlen); - return rv ? rv : (x->len - y->len); + return rv ? rv : (x->len - y->len); } /* @@ -2123,297 +2037,283 @@ addr_cmp (const void *a, const void *b) * is unimportant, if this is to scale. */ static int -ipsec_add_contact (struct message *msg) +ipsec_add_contact(struct message * msg) { - struct contact *new_contacts; - struct sockaddr *dst, *addr; - int cnt; - - if (contact_cnt == contact_limit) - { - cnt = contact_limit ? 2 * contact_limit : 64; - new_contacts = realloc (contacts, cnt * sizeof contacts[0]); - if (!new_contacts) - { - log_error ("ipsec_add_contact: realloc (%p, %lu) failed", contacts, - cnt * (unsigned long)sizeof contacts[0]); - return -1; + struct contact *new_contacts; + struct sockaddr *dst, *addr; + int cnt; + + if (contact_cnt == contact_limit) { + cnt = contact_limit ? 2 * contact_limit : 64; + new_contacts = realloc(contacts, cnt * sizeof contacts[0]); + if (!new_contacts) { + log_error("ipsec_add_contact: realloc (%p, %lu) failed", contacts, + cnt * (unsigned long) sizeof contacts[0]); + return -1; + } + contact_limit = cnt; + contacts = new_contacts; } - contact_limit = cnt; - contacts = new_contacts; - } - msg->transport->vtbl->get_dst (msg->transport, &dst); - addr = malloc (sysdep_sa_len (dst)); - if (!addr) - { - log_error ("ipsec_add_contact: malloc (%d) failed", sysdep_sa_len (dst)); - return -1; - } - memcpy (addr, dst, sysdep_sa_len (dst)); - contacts[contact_cnt].addr = addr; - contacts[contact_cnt++].len = sysdep_sa_len (dst); - - /* - * XXX There are better algorithms for already mostly-sorted data like - * this, but only qsort is standard. I will someday do this inline. - */ - qsort (contacts, contact_cnt, sizeof *contacts, addr_cmp); - return 0; + msg->transport->vtbl->get_dst(msg->transport, &dst); + addr = malloc(sysdep_sa_len(dst)); + if (!addr) { + log_error("ipsec_add_contact: malloc (%d) failed", sysdep_sa_len(dst)); + return -1; + } + memcpy(addr, dst, sysdep_sa_len(dst)); + contacts[contact_cnt].addr = addr; + contacts[contact_cnt++].len = sysdep_sa_len(dst); + + /* + * XXX There are better algorithms for already mostly-sorted data like + * this, but only qsort is standard. I will someday do this inline. + */ + qsort(contacts, contact_cnt, sizeof *contacts, addr_cmp); + return 0; } /* Return true if the recipient of MSG has already been contacted. */ static int -ipsec_contacted (struct message *msg) +ipsec_contacted(struct message * msg) { - struct contact contact; - - msg->transport->vtbl->get_dst (msg->transport, &contact.addr); - contact.len = sysdep_sa_len (contact.addr); - return contacts - ? (bsearch (&contact, contacts, contact_cnt, sizeof *contacts, addr_cmp) - != 0) - : 0; + struct contact contact; + + msg->transport->vtbl->get_dst(msg->transport, &contact.addr); + contact.len = sysdep_sa_len(contact.addr); + return contacts + ? (bsearch(&contact, contacts, contact_cnt, sizeof *contacts, addr_cmp) + != 0) + : 0; } /* Add a HASH for to MSG. */ -u_int8_t * -ipsec_add_hash_payload (struct message *msg, size_t hashsize) +u_int8_t * +ipsec_add_hash_payload(struct message * msg, size_t hashsize) { - u_int8_t *buf; - - buf = malloc (ISAKMP_HASH_SZ + hashsize); - if (!buf) - { - log_error ("ipsec_add_hash_payload: malloc (%lu) failed", - ISAKMP_HASH_SZ + (unsigned long)hashsize); - return 0; - } - - if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf, - ISAKMP_HASH_SZ + hashsize, 1)) - { - free (buf); - return 0; - } - - return buf; + u_int8_t *buf; + + buf = malloc(ISAKMP_HASH_SZ + hashsize); + if (!buf) { + log_error("ipsec_add_hash_payload: malloc (%lu) failed", + ISAKMP_HASH_SZ + (unsigned long) hashsize); + return 0; + } + if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH, buf, + ISAKMP_HASH_SZ + hashsize, 1)) { + free(buf); + return 0; + } + return buf; } /* Fill in the HASH payload of MSG. */ int -ipsec_fill_in_hash (struct message *msg) +ipsec_fill_in_hash(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa = isakmp_sa->data; - struct hash *hash = hash_get (isa->hash); - struct prf *prf; - struct payload *payload; - u_int8_t *buf; - u_int32_t i; - char header[80]; - - /* If no SKEYID_a, we need not do anything. */ - if (!isa->skeyid_a) - return 0; - - payload = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - if (!payload) - { - log_print ("ipsec_fill_in_hash: no HASH payload found"); - return -1; - } - buf = payload->p; - - /* Allocate the prf and start calculating our HASH(1). */ - LOG_DBG_BUF ((LOG_MISC, 90, "ipsec_fill_in_hash: SKEYID_a", isa->skeyid_a, - isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); - if (!prf) - return -1; - - prf->Init (prf->prfctx); - LOG_DBG_BUF ((LOG_MISC, 90, "ipsec_fill_in_hash: message_id", - exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - - /* Loop over all payloads after HASH(1). */ - for (i = 2; i < msg->iovlen; i++) - { - /* XXX Misleading payload type printouts. */ - snprintf (header, sizeof header, - "ipsec_fill_in_hash: payload %d after HASH(1)", i - 1); - LOG_DBG_BUF ((LOG_MISC, 90, header, msg->iov[i].iov_base, - msg->iov[i].iov_len)); - prf->Update (prf->prfctx, msg->iov[i].iov_base, msg->iov[i].iov_len); - } - prf->Final (buf + ISAKMP_HASH_DATA_OFF, prf->prfctx); - prf_free (prf); - LOG_DBG_BUF ((LOG_MISC, 80, "ipsec_fill_in_hash: HASH(1)", - buf + ISAKMP_HASH_DATA_OFF, hash->hashsize)); - - return 0; + struct exchange *exchange = msg->exchange; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct hash *hash = hash_get(isa->hash); + struct prf *prf; + struct payload *payload; + u_int8_t *buf; + u_int32_t i; + char header[80]; + + /* If no SKEYID_a, we need not do anything. */ + if (!isa->skeyid_a) + return 0; + + payload = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + if (!payload) { + log_print("ipsec_fill_in_hash: no HASH payload found"); + return -1; + } + buf = payload->p; + + /* Allocate the prf and start calculating our HASH(1). */ + LOG_DBG_BUF((LOG_MISC, 90, "ipsec_fill_in_hash: SKEYID_a", isa->skeyid_a, + isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); + if (!prf) + return -1; + + prf->Init(prf->prfctx); + LOG_DBG_BUF((LOG_MISC, 90, "ipsec_fill_in_hash: message_id", + exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + + /* Loop over all payloads after HASH(1). */ + for (i = 2; i < msg->iovlen; i++) { + /* XXX Misleading payload type printouts. */ + snprintf(header, sizeof header, + "ipsec_fill_in_hash: payload %d after HASH(1)", i - 1); + LOG_DBG_BUF((LOG_MISC, 90, header, msg->iov[i].iov_base, + msg->iov[i].iov_len)); + prf->Update(prf->prfctx, msg->iov[i].iov_base, msg->iov[i].iov_len); + } + prf->Final(buf + ISAKMP_HASH_DATA_OFF, prf->prfctx); + prf_free(prf); + LOG_DBG_BUF((LOG_MISC, 80, "ipsec_fill_in_hash: HASH(1)", + buf + ISAKMP_HASH_DATA_OFF, hash->hashsize)); + + return 0; } /* Add a HASH payload to MSG, if we have an ISAKMP SA we're protected by. */ static int -ipsec_informational_pre_hook (struct message *msg) +ipsec_informational_pre_hook(struct message * msg) { - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa; - struct hash *hash; - - if (!isakmp_sa) - return 0; - isa = isakmp_sa->data; - hash = hash_get (isa->hash); - return ipsec_add_hash_payload (msg, hash->hashsize) == 0; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa; + struct hash *hash; + + if (!isakmp_sa) + return 0; + isa = isakmp_sa->data; + hash = hash_get(isa->hash); + return ipsec_add_hash_payload(msg, hash->hashsize) == 0; } /* * Fill in the HASH payload in MSG, if we have an ISAKMP SA we're protected by. */ static int -ipsec_informational_post_hook (struct message *msg) +ipsec_informational_post_hook(struct message * msg) { - if (!msg->isakmp_sa) - return 0; - return ipsec_fill_in_hash (msg); + if (!msg->isakmp_sa) + return 0; + return ipsec_fill_in_hash(msg); } ssize_t -ipsec_id_size (char *section, u_int8_t *id) +ipsec_id_size(char *section, u_int8_t * id) { - char *type, *data; - - type = conf_get_str (section, "ID-type"); - if (!type) - { - log_print ("ipsec_id_size: section %s has no \"ID-type\" tag", section); - return -1; - } - - *id = constant_value (ipsec_id_cst, type); - switch (*id) - { - case IPSEC_ID_IPV4_ADDR: - return sizeof (struct in_addr); - case IPSEC_ID_IPV4_ADDR_SUBNET: - return 2 * sizeof (struct in_addr); - case IPSEC_ID_IPV6_ADDR: - return sizeof (struct in6_addr); - case IPSEC_ID_IPV6_ADDR_SUBNET: - return 2 * sizeof (struct in6_addr); - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - case IPSEC_ID_KEY_ID: - case IPSEC_ID_DER_ASN1_DN: - case IPSEC_ID_DER_ASN1_GN: - data = conf_get_str (section, "Name"); - if (!data) - { - log_print ("ipsec_id_size: section %s has no \"Name\" tag", section); - return -1; + char *type, *data; + + type = conf_get_str(section, "ID-type"); + if (!type) { + log_print("ipsec_id_size: section %s has no \"ID-type\" tag", section); + return -1; } - return strlen (data); - } - log_print ("ipsec_id_size: unrecognized/unsupported ID-type %d (%s)", - *id, type); - return -1; + *id = constant_value(ipsec_id_cst, type); + switch (*id) { + case IPSEC_ID_IPV4_ADDR: + return sizeof(struct in_addr); + case IPSEC_ID_IPV4_ADDR_SUBNET: + return 2 * sizeof(struct in_addr); + case IPSEC_ID_IPV6_ADDR: + return sizeof(struct in6_addr); + case IPSEC_ID_IPV6_ADDR_SUBNET: + return 2 * sizeof(struct in6_addr); + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + case IPSEC_ID_KEY_ID: + case IPSEC_ID_DER_ASN1_DN: + case IPSEC_ID_DER_ASN1_GN: + data = conf_get_str(section, "Name"); + if (!data) { + log_print("ipsec_id_size: section %s has no \"Name\" tag", section); + return -1; + } + return strlen(data); + } + log_print("ipsec_id_size: unrecognized/unsupported ID-type %d (%s)", + *id, type); + return -1; } /* * Generate a string version of the ID. */ -char * -ipsec_id_string (u_int8_t *id, size_t id_len) +char * +ipsec_id_string(u_int8_t * id, size_t id_len) { - char *buf = 0; - char *addrstr = 0; - size_t len, size; - - /* - * XXX Real ugly way of making the offsets correct. Be aware that id now - * will point before the actual buffer and cannot be dereferenced without - * an offset larger than or equal to ISAKM_GEN_SZ. - */ - id -= ISAKMP_GEN_SZ; - - /* This is the actual length of the ID data field. */ - id_len += ISAKMP_GEN_SZ - ISAKMP_ID_DATA_OFF; - - /* - * Conservative allocation. - * XXX I think the ASN1 DN case can be thought through to give a better - * estimate. - */ - size = MAX (sizeof "ipv6/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - sizeof "asn1_dn/" + id_len - ISAKMP_ID_DATA_OFF); - buf = malloc (size); - if (!buf) - /* XXX Log? */ - goto fail; - - switch (GET_ISAKMP_ID_TYPE (id)) - { - case IPSEC_ID_IPV4_ADDR: - if (id_len < sizeof (struct in_addr)) - goto fail; - util_ntoa (&addrstr, AF_INET, id + ISAKMP_ID_DATA_OFF); - if (!addrstr) - goto fail; - snprintf (buf, size, "ipv4/%s", addrstr); - break; - - case IPSEC_ID_IPV6_ADDR: - if (id_len < sizeof (struct in6_addr)) - goto fail; - util_ntoa (&addrstr, AF_INET6, id + ISAKMP_ID_DATA_OFF); - if (!addrstr) - goto fail; - snprintf (buf, size, "ipv6/%s", addrstr); - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - strlcpy (buf, - GET_ISAKMP_ID_TYPE (id) == IPSEC_ID_FQDN ? "fqdn/" : "ufqdn/", - size); - len = strlen (buf); - - memcpy (buf + len, id + ISAKMP_ID_DATA_OFF, id_len); - *(buf + len + id_len) = '\0'; - break; + char *buf = 0; + char *addrstr = 0; + size_t len, size; + + /* + * XXX Real ugly way of making the offsets correct. Be aware that id now + * will point before the actual buffer and cannot be dereferenced without + * an offset larger than or equal to ISAKM_GEN_SZ. + */ + id -= ISAKMP_GEN_SZ; + + /* This is the actual length of the ID data field. */ + id_len += ISAKMP_GEN_SZ - ISAKMP_ID_DATA_OFF; + + /* + * Conservative allocation. + * XXX I think the ASN1 DN case can be thought through to give a better + * estimate. + */ + size = MAX(sizeof "ipv6/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + sizeof "asn1_dn/" + id_len - ISAKMP_ID_DATA_OFF); + buf = malloc(size); + if (!buf) + /* XXX Log? */ + goto fail; + + switch (GET_ISAKMP_ID_TYPE(id)) { + case IPSEC_ID_IPV4_ADDR: + if (id_len < sizeof(struct in_addr)) + goto fail; + util_ntoa(&addrstr, AF_INET, id + ISAKMP_ID_DATA_OFF); + if (!addrstr) + goto fail; + snprintf(buf, size, "ipv4/%s", addrstr); + break; + + case IPSEC_ID_IPV6_ADDR: + if (id_len < sizeof(struct in6_addr)) + goto fail; + util_ntoa(&addrstr, AF_INET6, id + ISAKMP_ID_DATA_OFF); + if (!addrstr) + goto fail; + snprintf(buf, size, "ipv6/%s", addrstr); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + strlcpy(buf, + GET_ISAKMP_ID_TYPE(id) == IPSEC_ID_FQDN ? "fqdn/" : "ufqdn/", + size); + len = strlen(buf); + + memcpy(buf + len, id + ISAKMP_ID_DATA_OFF, id_len); + *(buf + len + id_len) = '\0'; + break; #ifdef USE_X509 - case IPSEC_ID_DER_ASN1_DN: - strlcpy (buf, "asn1_dn/", size); - len = strlen (buf); - addrstr = x509_DN_string (id + ISAKMP_ID_DATA_OFF, - id_len - ISAKMP_ID_DATA_OFF); - if (!addrstr) - goto fail; - if (size < len + strlen (addrstr) + 1) - goto fail; - strlcpy (buf + len, addrstr, size - len); - break; + case IPSEC_ID_DER_ASN1_DN: + strlcpy(buf, "asn1_dn/", size); + len = strlen(buf); + addrstr = x509_DN_string(id + ISAKMP_ID_DATA_OFF, + id_len - ISAKMP_ID_DATA_OFF); + if (!addrstr) + goto fail; + if (size < len + strlen(addrstr) + 1) + goto fail; + strlcpy(buf + len, addrstr, size - len); + break; #endif - default: - /* Unknown type. */ - LOG_DBG ((LOG_MISC, 10, "ipsec_id_string: unknown identity type %d\n", - GET_ISAKMP_ID_TYPE (id))); - goto fail; - } - - if (addrstr) - free (addrstr); - return buf; - - fail: - if (buf) - free (buf); - if (addrstr) - free (addrstr); - return 0; + default: + /* Unknown type. */ + LOG_DBG((LOG_MISC, 10, "ipsec_id_string: unknown identity type %d\n", + GET_ISAKMP_ID_TYPE(id))); + goto fail; + } + + if (addrstr) + free(addrstr); + return buf; + +fail: + if (buf) + free(buf); + if (addrstr) + free(addrstr); + return 0; } diff --git a/sbin/isakmpd/ipsec.h b/sbin/isakmpd/ipsec.h index e95a2abc9bb..a39184f041a 100644 --- a/sbin/isakmpd/ipsec.h +++ b/sbin/isakmpd/ipsec.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ipsec.h,v 1.22 2003/06/04 07:31:17 ho Exp $ */ -/* $EOM: ipsec.h,v 1.42 2000/12/03 07:58:20 angelos Exp $ */ +/* $OpenBSD: ipsec.h,v 1.23 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ipsec.h,v 1.42 2000/12/03 07:58:20 angelos Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -57,117 +57,121 @@ struct sa; * separated. */ struct ipsec_exch { - u_int flags; - struct hash *hash; - struct ike_auth *ike_auth; - struct group *group; - u_int16_t prf_type; - - /* 0 if no KEY_EXCH was proposed, 1 otherwise */ - u_int8_t pfs; - - /* - * A copy of the initiator SA payload body for later computation of hashes. - * Phase 1 only. - */ - size_t sa_i_b_len; - u_int8_t *sa_i_b; - - /* Diffie-Hellman values. */ - size_t g_x_len; - u_int8_t *g_xi; - u_int8_t *g_xr; - u_int8_t* g_xy; - - /* SKEYIDs. XXX Phase 1 only? */ - size_t skeyid_len; - u_int8_t *skeyid; - u_int8_t *skeyid_d; - u_int8_t *skeyid_a; - u_int8_t *skeyid_e; - - /* HASH_I & HASH_R. XXX Do these need to be saved here? */ - u_int8_t *hash_i; - u_int8_t *hash_r; - - /* KEYMAT */ - size_t keymat_len; - - /* Phase 2. */ - u_int8_t *id_ci; - size_t id_ci_sz; - u_int8_t *id_cr; - size_t id_cr_sz; + u_int flags; + struct hash *hash; + struct ike_auth *ike_auth; + struct group *group; + u_int16_t prf_type; + + /* 0 if no KEY_EXCH was proposed, 1 otherwise */ + u_int8_t pfs; + + /* + * A copy of the initiator SA payload body for later computation of hashes. + * Phase 1 only. + */ + size_t sa_i_b_len; + u_int8_t *sa_i_b; + + /* Diffie-Hellman values. */ + size_t g_x_len; + u_int8_t *g_xi; + u_int8_t *g_xr; + u_int8_t *g_xy; + + /* SKEYIDs. XXX Phase 1 only? */ + size_t skeyid_len; + u_int8_t *skeyid; + u_int8_t *skeyid_d; + u_int8_t *skeyid_a; + u_int8_t *skeyid_e; + + /* HASH_I & HASH_R. XXX Do these need to be saved here? */ + u_int8_t *hash_i; + u_int8_t *hash_r; + + /* KEYMAT */ + size_t keymat_len; + + /* Phase 2. */ + u_int8_t *id_ci; + size_t id_ci_sz; + u_int8_t *id_cr; + size_t id_cr_sz; #ifdef USE_ISAKMP_CFG - /* ISAKMP configuration mode parameters */ - u_int16_t cfg_id; - u_int16_t cfg_type; - LIST_HEAD (isakmp_cfg_attr_head, isakmp_cfg_attr) attrs; + /* ISAKMP configuration mode parameters */ + u_int16_t cfg_id; + u_int16_t cfg_type; + LIST_HEAD(isakmp_cfg_attr_head, isakmp_cfg_attr) attrs; #endif }; #define IPSEC_EXCH_FLAG_NO_ID 1 struct ipsec_sa { - /* Phase 1. */ - u_int8_t hash; - size_t skeyid_len; - u_int8_t *skeyid_d; - u_int8_t *skeyid_a; - u_int16_t prf_type; - - /* Phase 2. */ - u_int16_t group_desc; - - /* Tunnel parameters. These are in network byte order. */ - struct sockaddr *src_net; - struct sockaddr *src_mask; - struct sockaddr *dst_net; - struct sockaddr *dst_mask; - u_int8_t tproto; - u_int16_t sport; - u_int16_t dport; + /* Phase 1. */ + u_int8_t hash; + size_t skeyid_len; + u_int8_t *skeyid_d; + u_int8_t *skeyid_a; + u_int16_t prf_type; + + /* Phase 2. */ + u_int16_t group_desc; + + /* Tunnel parameters. These are in network byte order. */ + struct sockaddr *src_net; + struct sockaddr *src_mask; + struct sockaddr *dst_net; + struct sockaddr *dst_mask; + u_int8_t tproto; + u_int16_t sport; + u_int16_t dport; }; struct ipsec_proto { - /* Phase 2. */ - u_int16_t encap_mode; - u_int16_t auth; - u_int16_t keylen; - u_int16_t keyrounds; + /* Phase 2. */ + u_int16_t encap_mode; + u_int16_t auth; + u_int16_t keylen; + u_int16_t keyrounds; - /* This is not negotiated, but rather configured. */ - int32_t replay_window; + /* This is not negotiated, but rather configured. */ + int32_t replay_window; - /* KEYMAT */ - u_int8_t *keymat[2]; + /* KEYMAT */ + u_int8_t *keymat[2]; }; -extern u_int8_t *ipsec_add_hash_payload (struct message *msg, size_t); -extern int ipsec_ah_keylength (struct proto *); -extern u_int8_t *ipsec_build_id (char *, size_t *); -extern int ipsec_decode_attribute (u_int16_t, u_int8_t *, u_int16_t, void *); -extern void ipsec_decode_transform (struct message *, struct sa *, - struct proto *, u_int8_t *); -extern int ipsec_esp_authkeylength (struct proto *); -extern int ipsec_esp_enckeylength (struct proto *); -extern int ipsec_fill_in_hash (struct message *msg); -extern int ipsec_gen_g_x (struct message *); -extern int ipsec_get_id (char *, int *, struct sockaddr **, - struct sockaddr **, u_int8_t *, u_int16_t *); -extern ssize_t ipsec_id_size (char *, u_int8_t *); -extern char *ipsec_id_string (u_int8_t *, size_t); -extern void ipsec_init (void); -extern int ipsec_initial_contact (struct message *msg); -extern int ipsec_is_attribute_incompatible (u_int16_t, u_int8_t *, u_int16_t, - void *); -extern int ipsec_keymat_length (struct proto *); -extern int ipsec_save_g_x (struct message *); -extern struct sa *ipsec_sa_lookup (struct sockaddr *, u_int32_t, u_int8_t); - -extern char *ipsec_decode_ids(char *, u_int8_t *, size_t, u_int8_t *, size_t, - int); -extern int ipsec_clone_id(u_int8_t **, size_t *, u_int8_t *, size_t); - -#endif /* _IPSEC_H_ */ +extern u_int8_t *ipsec_add_hash_payload(struct message * msg, size_t); +extern int ipsec_ah_keylength(struct proto *); +extern u_int8_t *ipsec_build_id(char *, size_t *); +extern int ipsec_decode_attribute(u_int16_t, u_int8_t *, u_int16_t, void *); +extern void +ipsec_decode_transform(struct message *, struct sa *, + struct proto *, u_int8_t *); +extern int ipsec_esp_authkeylength(struct proto *); +extern int ipsec_esp_enckeylength(struct proto *); +extern int ipsec_fill_in_hash(struct message * msg); +extern int ipsec_gen_g_x(struct message *); +extern int +ipsec_get_id(char *, int *, struct sockaddr **, + struct sockaddr **, u_int8_t *, u_int16_t *); +extern ssize_t ipsec_id_size(char *, u_int8_t *); +extern char *ipsec_id_string(u_int8_t *, size_t); +extern void ipsec_init(void); +extern int ipsec_initial_contact(struct message * msg); +extern int +ipsec_is_attribute_incompatible(u_int16_t, u_int8_t *, u_int16_t, + void *); +extern int ipsec_keymat_length(struct proto *); +extern int ipsec_save_g_x(struct message *); +extern struct sa *ipsec_sa_lookup(struct sockaddr *, u_int32_t, u_int8_t); + +extern char * +ipsec_decode_ids(char *, u_int8_t *, size_t, u_int8_t *, size_t, + int); +extern int ipsec_clone_id(u_int8_t **, size_t *, u_int8_t *, size_t); + +#endif /* _IPSEC_H_ */ diff --git a/sbin/isakmpd/ipsec_doi.h b/sbin/isakmpd/ipsec_doi.h index 24ccd8cd264..c7000c76759 100644 --- a/sbin/isakmpd/ipsec_doi.h +++ b/sbin/isakmpd/ipsec_doi.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ipsec_doi.h,v 1.7 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ipsec_doi.h,v 1.10 1999/04/02 00:57:51 niklas Exp $ */ +/* $OpenBSD: ipsec_doi.h,v 1.8 2004/04/15 18:39:25 deraadt Exp $ */ +/* $EOM: ipsec_doi.h,v 1.10 1999/04/02 00:57:51 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -41,4 +41,4 @@ /* The low limit if valid SPI values. */ #define IPSEC_SPI_LOW 0x100 -#endif /* _IPSEC_DOI_H_ */ +#endif /* _IPSEC_DOI_H_ */ diff --git a/sbin/isakmpd/isakmp.h b/sbin/isakmpd/isakmp.h index 1ab711c14c3..11051fb7c15 100644 --- a/sbin/isakmpd/isakmp.h +++ b/sbin/isakmpd/isakmp.h @@ -1,5 +1,5 @@ -/* $OpenBSD: isakmp.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: isakmp.h,v 1.11 2000/07/05 10:48:43 ho Exp $ */ +/* $OpenBSD: isakmp.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: isakmp.h,v 1.11 2000/07/05 10:48:43 ho Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -56,4 +56,4 @@ #define ISAKMP_VERSION_MINOR(x) ((x) & 0xf) #define ISAKMP_VERSION_MAKE(maj, min) ((maj) << 4 | (min)) -#endif /* _ISAKMP_H_ */ +#endif /* _ISAKMP_H_ */ diff --git a/sbin/isakmpd/isakmp_cfg.c b/sbin/isakmpd/isakmp_cfg.c index 8788a02e518..9a31de1583a 100644 --- a/sbin/isakmpd/isakmp_cfg.c +++ b/sbin/isakmpd/isakmp_cfg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isakmp_cfg.c,v 1.27 2004/03/11 16:56:11 hshoexer Exp $ */ +/* $OpenBSD: isakmp_cfg.c,v 1.28 2004/04/15 18:39:26 deraadt Exp $ */ /* * Copyright (c) 2001 Niklas Hallqvist. All rights reserved. @@ -57,36 +57,38 @@ * Validation script used to test messages for correct content of * payloads depending on the exchange type. */ -int16_t script_transaction[] = { - ISAKMP_PAYLOAD_ATTRIBUTE, /* Initiator -> responder. */ - EXCHANGE_SCRIPT_SWITCH, - ISAKMP_PAYLOAD_ATTRIBUTE, /* Responder -> initiator. */ - EXCHANGE_SCRIPT_END +int16_t script_transaction[] = { + ISAKMP_PAYLOAD_ATTRIBUTE, /* Initiator -> responder. */ + EXCHANGE_SCRIPT_SWITCH, + ISAKMP_PAYLOAD_ATTRIBUTE, /* Responder -> initiator. */ + EXCHANGE_SCRIPT_END }; -static int cfg_decode_attribute (u_int16_t, u_int8_t *, u_int16_t, void *); -static int cfg_encode_attributes (struct isakmp_cfg_attr_head *, u_int32_t, - u_int32_t, char *, u_int8_t **, u_int16_t *); -static int cfg_initiator_send_ATTR (struct message *); -static int cfg_initiator_recv_ATTR (struct message *); -static int cfg_responder_recv_ATTR (struct message *); -static int cfg_responder_send_ATTR (struct message *); - -u_int8_t *cfg_add_hash (struct message *); -int cfg_finalize_hash (struct message *,u_int8_t *, u_int8_t *, - u_int16_t); -int cfg_verify_hash (struct message *msg); +static int cfg_decode_attribute(u_int16_t, u_int8_t *, u_int16_t, void *); +static int +cfg_encode_attributes(struct isakmp_cfg_attr_head *, u_int32_t, + u_int32_t, char *, u_int8_t **, u_int16_t *); +static int cfg_initiator_send_ATTR(struct message *); +static int cfg_initiator_recv_ATTR(struct message *); +static int cfg_responder_recv_ATTR(struct message *); +static int cfg_responder_send_ATTR(struct message *); + +u_int8_t *cfg_add_hash(struct message *); +int +cfg_finalize_hash(struct message *, u_int8_t *, u_int8_t *, + u_int16_t); +int cfg_verify_hash(struct message * msg); /* Server: SET/ACK Client; REQ/REPLY */ -int (*isakmp_cfg_initiator[]) (struct message *) = { - cfg_initiator_send_ATTR, - cfg_initiator_recv_ATTR +int (*isakmp_cfg_initiator[]) (struct message *) = { + cfg_initiator_send_ATTR, + cfg_initiator_recv_ATTR }; /* Server: REQ/REPLY Client: SET/ACK */ -int (*isakmp_cfg_responder[]) (struct message *) = { - cfg_responder_recv_ATTR, - cfg_responder_send_ATTR +int (*isakmp_cfg_responder[]) (struct message *) = { + cfg_responder_recv_ATTR, + cfg_responder_send_ATTR }; /* @@ -94,48 +96,43 @@ int (*isakmp_cfg_responder[]) (struct message *) = { * When we are "the client", this starts REQ/REPLY mode */ static int -cfg_initiator_send_ATTR (struct message *msg) +cfg_initiator_send_ATTR(struct message * msg) { - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_exch *ie = msg->exchange->data; - u_int8_t *hashp = 0, *attrp, *attr; - size_t attrlen, off; - char *id_string, *cfg_mode, *field; - struct sockaddr *sa; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_exch *ie = msg->exchange->data; + u_int8_t *hashp = 0, *attrp, *attr; + size_t attrlen, off; + char *id_string, *cfg_mode, *field; + struct sockaddr *sa; #define CFG_ATTR_BIT_MAX ISAKMP_CFG_ATTR_FUTURE_MIN /* XXX */ - bitstr_t bit_decl (attrbits, CFG_ATTR_BIT_MAX); - u_int16_t bit, length; - u_int32_t life; - - if (msg->exchange->phase == 2) - { - hashp = cfg_add_hash (msg); - if (!hashp) - return -1; - } - - /* We initiated this exchange, check isakmp_sa for other side. */ - if (isakmp_sa->initiator) - id_string = ipsec_id_string (isakmp_sa->id_r, isakmp_sa->id_r_len); - else - id_string = ipsec_id_string (isakmp_sa->id_i, isakmp_sa->id_i_len); - if (!id_string) - { - log_print ("cfg_initiator_send_ATTR: cannot parse ID"); - goto fail; - } - - /* Check for attribute list to send to the other side */ - attrlen = 0; - bit_nclear (attrbits, 0, CFG_ATTR_BIT_MAX - 1); - - cfg_mode = conf_get_str (id_string, "Mode"); - if (!cfg_mode || strcmp (cfg_mode, "SET") == 0) - { - /* SET/ACK mode */ - ie->cfg_type = ISAKMP_CFG_SET; - - LOG_DBG ((LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: SET/ACK mode")); + bitstr_t bit_decl(attrbits, CFG_ATTR_BIT_MAX); + u_int16_t bit, length; + u_int32_t life; + + if (msg->exchange->phase == 2) { + hashp = cfg_add_hash(msg); + if (!hashp) + return -1; + } + /* We initiated this exchange, check isakmp_sa for other side. */ + if (isakmp_sa->initiator) + id_string = ipsec_id_string(isakmp_sa->id_r, isakmp_sa->id_r_len); + else + id_string = ipsec_id_string(isakmp_sa->id_i, isakmp_sa->id_i_len); + if (!id_string) { + log_print("cfg_initiator_send_ATTR: cannot parse ID"); + goto fail; + } + /* Check for attribute list to send to the other side */ + attrlen = 0; + bit_nclear(attrbits, 0, CFG_ATTR_BIT_MAX - 1); + + cfg_mode = conf_get_str(id_string, "Mode"); + if (!cfg_mode || strcmp(cfg_mode, "SET") == 0) { + /* SET/ACK mode */ + ie->cfg_type = ISAKMP_CFG_SET; + + LOG_DBG((LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: SET/ACK mode")); #define ATTRFIND(STR,ATTR4,LEN4,ATTR6,LEN6) do \ { \ @@ -156,221 +153,192 @@ cfg_initiator_send_ATTR (struct message *msg) free (sa); \ } while (0) - /* XXX We don't simultaneously support IPv4 and IPv6 addresses. */ - ATTRFIND ("Address", ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS, 4, - ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS, 16); - ATTRFIND ("Netmask", ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK, 4, - ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK, 16); - ATTRFIND ("Nameserver", ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS, 4, - ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS, 16); - ATTRFIND ("WINS-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS, 4, - ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS, 16); - ATTRFIND ("DHCP-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP, 4, - ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP, 16); + /* + * XXX We don't simultaneously support IPv4 and IPv6 + * addresses. + */ + ATTRFIND("Address", ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS, 4, + ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS, 16); + ATTRFIND("Netmask", ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK, 4, + ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK, 16); + ATTRFIND("Nameserver", ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS, 4, + ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS, 16); + ATTRFIND("WINS-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS, 4, + ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS, 16); + ATTRFIND("DHCP-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP, 4, + ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP, 16); #ifdef notyet - ATTRFIND ("Network", ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET, 8, - ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET, 17); + ATTRFIND("Network", ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET, 8, + ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET, 17); #endif #undef ATTRFIND - if (conf_get_str (id_string, "Lifetime")) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY); - attrlen += ISAKMP_ATTR_SZ + 4; - } - } - else - { - struct conf_list *alist; - struct conf_list_node *anode; - - ie->cfg_type = ISAKMP_CFG_REQUEST; - - LOG_DBG ((LOG_NEGOTIATION, 10, - "cfg_initiator_send_ATTR: REQ/REPLY mode")); - - alist = conf_get_list (id_string, "Attributes"); - if (alist) - { - for (anode = TAILQ_FIRST (&alist->fields); anode; - anode = TAILQ_NEXT (anode, link)) - { - if (strcasecmp (anode->field, "Address") == 0) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS); - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS); - attrlen += ISAKMP_ATTR_SZ * 2; + if (conf_get_str(id_string, "Lifetime")) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY); + attrlen += ISAKMP_ATTR_SZ + 4; } - else if (strcasecmp (anode->field, "Netmask") == 0) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK); - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK); - attrlen += ISAKMP_ATTR_SZ * 2; + } else { + struct conf_list *alist; + struct conf_list_node *anode; + + ie->cfg_type = ISAKMP_CFG_REQUEST; + + LOG_DBG((LOG_NEGOTIATION, 10, + "cfg_initiator_send_ATTR: REQ/REPLY mode")); + + alist = conf_get_list(id_string, "Attributes"); + if (alist) { + for (anode = TAILQ_FIRST(&alist->fields); anode; + anode = TAILQ_NEXT(anode, link)) { + if (strcasecmp(anode->field, "Address") == 0) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS); + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS); + attrlen += ISAKMP_ATTR_SZ * 2; + } else if (strcasecmp(anode->field, "Netmask") == 0) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK); + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK); + attrlen += ISAKMP_ATTR_SZ * 2; + } else if (strcasecmp(anode->field, "Nameserver") == 0) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS); + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS); + attrlen += ISAKMP_ATTR_SZ * 2; + } else if (strcasecmp(anode->field, "WINS-server") == 0) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS); + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS); + attrlen += ISAKMP_ATTR_SZ * 2; + } else if (strcasecmp(anode->field, "DHCP-server") == 0) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP); + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP); + attrlen += ISAKMP_ATTR_SZ * 2; + } else if (strcasecmp(anode->field, "Lifetime") == 0) { + bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY); + attrlen += ISAKMP_ATTR_SZ; + } else { + log_print("cfg_initiator_send_ATTR: unknown attribute " + "%.20s in section [%s]", anode->field, id_string); + } + } + + conf_free_list(alist); } - else if (strcasecmp (anode->field, "Nameserver") == 0) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS); - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS); - attrlen += ISAKMP_ATTR_SZ * 2; - } - else if (strcasecmp (anode->field, "WINS-server") == 0) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS); - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS); - attrlen += ISAKMP_ATTR_SZ * 2; - } - else if (strcasecmp (anode->field, "DHCP-server") == 0) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP); - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP); - attrlen += ISAKMP_ATTR_SZ * 2; - } - else if (strcasecmp (anode->field, "Lifetime") == 0) - { - bit_set (attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY); - attrlen += ISAKMP_ATTR_SZ; - } - else - { - log_print ("cfg_initiator_send_ATTR: unknown attribute " - "%.20s in section [%s]", anode->field, id_string); - } - } + } - conf_free_list (alist); + if (attrlen == 0) { + /* No data found. */ + log_print("cfg_initiator_send_ATTR: no IKECFG attributes " + "found for [%s]", id_string); + + /* + * We can continue, but this indicates a configuration error that + * the user probably will want to correct. + */ + free(id_string); + return 0; + } + attrlen += ISAKMP_ATTRIBUTE_SZ; + attrp = calloc(1, attrlen); + if (!attrp) { + log_error("cfg_initiator_send_ATTR: calloc (1, %lu) failed", + (unsigned long) attrlen); + goto fail; } - } - - if (attrlen == 0) - { - /* No data found. */ - log_print ("cfg_initiator_send_ATTR: no IKECFG attributes " - "found for [%s]", id_string); - - /* - * We can continue, but this indicates a configuration error that - * the user probably will want to correct. - */ - free (id_string); - return 0; - } - - attrlen += ISAKMP_ATTRIBUTE_SZ; - attrp = calloc (1, attrlen); - if (!attrp) - { - log_error ("cfg_initiator_send_ATTR: calloc (1, %lu) failed", - (unsigned long)attrlen); - goto fail; - } - - if (message_add_payload (msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen, 1)) - { - free (attrp); - goto fail; - } - - SET_ISAKMP_ATTRIBUTE_TYPE (attrp, ie->cfg_type); - getrandom ((u_int8_t *)&ie->cfg_id, sizeof ie->cfg_id); - SET_ISAKMP_ATTRIBUTE_ID (attrp, ie->cfg_id); - - off = ISAKMP_ATTRIBUTE_SZ; - - /* - * Use the bitstring built previously to collect the right - * parameters for attrp. - */ - for (bit = 0; bit < CFG_ATTR_BIT_MAX; bit++) - if (bit_test (attrbits, bit)) - { - attr = attrp + off; - SET_ISAKMP_ATTR_TYPE (attr, bit); - - if (ie->cfg_type == ISAKMP_CFG_REQUEST) - { - off += ISAKMP_ATTR_SZ; - continue; - } - - /* All the other are similar, this is the odd one. */ - if (bit == ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY) - { - life = conf_get_num (id_string, "Lifetime", 1200); - SET_ISAKMP_ATTR_LENGTH_VALUE (attr, 4); - encode_32 (attr + ISAKMP_ATTR_VALUE_OFF, life); - off += ISAKMP_ATTR_SZ + 4; - continue; - } - - switch (bit) - { - case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: - length = 4; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: - length = 16; - break; - - default: - length = 0; /* Silence gcc. */ - } - - switch (bit) - { - case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: - field = "Address"; - break; - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: - field = "Netmask"; - break; - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: - field = "Nameserver"; - break; - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: - field = "DHCP-server"; - break; - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: - field = "WINS-server"; - break; - default: - field = 0; /* Silence gcc. */ - } - - sa = conf_get_address (id_string, field); - - SET_ISAKMP_ATTR_LENGTH_VALUE (attr, length); - memcpy (attr + ISAKMP_ATTR_VALUE_OFF, sockaddr_addrdata (sa), - length); - - free (sa); - - off += ISAKMP_ATTR_SZ + length; - } - - if (msg->exchange->phase == 2) - if (cfg_finalize_hash (msg, hashp, attrp, attrlen)) - goto fail; - - return 0; - - fail: - if (id_string) - free (id_string); - return -1; + if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen, 1)) { + free(attrp); + goto fail; + } + SET_ISAKMP_ATTRIBUTE_TYPE(attrp, ie->cfg_type); + getrandom((u_int8_t *) & ie->cfg_id, sizeof ie->cfg_id); + SET_ISAKMP_ATTRIBUTE_ID(attrp, ie->cfg_id); + + off = ISAKMP_ATTRIBUTE_SZ; + + /* + * Use the bitstring built previously to collect the right + * parameters for attrp. + */ + for (bit = 0; bit < CFG_ATTR_BIT_MAX; bit++) + if (bit_test(attrbits, bit)) { + attr = attrp + off; + SET_ISAKMP_ATTR_TYPE(attr, bit); + + if (ie->cfg_type == ISAKMP_CFG_REQUEST) { + off += ISAKMP_ATTR_SZ; + continue; + } + /* All the other are similar, this is the odd one. */ + if (bit == ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY) { + life = conf_get_num(id_string, "Lifetime", 1200); + SET_ISAKMP_ATTR_LENGTH_VALUE(attr, 4); + encode_32(attr + ISAKMP_ATTR_VALUE_OFF, life); + off += ISAKMP_ATTR_SZ + 4; + continue; + } + switch (bit) { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + length = 4; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + length = 16; + break; + + default: + length = 0; /* Silence gcc. */ + } + + switch (bit) { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + field = "Address"; + break; + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + field = "Netmask"; + break; + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + field = "Nameserver"; + break; + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + field = "DHCP-server"; + break; + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + field = "WINS-server"; + break; + default: + field = 0; /* Silence gcc. */ + } + + sa = conf_get_address(id_string, field); + + SET_ISAKMP_ATTR_LENGTH_VALUE(attr, length); + memcpy(attr + ISAKMP_ATTR_VALUE_OFF, sockaddr_addrdata(sa), + length); + + free(sa); + + off += ISAKMP_ATTR_SZ + length; + } + if (msg->exchange->phase == 2) + if (cfg_finalize_hash(msg, hashp, attrp, attrlen)) + goto fail; + + return 0; + +fail: + if (id_string) + free(id_string); + return -1; } /* @@ -378,104 +346,101 @@ cfg_initiator_send_ATTR (struct message *msg) * As "the client", this ends REQ/REPLY. */ static int -cfg_initiator_recv_ATTR (struct message *msg) +cfg_initiator_recv_ATTR(struct message * msg) { - struct payload *attrp - = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ATTRIBUTE]); - struct ipsec_exch *ie = msg->exchange->data; - struct sa *isakmp_sa = msg->isakmp_sa; - struct isakmp_cfg_attr *attr; - struct sockaddr *sa; - const char *uk_addr = "<unknown>"; - char *addr; - - if (msg->exchange->phase == 2) - if (cfg_verify_hash (msg)) - return -1; - - /* Sanity. */ - if (ie->cfg_id != GET_ISAKMP_ATTRIBUTE_ID (attrp->p)) - { - log_print ("cfg_initiator_recv_ATTR: cfg packet ID does not match!"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]) - { - case ISAKMP_CFG_ACK: - if (ie->cfg_type != ISAKMP_CFG_SET) - { - log_print ("cfg_initiator_recv_ATTR: bad packet type ACK"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; + struct payload *attrp + = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_ATTRIBUTE]); + struct ipsec_exch *ie = msg->exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + struct isakmp_cfg_attr *attr; + struct sockaddr *sa; + const char *uk_addr = "<unknown>"; + char *addr; + + if (msg->exchange->phase == 2) + if (cfg_verify_hash(msg)) + return -1; + + /* Sanity. */ + if (ie->cfg_id != GET_ISAKMP_ATTRIBUTE_ID(attrp->p)) { + log_print("cfg_initiator_recv_ATTR: cfg packet ID does not match!"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; } - break; - case ISAKMP_CFG_REPLY: - if (ie->cfg_type != ISAKMP_CFG_REQUEST) - { - log_print ("cfg_initiator_recv_ATTR: bad packet type REPLY"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; + switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]) { + case ISAKMP_CFG_ACK: + if (ie->cfg_type != ISAKMP_CFG_SET) { + log_print("cfg_initiator_recv_ATTR: bad packet type ACK"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + break; + case ISAKMP_CFG_REPLY: + if (ie->cfg_type != ISAKMP_CFG_REQUEST) { + log_print("cfg_initiator_recv_ATTR: bad packet type REPLY"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; + } + break; + + default: + log_print("cfg_initiator_recv_ATTR: " + "unexpected configuration message type %d", + attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + return -1; } - break; - - default: - log_print ("cfg_initiator_recv_ATTR: " - "unexpected configuration message type %d", - attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - attribute_map (attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (attrp->p) + + attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF, cfg_decode_attribute, ie); - switch (ie->cfg_type) - { - case ISAKMP_CFG_ACK: - { - /* SET/ACK -- Server side (ACK from client) */ - msg->transport->vtbl->get_src (isakmp_sa->transport, &sa); - if (sockaddr2text (sa, &addr, 0) < 0) - addr = (char *)uk_addr; - - for (attr = LIST_FIRST (&ie->attrs); attr; - attr = LIST_NEXT (attr, link)) - LOG_DBG ((LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " - "client %s ACKs attribute %s", addr, - constant_name (isakmp_cfg_attr_cst, attr->type))); - - if (addr != uk_addr) - free (addr); - } - break; - - case ISAKMP_CFG_REPLY: - { - /* REQ/REPLY: effect attributes we've gotten responses on. */ - msg->transport->vtbl->get_src (isakmp_sa->transport, &sa); - if (sockaddr2text (sa, &addr, 0) < 0) - addr = (char *)uk_addr; - - for (attr = LIST_FIRST (&ie->attrs); attr; - attr = LIST_NEXT (attr, link)) - LOG_DBG ((LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " - "server %s replied with attribute %s", addr, - constant_name (isakmp_cfg_attr_cst, attr->type))); - - if (addr != uk_addr) - free (addr); - } - break; - - default: - break; - } - - attrp->flags |= PL_MARK; - return 0; + switch (ie->cfg_type) { + case ISAKMP_CFG_ACK: + { + /* SET/ACK -- Server side (ACK from client) */ + msg->transport->vtbl->get_src(isakmp_sa->transport, &sa); + if (sockaddr2text(sa, &addr, 0) < 0) + addr = (char *) uk_addr; + + for (attr = LIST_FIRST(&ie->attrs); attr; + attr = LIST_NEXT(attr, link)) + LOG_DBG((LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " + "client %s ACKs attribute %s", addr, + constant_name(isakmp_cfg_attr_cst, attr->type))); + + if (addr != uk_addr) + free(addr); + } + break; + + case ISAKMP_CFG_REPLY: + { + /* + * REQ/REPLY: effect attributes we've gotten + * responses on. + */ + msg->transport->vtbl->get_src(isakmp_sa->transport, &sa); + if (sockaddr2text(sa, &addr, 0) < 0) + addr = (char *) uk_addr; + + for (attr = LIST_FIRST(&ie->attrs); attr; + attr = LIST_NEXT(attr, link)) + LOG_DBG((LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " + "server %s replied with attribute %s", addr, + constant_name(isakmp_cfg_attr_cst, attr->type))); + + if (addr != uk_addr) + free(addr); + } + break; + + default: + break; + } + + attrp->flags |= PL_MARK; + return 0; } /* @@ -483,80 +448,78 @@ cfg_initiator_recv_ATTR (struct message *msg) * As "the client", this starts SET/ACK (initiated by the server). */ static int -cfg_responder_recv_ATTR (struct message *msg) +cfg_responder_recv_ATTR(struct message * msg) { - struct payload *attrp - = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ATTRIBUTE]); - struct ipsec_exch *ie = msg->exchange->data; - struct sa *isakmp_sa = msg->isakmp_sa; - struct isakmp_cfg_attr *attr; - struct sockaddr *sa; - char *addr; - - if (msg->exchange->phase == 2) - if (cfg_verify_hash (msg)) - return -1; - - ie->cfg_id = GET_ISAKMP_ATTRIBUTE_ID (attrp->p); - ie->cfg_type = attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]; - - switch (ie->cfg_type) - { - case ISAKMP_CFG_REQUEST: - case ISAKMP_CFG_SET: - break; - - default: - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - log_print ("cfg_responder_recv_ATTR: " - "unexpected configuration message type %d", ie->cfg_type); - return -1; - } - - attribute_map (attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (attrp->p) - - ISAKMP_TRANSFORM_SA_ATTRS_OFF, cfg_decode_attribute, ie); + struct payload *attrp + = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_ATTRIBUTE]); + struct ipsec_exch *ie = msg->exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + struct isakmp_cfg_attr *attr; + struct sockaddr *sa; + char *addr; + + if (msg->exchange->phase == 2) + if (cfg_verify_hash(msg)) + return -1; + + ie->cfg_id = GET_ISAKMP_ATTRIBUTE_ID(attrp->p); + ie->cfg_type = attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]; + + switch (ie->cfg_type) { + case ISAKMP_CFG_REQUEST: + case ISAKMP_CFG_SET: + break; - switch (ie->cfg_type) - { - case ISAKMP_CFG_REQUEST: - /* We're done. */ - break; + default: + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + log_print("cfg_responder_recv_ATTR: " + "unexpected configuration message type %d", ie->cfg_type); + return -1; + } - case ISAKMP_CFG_SET: - { - /* SET/ACK -- Client side (SET from server) */ - const char *uk_addr = "<unknown>"; + attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(attrp->p) + - ISAKMP_TRANSFORM_SA_ATTRS_OFF, cfg_decode_attribute, ie); - msg->transport->vtbl->get_dst (isakmp_sa->transport, &sa); - if (sockaddr2text (sa, &addr, 0) < 0) - addr = (char *)uk_addr; + switch (ie->cfg_type) { + case ISAKMP_CFG_REQUEST: + /* We're done. */ + break; - for (attr = LIST_FIRST (&ie->attrs); attr; - attr = LIST_NEXT (attr, link)) - LOG_DBG ((LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " - "server %s asks us to SET attribute %s", addr, - constant_name (isakmp_cfg_attr_cst, attr->type))); + case ISAKMP_CFG_SET: + { + /* SET/ACK -- Client side (SET from server) */ + const char *uk_addr = "<unknown>"; + + msg->transport->vtbl->get_dst(isakmp_sa->transport, &sa); + if (sockaddr2text(sa, &addr, 0) < 0) + addr = (char *) uk_addr; + + for (attr = LIST_FIRST(&ie->attrs); attr; + attr = LIST_NEXT(attr, link)) + LOG_DBG((LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " + "server %s asks us to SET attribute %s", addr, + constant_name(isakmp_cfg_attr_cst, attr->type))); + + /* + * XXX Here's the place to add code to walk through each attribute + * XXX and send them along to dhclient or whatever. Each attribute + * XXX that we act upon (such as setting a netmask), should be + * XXX marked like this for us to send the proper ACK response: + * XXX attr->attr_used++; + */ + + if (addr != uk_addr) + free(addr); + } + break; - /* - * XXX Here's the place to add code to walk through each attribute - * XXX and send them along to dhclient or whatever. Each attribute - * XXX that we act upon (such as setting a netmask), should be - * XXX marked like this for us to send the proper ACK response: - * XXX attr->attr_used++; - */ - - if (addr != uk_addr) - free (addr); - } - break; - - default: - break; - } - - attrp->flags |= PL_MARK; - return 0; + default: + break; + } + + attrp->flags |= PL_MARK; + return 0; } /* @@ -564,152 +527,136 @@ cfg_responder_recv_ATTR (struct message *msg) * As "the client", this ends SET/ACK mode. */ static int -cfg_responder_send_ATTR (struct message *msg) +cfg_responder_send_ATTR(struct message * msg) { - struct ipsec_exch *ie = msg->exchange->data; - struct sa *isakmp_sa = msg->isakmp_sa; - u_int8_t *hashp = 0, *attrp; - u_int16_t attrlen; - char *id_string; - - if (msg->exchange->phase == 2) - { - hashp = cfg_add_hash (msg); - if (!hashp) - return -1; - } - - /* We are responder, check isakmp_sa for other side. */ - if (isakmp_sa->initiator ^ (ie->cfg_type == ISAKMP_CFG_REQUEST)) - id_string = ipsec_id_string (isakmp_sa->id_i, isakmp_sa->id_i_len); - else - id_string = ipsec_id_string (isakmp_sa->id_r, isakmp_sa->id_r_len); - if (!id_string) - { - log_print ("cfg_responder_send_ATTR: cannot parse client's ID"); - return -1; - } - - if (cfg_encode_attributes (&ie->attrs, (ie->cfg_type == ISAKMP_CFG_SET ? - ISAKMP_CFG_ACK : ISAKMP_CFG_REPLY), - ie->cfg_id, id_string, &attrp, &attrlen)) - { - free (id_string); - return -1; - } - free (id_string); - - if (message_add_payload (msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen, 1)) - { - free (attrp); - return -1; - } - - if (msg->exchange->phase == 2) - if (cfg_finalize_hash (msg, hashp, attrp, attrlen)) - return -1; - - return 0; + struct ipsec_exch *ie = msg->exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + u_int8_t *hashp = 0, *attrp; + u_int16_t attrlen; + char *id_string; + + if (msg->exchange->phase == 2) { + hashp = cfg_add_hash(msg); + if (!hashp) + return -1; + } + /* We are responder, check isakmp_sa for other side. */ + if (isakmp_sa->initiator ^ (ie->cfg_type == ISAKMP_CFG_REQUEST)) + id_string = ipsec_id_string(isakmp_sa->id_i, isakmp_sa->id_i_len); + else + id_string = ipsec_id_string(isakmp_sa->id_r, isakmp_sa->id_r_len); + if (!id_string) { + log_print("cfg_responder_send_ATTR: cannot parse client's ID"); + return -1; + } + if (cfg_encode_attributes(&ie->attrs, (ie->cfg_type == ISAKMP_CFG_SET ? + ISAKMP_CFG_ACK : ISAKMP_CFG_REPLY), + ie->cfg_id, id_string, &attrp, &attrlen)) { + free(id_string); + return -1; + } + free(id_string); + + if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen, 1)) { + free(attrp); + return -1; + } + if (msg->exchange->phase == 2) + if (cfg_finalize_hash(msg, hashp, attrp, attrlen)) + return -1; + + return 0; } -u_int8_t * -cfg_add_hash (struct message *msg) +u_int8_t * +cfg_add_hash(struct message * msg) { - struct ipsec_sa *isa = msg->isakmp_sa->data; - struct hash *hash = hash_get (isa->hash); - u_int8_t *hashp; - - hashp = malloc (ISAKMP_HASH_SZ + hash->hashsize); - if (!hashp) - { - log_error ("cfg_add_hash: malloc (%lu) failed", - ISAKMP_HASH_SZ + (unsigned long)hash->hashsize); - return 0; - } - if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, hashp, - ISAKMP_HASH_SZ + hash->hashsize, 1)) - { - free (hashp); - return 0; - } - return hashp; + struct ipsec_sa *isa = msg->isakmp_sa->data; + struct hash *hash = hash_get(isa->hash); + u_int8_t *hashp; + + hashp = malloc(ISAKMP_HASH_SZ + hash->hashsize); + if (!hashp) { + log_error("cfg_add_hash: malloc (%lu) failed", + ISAKMP_HASH_SZ + (unsigned long) hash->hashsize); + return 0; + } + if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH, hashp, + ISAKMP_HASH_SZ + hash->hashsize, 1)) { + free(hashp); + return 0; + } + return hashp; } int -cfg_finalize_hash (struct message *msg, u_int8_t *hashp, u_int8_t *data, - u_int16_t length) +cfg_finalize_hash(struct message * msg, u_int8_t * hashp, u_int8_t * data, + u_int16_t length) { - struct ipsec_sa *isa = msg->isakmp_sa->data; - struct prf *prf; - - prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); - if (!prf) - return -1; - - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, msg->exchange->message_id, - ISAKMP_HDR_MESSAGE_ID_LEN); - prf->Update (prf->prfctx, data, length); - prf->Final (hashp + ISAKMP_GEN_SZ, prf->prfctx); - prf_free (prf); - return 0; + struct ipsec_sa *isa = msg->isakmp_sa->data; + struct prf *prf; + + prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, isa->skeyid_len); + if (!prf) + return -1; + + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, msg->exchange->message_id, + ISAKMP_HDR_MESSAGE_ID_LEN); + prf->Update(prf->prfctx, data, length); + prf->Final(hashp + ISAKMP_GEN_SZ, prf->prfctx); + prf_free(prf); + return 0; } int -cfg_verify_hash (struct message *msg) +cfg_verify_hash(struct message * msg) { - struct payload *hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - struct ipsec_sa *isa = msg->isakmp_sa->data; - struct prf *prf; - u_int8_t *hash, *comp_hash; - size_t hash_len; - - if (!hashp) - { - log_print ("cfg_verify_hash: phase 2 message missing HASH"); - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); - return -1; - } - - hash = hashp->p; - hash_len = GET_ISAKMP_GEN_LENGTH (hash); - comp_hash = malloc (hash_len - ISAKMP_GEN_SZ); - if (!comp_hash) - { - log_error ("cfg_verify_hash: malloc (%lu) failed", - (unsigned long)hash_len - ISAKMP_GEN_SZ); - return -1; - } - - /* Verify hash. */ - prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, - isa->skeyid_len); - if (!prf) - { - free (comp_hash); - return -1; - } - - prf->Init (prf->prfctx); - prf->Update (prf->prfctx, msg->exchange->message_id, - ISAKMP_HDR_MESSAGE_ID_LEN); - prf->Update (prf->prfctx, hash + hash_len, - msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len); - prf->Final (comp_hash, prf->prfctx); - prf_free (prf); - - if (memcmp (hash + ISAKMP_GEN_SZ, comp_hash, hash_len - ISAKMP_GEN_SZ) != 0) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); - free (comp_hash); - return -1; - } - free (comp_hash); - - /* Mark the HASH as handled. */ - hashp->flags |= PL_MARK; - - return 0; + struct payload *hashp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + struct ipsec_sa *isa = msg->isakmp_sa->data; + struct prf *prf; + u_int8_t *hash, *comp_hash; + size_t hash_len; + + if (!hashp) { + log_print("cfg_verify_hash: phase 2 message missing HASH"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + return -1; + } + hash = hashp->p; + hash_len = GET_ISAKMP_GEN_LENGTH(hash); + comp_hash = malloc(hash_len - ISAKMP_GEN_SZ); + if (!comp_hash) { + log_error("cfg_verify_hash: malloc (%lu) failed", + (unsigned long) hash_len - ISAKMP_GEN_SZ); + return -1; + } + /* Verify hash. */ + prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a, + isa->skeyid_len); + if (!prf) { + free(comp_hash); + return -1; + } + prf->Init(prf->prfctx); + prf->Update(prf->prfctx, msg->exchange->message_id, + ISAKMP_HDR_MESSAGE_ID_LEN); + prf->Update(prf->prfctx, hash + hash_len, + msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len); + prf->Final(comp_hash, prf->prfctx); + prf_free(prf); + + if (memcmp(hash + ISAKMP_GEN_SZ, comp_hash, hash_len - ISAKMP_GEN_SZ) != 0) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + free(comp_hash); + return -1; + } + free(comp_hash); + + /* Mark the HASH as handled. */ + hashp->flags |= PL_MARK; + + return 0; } /* @@ -718,303 +665,277 @@ cfg_verify_hash (struct message *msg) * attributes indexed by type for easy retrieval. */ static int -cfg_decode_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vie) +cfg_decode_attribute(u_int16_t type, u_int8_t * value, u_int16_t len, + void *vie) { - struct ipsec_exch *ie = vie; - struct isakmp_cfg_attr *attr; - - if (type >= ISAKMP_CFG_ATTR_PRIVATE_MIN - && type <= ISAKMP_CFG_ATTR_PRIVATE_MAX) - return 0; - if (type == 0 || type >= ISAKMP_CFG_ATTR_FUTURE_MIN) - { - LOG_DBG ((LOG_NEGOTIATION, 30, - "cfg_decode_attribute: invalid attr type %u", type)); - return -1; - } - - attr = calloc (1, sizeof *attr); - if (!attr) - { - log_error ("cfg_decode_attribute: calloc (1, %lu) failed", - (unsigned long)sizeof *attr); - return -1; - } - attr->type = type; - attr->length = len; - if (len) - { - attr->value = malloc (len); - if (!attr->value) - { - log_error ("cfg_decode_attribute: malloc (%d) failed", len); - free (attr); - /* Should we also deallocate all other values? */ - return -1; + struct ipsec_exch *ie = vie; + struct isakmp_cfg_attr *attr; + + if (type >= ISAKMP_CFG_ATTR_PRIVATE_MIN + && type <= ISAKMP_CFG_ATTR_PRIVATE_MAX) + return 0; + if (type == 0 || type >= ISAKMP_CFG_ATTR_FUTURE_MIN) { + LOG_DBG((LOG_NEGOTIATION, 30, + "cfg_decode_attribute: invalid attr type %u", type)); + return -1; + } + attr = calloc(1, sizeof *attr); + if (!attr) { + log_error("cfg_decode_attribute: calloc (1, %lu) failed", + (unsigned long) sizeof *attr); + return -1; + } + attr->type = type; + attr->length = len; + if (len) { + attr->value = malloc(len); + if (!attr->value) { + log_error("cfg_decode_attribute: malloc (%d) failed", len); + free(attr); + /* Should we also deallocate all other values? */ + return -1; + } + memcpy(attr->value, value, len); } - memcpy (attr->value, value, len); - } - LIST_INSERT_HEAD (&ie->attrs, attr, link); - return 0; + LIST_INSERT_HEAD(&ie->attrs, attr, link); + return 0; } /* * Encode list of attributes from ie->attrs into a attribute payload. */ static int -cfg_encode_attributes (struct isakmp_cfg_attr_head *attrs, u_int32_t type, - u_int32_t cfg_id, char *id_string, u_int8_t **attrp, - u_int16_t *len) +cfg_encode_attributes(struct isakmp_cfg_attr_head * attrs, u_int32_t type, + u_int32_t cfg_id, char *id_string, u_int8_t ** attrp, + u_int16_t * len) { - struct isakmp_cfg_attr *attr; - struct sockaddr *sa; - sa_family_t family; - u_int32_t value; - u_int16_t off; - char *field; - - /* Compute length */ - *len = ISAKMP_ATTRIBUTE_SZ; - for (attr = LIST_FIRST (attrs); attr; attr = LIST_NEXT (attr, link)) - { - /* With ACK we only include the attrs we've actually used. */ - if (type == ISAKMP_CFG_ACK && attr->attr_used == 0) - continue; - - switch (attr->type) - { - case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: - case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY: - attr->length = 4; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: - attr->length = 8; - break; - - case ISAKMP_CFG_ATTR_APPLICATION_VERSION: - /* XXX So far no version identifier of isakmpd here. */ - attr->length = 0; - break; - - case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES: - attr->length = 2 * 15; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: - attr->length = 16; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: - attr->length = 17; - break; + struct isakmp_cfg_attr *attr; + struct sockaddr *sa; + sa_family_t family; + u_int32_t value; + u_int16_t off; + char *field; + + /* Compute length */ + *len = ISAKMP_ATTRIBUTE_SZ; + for (attr = LIST_FIRST(attrs); attr; attr = LIST_NEXT(attr, link)) { + /* With ACK we only include the attrs we've actually used. */ + if (type == ISAKMP_CFG_ACK && attr->attr_used == 0) + continue; + + switch (attr->type) { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY: + attr->length = 4; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: + attr->length = 8; + break; + + case ISAKMP_CFG_ATTR_APPLICATION_VERSION: + /* XXX So far no version identifier of isakmpd here. */ + attr->length = 0; + break; + + case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES: + attr->length = 2 * 15; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + attr->length = 16; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: + attr->length = 17; + break; + + default: + attr->ignore++; + /* XXX Log! */ + } + *len += ISAKMP_ATTR_SZ + attr->length; + } - default: - attr->ignore++; - /* XXX Log! */ + /* Allocate enough space for the payload */ + *attrp = calloc(1, *len); + if (!*attrp) { + log_error("cfg_encode_attributes: calloc (1, %lu) failed", + (unsigned long) *len); + return -1; } - *len += ISAKMP_ATTR_SZ + attr->length; - } - - /* Allocate enough space for the payload */ - *attrp = calloc (1, *len); - if (!*attrp) - { - log_error ("cfg_encode_attributes: calloc (1, %lu) failed", - (unsigned long)*len); - return -1; - } - - SET_ISAKMP_ATTRIBUTE_TYPE (*attrp, type); - SET_ISAKMP_ATTRIBUTE_ID (*attrp, cfg_id); - - off = ISAKMP_ATTRIBUTE_SZ; - for (attr = LIST_FIRST (attrs); attr; attr = LIST_NEXT (attr, link)) - { - /* With ACK we only include the attrs we've actually used. */ - if (type == ISAKMP_CFG_ACK && attr->attr_used == 0) - continue; - - switch (attr->type) - { - case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: - family = AF_INET; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: - family = AF_INET6; - break; - - default: - family = 0; - break; - } - - switch (attr->type) - { - case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: - field = "Address"; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: - field = "Network"; /* XXX or just "Address" */ - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: - field = "Netmask"; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: - field = "DHCP-server"; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: - field = "Nameserver"; - break; - - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: - field = "WINS-server"; - break; - - default: - field = 0; - } - - switch (attr->type) - { - case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: - case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: - sa = conf_get_address (id_string, field); - if (!sa) - { - LOG_DBG ((LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " - "attribute not found: %s", field)); - attr->length = 0; - break; - } - - if (sa->sa_family != family) - { - log_print ("cfg_responder_send_ATTR: attribute %s - expected %s " - "got %s data", field, - (family == AF_INET ? "IPv4" : "IPv6"), - (sa->sa_family == AF_INET ? "IPv4" : "IPv6")); - free (sa); - attr->length = 0; - break; - } - - /* Temporary limit length for the _SUBNET types. */ - if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET) - attr->length = 4; - else if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET) - attr->length = 16; - - memcpy (*attrp + off + ISAKMP_ATTR_VALUE_OFF, sockaddr_addrdata (sa), - attr->length); - free (sa); - - /* _SUBNET types need some extra work. */ - if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET) - { - sa = conf_get_address (id_string, "Netmask"); - if (!sa) - { - LOG_DBG ((LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " - "attribute not found: Netmask")); - attr->length = 0; - break; - } - if (sa->sa_family != AF_INET) - { - log_print ("cfg_responder_send_ATTR: attribute Netmask - " - "expected IPv4 got IPv6 data"); - free (sa); - attr->length = 0; - break; - } - memcpy (*attrp + off + ISAKMP_ATTR_VALUE_OFF + attr->length, - sockaddr_addrdata (sa), attr->length); - attr->length = 8; - free (sa); - } - else if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET) - { - int prefix = conf_get_num (id_string, "Prefix", -1); - - if (prefix == -1) - { - log_print ("cfg_responder_send_ATTR: " - "attribute not found: Prefix"); - attr->length = 0; - break; + SET_ISAKMP_ATTRIBUTE_TYPE(*attrp, type); + SET_ISAKMP_ATTRIBUTE_ID(*attrp, cfg_id); + + off = ISAKMP_ATTRIBUTE_SZ; + for (attr = LIST_FIRST(attrs); attr; attr = LIST_NEXT(attr, link)) { + /* With ACK we only include the attrs we've actually used. */ + if (type == ISAKMP_CFG_ACK && attr->attr_used == 0) + continue; + + switch (attr->type) { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + family = AF_INET; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + family = AF_INET6; + break; + + default: + family = 0; + break; } - else if (prefix < -1 || prefix > 128) - { - log_print ("cfg_responder_send_ATTR: attribute Prefix - " - "invalid value %d", prefix); - attr->length = 0; - break; - } - - *(*attrp + off + ISAKMP_ATTR_VALUE_OFF + 16) = (u_int8_t)prefix; - attr->length = 17; - } - break; - case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY: - value = conf_get_num (id_string, "Lifetime", 1200); - encode_32 (*attrp + off + ISAKMP_ATTR_VALUE_OFF, value); - break; - - case ISAKMP_CFG_ATTR_APPLICATION_VERSION: - /* XXX So far no version identifier of isakmpd here. */ - break; + switch (attr->type) { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + field = "Address"; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: + field = "Network"; /* XXX or just "Address" */ + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + field = "Netmask"; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + field = "DHCP-server"; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + field = "Nameserver"; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + field = "WINS-server"; + break; + + default: + field = 0; + } - case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES: - break; + switch (attr->type) { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + sa = conf_get_address(id_string, field); + if (!sa) { + LOG_DBG((LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " + "attribute not found: %s", field)); + attr->length = 0; + break; + } + if (sa->sa_family != family) { + log_print("cfg_responder_send_ATTR: attribute %s - expected %s " + "got %s data", field, + (family == AF_INET ? "IPv4" : "IPv6"), + (sa->sa_family == AF_INET ? "IPv4" : "IPv6")); + free(sa); + attr->length = 0; + break; + } + /* Temporary limit length for the _SUBNET types. */ + if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET) + attr->length = 4; + else if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET) + attr->length = 16; + + memcpy(*attrp + off + ISAKMP_ATTR_VALUE_OFF, sockaddr_addrdata(sa), + attr->length); + free(sa); + + /* _SUBNET types need some extra work. */ + if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET) { + sa = conf_get_address(id_string, "Netmask"); + if (!sa) { + LOG_DBG((LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " + "attribute not found: Netmask")); + attr->length = 0; + break; + } + if (sa->sa_family != AF_INET) { + log_print("cfg_responder_send_ATTR: attribute Netmask - " + "expected IPv4 got IPv6 data"); + free(sa); + attr->length = 0; + break; + } + memcpy(*attrp + off + ISAKMP_ATTR_VALUE_OFF + attr->length, + sockaddr_addrdata(sa), attr->length); + attr->length = 8; + free(sa); + } else if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET) { + int prefix = conf_get_num(id_string, "Prefix", -1); + + if (prefix == -1) { + log_print("cfg_responder_send_ATTR: " + "attribute not found: Prefix"); + attr->length = 0; + break; + } else if (prefix < -1 || prefix > 128) { + log_print("cfg_responder_send_ATTR: attribute Prefix - " + "invalid value %d", prefix); + attr->length = 0; + break; + } + *(*attrp + off + ISAKMP_ATTR_VALUE_OFF + 16) = (u_int8_t) prefix; + attr->length = 17; + } + break; + + case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY: + value = conf_get_num(id_string, "Lifetime", 1200); + encode_32(*attrp + off + ISAKMP_ATTR_VALUE_OFF, value); + break; + + case ISAKMP_CFG_ATTR_APPLICATION_VERSION: + /* XXX So far no version identifier of isakmpd here. */ + break; + + case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES: + break; + + default: + break; + } - default: - break; + SET_ISAKMP_ATTR_TYPE(*attrp + off, attr->type); + SET_ISAKMP_ATTR_LENGTH_VALUE(*attrp + off, attr->length); + off += ISAKMP_ATTR_VALUE_OFF + attr->length; } - SET_ISAKMP_ATTR_TYPE (*attrp + off, attr->type); - SET_ISAKMP_ATTR_LENGTH_VALUE (*attrp + off, attr->length); - off += ISAKMP_ATTR_VALUE_OFF + attr->length; - } - - return 0; + return 0; } diff --git a/sbin/isakmpd/isakmp_cfg.h b/sbin/isakmpd/isakmp_cfg.h index cdad6e2507f..58f9e00f235 100644 --- a/sbin/isakmpd/isakmp_cfg.h +++ b/sbin/isakmpd/isakmp_cfg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isakmp_cfg.h,v 1.3 2003/06/03 14:28:16 ho Exp $ */ +/* $OpenBSD: isakmp_cfg.h,v 1.4 2004/04/15 18:39:26 deraadt Exp $ */ /* * Copyright (c) 2001 Niklas Hallqvist. All rights reserved. @@ -35,19 +35,19 @@ #include <sys/queue.h> struct isakmp_cfg_attr { - LIST_ENTRY (isakmp_cfg_attr) link; - u_int16_t type; - u_int8_t attr_used; - /* 8 bits just to be well-aligned. */ - u_int8_t ignore; - size_t length; - void *value; + LIST_ENTRY(isakmp_cfg_attr) link; + u_int16_t type; + u_int8_t attr_used; + /* 8 bits just to be well-aligned. */ + u_int8_t ignore; + size_t length; + void *value; }; struct message; -extern int (*isakmp_cfg_initiator[]) (struct message *); -extern int (*isakmp_cfg_responder[]) (struct message *); -extern int16_t script_transaction[]; +extern int (*isakmp_cfg_initiator[]) (struct message *); +extern int (*isakmp_cfg_responder[]) (struct message *); +extern int16_t script_transaction[]; -#endif /* _ISAKMP_CFG_H_ */ +#endif /* _ISAKMP_CFG_H_ */ diff --git a/sbin/isakmpd/isakmp_doi.c b/sbin/isakmpd/isakmp_doi.c index 0aab1c83712..1ef681f0942 100644 --- a/sbin/isakmpd/isakmp_doi.c +++ b/sbin/isakmpd/isakmp_doi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: isakmp_doi.c,v 1.18 2004/03/10 23:08:49 hshoexer Exp $ */ -/* $EOM: isakmp_doi.c,v 1.42 2000/09/12 16:29:41 ho Exp $ */ +/* $OpenBSD: isakmp_doi.c,v 1.19 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: isakmp_doi.c,v 1.42 2000/09/12 16:29:41 ho Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -50,219 +50,215 @@ #include "util.h" #ifdef USE_DEBUG -static int isakmp_debug_attribute (u_int16_t, u_int8_t *, u_int16_t, void *); +static int isakmp_debug_attribute(u_int16_t, u_int8_t *, u_int16_t, void *); #endif -static void isakmp_finalize_exchange (struct message *); -static struct keystate *isakmp_get_keystate (struct message *); -static int isakmp_initiator (struct message *); -static int isakmp_responder (struct message *); -static void isakmp_setup_situation (u_int8_t *); -static size_t isakmp_situation_size (void); -static u_int8_t isakmp_spi_size (u_int8_t); -static int isakmp_validate_attribute (u_int16_t, u_int8_t *, u_int16_t, - void *); -static int isakmp_validate_exchange (u_int8_t); -static int isakmp_validate_id_information (u_int8_t, u_int8_t *, u_int8_t *, - size_t, struct exchange *); -static int isakmp_validate_key_information (u_int8_t *, size_t); -static int isakmp_validate_notification (u_int16_t); -static int isakmp_validate_proto (u_int8_t); -static int isakmp_validate_situation (u_int8_t *, size_t *, size_t); -static int isakmp_validate_transform_id (u_int8_t, u_int8_t); +static void isakmp_finalize_exchange(struct message *); +static struct keystate *isakmp_get_keystate(struct message *); +static int isakmp_initiator(struct message *); +static int isakmp_responder(struct message *); +static void isakmp_setup_situation(u_int8_t *); +static size_t isakmp_situation_size(void); +static u_int8_t isakmp_spi_size(u_int8_t); +static int +isakmp_validate_attribute(u_int16_t, u_int8_t *, u_int16_t, + void *); +static int isakmp_validate_exchange(u_int8_t); +static int +isakmp_validate_id_information(u_int8_t, u_int8_t *, u_int8_t *, + size_t, struct exchange *); +static int isakmp_validate_key_information(u_int8_t *, size_t); +static int isakmp_validate_notification(u_int16_t); +static int isakmp_validate_proto(u_int8_t); +static int isakmp_validate_situation(u_int8_t *, size_t *, size_t); +static int isakmp_validate_transform_id(u_int8_t, u_int8_t); static struct doi isakmp_doi = { - { 0 }, ISAKMP_DOI_ISAKMP, 0, 0, 0, + {0}, ISAKMP_DOI_ISAKMP, 0, 0, 0, #ifdef USE_DEBUG - isakmp_debug_attribute, + isakmp_debug_attribute, #endif - 0, /* delete_spi not needed. */ - 0, /* exchange_script not needed. */ - isakmp_finalize_exchange, - 0, /* free_exchange_data not needed. */ - 0, /* free_proto_data not needed. */ - 0, /* free_sa_data not needed. */ - isakmp_get_keystate, - 0, /* get_spi not needed. */ - 0, /* handle_leftover_payload not needed. */ - 0, /* informational_post_hook not needed. */ - 0, /* informational_pre_hook not needed. */ - 0, /* XXX need maybe be filled-in. */ - 0, /* proto_init not needed. */ - isakmp_setup_situation, - isakmp_situation_size, - isakmp_spi_size, - isakmp_validate_attribute, - isakmp_validate_exchange, - isakmp_validate_id_information, - isakmp_validate_key_information, - isakmp_validate_notification, - isakmp_validate_proto, - isakmp_validate_situation, - isakmp_validate_transform_id, - isakmp_initiator, - isakmp_responder, + 0, /* delete_spi not needed. */ + 0, /* exchange_script not needed. */ + isakmp_finalize_exchange, + 0, /* free_exchange_data not needed. */ + 0, /* free_proto_data not needed. */ + 0, /* free_sa_data not needed. */ + isakmp_get_keystate, + 0, /* get_spi not needed. */ + 0, /* handle_leftover_payload not needed. */ + 0, /* informational_post_hook not needed. */ + 0, /* informational_pre_hook not needed. */ + 0, /* XXX need maybe be filled-in. */ + 0, /* proto_init not needed. */ + isakmp_setup_situation, + isakmp_situation_size, + isakmp_spi_size, + isakmp_validate_attribute, + isakmp_validate_exchange, + isakmp_validate_id_information, + isakmp_validate_key_information, + isakmp_validate_notification, + isakmp_validate_proto, + isakmp_validate_situation, + isakmp_validate_transform_id, + isakmp_initiator, + isakmp_responder, #ifdef USE_DEBUG - ipsec_decode_ids + ipsec_decode_ids #endif }; /* Requires doi_init to already have been called. */ void -isakmp_doi_init (void) +isakmp_doi_init(void) { - doi_register (&isakmp_doi); + doi_register(&isakmp_doi); } #ifdef USE_DEBUG int -isakmp_debug_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vmsg) +isakmp_debug_attribute(u_int16_t type, u_int8_t * value, u_int16_t len, + void *vmsg) { - /* XXX Not implemented yet. */ - return 0; + /* XXX Not implemented yet. */ + return 0; } -#endif /* USE_DEBUG */ +#endif /* USE_DEBUG */ static void -isakmp_finalize_exchange (struct message *msg) +isakmp_finalize_exchange(struct message * msg) { } static struct keystate * -isakmp_get_keystate (struct message *msg) +isakmp_get_keystate(struct message * msg) { - return 0; + return 0; } static void -isakmp_setup_situation (u_int8_t *buf) +isakmp_setup_situation(u_int8_t * buf) { - /* Nothing to do. */ + /* Nothing to do. */ } static size_t -isakmp_situation_size (void) +isakmp_situation_size(void) { - return 0; + return 0; } static u_int8_t -isakmp_spi_size (u_int8_t proto) +isakmp_spi_size(u_int8_t proto) { - /* One way to specify ISAKMP SPIs is to say they're zero-sized. */ - return 0; + /* One way to specify ISAKMP SPIs is to say they're zero-sized. */ + return 0; } static int -isakmp_validate_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, - void *vmsg) +isakmp_validate_attribute(u_int16_t type, u_int8_t *value, u_int16_t len, + void *vmsg) { - /* XXX Not implemented yet. */ - return -1; + /* XXX Not implemented yet. */ + return -1; } static int -isakmp_validate_exchange (u_int8_t exch) +isakmp_validate_exchange(u_int8_t exch) { - /* If we get here the exchange is invalid. */ - return -1; + /* If we get here the exchange is invalid. */ + return -1; } static int -isakmp_validate_id_information (u_int8_t type, u_int8_t *extra, u_int8_t *buf, - size_t sz, struct exchange *exchange) +isakmp_validate_id_information(u_int8_t type, u_int8_t *extra, u_int8_t *buf, + size_t sz, struct exchange *exchange) { - return zero_test (extra, ISAKMP_ID_DOI_DATA_LEN); + return zero_test(extra, ISAKMP_ID_DOI_DATA_LEN); } static int -isakmp_validate_key_information (u_int8_t *buf, size_t sz) +isakmp_validate_key_information(u_int8_t *buf, size_t sz) { - /* Nothing to do. */ - return 0; + /* Nothing to do. */ + return 0; } static int -isakmp_validate_notification (u_int16_t type) +isakmp_validate_notification(u_int16_t type) { - /* If we get here the message type is invalid. */ - return -1; + /* If we get here the message type is invalid. */ + return -1; } static int -isakmp_validate_proto (u_int8_t proto) +isakmp_validate_proto(u_int8_t proto) { - /* If we get here the protocol is invalid. */ - return -1; + /* If we get here the protocol is invalid. */ + return -1; } static int -isakmp_validate_situation (u_int8_t *buf, size_t *sz, size_t len) +isakmp_validate_situation(u_int8_t *buf, size_t *sz, size_t len) { - /* There are no situations in the ISAKMP DOI. */ - *sz = 0; - return 0; + /* There are no situations in the ISAKMP DOI. */ + *sz = 0; + return 0; } static int -isakmp_validate_transform_id (u_int8_t proto, u_int8_t transform_id) +isakmp_validate_transform_id(u_int8_t proto, u_int8_t transform_id) { - /* XXX Not yet implemented. */ - return -1; + /* XXX Not yet implemented. */ + return -1; } static int -isakmp_initiator (struct message *msg) +isakmp_initiator(struct message *msg) { - if (msg->exchange->type != ISAKMP_EXCH_INFO) - { - log_print ("isakmp_initiator: unsupported exchange type %d in phase %d", - msg->exchange->type, msg->exchange->phase); - return -1; - } - - return message_send_info (msg); + if (msg->exchange->type != ISAKMP_EXCH_INFO) { + log_print("isakmp_initiator: unsupported exchange type %d in phase %d", + msg->exchange->type, msg->exchange->phase); + return -1; + } + return message_send_info(msg); } static int -isakmp_responder (struct message *msg) +isakmp_responder(struct message * msg) { - struct payload *p; + struct payload *p; - switch (msg->exchange->type) - { - case ISAKMP_EXCH_INFO: - for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_NOTIFY]); p; - p = TAILQ_NEXT (p, link)) - { - LOG_DBG ((LOG_EXCHANGE, 10, - "isakmp_responder: got NOTIFY of type %s, ignoring", - constant_name (isakmp_notify_cst, - GET_ISAKMP_NOTIFY_MSG_TYPE (p->p)))); - p->flags |= PL_MARK; - } + switch (msg->exchange->type) { + case ISAKMP_EXCH_INFO: + for (p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_NOTIFY]); p; + p = TAILQ_NEXT(p, link)) { + LOG_DBG((LOG_EXCHANGE, 10, + "isakmp_responder: got NOTIFY of type %s, ignoring", + constant_name(isakmp_notify_cst, + GET_ISAKMP_NOTIFY_MSG_TYPE(p->p)))); + p->flags |= PL_MARK; + } - for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_DELETE]); p; - p = TAILQ_NEXT (p, link)) - { - LOG_DBG ((LOG_EXCHANGE, 10, - "isakmp_responder: got DELETE, ignoring")); - p->flags |= PL_MARK; - } - return 0; + for (p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_DELETE]); p; + p = TAILQ_NEXT(p, link)) { + LOG_DBG((LOG_EXCHANGE, 10, + "isakmp_responder: got DELETE, ignoring")); + p->flags |= PL_MARK; + } + return 0; #ifdef USE_ISAKMP_CFG - case ISAKMP_EXCH_TRANSACTION: - /* return 0 isakmp_cfg_responder (msg); */ + case ISAKMP_EXCH_TRANSACTION: + /* return 0 isakmp_cfg_responder (msg); */ #endif /* USE_ISAKMP_CFG */ - default: - /* XXX So far we don't accept any proposals. */ - if (TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA])) - { - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - return -1; + default: + /* XXX So far we don't accept any proposals. */ + if (TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_SA])) { + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + return -1; + } } - } - return 0; + return 0; } diff --git a/sbin/isakmpd/isakmp_doi.h b/sbin/isakmpd/isakmp_doi.h index c0bb521013b..13a485b9107 100644 --- a/sbin/isakmpd/isakmp_doi.h +++ b/sbin/isakmpd/isakmp_doi.h @@ -1,5 +1,5 @@ -/* $OpenBSD: isakmp_doi.h,v 1.4 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: isakmp_doi.h,v 1.1 1998/07/07 23:20:29 niklas Exp $ */ +/* $OpenBSD: isakmp_doi.h,v 1.5 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: isakmp_doi.h,v 1.1 1998/07/07 23:20:29 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -32,6 +32,6 @@ #ifndef _ISAKMP_DOI_H_ #define _ISAKMP_DOI_H_ -extern void isakmp_doi_init (void); +extern void isakmp_doi_init(void); -#endif /* _ISAKMP_DOI_H_ */ +#endif /* _ISAKMP_DOI_H_ */ diff --git a/sbin/isakmpd/isakmpd.c b/sbin/isakmpd/isakmpd.c index 3130491da1e..bdb61b733fd 100644 --- a/sbin/isakmpd/isakmpd.c +++ b/sbin/isakmpd/isakmpd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: isakmpd.c,v 1.60 2004/04/08 10:05:54 hshoexer Exp $ */ -/* $EOM: isakmpd.c,v 1.54 2000/10/05 09:28:22 niklas Exp $ */ +/* $OpenBSD: isakmpd.c,v 1.61 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: isakmpd.c,v 1.54 2000/10/05 09:28:22 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -64,13 +64,13 @@ #include "policy.h" #endif -static void usage (void); +static void usage(void); /* * Set if -d is given, currently just for running in the foreground and log * to stderr instead of syslog. */ -int debug = 0; +int debug = 0; /* * If we receive a SIGHUP signal, this flag gets set to show we need to @@ -84,7 +84,7 @@ volatile sig_atomic_t sighupped = 0; * via the -R parameter. */ volatile sig_atomic_t sigusr1ed = 0; -static char *report_file = "/var/run/isakmpd.report"; +static char *report_file = "/var/run/isakmpd.report"; /* * If we receive a USR2 signal, this flag gets set to show we need to @@ -99,442 +99,419 @@ volatile sig_atomic_t sigusr2ed = 0; * Also on recv of an INT signal (Ctrl-C out of an '-d' session, typically). */ volatile sig_atomic_t sigtermed = 0; -void daemon_shutdown_now (int); +void daemon_shutdown_now(int); /* The default path of the PID file. */ -static char *pid_file = "/var/run/isakmpd.pid"; +static char *pid_file = "/var/run/isakmpd.pid"; #ifdef USE_DEBUG /* The path of the IKE packet capture log file. */ -static char *pcap_file = 0; +static char *pcap_file = 0; #endif static void -usage (void) +usage(void) { - fprintf (stderr, - "usage: %s [-4] [-6] [-c config-file] [-d] [-D class=level]\n" - " [-f fifo] [-i pid-file] [-n] [-p listen-port]\n" - " [-P local-port] [-L] [-l packetlog-file] [-r seed]\n" - " [-R report-file] [-v]\n", - sysdep_progname ()); - exit (1); + fprintf(stderr, + "usage: %s [-4] [-6] [-c config-file] [-d] [-D class=level]\n" + " [-f fifo] [-i pid-file] [-n] [-p listen-port]\n" + " [-P local-port] [-L] [-l packetlog-file] [-r seed]\n" + " [-R report-file] [-v]\n", + sysdep_progname()); + exit(1); } static void -parse_args (int argc, char *argv[]) +parse_args(int argc, char *argv[]) { - int ch; - char *ep; + int ch; + char *ep; #ifdef USE_DEBUG - int cls, level; - int do_packetlog = 0; + int cls, level; + int do_packetlog = 0; #endif - while ((ch = getopt (argc, argv, "46c:dD:f:i:np:P:Ll:r:R:v")) != -1) { - switch (ch) { - case '4': - bind_family |= BIND_FAMILY_INET4; - break; + while ((ch = getopt(argc, argv, "46c:dD:f:i:np:P:Ll:r:R:v")) != -1) { + switch (ch) { + case '4': + bind_family |= BIND_FAMILY_INET4; + break; - case '6': - bind_family |= BIND_FAMILY_INET6; - break; + case '6': + bind_family |= BIND_FAMILY_INET6; + break; - case 'c': - conf_path = optarg; - break; + case 'c': + conf_path = optarg; + break; - case 'd': - debug++; - break; + case 'd': + debug++; + break; #ifdef USE_DEBUG - case 'D': - if (sscanf (optarg, "%d=%d", &cls, &level) != 2) - { - if (sscanf (optarg, "A=%d", &level) == 1) - { - for (cls = 0; cls < LOG_ENDCLASS; cls++) - log_debug_cmd (cls, level); - } - else - log_print ("parse_args: -D argument unparseable: %s", optarg); - } - else - log_debug_cmd (cls, level); - break; -#endif /* USE_DEBUG */ - - case 'f': - ui_fifo = optarg; - break; - - case 'i': - pid_file = optarg; - break; - - case 'n': - app_none++; - break; - - case 'p': - udp_default_port = optarg; - break; - - case 'P': - udp_bind_port = optarg; - break; + case 'D': + if (sscanf(optarg, "%d=%d", &cls, &level) != 2) { + if (sscanf(optarg, "A=%d", &level) == 1) { + for (cls = 0; cls < LOG_ENDCLASS; cls++) + log_debug_cmd(cls, level); + } else + log_print("parse_args: -D argument unparseable: %s", optarg); + } else + log_debug_cmd(cls, level); + break; +#endif /* USE_DEBUG */ + + case 'f': + ui_fifo = optarg; + break; + + case 'i': + pid_file = optarg; + break; + + case 'n': + app_none++; + break; + + case 'p': + udp_default_port = optarg; + break; + + case 'P': + udp_bind_port = optarg; + break; #ifdef USE_DEBUG - case 'l': - pcap_file = optarg; - /* Fallthrough intended. */ - - case 'L': - do_packetlog++; - break; -#endif /* USE_DEBUG */ - - case 'r': - seed = strtoul (optarg, &ep, 0); - srandom (seed); - if (*ep != '\0') - log_fatal ("parse_args: invalid numeric arg to -r (%s)", optarg); - regrand = 1; - break; - - case 'R': - report_file = optarg; - break; - - case 'v': - verbose_logging = 1; - break; - - case '?': - default: - usage (); - } - } - argc -= optind; - argv += optind; + case 'l': + pcap_file = optarg; + /* Fallthrough intended. */ + + case 'L': + do_packetlog++; + break; +#endif /* USE_DEBUG */ + + case 'r': + seed = strtoul(optarg, &ep, 0); + srandom(seed); + if (*ep != '\0') + log_fatal("parse_args: invalid numeric arg to -r (%s)", optarg); + regrand = 1; + break; + + case 'R': + report_file = optarg; + break; + + case 'v': + verbose_logging = 1; + break; + + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; #ifdef USE_DEBUG - if (do_packetlog && !pcap_file) - pcap_file = PCAP_FILE_DEFAULT; + if (do_packetlog && !pcap_file) + pcap_file = PCAP_FILE_DEFAULT; #endif } static void -sighup (int sig) +sighup(int sig) { - sighupped = 1; + sighupped = 1; } /* Report internal state on SIGUSR1. */ static void -report (void) +report(void) { - FILE *rfp, *old; - mode_t old_umask; - - old_umask = umask (S_IRWXG | S_IRWXO); - rfp = monitor_fopen (report_file, "w"); - umask (old_umask); - - if (!rfp) - { - log_error ("report: fopen (\"%s\", \"w\") failed", report_file); - return; - } - - /* Divert the log channel to the report file during the report. */ - old = log_current (); - log_to (rfp); - ui_report ("r"); - log_to (old); - fclose (rfp); - - sigusr1ed = 0; + FILE *rfp, *old; + mode_t old_umask; + + old_umask = umask(S_IRWXG | S_IRWXO); + rfp = monitor_fopen(report_file, "w"); + umask(old_umask); + + if (!rfp) { + log_error("report: fopen (\"%s\", \"w\") failed", report_file); + return; + } + /* Divert the log channel to the report file during the report. */ + old = log_current(); + log_to(rfp); + ui_report("r"); + log_to(old); + fclose(rfp); + + sigusr1ed = 0; } static void -sigusr1 (int sig) +sigusr1(int sig) { - sigusr1ed = 1; + sigusr1ed = 1; } /* Rehash soft expiration timers on SIGUSR2. */ static void -rehash_timers (void) +rehash_timers(void) { #if 0 - /* XXX - not yet */ - log_print ("SIGUSR2 received, rehashing soft expiration timers."); + /* XXX - not yet */ + log_print("SIGUSR2 received, rehashing soft expiration timers."); - timer_rehash_timers (); + timer_rehash_timers(); #endif - sigusr2ed = 0; + sigusr2ed = 0; } static void -sigusr2 (int sig) +sigusr2(int sig) { - sigusr2ed = 1; + sigusr2ed = 1; } static int -phase2_sa_check (struct sa *sa, void *arg) +phase2_sa_check(struct sa * sa, void *arg) { - return sa->phase == 2; + return sa->phase == 2; } static void -daemon_shutdown (void) +daemon_shutdown(void) { - /* Perform a (protocol-wise) clean shutdown of the daemon. */ - struct sa *sa; - - if (sigtermed == 1) - { - log_print ("isakmpd: shutting down..."); - - /* Delete all active phase 2 SAs. */ - while ((sa = sa_find (phase2_sa_check, NULL))) - { - /* Each DELETE is another (outgoing) message. */ - sa_delete (sa, 1); + /* Perform a (protocol-wise) clean shutdown of the daemon. */ + struct sa *sa; + + if (sigtermed == 1) { + log_print("isakmpd: shutting down..."); + + /* Delete all active phase 2 SAs. */ + while ((sa = sa_find(phase2_sa_check, NULL))) { + /* Each DELETE is another (outgoing) message. */ + sa_delete(sa, 1); + } + sigtermed++; } - sigtermed++; - } - - if (transport_prio_sendqs_empty ()) - { - /* - * When the prioritized transport sendq:s are empty, i.e all - * the DELETE notifications have been sent, we can shutdown. - */ - + if (transport_prio_sendqs_empty()) { + /* + * When the prioritized transport sendq:s are empty, i.e all + * the DELETE notifications have been sent, we can shutdown. + */ + #ifdef USE_DEBUG - log_packet_stop (); + log_packet_stop(); #endif - /* Remove FIFO and pid files. */ - unlink (ui_fifo); - unlink (pid_file); - log_print ("isakmpd: exit"); - exit (0); - } + /* Remove FIFO and pid files. */ + unlink(ui_fifo); + unlink(pid_file); + log_print("isakmpd: exit"); + exit(0); + } } /* Called on SIGTERM, SIGINT or by ui_shutdown_daemon(). */ void -daemon_shutdown_now (int sig) +daemon_shutdown_now(int sig) { - sigtermed = 1; + sigtermed = 1; } /* Write pid file. */ static void -write_pid_file (void) +write_pid_file(void) { - FILE *fp; - - /* Ignore errors. This will fail with USE_PRIVSEP. */ - unlink (pid_file); - - fp = monitor_fopen (pid_file, "w"); - if (fp != NULL) - { - if (fprintf (fp, "%ld\n", (long) getpid ()) < 0) - log_error ("write_pid_file: failed to write PID to \"%.100s\"", - pid_file); - fclose (fp); - } - else - log_fatal ("write_pid_file: fopen (\"%.100s\", \"w\") failed", pid_file); + FILE *fp; + + /* Ignore errors. This will fail with USE_PRIVSEP. */ + unlink(pid_file); + + fp = monitor_fopen(pid_file, "w"); + if (fp != NULL) { + if (fprintf(fp, "%ld\n", (long) getpid()) < 0) + log_error("write_pid_file: failed to write PID to \"%.100s\"", + pid_file); + fclose(fp); + } else + log_fatal("write_pid_file: fopen (\"%.100s\", \"w\") failed", pid_file); } int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - fd_set *rfds, *wfds; - int n, m; - size_t mask_size; - struct timeval tv, *timeout; + fd_set *rfds, *wfds; + int n, m; + size_t mask_size; + struct timeval tv, *timeout; #if defined (HAVE_CLOSEFROM) && (!defined (OpenBSD) || (OpenBSD >= 200405)) - closefrom (STDERR_FILENO + 1); + closefrom(STDERR_FILENO + 1); #else - m = getdtablesize (); - for (n = STDERR_FILENO + 1; n < m; n++) - (void)close (n); + m = getdtablesize(); + for (n = STDERR_FILENO + 1; n < m; n++) + (void) close(n); #endif - /* Make sure init() won't alloc fd 0, 1 or 2, as daemon() will close them. */ - for (n = 0; n <= 2; n++) - if (fcntl (n, F_GETFL, 0) == -1 && errno == EBADF) - (void)open ("/dev/null", n ? O_WRONLY : O_RDONLY, 0); - - for (n = 1; n < _NSIG; n++) - signal (n, SIG_DFL); - - /* Log cmd line parsing and initialization errors to stderr. */ - log_to (stderr); - parse_args (argc, argv); - log_init (debug); - - /* - * Do a clean daemon shutdown on TERM/INT. These signals must be - * initialized before monitor_init(). INT is only used with '-d'. - */ - signal (SIGTERM, daemon_shutdown_now); - if (debug == 1) /* i.e '-dd' will skip this. */ - signal (SIGINT, daemon_shutdown_now); - - /* Daemonize before forking unpriv'ed child */ - if (!debug) - if (daemon (0, 0)) - log_fatal ("main: daemon (0, 0) failed"); - - /* Set timezone before priv'separation */ - tzset(); + /* + * Make sure init() won't alloc fd 0, 1 or 2, as daemon() will close + * them. + */ + for (n = 0; n <= 2; n++) + if (fcntl(n, F_GETFL, 0) == -1 && errno == EBADF) + (void) open("/dev/null", n ? O_WRONLY : O_RDONLY, 0); + + for (n = 1; n < _NSIG; n++) + signal(n, SIG_DFL); + + /* Log cmd line parsing and initialization errors to stderr. */ + log_to(stderr); + parse_args(argc, argv); + log_init(debug); + + /* + * Do a clean daemon shutdown on TERM/INT. These signals must be + * initialized before monitor_init(). INT is only used with '-d'. + */ + signal(SIGTERM, daemon_shutdown_now); + if (debug == 1) /* i.e '-dd' will skip this. */ + signal(SIGINT, daemon_shutdown_now); + + /* Daemonize before forking unpriv'ed child */ + if (!debug) + if (daemon(0, 0)) + log_fatal("main: daemon (0, 0) failed"); + + /* Set timezone before priv'separation */ + tzset(); #if defined (USE_PRIVSEP) - if (monitor_init ()) - { - /* The parent, with privileges enters infinite monitor loop. */ - monitor_loop (debug); - exit (0); /* Never reached. */ - } - - /* Child process only from this point on, no privileges left. */ + if (monitor_init()) { + /* The parent, with privileges enters infinite monitor loop. */ + monitor_loop(debug); + exit(0); /* Never reached. */ + } + /* Child process only from this point on, no privileges left. */ #endif - init (); + init(); - write_pid_file (); + write_pid_file(); - /* Reinitialize on HUP reception. */ - signal (SIGHUP, sighup); + /* Reinitialize on HUP reception. */ + signal(SIGHUP, sighup); - /* Report state on USR1 reception. */ - signal (SIGUSR1, sigusr1); + /* Report state on USR1 reception. */ + signal(SIGUSR1, sigusr1); - /* Rehash soft expiration timers on USR2 reception. */ - signal (SIGUSR2, sigusr2); + /* Rehash soft expiration timers on USR2 reception. */ + signal(SIGUSR2, sigusr2); #if defined (USE_DEBUG) - /* If we wanted IKE packet capture to file, initialize it now. */ - if (pcap_file != 0) - log_packet_init (pcap_file); + /* If we wanted IKE packet capture to file, initialize it now. */ + if (pcap_file != 0) + log_packet_init(pcap_file); #endif - /* Allocate the file descriptor sets just big enough. */ - n = getdtablesize (); - mask_size = howmany (n, NFDBITS) * sizeof (fd_mask); - rfds = (fd_set *)malloc (mask_size); - if (!rfds) - log_fatal ("main: malloc (%lu) failed", (unsigned long)mask_size); - wfds = (fd_set *)malloc (mask_size); - if (!wfds) - log_fatal ("main: malloc (%lu) failed", (unsigned long)mask_size); + /* Allocate the file descriptor sets just big enough. */ + n = getdtablesize(); + mask_size = howmany(n, NFDBITS) * sizeof(fd_mask); + rfds = (fd_set *) malloc(mask_size); + if (!rfds) + log_fatal("main: malloc (%lu) failed", (unsigned long) mask_size); + wfds = (fd_set *) malloc(mask_size); + if (!wfds) + log_fatal("main: malloc (%lu) failed", (unsigned long) mask_size); #if defined (USE_PRIVSEP) - monitor_init_done(); + monitor_init_done(); #endif - while (1) - { - /* If someone has sent SIGHUP to us, reconfigure. */ - if (sighupped) - { - log_print ("SIGHUP received"); - reinit (); - sighupped = 0; - } - - /* and if someone sent SIGUSR1, do a state report. */ - if (sigusr1ed) - { - log_print ("SIGUSR1 received"); - report (); - } - - /* and if someone sent SIGUSR2, do a timer rehash. */ - if (sigusr2ed) - { - log_print ("SIGUSR2 received"); - rehash_timers (); - } - - /* - * and if someone set 'sigtermed' (SIGTERM, SIGINT or via the UI), - * this indicates we should start a controlled shutdown of the daemon. - * - * Note: Since _one_ message is sent per iteration of this enclosing - * while-loop, and we want to send a number of DELETE notifications, - * we must loop atleast this number of times. The daemon_shutdown() - * function starts by queueing the DELETEs, all other calls just - * increments the 'sigtermed' variable until it reaches a "safe" - * value, and the daemon exits. - */ - if (sigtermed) - daemon_shutdown (); - - /* Setup the descriptors to look for incoming messages at. */ - memset (rfds, 0, mask_size); - n = transport_fd_set (rfds); - FD_SET (ui_socket, rfds); - if (ui_socket + 1 > n) - n = ui_socket + 1; - - /* - * XXX Some day we might want to deal with an abstract application - * class instead, with many instantiations possible. - */ - if (!app_none && app_socket >= 0) - { - FD_SET (app_socket, rfds); - if (app_socket + 1 > n) - n = app_socket + 1; - } - - /* Setup the descriptors that have pending messages to send. */ - memset (wfds, 0, mask_size); - m = transport_pending_wfd_set (wfds); - if (m > n) - n = m; - - /* Find out when the next timed event is. */ - timeout = &tv; - timer_next_event (&timeout); - - n = select (n, rfds, wfds, 0, timeout); - if (n == -1) - { - if (errno != EINTR) - { - log_error ("main: select"); - - /* - * In order to give the unexpected error condition time to - * resolve without letting this process eat up all available CPU - * we sleep for a short while. - */ - sleep (1); - } - } - else if (n) - { - transport_handle_messages (rfds); - transport_send_messages (wfds); - if (FD_ISSET (ui_socket, rfds)) - ui_handler (); - if (!app_none && app_socket >= 0 && FD_ISSET (app_socket, rfds)) - app_handler (); + while (1) { + /* If someone has sent SIGHUP to us, reconfigure. */ + if (sighupped) { + log_print("SIGHUP received"); + reinit(); + sighupped = 0; + } + /* and if someone sent SIGUSR1, do a state report. */ + if (sigusr1ed) { + log_print("SIGUSR1 received"); + report(); + } + /* and if someone sent SIGUSR2, do a timer rehash. */ + if (sigusr2ed) { + log_print("SIGUSR2 received"); + rehash_timers(); + } + /* + * and if someone set 'sigtermed' (SIGTERM, SIGINT or via the UI), + * this indicates we should start a controlled shutdown of the daemon. + * + * Note: Since _one_ message is sent per iteration of this enclosing + * while-loop, and we want to send a number of DELETE notifications, + * we must loop atleast this number of times. The daemon_shutdown() + * function starts by queueing the DELETEs, all other calls just + * increments the 'sigtermed' variable until it reaches a "safe" + * value, and the daemon exits. + */ + if (sigtermed) + daemon_shutdown(); + + /* Setup the descriptors to look for incoming messages at. */ + memset(rfds, 0, mask_size); + n = transport_fd_set(rfds); + FD_SET(ui_socket, rfds); + if (ui_socket + 1 > n) + n = ui_socket + 1; + + /* + * XXX Some day we might want to deal with an abstract application + * class instead, with many instantiations possible. + */ + if (!app_none && app_socket >= 0) { + FD_SET(app_socket, rfds); + if (app_socket + 1 > n) + n = app_socket + 1; + } + /* Setup the descriptors that have pending messages to send. */ + memset(wfds, 0, mask_size); + m = transport_pending_wfd_set(wfds); + if (m > n) + n = m; + + /* Find out when the next timed event is. */ + timeout = &tv; + timer_next_event(&timeout); + + n = select(n, rfds, wfds, 0, timeout); + if (n == -1) { + if (errno != EINTR) { + log_error("main: select"); + + /* + * In order to give the unexpected error + * condition time to resolve without letting + * this process eat up all available CPU + * we sleep for a short while. + */ + sleep(1); + } + } else if (n) { + transport_handle_messages(rfds); + transport_send_messages(wfds); + if (FD_ISSET(ui_socket, rfds)) + ui_handler(); + if (!app_none && app_socket >= 0 && FD_ISSET(app_socket, rfds)) + app_handler(); + } + timer_handle_expirations(); } - timer_handle_expirations (); - } } diff --git a/sbin/isakmpd/key.c b/sbin/isakmpd/key.c index c1426abe628..15aac15936f 100644 --- a/sbin/isakmpd/key.c +++ b/sbin/isakmpd/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.14 2004/04/07 22:45:04 ho Exp $ */ +/* $OpenBSD: key.c,v 1.15 2004/04/15 18:39:26 deraadt Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * @@ -31,159 +31,154 @@ #include "x509.h" void -key_free (int type, int private, void *key) +key_free(int type, int private, void *key) { - switch (type) - { - case ISAKMP_KEY_PASSPHRASE: - free (key); - break; - case ISAKMP_KEY_RSA: - RSA_free (key); - break; - case ISAKMP_KEY_NONE: - default: - log_error ("key_free: unknown/unsupportedkey type %d", type); - break; - } + switch (type) { + case ISAKMP_KEY_PASSPHRASE: + free(key); + break; + case ISAKMP_KEY_RSA: + RSA_free(key); + break; + case ISAKMP_KEY_NONE: + default: + log_error("key_free: unknown/unsupportedkey type %d", type); + break; + } } /* Convert from internal form to serialized */ void -key_serialize (int type, int private, void *key, u_int8_t **data, size_t *datalen) +key_serialize(int type, int private, void *key, u_int8_t **data, size_t *datalen) { - u_int8_t *p; - - switch (type) - { - case ISAKMP_KEY_PASSPHRASE: - *datalen = strlen ((char *)key); - *data = (u_int8_t *)strdup ((char *)key); - break; - case ISAKMP_KEY_RSA: - switch (private) - { - case ISAKMP_KEYTYPE_PUBLIC: - *datalen = i2d_RSAPublicKey ((RSA *)key, NULL); - *data = p = malloc (*datalen); - if (!p) - { - log_error ("key_serialize: malloc (%lu) failed", - (unsigned long)*datalen); - return; - } - *datalen = i2d_RSAPublicKey ((RSA *)key, &p); - break; - - case ISAKMP_KEYTYPE_PRIVATE: - *datalen = i2d_RSAPrivateKey ((RSA *)key, NULL); - *data = p = malloc (*datalen); - if (!p) - { - log_error ("key_serialize: malloc (%lu) failed", - (unsigned long)*datalen); - return; - } - *datalen = i2d_RSAPrivateKey ((RSA *)key, &p); - break; + u_int8_t *p; + + switch (type) { + case ISAKMP_KEY_PASSPHRASE: + *datalen = strlen((char *) key); + *data = (u_int8_t *) strdup((char *) key); + break; + case ISAKMP_KEY_RSA: + switch (private) { + case ISAKMP_KEYTYPE_PUBLIC: + *datalen = i2d_RSAPublicKey((RSA *) key, NULL); + *data = p = malloc(*datalen); + if (!p) { + log_error("key_serialize: malloc (%lu) failed", + (unsigned long) *datalen); + return; + } + *datalen = i2d_RSAPublicKey((RSA *) key, &p); + break; + + case ISAKMP_KEYTYPE_PRIVATE: + *datalen = i2d_RSAPrivateKey((RSA *) key, NULL); + *data = p = malloc(*datalen); + if (!p) { + log_error("key_serialize: malloc (%lu) failed", + (unsigned long) *datalen); + return; + } + *datalen = i2d_RSAPrivateKey((RSA *) key, &p); + break; + } + break; + default: + log_error("key_serialize: unknown/unsupported key type %d", type); + break; } - break; - default: - log_error ("key_serialize: unknown/unsupported key type %d", type); - break; - } } /* Convert from serialized to printable */ char * -key_printable (int type, int private, u_int8_t *data, int datalen) +key_printable(int type, int private, u_int8_t *data, int datalen) { - char *s; - int i; - - switch (type) - { - case ISAKMP_KEY_PASSPHRASE: - return strdup ((char *)data); - - case ISAKMP_KEY_RSA: - s = malloc (datalen * 2 + 1); - if (!s) - { - log_error ("key_printable: malloc (%d) failed", datalen * 2 + 1); - return 0; + char *s; + int i; + + switch (type) { + case ISAKMP_KEY_PASSPHRASE: + return strdup((char *) data); + + case ISAKMP_KEY_RSA: + s = malloc(datalen * 2 + 1); + if (!s) { + log_error("key_printable: malloc (%d) failed", + datalen * 2 + 1); + return 0; + } + for (i = 0; i < datalen; i++) + snprintf(s + (2 * i), 2 * (datalen - i) + 1, "%02x", + data[i]); + return s; + + default: + log_error("key_printable: unknown/unsupported key type %d", type); + return 0; } - for (i = 0; i < datalen; i++) - snprintf (s + (2 * i), 2 * (datalen - i) + 1, "%02x", data[i]); - return s; - - default: - log_error ("key_printable: unknown/unsupported key type %d", type); - return 0; - } } /* Convert from serialized to internal. */ void * -key_internalize (int type, int private, u_int8_t *data, int datalen) +key_internalize(int type, int private, u_int8_t *data, int datalen) { - switch (type) - { - case ISAKMP_KEY_PASSPHRASE: - return strdup ((char *)data); - case ISAKMP_KEY_RSA: - switch (private) - { + switch (type) { + case ISAKMP_KEY_PASSPHRASE: + return strdup((char *) data); + case ISAKMP_KEY_RSA: + switch (private) { #if OPENSSL_VERSION_NUMBER >= 0x00907000L - case ISAKMP_KEYTYPE_PUBLIC: - return d2i_RSAPublicKey (NULL, (const u_int8_t **)&data, datalen); - case ISAKMP_KEYTYPE_PRIVATE: - return d2i_RSAPrivateKey (NULL, (const u_int8_t **)&data, datalen); + case ISAKMP_KEYTYPE_PUBLIC: + return d2i_RSAPublicKey(NULL, + (const u_int8_t **)&data, datalen); + case ISAKMP_KEYTYPE_PRIVATE: + return d2i_RSAPrivateKey(NULL, + (const u_int8_t **)&data, datalen); #else - case ISAKMP_KEYTYPE_PUBLIC: - return d2i_RSAPublicKey (NULL, &data, datalen); - case ISAKMP_KEYTYPE_PRIVATE: - return d2i_RSAPrivateKey (NULL, &data, datalen); + case ISAKMP_KEYTYPE_PUBLIC: + return d2i_RSAPublicKey(NULL, &data, datalen); + case ISAKMP_KEYTYPE_PRIVATE: + return d2i_RSAPrivateKey(NULL, &data, datalen); #endif + default: + log_error("key_internalize: not public or private " + "RSA key passed"); + return 0; + } + break; default: - log_error ("key_internalize: not public or private RSA key passed"); - return 0; + log_error("key_internalize: unknown/unsupported key type %d", + type); + break; } - break; - default: - log_error ("key_internalize: unknown/unsupported key type %d", type); - break; - } - return 0; + return 0; } /* Convert from printable to serialized */ void -key_from_printable (int type, int private, char *key, u_int8_t **data, - u_int32_t *datalen) +key_from_printable(int type, int private, char *key, u_int8_t **data, + u_int32_t *datalen) { - switch (type) - { - case ISAKMP_KEY_PASSPHRASE: - *datalen = strlen (key); - *data = (u_int8_t *)strdup (key); - break; - - case ISAKMP_KEY_RSA: - *datalen = (strlen (key) + 1) / 2; /* Round up, just in case */ - *data = malloc (*datalen); - if (!*data) - { - log_error ("key_from_printable: malloc (%d) failed", *datalen); - return; + switch (type) { + case ISAKMP_KEY_PASSPHRASE: + *datalen = strlen(key); + *data = (u_int8_t *) strdup(key); + break; + + case ISAKMP_KEY_RSA: + *datalen = (strlen(key) + 1) / 2; /* Round up, just in case */ + *data = malloc(*datalen); + if (!*data) { + log_error("key_from_printable: malloc (%d) failed", *datalen); + return; + } + *datalen = hex2raw(key, *data, *datalen); + break; + + default: + log_error("key_from_printable: unknown/unsupported key type %d", type); + *data = 0; + break; } - *datalen = hex2raw (key, *data, *datalen); - break; - - default: - log_error ("key_from_printable: unknown/unsupported key type %d", type); - *data = 0; - break; - } } diff --git a/sbin/isakmpd/key.h b/sbin/isakmpd/key.h index b31c7c92397..81b13289046 100644 --- a/sbin/isakmpd/key.h +++ b/sbin/isakmpd/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.6 2002/09/11 09:50:44 ho Exp $ */ +/* $OpenBSD: key.h,v 1.7 2004/04/15 18:39:26 deraadt Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * @@ -31,9 +31,9 @@ #define ISAKMP_KEYTYPE_PUBLIC 0 #define ISAKMP_KEYTYPE_PRIVATE 1 -void key_free (int, int, void *); -void key_serialize (int, int, void *, u_int8_t **, size_t *); -char *key_printable (int, int, u_int8_t *, int); -void key_from_printable (int, int, char *, u_int8_t **, u_int32_t *); -void *key_internalize (int, int, u_int8_t *, int); -#endif /* _KEY_H_ */ +void key_free(int, int, void *); +void key_serialize(int, int, void *, u_int8_t **, size_t *); +char *key_printable(int, int, u_int8_t *, int); +void key_from_printable(int, int, char *, u_int8_t **, u_int32_t *); +void *key_internalize(int, int, u_int8_t *, int); +#endif /* _KEY_H_ */ diff --git a/sbin/isakmpd/libcrypto.c b/sbin/isakmpd/libcrypto.c index 482f61c54de..d66c58a47ca 100644 --- a/sbin/isakmpd/libcrypto.c +++ b/sbin/isakmpd/libcrypto.c @@ -1,5 +1,5 @@ -/* $OpenBSD: libcrypto.c,v 1.15 2003/06/04 07:31:17 ho Exp $ */ -/* $EOM: libcrypto.c,v 1.14 2000/09/28 12:53:27 niklas Exp $ */ +/* $OpenBSD: libcrypto.c,v 1.16 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: libcrypto.c,v 1.14 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -34,17 +34,16 @@ #include "libcrypto.h" void -libcrypto_init (void) +libcrypto_init(void) { #if defined (USE_X509) && defined (USE_LIBCRYPTO) - /* Add all algorithms known by SSL */ + /* Add all algorithms known by SSL */ #if OPENSSL_VERSION_NUMBER >= 0x00905100L - OpenSSL_add_all_algorithms (); + OpenSSL_add_all_algorithms(); #else - SSLeay_add_all_algorithms (); + SSLeay_add_all_algorithms(); #endif #endif /* USE_X509 && USE_LIBCRYPTO */ } - diff --git a/sbin/isakmpd/libcrypto.h b/sbin/isakmpd/libcrypto.h index b3892b7eedd..e9581bfc1dd 100644 --- a/sbin/isakmpd/libcrypto.h +++ b/sbin/isakmpd/libcrypto.h @@ -1,5 +1,5 @@ -/* $OpenBSD: libcrypto.h,v 1.15 2003/06/04 07:31:17 ho Exp $ */ -/* $EOM: libcrypto.h,v 1.16 2000/09/28 12:53:27 niklas Exp $ */ +/* $OpenBSD: libcrypto.h,v 1.16 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: libcrypto.h,v 1.16 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -45,8 +45,8 @@ #include <openssl/x509_vfy.h> #include <openssl/x509.h> -#endif /* USE_X509 */ +#endif /* USE_X509 */ -extern void libcrypto_init (void); +extern void libcrypto_init(void); -#endif /* _LIBCRYPTO_H_ */ +#endif /* _LIBCRYPTO_H_ */ diff --git a/sbin/isakmpd/log.c b/sbin/isakmpd/log.c index 273e1237aa7..c48b8771eaa 100644 --- a/sbin/isakmpd/log.c +++ b/sbin/isakmpd/log.c @@ -1,5 +1,5 @@ -/* $OpenBSD: log.c,v 1.42 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $ */ +/* $OpenBSD: log.c,v 1.43 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -50,7 +50,7 @@ #include "sysdep/common/pcap.h" #endif -#endif /* USE_DEBUG */ +#endif /* USE_DEBUG */ #include <errno.h> #include <stdio.h> @@ -66,654 +66,616 @@ #include "monitor.h" #include "util.h" -static void _log_print (int, int, const char *, va_list, int, int); +static void _log_print(int, int, const char *, va_list, int, int); -static FILE *log_output; +static FILE *log_output; -int verbose_logging = 0; +int verbose_logging = 0; #if defined (USE_DEBUG) -static int log_level[LOG_ENDCLASS]; +static int log_level[LOG_ENDCLASS]; #define TCPDUMP_MAGIC 0xa1b2c3d4 #define SNAPLEN (64 * 1024) struct packhdr { - struct pcap_pkthdr pcap; /* pcap file packet header */ - u_int32_t sa_family; /* address family */ - union { - struct ip ip4; /* IPv4 header (w/o options) */ - struct ip6_hdr ip6; /* IPv6 header */ - } ip; + struct pcap_pkthdr pcap;/* pcap file packet header */ + u_int32_t sa_family; /* address family */ + union { + struct ip ip4; /* IPv4 header (w/o options) */ + struct ip6_hdr ip6; /* IPv6 header */ + } ip; }; struct isakmp_hdr { - u_int8_t icookie[8], rcookie[8]; - u_int8_t next, ver, type, flags; - u_int32_t msgid, len; + u_int8_t icookie[8], rcookie[8]; + u_int8_t next, ver, type, flags; + u_int32_t msgid, len; }; -static char *pcaplog_file = NULL; -static FILE *packet_log; +static char *pcaplog_file = NULL; +static FILE *packet_log; static u_int8_t *packet_buf = NULL; -static int udp_cksum (struct packhdr *, const struct udphdr *, u_int16_t *); -static u_int16_t in_cksum (const u_int16_t *, int); -#endif /* USE_DEBUG */ +static int udp_cksum(struct packhdr *, const struct udphdr *, u_int16_t *); +static u_int16_t in_cksum(const u_int16_t *, int); +#endif /* USE_DEBUG */ void -log_init (int debug) +log_init(int debug) { - if (debug) - log_output = stderr; - else - log_to (0); /* syslog */ + if (debug) + log_output = stderr; + else + log_to(0); /* syslog */ } void -log_reinit (void) +log_reinit(void) { - struct conf_list *logging; + struct conf_list *logging; #ifdef USE_DEBUG - struct conf_list_node *logclass; - int class, level; -#endif /* USE_DEBUG */ - - logging = conf_get_list ("General", "Logverbose"); - if (logging) - { - verbose_logging = 1; - conf_free_list (logging); - } - - + struct conf_list_node *logclass; + int class, level; +#endif /* USE_DEBUG */ + + logging = conf_get_list("General", "Logverbose"); + if (logging) { + verbose_logging = 1; + conf_free_list(logging); + } #ifdef USE_DEBUG - logging = conf_get_list ("General", "Loglevel"); - if (logging) - { - for (logclass = TAILQ_FIRST (&logging->fields); logclass; - logclass = TAILQ_NEXT (logclass, link)) - { - if (sscanf (logclass->field, "%d=%d", &class, &level) != 2) - { - if (sscanf (logclass->field, "A=%d", &level) == 1) - for (class = 0; class < LOG_ENDCLASS; class++) - log_debug_cmd (class, level); - else - { - log_print ("init: invalid logging class or level: %s", - logclass->field); - continue; - } - } - else - log_debug_cmd (class, level); + logging = conf_get_list("General", "Loglevel"); + if (!logging) + return; + + for (logclass = TAILQ_FIRST(&logging->fields); logclass; + logclass = TAILQ_NEXT(logclass, link)) { + if (sscanf(logclass->field, "%d=%d", &class, &level) != 2) { + if (sscanf(logclass->field, "A=%d", &level) == 1) + for (class = 0; class < LOG_ENDCLASS; class++) + log_debug_cmd(class, level); + else { + log_print("init: invalid logging class or level: %s", + logclass->field); + continue; + } + } else + log_debug_cmd(class, level); } - conf_free_list (logging); - } -#endif /* USE_DEBUG */ + conf_free_list(logging); +#endif /* USE_DEBUG */ } void -log_to (FILE *f) +log_to(FILE *f) { - if (!log_output && f) - closelog (); - log_output = f; - if (!f) - openlog ("isakmpd", LOG_PID | LOG_CONS, LOG_DAEMON); + if (!log_output && f) + closelog(); + log_output = f; + if (!f) + openlog("isakmpd", LOG_PID | LOG_CONS, LOG_DAEMON); } FILE * -log_current (void) +log_current(void) { - return log_output; + return log_output; } static char * -_log_get_class (int error_class) +_log_get_class(int error_class) { - /* XXX For test purposes. To be removed later on? */ - static char *class_text[] = LOG_CLASSES_TEXT; - - if (error_class < 0) - return "Dflt"; - else if (error_class >= LOG_ENDCLASS) - return "Unkn"; - else - return class_text[error_class]; + /* XXX For test purposes. To be removed later on? */ + static char *class_text[] = LOG_CLASSES_TEXT; + + if (error_class < 0) + return "Dflt"; + else if (error_class >= LOG_ENDCLASS) + return "Unkn"; + else + return class_text[error_class]; } static void -_log_print (int error, int syslog_level, const char *fmt, va_list ap, - int class, int level) +_log_print(int error, int syslog_level, const char *fmt, va_list ap, + int class, int level) { - char buffer[LOG_SIZE], nbuf[LOG_SIZE + 32]; - static const char fallback_msg[] = - "write to log file failed (errno %d), redirecting output to syslog"; - int len; - struct tm *tm; - struct timeval now; - time_t t; - - len = vsnprintf (buffer, sizeof buffer, fmt, ap); - if (len > 0 && len < (int)sizeof buffer - 1 && error) - snprintf (buffer + len, sizeof buffer - len, ": %s", strerror (errno)); - if (log_output) - { - gettimeofday (&now, 0); - t = now.tv_sec; - tm = localtime (&t); - if (class >= 0) - snprintf (nbuf, sizeof nbuf, "%02d%02d%02d.%06ld %s %02d ", - tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec, - _log_get_class (class), level); - else /* LOG_PRINT (-1) or LOG_REPORT (-2) */ - snprintf (nbuf, sizeof nbuf, "%02d%02d%02d.%06ld %s ", tm->tm_hour, - tm->tm_min, tm->tm_sec, now.tv_usec, - class == LOG_PRINT ? "Default" : "Report>"); - strlcat (nbuf, buffer, sizeof nbuf); + char buffer[LOG_SIZE], nbuf[LOG_SIZE + 32]; + static const char fallback_msg[] = + "write to log file failed (errno %d), redirecting output to syslog"; + int len; + struct tm *tm; + struct timeval now; + time_t t; + + len = vsnprintf(buffer, sizeof buffer, fmt, ap); + if (len > 0 && len < (int) sizeof buffer - 1 && error) + snprintf(buffer + len, sizeof buffer - len, ": %s", strerror(errno)); + if (log_output) { + gettimeofday(&now, 0); + t = now.tv_sec; + tm = localtime(&t); + if (class >= 0) + snprintf(nbuf, sizeof nbuf, "%02d%02d%02d.%06ld %s %02d ", + tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec, + _log_get_class(class), level); + else /* LOG_PRINT (-1) or LOG_REPORT (-2) */ + snprintf(nbuf, sizeof nbuf, "%02d%02d%02d.%06ld %s ", + tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec, + class == LOG_PRINT ? "Default" : "Report>"); + strlcat(nbuf, buffer, sizeof nbuf); #if defined (USE_PRIVSEP) - strlcat (nbuf, getuid () ? "" : " [priv]", LOG_SIZE + 32); + strlcat(nbuf, getuid() ? "" : " [priv]", LOG_SIZE + 32); #endif - strlcat (nbuf, "\n", sizeof nbuf); - - if (fwrite (nbuf, strlen (nbuf), 1, log_output) == 0) - { - /* Report fallback. */ - syslog (LOG_ALERT, fallback_msg, errno); - fprintf (log_output, fallback_msg, errno); - - /* - * Close log_output to prevent isakmpd from locking the file. - * We may need to explicitly close stdout to do this properly. - * XXX - Figure out how to match two FILE *'s and rewrite. - */ - if (fileno (log_output) != -1 - && fileno (stdout) == fileno (log_output)) - fclose (stdout); - fclose (log_output); - - /* Fallback to syslog. */ - log_to (0); - - /* (Re)send current message to syslog(). */ - syslog (class == LOG_REPORT ? LOG_ALERT - : syslog_level, "%s", buffer); - } - } - else - syslog (class == LOG_REPORT ? LOG_ALERT : syslog_level, "%s", buffer); + strlcat(nbuf, "\n", sizeof nbuf); + + if (fwrite(nbuf, strlen(nbuf), 1, log_output) == 0) { + /* Report fallback. */ + syslog(LOG_ALERT, fallback_msg, errno); + fprintf(log_output, fallback_msg, errno); + + /* + * Close log_output to prevent isakmpd from locking the file. + * We may need to explicitly close stdout to do this properly. + * XXX - Figure out how to match two FILE *'s and rewrite. + */ + if (fileno(log_output) != -1 && + fileno(stdout) == fileno(log_output)) + fclose(stdout); + fclose(log_output); + + /* Fallback to syslog. */ + log_to(0); + + /* (Re)send current message to syslog(). */ + syslog(class == LOG_REPORT ? LOG_ALERT : + syslog_level, "%s", buffer); + } + } else + syslog(class == LOG_REPORT ? LOG_ALERT : syslog_level, + "%s", buffer); } #ifdef USE_DEBUG void -log_debug (int cls, int level, const char *fmt, ...) +log_debug(int cls, int level, const char *fmt, ...) { - va_list ap; - - /* - * If we are not debugging this class, or the level is too low, just return. - */ - if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls])) - return; - va_start (ap, fmt); - _log_print (0, LOG_INFO, fmt, ap, cls, level); - va_end (ap); + va_list ap; + + /* + * If we are not debugging this class, or the level is too low, just return. + */ + if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls])) + return; + va_start(ap, fmt); + _log_print(0, LOG_INFO, fmt, ap, cls, level); + va_end(ap); } void -log_debug_buf (int cls, int level, const char *header, const u_int8_t *buf, - size_t sz) +log_debug_buf(int cls, int level, const char *header, const u_int8_t *buf, + size_t sz) { - char s[73]; - size_t i, j; - - /* - * If we are not debugging this class, or the level is too low, just return. - */ - if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls])) - return; - - log_debug (cls, level, "%s:", header); - for (i = j = 0; i < sz;) - { - snprintf (s + j, sizeof s - j, "%02x", buf[i++]); - j += 2; - if (i % 4 == 0) - { - if (i % 32 == 0) - { - s[j] = '\0'; - log_debug (cls, level, "%s", s); - j = 0; - } - else - s[j++] = ' '; + size_t i, j; + char s[73]; + + /* + * If we are not debugging this class, or the level is too low, just return. + */ + if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls])) + return; + + log_debug(cls, level, "%s:", header); + for (i = j = 0; i < sz;) { + snprintf(s + j, sizeof s - j, "%02x", buf[i++]); + j += 2; + if (i % 4 == 0) { + if (i % 32 == 0) { + s[j] = '\0'; + log_debug(cls, level, "%s", s); + j = 0; + } else + s[j++] = ' '; + } + } + if (j) { + s[j] = '\0'; + log_debug(cls, level, "%s", s); } - } - if (j) - { - s[j] = '\0'; - log_debug (cls, level, "%s", s); - } } void -log_debug_cmd (int cls, int level) +log_debug_cmd(int cls, int level) { - if (cls < 0 || cls >= LOG_ENDCLASS) - { - log_print ("log_debug_cmd: invalid debugging class %d", cls); - return; - } - - if (level < 0) - { - log_print ("log_debug_cmd: invalid debugging level %d for class %d", - level, cls); - return; - } - - if (level == log_level[cls]) - log_print ("log_debug_cmd: log level unchanged for class %d", cls); - else - { - log_print ("log_debug_cmd: log level changed from %d to %d for class %d", - log_level[cls], level, cls); - log_level[cls] = level; - } + if (cls < 0 || cls >= LOG_ENDCLASS) { + log_print("log_debug_cmd: invalid debugging class %d", cls); + return; + } + if (level < 0) { + log_print("log_debug_cmd: invalid debugging level %d for class %d", + level, cls); + return; + } + if (level == log_level[cls]) + log_print("log_debug_cmd: log level unchanged for class %d", cls); + else { + log_print("log_debug_cmd: log level changed from %d to %d for class %d", + log_level[cls], level, cls); + log_level[cls] = level; + } } void -log_debug_toggle (void) +log_debug_toggle(void) { - static int log_level_copy[LOG_ENDCLASS], toggle = 0; - - if (!toggle) - { - LOG_DBG ((LOG_MISC, 50, "log_debug_toggle: debug levels cleared")); - memcpy (&log_level_copy, &log_level, sizeof log_level); - memset (&log_level, 0, sizeof log_level); - } - else - { - memcpy (&log_level, &log_level_copy, sizeof log_level); - LOG_DBG ((LOG_MISC, 50, "log_debug_toggle: debug levels restored")); - } - toggle = !toggle; + static int log_level_copy[LOG_ENDCLASS], toggle = 0; + + if (!toggle) { + LOG_DBG((LOG_MISC, 50, "log_debug_toggle: debug levels cleared")); + memcpy(&log_level_copy, &log_level, sizeof log_level); + memset(&log_level, 0, sizeof log_level); + } else { + memcpy(&log_level, &log_level_copy, sizeof log_level); + LOG_DBG((LOG_MISC, 50, "log_debug_toggle: debug levels restored")); + } + toggle = !toggle; } -#endif /* USE_DEBUG */ +#endif /* USE_DEBUG */ void -log_print (const char *fmt, ...) +log_print(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start (ap, fmt); - _log_print (0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0); - va_end (ap); + va_start(ap, fmt); + _log_print(0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0); + va_end(ap); } void -log_verbose (const char *fmt, ...) +log_verbose(const char *fmt, ...) { - va_list ap; + va_list ap; #ifdef USE_DEBUG - int i; -#endif /* USE_DEBUG */ + int i; +#endif /* USE_DEBUG */ - if (verbose_logging == 0) - return; + if (verbose_logging == 0) + return; #ifdef USE_DEBUG - for (i = 0; i < LOG_ENDCLASS; i++) - if (log_level[i] > 0) - return; + for (i = 0; i < LOG_ENDCLASS; i++) + if (log_level[i] > 0) + return; #endif - va_start (ap, fmt); - _log_print (0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0); - va_end (ap); + va_start(ap, fmt); + _log_print(0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0); + va_end(ap); } void -log_error (const char *fmt, ...) +log_error(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start (ap, fmt); - _log_print (1, LOG_ERR, fmt, ap, LOG_PRINT, 0); - va_end (ap); + va_start(ap, fmt); + _log_print(1, LOG_ERR, fmt, ap, LOG_PRINT, 0); + va_end(ap); } void -log_fatal (const char *fmt, ...) +log_fatal(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start (ap, fmt); - _log_print (1, LOG_CRIT, fmt, ap, LOG_PRINT, 0); - va_end (ap); - exit (1); + va_start(ap, fmt); + _log_print(1, LOG_CRIT, fmt, ap, LOG_PRINT, 0); + va_end(ap); + exit(1); } #ifdef USE_DEBUG void -log_packet_init (char *newname) +log_packet_init(char *newname) { - struct pcap_file_header sf_hdr; - struct stat st; - mode_t old_umask; - char *mode; - - /* Allocate packet buffer first time through. */ - if (!packet_buf) - packet_buf = malloc (SNAPLEN); - - if (!packet_buf) - { - log_error ("log_packet_init: malloc (%d) failed", SNAPLEN); - return; - } - - if (pcaplog_file && strcmp (pcaplog_file, PCAP_FILE_DEFAULT) != 0) - free (pcaplog_file); - - pcaplog_file = strdup (newname); - if (!pcaplog_file) - { - log_error ("log_packet_init: strdup (\"%s\") failed", newname); - return; - } - - /* Does the file already exist? XXX lstat() or stat()? */ + struct pcap_file_header sf_hdr; + struct stat st; + mode_t old_umask; + char *mode; + + /* Allocate packet buffer first time through. */ + if (!packet_buf) + packet_buf = malloc(SNAPLEN); + + if (!packet_buf) { + log_error("log_packet_init: malloc (%d) failed", SNAPLEN); + return; + } + if (pcaplog_file && strcmp(pcaplog_file, PCAP_FILE_DEFAULT) != 0) + free(pcaplog_file); + + pcaplog_file = strdup(newname); + if (!pcaplog_file) { + log_error("log_packet_init: strdup (\"%s\") failed", newname); + return; + } + /* Does the file already exist? XXX lstat() or stat()? */ #if defined (USE_PRIVSEP) - /* XXX This is a fstat! */ - if (monitor_stat (pcaplog_file, &st) == 0) + /* XXX This is a fstat! */ + if (monitor_stat(pcaplog_file, &st) == 0) { #else - if (lstat (pcaplog_file, &st) == 0) + if (lstat(pcaplog_file, &st) == 0) { #endif - { - /* Sanity checks. */ - if ((st.st_mode & S_IFMT) != S_IFREG) - { - log_print ("log_packet_init: existing capture file is " - "not a regular file"); - return; + /* Sanity checks. */ + if ((st.st_mode & S_IFMT) != S_IFREG) { + log_print("log_packet_init: existing capture file is " + "not a regular file"); + return; + } + if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + log_print("log_packet_init: existing capture " + "file has bad modes"); + return; + } + /* + * XXX It would be nice to check if it actually is a pcap + * file... + */ + + mode = "a"; + } else + mode = "w"; + + old_umask = umask(S_IRWXG | S_IRWXO); + packet_log = monitor_fopen(pcaplog_file, mode); + umask(old_umask); + + if (!packet_log) { + log_error("log_packet_init: fopen (\"%s\", \"%s\") failed", + pcaplog_file, mode); + return; } - - if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) - { - log_print ("log_packet_init: existing capture file has bad modes"); - return; + log_print("log_packet_init: starting IKE packet capture to file \"%s\"", + pcaplog_file); + + /* If this is a new file, we need to write a PCAP header to it. */ + if (*mode == 'w') { + sf_hdr.magic = TCPDUMP_MAGIC; + sf_hdr.version_major = PCAP_VERSION_MAJOR; + sf_hdr.version_minor = PCAP_VERSION_MINOR; + sf_hdr.thiszone = 0; + sf_hdr.snaplen = SNAPLEN; + sf_hdr.sigfigs = 0; + sf_hdr.linktype = DLT_LOOP; + + fwrite((char *) &sf_hdr, sizeof sf_hdr, 1, packet_log); + fflush(packet_log); } - - /* XXX It would be nice to check if it actually is a pcap file... */ - - mode = "a"; - } - else - mode = "w"; - - old_umask = umask (S_IRWXG | S_IRWXO); - packet_log = monitor_fopen (pcaplog_file, mode); - umask (old_umask); - - if (!packet_log) - { - log_error ("log_packet_init: fopen (\"%s\", \"%s\") failed", - pcaplog_file, mode); - return; - } - - log_print ("log_packet_init: starting IKE packet capture to file \"%s\"", - pcaplog_file); - - /* If this is a new file, we need to write a PCAP header to it. */ - if (*mode == 'w') - { - sf_hdr.magic = TCPDUMP_MAGIC; - sf_hdr.version_major = PCAP_VERSION_MAJOR; - sf_hdr.version_minor = PCAP_VERSION_MINOR; - sf_hdr.thiszone = 0; - sf_hdr.snaplen = SNAPLEN; - sf_hdr.sigfigs = 0; - sf_hdr.linktype = DLT_LOOP; - - fwrite ((char *)&sf_hdr, sizeof sf_hdr, 1, packet_log); - fflush (packet_log); - } } void -log_packet_restart (char *newname) +log_packet_restart(char *newname) { - if (packet_log) - { - log_print ("log_packet_restart: capture already active on file \"%s\"", - pcaplog_file); - return; - } - - if (newname) - log_packet_init (newname); - else if (!pcaplog_file) - log_packet_init (PCAP_FILE_DEFAULT); - else - log_packet_init (pcaplog_file); + if (packet_log) { + log_print("log_packet_restart: capture already active on file \"%s\"", + pcaplog_file); + return; + } + if (newname) + log_packet_init(newname); + else if (!pcaplog_file) + log_packet_init(PCAP_FILE_DEFAULT); + else + log_packet_init(pcaplog_file); } void -log_packet_stop (void) +log_packet_stop(void) { - /* Stop capture. */ - if (packet_log) - { - fclose (packet_log); - log_print ("log_packet_stop: stopped capture"); - } - packet_log = 0; + /* Stop capture. */ + if (packet_log) { + fclose(packet_log); + log_print("log_packet_stop: stopped capture"); + } + packet_log = 0; } void -log_packet_iov (struct sockaddr *src, struct sockaddr *dst, struct iovec *iov, - int iovcnt) +log_packet_iov(struct sockaddr * src, struct sockaddr * dst, struct iovec * iov, + int iovcnt) { - struct isakmp_hdr *isakmphdr; - struct packhdr hdr; - struct udphdr udp; - int off, datalen, hdrlen, i; - struct timeval tv; - - for (i = 0, datalen = 0; i < iovcnt; i++) - datalen += iov[i].iov_len; - - if (!packet_log || datalen > SNAPLEN) - return; - - /* copy packet into buffer */ - for (i = 0, off = 0; i < iovcnt; i++) - { - memcpy (packet_buf + off, iov[i].iov_base, iov[i].iov_len); - off += iov[i].iov_len; - } - - memset (&hdr, 0, sizeof hdr); - memset (&udp, 0, sizeof udp); - - /* isakmp - turn off the encryption bit in the isakmp hdr */ - isakmphdr = (struct isakmp_hdr *)packet_buf; - isakmphdr->flags &= ~(ISAKMP_FLAGS_ENC); - - /* udp */ - udp.uh_sport = sockaddr_port (src); - udp.uh_dport = sockaddr_port (dst); - datalen += sizeof udp; - udp.uh_ulen = htons (datalen); - - /* ip */ - hdr.sa_family = htonl (src->sa_family); - switch (src->sa_family) - { - default: - /* Assume IPv4. XXX Can 'default' ever happen here? */ - hdr.sa_family = htonl (AF_INET); - hdr.ip.ip4.ip_src.s_addr = 0x02020202; - hdr.ip.ip4.ip_dst.s_addr = 0x01010101; - /* The rest of the setup is common to AF_INET. */ - goto setup_ip4; - - case AF_INET: - hdr.ip.ip4.ip_src.s_addr = ((struct sockaddr_in *)src)->sin_addr.s_addr; - hdr.ip.ip4.ip_dst.s_addr = ((struct sockaddr_in *)dst)->sin_addr.s_addr; - - setup_ip4: - hdrlen = sizeof hdr.ip.ip4; - hdr.ip.ip4.ip_v = 0x4; - hdr.ip.ip4.ip_hl = 0x5; - hdr.ip.ip4.ip_p = IPPROTO_UDP; - hdr.ip.ip4.ip_len = htons (datalen + hdrlen); - /* Let's use the IP ID as a "packet counter". */ - i = ntohs (hdr.ip.ip4.ip_id) + 1; - hdr.ip.ip4.ip_id = htons (i); - /* Calculate IP header checksum. */ - hdr.ip.ip4.ip_sum = in_cksum ((u_int16_t *)&hdr.ip.ip4, - hdr.ip.ip4.ip_hl << 2); - break; - - case AF_INET6: - hdrlen = sizeof (hdr.ip.ip6); - hdr.ip.ip6.ip6_vfc = IPV6_VERSION; - hdr.ip.ip6.ip6_nxt = IPPROTO_UDP; - hdr.ip.ip6.ip6_plen = udp.uh_ulen; - memcpy (&hdr.ip.ip6.ip6_src, &((struct sockaddr_in6 *)src)->sin6_addr, - sizeof hdr.ip.ip6.ip6_src); - memcpy (&hdr.ip.ip6.ip6_dst, &((struct sockaddr_in6 *)dst)->sin6_addr, - sizeof hdr.ip.ip6.ip6_dst); - break; - } - - /* Calculate UDP checksum. */ - udp.uh_sum = udp_cksum (&hdr, &udp, (u_int16_t *)packet_buf); - hdrlen += sizeof hdr.sa_family; - - /* pcap file packet header */ - gettimeofday (&tv, 0); - hdr.pcap.ts.tv_sec = tv.tv_sec; - hdr.pcap.ts.tv_usec = tv.tv_usec; - hdr.pcap.caplen = datalen + hdrlen; - hdr.pcap.len = datalen + hdrlen; - - hdrlen += sizeof (struct pcap_pkthdr); - datalen -= sizeof (struct udphdr); - - /* Write to pcap file. */ - fwrite (&hdr, hdrlen, 1, packet_log); /* pcap + IP */ - fwrite (&udp, sizeof (struct udphdr), 1, packet_log); /* UDP */ - fwrite (packet_buf, datalen, 1, packet_log); /* IKE-data */ - fflush (packet_log); - return; + struct isakmp_hdr *isakmphdr; + struct packhdr hdr; + struct udphdr udp; + int off, datalen, hdrlen, i; + struct timeval tv; + + for (i = 0, datalen = 0; i < iovcnt; i++) + datalen += iov[i].iov_len; + + if (!packet_log || datalen > SNAPLEN) + return; + + /* copy packet into buffer */ + for (i = 0, off = 0; i < iovcnt; i++) { + memcpy(packet_buf + off, iov[i].iov_base, iov[i].iov_len); + off += iov[i].iov_len; + } + + memset(&hdr, 0, sizeof hdr); + memset(&udp, 0, sizeof udp); + + /* isakmp - turn off the encryption bit in the isakmp hdr */ + isakmphdr = (struct isakmp_hdr *) packet_buf; + isakmphdr->flags &= ~(ISAKMP_FLAGS_ENC); + + /* udp */ + udp.uh_sport = sockaddr_port(src); + udp.uh_dport = sockaddr_port(dst); + datalen += sizeof udp; + udp.uh_ulen = htons(datalen); + + /* ip */ + hdr.sa_family = htonl(src->sa_family); + switch (src->sa_family) { + default: + /* Assume IPv4. XXX Can 'default' ever happen here? */ + hdr.sa_family = htonl(AF_INET); + hdr.ip.ip4.ip_src.s_addr = 0x02020202; + hdr.ip.ip4.ip_dst.s_addr = 0x01010101; + /* The rest of the setup is common to AF_INET. */ + goto setup_ip4; + + case AF_INET: + hdr.ip.ip4.ip_src.s_addr = ((struct sockaddr_in *) src)->sin_addr.s_addr; + hdr.ip.ip4.ip_dst.s_addr = ((struct sockaddr_in *) dst)->sin_addr.s_addr; + +setup_ip4: + hdrlen = sizeof hdr.ip.ip4; + hdr.ip.ip4.ip_v = 0x4; + hdr.ip.ip4.ip_hl = 0x5; + hdr.ip.ip4.ip_p = IPPROTO_UDP; + hdr.ip.ip4.ip_len = htons(datalen + hdrlen); + /* Let's use the IP ID as a "packet counter". */ + i = ntohs(hdr.ip.ip4.ip_id) + 1; + hdr.ip.ip4.ip_id = htons(i); + /* Calculate IP header checksum. */ + hdr.ip.ip4.ip_sum = in_cksum((u_int16_t *) & hdr.ip.ip4, + hdr.ip.ip4.ip_hl << 2); + break; + + case AF_INET6: + hdrlen = sizeof(hdr.ip.ip6); + hdr.ip.ip6.ip6_vfc = IPV6_VERSION; + hdr.ip.ip6.ip6_nxt = IPPROTO_UDP; + hdr.ip.ip6.ip6_plen = udp.uh_ulen; + memcpy(&hdr.ip.ip6.ip6_src, &((struct sockaddr_in6 *) src)->sin6_addr, + sizeof hdr.ip.ip6.ip6_src); + memcpy(&hdr.ip.ip6.ip6_dst, &((struct sockaddr_in6 *) dst)->sin6_addr, + sizeof hdr.ip.ip6.ip6_dst); + break; + } + + /* Calculate UDP checksum. */ + udp.uh_sum = udp_cksum(&hdr, &udp, (u_int16_t *) packet_buf); + hdrlen += sizeof hdr.sa_family; + + /* pcap file packet header */ + gettimeofday(&tv, 0); + hdr.pcap.ts.tv_sec = tv.tv_sec; + hdr.pcap.ts.tv_usec = tv.tv_usec; + hdr.pcap.caplen = datalen + hdrlen; + hdr.pcap.len = datalen + hdrlen; + + hdrlen += sizeof(struct pcap_pkthdr); + datalen -= sizeof(struct udphdr); + + /* Write to pcap file. */ + fwrite(&hdr, hdrlen, 1, packet_log); /* pcap + IP */ + fwrite(&udp, sizeof(struct udphdr), 1, packet_log); /* UDP */ + fwrite(packet_buf, datalen, 1, packet_log); /* IKE-data */ + fflush(packet_log); } /* Copied from tcpdump/print-udp.c, mostly rewritten. */ static int -udp_cksum (struct packhdr *hdr, const struct udphdr *u, u_int16_t *d) +udp_cksum(struct packhdr *hdr, const struct udphdr *u, u_int16_t *d) { - int i, hdrlen, tlen = ntohs (u->uh_ulen) - sizeof (struct udphdr); - struct ip *ip4; - struct ip6_hdr *ip6; - - union phu { - struct ip4pseudo { - struct in_addr src; - struct in_addr dst; - u_int8_t z; - u_int8_t proto; - u_int16_t len; - } ip4p; - struct ip6pseudo { - struct in6_addr src; - struct in6_addr dst; - u_int32_t plen; - u_int16_t z0; - u_int8_t z1; - u_int8_t nxt; - } ip6p; - u_int16_t pa[20]; - } phu; - const u_int16_t *sp; - u_int32_t sum; - - /* Setup pseudoheader. */ - memset (phu.pa, 0, sizeof phu); - switch (ntohl (hdr->sa_family)) - { - case AF_INET: - ip4 = &hdr->ip.ip4; - memcpy (&phu.ip4p.src, &ip4->ip_src, sizeof (struct in_addr)); - memcpy (&phu.ip4p.dst, &ip4->ip_dst, sizeof (struct in_addr)); - phu.ip4p.proto = ip4->ip_p; - phu.ip4p.len = u->uh_ulen; - hdrlen = sizeof phu.ip4p; - break; - - case AF_INET6: - ip6 = &hdr->ip.ip6; - memcpy (&phu.ip6p.src, &ip6->ip6_src, sizeof (phu.ip6p.src)); - memcpy (&phu.ip6p.dst, &ip6->ip6_dst, sizeof (phu.ip6p.dst)); - phu.ip6p.plen = u->uh_ulen; - phu.ip6p.nxt = ip6->ip6_nxt; - hdrlen = sizeof phu.ip6p; - break; - - default: - return 0; - } - - /* IPv6 wants a 0xFFFF checksum "on error", not 0x0. */ - if (tlen < 0) - return (ntohl (hdr->sa_family) == AF_INET ? 0 : 0xFFFF); - - sum = 0; - for (i = 0; i < hdrlen; i += 2) - sum += phu.pa[i/2]; - - sp = (u_int16_t *)u; - for (i = 0; i < (int)sizeof (struct udphdr); i += 2) - sum += *sp++; - - sp = d; - for (i = 0; i < (tlen&~1); i += 2) - sum += *sp++; - - if (tlen & 1) - sum += htons ((*(const char *)sp) << 8); - - while (sum > 0xffff) - sum = (sum & 0xffff) + (sum >> 16); - sum = ~sum & 0xffff; - - return sum; + struct ip *ip4; + struct ip6_hdr *ip6; + int i, hdrlen, tlen = ntohs(u->uh_ulen) - sizeof(struct udphdr); + + union phu { + struct ip4pseudo { + struct in_addr src; + struct in_addr dst; + u_int8_t z; + u_int8_t proto; + u_int16_t len; + } ip4p; + struct ip6pseudo { + struct in6_addr src; + struct in6_addr dst; + u_int32_t plen; + u_int16_t z0; + u_int8_t z1; + u_int8_t nxt; + } ip6p; + u_int16_t pa[20]; + } phu; + const u_int16_t *sp; + u_int32_t sum; + + /* Setup pseudoheader. */ + memset(phu.pa, 0, sizeof phu); + switch (ntohl(hdr->sa_family)) { + case AF_INET: + ip4 = &hdr->ip.ip4; + memcpy(&phu.ip4p.src, &ip4->ip_src, sizeof(struct in_addr)); + memcpy(&phu.ip4p.dst, &ip4->ip_dst, sizeof(struct in_addr)); + phu.ip4p.proto = ip4->ip_p; + phu.ip4p.len = u->uh_ulen; + hdrlen = sizeof phu.ip4p; + break; + + case AF_INET6: + ip6 = &hdr->ip.ip6; + memcpy(&phu.ip6p.src, &ip6->ip6_src, sizeof(phu.ip6p.src)); + memcpy(&phu.ip6p.dst, &ip6->ip6_dst, sizeof(phu.ip6p.dst)); + phu.ip6p.plen = u->uh_ulen; + phu.ip6p.nxt = ip6->ip6_nxt; + hdrlen = sizeof phu.ip6p; + break; + + default: + return 0; + } + + /* IPv6 wants a 0xFFFF checksum "on error", not 0x0. */ + if (tlen < 0) + return (ntohl(hdr->sa_family) == AF_INET ? 0 : 0xFFFF); + + sum = 0; + for (i = 0; i < hdrlen; i += 2) + sum += phu.pa[i / 2]; + + sp = (u_int16_t *) u; + for (i = 0; i < (int) sizeof(struct udphdr); i += 2) + sum += *sp++; + + sp = d; + for (i = 0; i < (tlen & ~1); i += 2) + sum += *sp++; + + if (tlen & 1) + sum += htons((*(const char *) sp) << 8); + + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum = ~sum & 0xffff; + + return sum; } /* Copied from tcpdump/print-ip.c, modified. */ static u_int16_t -in_cksum (const u_int16_t *w, int len) +in_cksum(const u_int16_t *w, int len) { - int nleft = len, sum = 0; - u_int16_t answer; - - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } - if (nleft == 1) - sum += htons (*(u_char *)w << 8); - - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return answer; + int nleft = len, sum = 0; + u_int16_t answer; + + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + if (nleft == 1) + sum += htons(*(u_char *) w << 8); + + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return answer; } -#endif /* USE_DEBUG */ +#endif /* USE_DEBUG */ diff --git a/sbin/isakmpd/log.h b/sbin/isakmpd/log.h index df96760b79f..1efa9e78d0e 100644 --- a/sbin/isakmpd/log.h +++ b/sbin/isakmpd/log.h @@ -1,5 +1,5 @@ -/* $OpenBSD: log.h,v 1.19 2004/02/25 16:01:28 hshoexer Exp $ */ -/* $EOM: log.h,v 1.19 2000/03/30 14:27:23 ho Exp $ */ +/* $OpenBSD: log.h,v 1.20 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: log.h,v 1.19 2000/03/30 14:27:23 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -38,7 +38,7 @@ #include <sys/uio.h> #include <stdio.h> -extern int verbose_logging; +extern int verbose_logging; /* * We cannot do the log strings dynamically sizeable as out of memory is one @@ -47,8 +47,8 @@ extern int verbose_logging; #define LOG_SIZE 200 enum log_classes { - LOG_MISC, LOG_TRANSPORT, LOG_MESSAGE, LOG_CRYPTO, LOG_TIMER, LOG_SYSDEP, - LOG_SA, LOG_EXCHANGE, LOG_NEGOTIATION, LOG_POLICY, LOG_UI, LOG_ENDCLASS + LOG_MISC, LOG_TRANSPORT, LOG_MESSAGE, LOG_CRYPTO, LOG_TIMER, LOG_SYSDEP, + LOG_SA, LOG_EXCHANGE, LOG_NEGOTIATION, LOG_POLICY, LOG_UI, LOG_ENDCLASS }; #define LOG_CLASSES_TEXT \ { "Misc", "Trpt", "Mesg", "Cryp", "Timr", "Sdep", "SA ", "Exch", "Negt", \ @@ -66,37 +66,39 @@ enum log_classes { #define LOG_DBG(x) log_debug x #define LOG_DBG_BUF(x) log_debug_buf x -extern void log_debug (int, int, const char *, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern void log_debug_buf (int, int, const char *, const u_int8_t *, size_t); -extern void log_debug_cmd (int, int); -extern void log_debug_toggle (void); +extern void +log_debug(int, int, const char *,...) +__attribute__((__format__(__printf__, 3, 4))); + extern void log_debug_buf(int, int, const char *, const u_int8_t *, size_t); + extern void log_debug_cmd(int, int); + extern void log_debug_toggle(void); #define PCAP_FILE_DEFAULT "/var/run/isakmpd.pcap" -extern void log_packet_init (char *); -extern void log_packet_iov (struct sockaddr *, struct sockaddr *, - struct iovec *, int); -extern void log_packet_restart (char *); -extern void log_packet_stop (void); + extern void log_packet_init(char *); + extern void log_packet_iov(struct sockaddr *, struct sockaddr *, + struct iovec *, int); + extern void log_packet_restart(char *); + extern void log_packet_stop(void); -#else /* !USE_DEBUG */ +#else /* !USE_DEBUG */ #define LOG_DBG(x) #define LOG_DBG_BUF(x) -#endif /* USE_DEBUG */ - -extern FILE *log_current (void); -extern void log_error (const char *, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); -extern void log_fatal (const char *, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); -extern void log_print (const char *, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); -extern void log_verbose (const char *, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); -extern void log_to (FILE *); -extern void log_init (int); -extern void log_reinit (void); - -#endif /* _LOG_H_ */ +#endif /* USE_DEBUG */ + +extern FILE *log_current(void); +extern void +log_error(const char *,...) +__attribute__((__format__(__printf__, 1, 2))); + extern void log_fatal(const char *,...) + __attribute__((__format__(__printf__, 1, 2))); + extern void log_print(const char *,...) + __attribute__((__format__(__printf__, 1, 2))); + extern void log_verbose(const char *,...) + __attribute__((__format__(__printf__, 1, 2))); + extern void log_to(FILE *); + extern void log_init(int); + extern void log_reinit(void); + +#endif /* _LOG_H_ */ diff --git a/sbin/isakmpd/math_2n.c b/sbin/isakmpd/math_2n.c index 4b600d04b8a..c5e37b3a27e 100644 --- a/sbin/isakmpd/math_2n.c +++ b/sbin/isakmpd/math_2n.c @@ -1,5 +1,5 @@ -/* $OpenBSD: math_2n.c,v 1.13 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: math_2n.c,v 1.15 1999/04/20 09:23:30 niklas Exp $ */ +/* $OpenBSD: math_2n.c,v 1.14 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_2n.c,v 1.15 1999/04/20 09:23:30 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -48,507 +48,486 @@ #include "math_2n.h" #include "util.h" -static u_int8_t hex2int (char); +static u_int8_t hex2int(char); -static char int2hex[] = "0123456789abcdef"; -CHUNK_TYPE b2n_mask[CHUNK_BITS] = { - 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80, +static char int2hex[] = "0123456789abcdef"; +CHUNK_TYPE b2n_mask[CHUNK_BITS] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, #if CHUNK_BITS > 8 - 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, #if CHUNK_BITS > 16 - 0x00010000,0x00020000,0x00040000,0x00080000, - 0x00100000,0x00200000,0x00400000,0x00800000, - 0x01000000,0x02000000,0x04000000,0x08000000, - 0x10000000,0x20000000,0x40000000,0x80000000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, #endif #endif }; /* Convert a hex character to its integer value. */ -static u_int8_t -hex2int (char c) +static u_int8_t +hex2int(char c) { - if (c <= '9') - return c - '0'; - if (c <= 'f') - return 10 + c - 'a'; + if (c <= '9') + return c - '0'; + if (c <= 'f') + return 10 + c - 'a'; - return 0; + return 0; } int -b2n_random (b2n_ptr n, u_int32_t bits) +b2n_random(b2n_ptr n, u_int32_t bits) { - if (b2n_resize (n, (CHUNK_MASK + bits) >> CHUNK_SHIFTS)) - return -1; + if (b2n_resize(n, (CHUNK_MASK + bits) >> CHUNK_SHIFTS)) + return -1; - getrandom ((u_int8_t *)n->limp, CHUNK_BYTES * n->chunks); + getrandom((u_int8_t *) n->limp, CHUNK_BYTES * n->chunks); - /* Get the number of significant bits right */ - if (bits & CHUNK_MASK) - { - CHUNK_TYPE m = (((1 << ((bits & CHUNK_MASK)-1)) - 1) << 1) | 1; - n->limp[n->chunks-1] &= m; - } - - n->dirty = 1; - return 0; + /* Get the number of significant bits right */ + if (bits & CHUNK_MASK) { + CHUNK_TYPE m = (((1 << ((bits & CHUNK_MASK) - 1)) - 1) << 1) | 1; + n->limp[n->chunks - 1] &= m; + } + n->dirty = 1; + return 0; } /* b2n management functions */ void -b2n_init (b2n_ptr n) +b2n_init(b2n_ptr n) { - n->chunks = 0; - n->limp = 0; + n->chunks = 0; + n->limp = 0; } void -b2n_clear (b2n_ptr n) +b2n_clear(b2n_ptr n) { - if (n->limp) - free (n->limp); + if (n->limp) + free(n->limp); } int -b2n_resize (b2n_ptr n, unsigned int chunks) +b2n_resize(b2n_ptr n, unsigned int chunks) { - size_t old = n->chunks; - size_t size; - CHUNK_TYPE *new; + size_t old = n->chunks; + size_t size; + CHUNK_TYPE *new; - if (chunks == 0) - chunks = 1; + if (chunks == 0) + chunks = 1; - if (chunks == old) - return 0; + if (chunks == old) + return 0; - size = CHUNK_BYTES * chunks; + size = CHUNK_BYTES * chunks; - new = realloc (n->limp, size); - if (!new) - return -1; + new = realloc(n->limp, size); + if (!new) + return -1; - n->limp = new; - n->chunks = chunks; - n->bits = chunks << CHUNK_SHIFTS; - n->dirty = 1; + n->limp = new; + n->chunks = chunks; + n->bits = chunks << CHUNK_SHIFTS; + n->dirty = 1; - if (chunks > old) - memset (n->limp + old, 0, size - CHUNK_BYTES * old); + if (chunks > old) + memset(n->limp + old, 0, size - CHUNK_BYTES * old); - return 0; + return 0; } /* Simple assignment functions. */ int -b2n_set (b2n_ptr d, b2n_ptr s) +b2n_set(b2n_ptr d, b2n_ptr s) { - if (d == s) - return 0; - - b2n_sigbit (s); - if (b2n_resize (d, (CHUNK_MASK + s->bits) >> CHUNK_SHIFTS)) - return -1; - memcpy (d->limp, s->limp, CHUNK_BYTES * d->chunks); - d->bits = s->bits; - d->dirty = s->dirty; - return 0; + if (d == s) + return 0; + + b2n_sigbit(s); + if (b2n_resize(d, (CHUNK_MASK + s->bits) >> CHUNK_SHIFTS)) + return -1; + memcpy(d->limp, s->limp, CHUNK_BYTES * d->chunks); + d->bits = s->bits; + d->dirty = s->dirty; + return 0; } int -b2n_set_null (b2n_ptr n) +b2n_set_null(b2n_ptr n) { - if (b2n_resize (n, 1)) - return -1; - n->limp[0] = n->bits = n->dirty = 0; - return 0; + if (b2n_resize(n, 1)) + return -1; + n->limp[0] = n->bits = n->dirty = 0; + return 0; } int -b2n_set_ui (b2n_ptr n, unsigned int val) +b2n_set_ui(b2n_ptr n, unsigned int val) { #if CHUNK_BITS < 32 - int i, chunks; + int i, chunks; - chunks = (CHUNK_BYTES - 1 + sizeof (val)) / CHUNK_BYTES; + chunks = (CHUNK_BYTES - 1 + sizeof(val)) / CHUNK_BYTES; - if (b2n_resize (n, chunks)) - return -1; + if (b2n_resize(n, chunks)) + return -1; - for (i = 0; i < chunks; i++) - { - n->limp[i] = val & CHUNK_BMASK; - val >>= CHUNK_BITS; - } + for (i = 0; i < chunks; i++) { + n->limp[i] = val & CHUNK_BMASK; + val >>= CHUNK_BITS; + } #else - if (b2n_resize (n, 1)) - return -1; - n->limp[0] = val; + if (b2n_resize(n, 1)) + return -1; + n->limp[0] = val; #endif - n->dirty = 1; - return 0; + n->dirty = 1; + return 0; } /* XXX This one only takes hex at the moment. */ int -b2n_set_str (b2n_ptr n, char *str) +b2n_set_str(b2n_ptr n, char *str) { - int i, j, w, len, chunks; - CHUNK_TYPE tmp; - - if (strncasecmp (str, "0x", 2)) - return -1; - - /* Make the hex string even lengthed */ - len = strlen (str) - 2; - if (len & 1) - { - len ++; - str ++; - } - else - str += 2; - - len /= 2; - - chunks = (CHUNK_BYTES - 1 + len) / CHUNK_BYTES; - if (b2n_resize (n, chunks)) - return -1; - memset (n->limp, 0, CHUNK_BYTES * n->chunks); - - for (w = 0, i = 0; i < chunks; i++) - { - tmp = 0; - for (j = (i == 0 ? ((len - 1) % CHUNK_BYTES) + 1 : CHUNK_BYTES); j > 0; - j--) - { - tmp <<= 8; - tmp |= (hex2int (str[w]) << 4) | hex2int (str[w + 1]); - w += 2; + int i, j, w, len, chunks; + CHUNK_TYPE tmp; + + if (strncasecmp(str, "0x", 2)) + return -1; + + /* Make the hex string even lengthed */ + len = strlen(str) - 2; + if (len & 1) { + len++; + str++; + } else + str += 2; + + len /= 2; + + chunks = (CHUNK_BYTES - 1 + len) / CHUNK_BYTES; + if (b2n_resize(n, chunks)) + return -1; + memset(n->limp, 0, CHUNK_BYTES * n->chunks); + + for (w = 0, i = 0; i < chunks; i++) { + tmp = 0; + for (j = (i == 0 ? ((len - 1) % CHUNK_BYTES) + 1 : CHUNK_BYTES); j > 0; + j--) { + tmp <<= 8; + tmp |= (hex2int(str[w]) << 4) | hex2int(str[w + 1]); + w += 2; + } + n->limp[chunks - 1 - i] = tmp; } - n->limp[chunks - 1 - i] = tmp; - } - n->dirty = 1; - return 0; + n->dirty = 1; + return 0; } /* Output function, mainly for debugging purposes. */ void -b2n_print (b2n_ptr n) +b2n_print(b2n_ptr n) { - int i, j, w, flag = 0; - int left; - char buffer[2 * CHUNK_BYTES]; - CHUNK_TYPE tmp; - - left = ((((7 + b2n_sigbit (n)) >> 3) - 1) % CHUNK_BYTES) + 1; - printf ("0x"); - for (i = 0; i < n->chunks; i++) - { - tmp = n->limp[n->chunks - 1 - i]; - memset (buffer, '0', sizeof (buffer)); - for (w = 0, j = (i == 0 ? left : CHUNK_BYTES); j > 0; j--) - { - buffer[w++] = int2hex[(tmp >> 4) & 0xf]; - buffer[w++] = int2hex[tmp & 0xf]; - tmp >>= 8; + int i, j, w, flag = 0; + int left; + char buffer[2 * CHUNK_BYTES]; + CHUNK_TYPE tmp; + + left = ((((7 + b2n_sigbit(n)) >> 3) - 1) % CHUNK_BYTES) + 1; + printf("0x"); + for (i = 0; i < n->chunks; i++) { + tmp = n->limp[n->chunks - 1 - i]; + memset(buffer, '0', sizeof(buffer)); + for (w = 0, j = (i == 0 ? left : CHUNK_BYTES); j > 0; j--) { + buffer[w++] = int2hex[(tmp >> 4) & 0xf]; + buffer[w++] = int2hex[tmp & 0xf]; + tmp >>= 8; + } + + for (j = (i == 0 ? left - 1 : CHUNK_BYTES - 1); j >= 0; j--) + if (flag || (i == n->chunks - 1 && j == 0) || + buffer[2 * j] != '0' || buffer[2 * j + 1] != '0') { + putchar(buffer[2 * j]); + putchar(buffer[2 * j + 1]); + flag = 1; + } } - - for (j = (i == 0 ? left - 1: CHUNK_BYTES - 1); j >= 0; j--) - if (flag || (i == n->chunks - 1 && j == 0) || - buffer[2 * j] != '0' || buffer[2 * j + 1] != '0') - { - putchar (buffer[2 * j]); - putchar (buffer[2 * j + 1]); - flag = 1; - } - } - printf ("\n"); + printf("\n"); } int -b2n_snprint (char *buf, size_t sz, b2n_ptr n) +b2n_snprint(char *buf, size_t sz, b2n_ptr n) { - int i, j, w, flag = 0; - size_t k; - int left; - char buffer[2 * CHUNK_BYTES]; - CHUNK_TYPE tmp; - - left = ((((7 + b2n_sigbit (n)) >> 3) - 1) % CHUNK_BYTES) + 1; - - k = strlcpy (buf, "0x", sz); - for (i = 0; i < n->chunks && k < sz - 1; i++) - { - tmp = n->limp[n->chunks - 1 - i]; - memset (buffer, '0', sizeof (buffer)); - for (w = 0, j = (i == 0 ? left : CHUNK_BYTES); j > 0; j--) - { - buffer[w++] = int2hex[(tmp >> 4) & 0xf]; - buffer[w++] = int2hex[tmp & 0xf]; - tmp >>= 8; + int i, j, w, flag = 0; + size_t k; + int left; + char buffer[2 * CHUNK_BYTES]; + CHUNK_TYPE tmp; + + left = ((((7 + b2n_sigbit(n)) >> 3) - 1) % CHUNK_BYTES) + 1; + + k = strlcpy(buf, "0x", sz); + for (i = 0; i < n->chunks && k < sz - 1; i++) { + tmp = n->limp[n->chunks - 1 - i]; + memset(buffer, '0', sizeof(buffer)); + for (w = 0, j = (i == 0 ? left : CHUNK_BYTES); j > 0; j--) { + buffer[w++] = int2hex[(tmp >> 4) & 0xf]; + buffer[w++] = int2hex[tmp & 0xf]; + tmp >>= 8; + } + + for (j = (i == 0 ? left - 1 : CHUNK_BYTES - 1); j >= 0 && k < sz - 3; j--) + if (flag || (i == n->chunks - 1 && j == 0) || + buffer[2 * j] != '0' || buffer[2 * j + 1] != '0') { + buf[k++] = buffer[2 * j]; + buf[k++] = buffer[2 * j + 1]; + flag = 1; + } } - for (j = (i == 0 ? left - 1: CHUNK_BYTES - 1); j >= 0 && k < sz - 3; j--) - if (flag || (i == n->chunks - 1 && j == 0) || - buffer[2 * j] != '0' || buffer[2 * j + 1] != '0') - { - buf[k++] = buffer[2 * j]; - buf[k++] = buffer[2 * j + 1]; - flag = 1; - } - } - - buf[k++] = 0; - return k; + buf[k++] = 0; + return k; } /* Arithmetic functions. */ u_int32_t -b2n_sigbit (b2n_ptr n) +b2n_sigbit(b2n_ptr n) { - int i, j; + int i, j; - if (!n->dirty) - return n->bits; + if (!n->dirty) + return n->bits; - for (i = n->chunks - 1; i > 0; i--) - if (n->limp[i]) - break; + for (i = n->chunks - 1; i > 0; i--) + if (n->limp[i]) + break; - if (!n->limp[i]) - return 0; + if (!n->limp[i]) + return 0; - for (j = CHUNK_MASK; j > 0; j--) - if (n->limp[i] & b2n_mask[j]) - break; + for (j = CHUNK_MASK; j > 0; j--) + if (n->limp[i] & b2n_mask[j]) + break; - n->bits = (i << CHUNK_SHIFTS) + j + 1; - n->dirty = 0; - return n->bits; + n->bits = (i << CHUNK_SHIFTS) + j + 1; + n->dirty = 0; + return n->bits; } /* Addition on GF(2)[x] is nice, its just an XOR. */ int -b2n_add (b2n_ptr d, b2n_ptr a, b2n_ptr b) +b2n_add(b2n_ptr d, b2n_ptr a, b2n_ptr b) { - int i; - b2n_ptr bmin, bmax; - - if (!b2n_cmp_null (a)) - return b2n_set (d, b); - - if (!b2n_cmp_null (b)) - return b2n_set (d, a); - - bmin = B2N_MIN (a,b); - bmax = B2N_MAX (a,b); - - if (b2n_resize (d, bmax->chunks)) - return -1; - - for (i = 0; i < bmin->chunks; i++) - d->limp[i] = bmax->limp[i] ^ bmin->limp[i]; - - /* - * If d is not bmax, we have to copy the rest of the bytes, and also - * need to adjust to number of relevant bits. - */ - if (d != bmax) - { - for ( ; i < bmax->chunks; i++) - d->limp[i] = bmax->limp[i]; - - d->bits = bmax->bits; - } - - /* - * Help to converse memory. When the result of the addition is zero - * truncate the used amount of memory. - */ - if (d != bmax && !b2n_cmp_null (d)) - return b2n_set_null (d); - else - d->dirty = 1; - return 0; + int i; + b2n_ptr bmin, bmax; + + if (!b2n_cmp_null(a)) + return b2n_set(d, b); + + if (!b2n_cmp_null(b)) + return b2n_set(d, a); + + bmin = B2N_MIN(a, b); + bmax = B2N_MAX(a, b); + + if (b2n_resize(d, bmax->chunks)) + return -1; + + for (i = 0; i < bmin->chunks; i++) + d->limp[i] = bmax->limp[i] ^ bmin->limp[i]; + + /* + * If d is not bmax, we have to copy the rest of the bytes, and also + * need to adjust to number of relevant bits. + */ + if (d != bmax) { + for (; i < bmax->chunks; i++) + d->limp[i] = bmax->limp[i]; + + d->bits = bmax->bits; + } + /* + * Help to converse memory. When the result of the addition is zero + * truncate the used amount of memory. + */ + if (d != bmax && !b2n_cmp_null(d)) + return b2n_set_null(d); + else + d->dirty = 1; + return 0; } /* Compare two polynomials. */ int -b2n_cmp (b2n_ptr n, b2n_ptr m) +b2n_cmp(b2n_ptr n, b2n_ptr m) { - int sn, sm; - int i; + int sn, sm; + int i; - sn = b2n_sigbit (n); - sm = b2n_sigbit (m); + sn = b2n_sigbit(n); + sm = b2n_sigbit(m); - if (sn > sm) - return 1; - if (sn < sm) - return -1; + if (sn > sm) + return 1; + if (sn < sm) + return -1; - for (i = n->chunks-1; i >= 0; i--) - if (n->limp[i] > m->limp[i]) - return 1; - else if (n->limp[i] < m->limp[i]) - return -1; + for (i = n->chunks - 1; i >= 0; i--) + if (n->limp[i] > m->limp[i]) + return 1; + else if (n->limp[i] < m->limp[i]) + return -1; - return 0; + return 0; } int -b2n_cmp_null (b2n_ptr a) +b2n_cmp_null(b2n_ptr a) { - int i = 0; + int i = 0; - do - { - if (a->limp[i]) - return 1; - } - while (++i < a->chunks); + do { + if (a->limp[i]) + return 1; + } + while (++i < a->chunks); - return 0; + return 0; } /* Left shift, needed for polynomial multiplication. */ int -b2n_lshift (b2n_ptr d, b2n_ptr n, unsigned int s) +b2n_lshift(b2n_ptr d, b2n_ptr n, unsigned int s) { - int i, maj, min, chunks; - u_int16_t bits = b2n_sigbit (n), add; - CHUNK_TYPE *p, *op; - - if (!s) - return b2n_set (d, n); - - maj = s >> CHUNK_SHIFTS; - min = s & CHUNK_MASK; - - add = (!(bits & CHUNK_MASK) || ((bits & CHUNK_MASK) + min) > CHUNK_MASK) - ? 1 : 0; - chunks = n->chunks; - if (b2n_resize (d, chunks + maj + add)) - return -1; - memmove (d->limp + maj, n->limp, CHUNK_BYTES * chunks); - - if (maj) - memset (d->limp, 0, CHUNK_BYTES * maj); - if (add) - d->limp[d->chunks - 1] = 0; - - /* If !min there are no bit shifts, we are done */ - if (!min) - return 0; - - op = p = &d->limp[d->chunks - 1]; - for (i = d->chunks - 2; i >= maj; i--) - { - op--; - *p = (*p << min) | (*op >> (CHUNK_BITS - min)); - p--; - } - *p <<= min; - - d->dirty = 0; - d->bits = bits + (maj << CHUNK_SHIFTS) + min; - return 0; + int i, maj, min, chunks; + u_int16_t bits = b2n_sigbit(n), add; + CHUNK_TYPE *p, *op; + + if (!s) + return b2n_set(d, n); + + maj = s >> CHUNK_SHIFTS; + min = s & CHUNK_MASK; + + add = (!(bits & CHUNK_MASK) || ((bits & CHUNK_MASK) + min) > CHUNK_MASK) + ? 1 : 0; + chunks = n->chunks; + if (b2n_resize(d, chunks + maj + add)) + return -1; + memmove(d->limp + maj, n->limp, CHUNK_BYTES * chunks); + + if (maj) + memset(d->limp, 0, CHUNK_BYTES * maj); + if (add) + d->limp[d->chunks - 1] = 0; + + /* If !min there are no bit shifts, we are done */ + if (!min) + return 0; + + op = p = &d->limp[d->chunks - 1]; + for (i = d->chunks - 2; i >= maj; i--) { + op--; + *p = (*p << min) | (*op >> (CHUNK_BITS - min)); + p--; + } + *p <<= min; + + d->dirty = 0; + d->bits = bits + (maj << CHUNK_SHIFTS) + min; + return 0; } /* Right shift, needed for polynomial division. */ int -b2n_rshift (b2n_ptr d, b2n_ptr n, unsigned int s) +b2n_rshift(b2n_ptr d, b2n_ptr n, unsigned int s) { - int maj, min, size = n->chunks, newsize; - b2n_ptr tmp; + int maj, min, size = n->chunks, newsize; + b2n_ptr tmp; - if (!s) - return b2n_set (d, n); + if (!s) + return b2n_set(d, n); - maj = s >> CHUNK_SHIFTS; + maj = s >> CHUNK_SHIFTS; - newsize = size - maj; + newsize = size - maj; - if (size < maj) - return b2n_set_null (d); + if (size < maj) + return b2n_set_null(d); - min = (CHUNK_BITS - (s & CHUNK_MASK)) & CHUNK_MASK; - if (min) - { - if ((b2n_sigbit (n) & CHUNK_MASK) > (u_int32_t)min) - newsize++; + min = (CHUNK_BITS - (s & CHUNK_MASK)) & CHUNK_MASK; + if (min) { + if ((b2n_sigbit(n) & CHUNK_MASK) > (u_int32_t) min) + newsize++; - if (b2n_lshift (d, n, min)) - return -1; - tmp = d; - } - else - tmp = n; + if (b2n_lshift(d, n, min)) + return -1; + tmp = d; + } else + tmp = n; - memmove (d->limp, tmp->limp + maj + (min ? 1 : 0), CHUNK_BYTES * newsize); - if (b2n_resize (d, newsize)) - return -1; + memmove(d->limp, tmp->limp + maj + (min ? 1 : 0), CHUNK_BYTES * newsize); + if (b2n_resize(d, newsize)) + return -1; - d->bits = tmp->bits - ((maj + (min ? 1 : 0)) << CHUNK_SHIFTS); - return 0; + d->bits = tmp->bits - ((maj + (min ? 1 : 0)) << CHUNK_SHIFTS); + return 0; } /* Normal polynomial multiplication. */ int -b2n_mul (b2n_ptr d, b2n_ptr n, b2n_ptr m) +b2n_mul(b2n_ptr d, b2n_ptr n, b2n_ptr m) { - int i, j; - b2n_t tmp, tmp2; - - if (!b2n_cmp_null (m) || !b2n_cmp_null (n)) - return b2n_set_null (d); - - if (b2n_sigbit (m) == 1) - return b2n_set (d, n); - - if (b2n_sigbit (n) == 1) - return b2n_set (d, m); - - b2n_init (tmp); - b2n_init (tmp2); - - if (b2n_set (tmp, B2N_MAX (n, m))) - goto fail; - if (b2n_set (tmp2, B2N_MIN (n, m))) - goto fail; - - if (b2n_set_null (d)) - goto fail; - - for (i = 0; i < tmp2->chunks; i++) - if (tmp2->limp[i]) - for (j = 0; j < CHUNK_BITS; j++) - { - if (tmp2->limp[i] & b2n_mask[j]) - if (b2n_add (d, d, tmp)) - goto fail; - - if (b2n_lshift (tmp, tmp, 1)) - goto fail; - } - else - if (b2n_lshift (tmp, tmp, CHUNK_BITS)) - goto fail; - - b2n_clear (tmp); - b2n_clear (tmp2); - return 0; - - fail: - b2n_clear (tmp); - b2n_clear (tmp2); - return -1; + int i, j; + b2n_t tmp, tmp2; + + if (!b2n_cmp_null(m) || !b2n_cmp_null(n)) + return b2n_set_null(d); + + if (b2n_sigbit(m) == 1) + return b2n_set(d, n); + + if (b2n_sigbit(n) == 1) + return b2n_set(d, m); + + b2n_init(tmp); + b2n_init(tmp2); + + if (b2n_set(tmp, B2N_MAX(n, m))) + goto fail; + if (b2n_set(tmp2, B2N_MIN(n, m))) + goto fail; + + if (b2n_set_null(d)) + goto fail; + + for (i = 0; i < tmp2->chunks; i++) + if (tmp2->limp[i]) + for (j = 0; j < CHUNK_BITS; j++) { + if (tmp2->limp[i] & b2n_mask[j]) + if (b2n_add(d, d, tmp)) + goto fail; + + if (b2n_lshift(tmp, tmp, 1)) + goto fail; + } + else if (b2n_lshift(tmp, tmp, CHUNK_BITS)) + goto fail; + + b2n_clear(tmp); + b2n_clear(tmp2); + return 0; + +fail: + b2n_clear(tmp); + b2n_clear(tmp2); + return -1; } /* @@ -556,46 +535,42 @@ b2n_mul (b2n_ptr d, b2n_ptr n, b2n_ptr m) * multiplication. */ int -b2n_square (b2n_ptr d, b2n_ptr n) +b2n_square(b2n_ptr d, b2n_ptr n) { - int i, j, maj, min, bits, chunk; - b2n_t t; - - maj = b2n_sigbit (n); - min = maj & CHUNK_MASK; - maj = (maj + CHUNK_MASK) >> CHUNK_SHIFTS; - - b2n_init (t); - if (b2n_resize (t, 2 * maj + ((CHUNK_MASK + 2 * min) >> CHUNK_SHIFTS))) - { - b2n_clear (t); - return -1; - } - - chunk = 0; - bits = 0; - - for (i = 0; i < maj; i++) - if (n->limp[i]) - for (j = 0; j < CHUNK_BITS; j++) - { - if (n->limp[i] & b2n_mask[j]) - t->limp[chunk] ^= b2n_mask[bits]; - - bits += 2; - if (bits >= CHUNK_BITS) - { - chunk++; - bits &= CHUNK_MASK; - } - } - else - chunk += 2; + int i, j, maj, min, bits, chunk; + b2n_t t; + + maj = b2n_sigbit(n); + min = maj & CHUNK_MASK; + maj = (maj + CHUNK_MASK) >> CHUNK_SHIFTS; - t->dirty = 1; - B2N_SWAP (d, t); - b2n_clear (t); - return 0; + b2n_init(t); + if (b2n_resize(t, 2 * maj + ((CHUNK_MASK + 2 * min) >> CHUNK_SHIFTS))) { + b2n_clear(t); + return -1; + } + chunk = 0; + bits = 0; + + for (i = 0; i < maj; i++) + if (n->limp[i]) + for (j = 0; j < CHUNK_BITS; j++) { + if (n->limp[i] & b2n_mask[j]) + t->limp[chunk] ^= b2n_mask[bits]; + + bits += 2; + if (bits >= CHUNK_BITS) { + chunk++; + bits &= CHUNK_MASK; + } + } + else + chunk += 2; + + t->dirty = 1; + B2N_SWAP(d, t); + b2n_clear(t); + return 0; } /* @@ -603,248 +578,240 @@ b2n_square (b2n_ptr d, b2n_ptr n) * These functions are far from optimal in speed. */ int -b2n_div_q (b2n_ptr d, b2n_ptr n, b2n_ptr m) +b2n_div_q(b2n_ptr d, b2n_ptr n, b2n_ptr m) { - b2n_t r; - int rv; + b2n_t r; + int rv; - b2n_init (r); - rv = b2n_div (d, r, n, m); - b2n_clear (r); - return rv; + b2n_init(r); + rv = b2n_div(d, r, n, m); + b2n_clear(r); + return rv; } int -b2n_div_r (b2n_ptr r, b2n_ptr n, b2n_ptr m) +b2n_div_r(b2n_ptr r, b2n_ptr n, b2n_ptr m) { - b2n_t q; - int rv; + b2n_t q; + int rv; - b2n_init (q); - rv = b2n_div (q, r, n, m); - b2n_clear (q); - return rv; + b2n_init(q); + rv = b2n_div(q, r, n, m); + b2n_clear(q); + return rv; } int -b2n_div (b2n_ptr q, b2n_ptr r, b2n_ptr n, b2n_ptr m) +b2n_div(b2n_ptr q, b2n_ptr r, b2n_ptr n, b2n_ptr m) { - int i, j, len, bits; - u_int32_t sm, sn; - b2n_t nenn, div, shift, mask; - - /* If Teiler > Zaehler, the result is 0 */ - if ((sm = b2n_sigbit (m)) > (sn = b2n_sigbit (n))) - { - if (b2n_set_null (q)) - return -1; - return b2n_set (r, n); - } - - if (sm == 0) - /* Division by Zero */ - return -1; - else if (sm == 1) - { - /* Division by the One-Element */ - if (b2n_set (q, n)) - return -1; - return b2n_set_null (r); - } - - b2n_init (nenn); - b2n_init (div); - b2n_init (shift); - b2n_init (mask); - - if (b2n_set (nenn, n)) - goto fail; - if (b2n_set (div, m)) - goto fail; - if (b2n_set (shift, m)) - goto fail; - if (b2n_set_ui (mask, 1)) - goto fail; - - if (b2n_resize (q, (sn - sm + CHUNK_MASK) >> CHUNK_SHIFTS)) - goto fail; - memset (q->limp, 0, CHUNK_BYTES * q->chunks); - - if (b2n_lshift (shift, shift, sn - sm)) - goto fail; - if (b2n_lshift (mask, mask, sn - sm)) - goto fail; - - /* Number of significant octets */ - len = (sn - 1) >> CHUNK_SHIFTS; - /* The first iteration is done over the relevant bits */ - bits = (CHUNK_MASK + sn) & CHUNK_MASK; - for (i = len; i >= 0 && b2n_sigbit (nenn) >= sm; i--) - for (j = (i == len ? bits : CHUNK_MASK); j >= 0 && b2n_sigbit (nenn) >= sm; - j--) - { - if (nenn->limp[i] & b2n_mask[j]) - { - if (b2n_sub (nenn, nenn, shift)) - goto fail; - if (b2n_add (q, q, mask)) - goto fail; - } - if (b2n_rshift (shift, shift, 1)) - goto fail; - if (b2n_rshift (mask, mask, 1)) - goto fail; - } - - B2N_SWAP (r, nenn); - - b2n_clear (nenn); - b2n_clear (div); - b2n_clear (shift); - b2n_clear (mask); - return 0; + int i, j, len, bits; + u_int32_t sm, sn; + b2n_t nenn, div, shift, mask; + + /* If Teiler > Zaehler, the result is 0 */ + if ((sm = b2n_sigbit(m)) > (sn = b2n_sigbit(n))) { + if (b2n_set_null(q)) + return -1; + return b2n_set(r, n); + } + if (sm == 0) + /* Division by Zero */ + return -1; + else if (sm == 1) { + /* Division by the One-Element */ + if (b2n_set(q, n)) + return -1; + return b2n_set_null(r); + } + b2n_init(nenn); + b2n_init(div); + b2n_init(shift); + b2n_init(mask); + + if (b2n_set(nenn, n)) + goto fail; + if (b2n_set(div, m)) + goto fail; + if (b2n_set(shift, m)) + goto fail; + if (b2n_set_ui(mask, 1)) + goto fail; + + if (b2n_resize(q, (sn - sm + CHUNK_MASK) >> CHUNK_SHIFTS)) + goto fail; + memset(q->limp, 0, CHUNK_BYTES * q->chunks); + + if (b2n_lshift(shift, shift, sn - sm)) + goto fail; + if (b2n_lshift(mask, mask, sn - sm)) + goto fail; + + /* Number of significant octets */ + len = (sn - 1) >> CHUNK_SHIFTS; + /* The first iteration is done over the relevant bits */ + bits = (CHUNK_MASK + sn) & CHUNK_MASK; + for (i = len; i >= 0 && b2n_sigbit(nenn) >= sm; i--) + for (j = (i == len ? bits : CHUNK_MASK); j >= 0 && b2n_sigbit(nenn) >= sm; + j--) { + if (nenn->limp[i] & b2n_mask[j]) { + if (b2n_sub(nenn, nenn, shift)) + goto fail; + if (b2n_add(q, q, mask)) + goto fail; + } + if (b2n_rshift(shift, shift, 1)) + goto fail; + if (b2n_rshift(mask, mask, 1)) + goto fail; + } + + B2N_SWAP(r, nenn); + + b2n_clear(nenn); + b2n_clear(div); + b2n_clear(shift); + b2n_clear(mask); + return 0; fail: - b2n_clear (nenn); - b2n_clear (div); - b2n_clear (shift); - b2n_clear (mask); - return -1; + b2n_clear(nenn); + b2n_clear(div); + b2n_clear(shift); + b2n_clear(mask); + return -1; } /* Functions for Operation on GF(2**n) ~= GF(2)[x]/p(x). */ int -b2n_mod (b2n_ptr m, b2n_ptr n, b2n_ptr p) +b2n_mod(b2n_ptr m, b2n_ptr n, b2n_ptr p) { - int bits, size; - - if (b2n_div_r (m, n, p)) - return -1; - - bits = b2n_sigbit (m); - size = ((CHUNK_MASK + bits) >> CHUNK_SHIFTS); - if (size == 0) - size = 1; - if (m->chunks > size) - if (b2n_resize (m, size)) - return -1; - - m->bits = bits; - m->dirty = 0; - return 0; + int bits, size; + + if (b2n_div_r(m, n, p)) + return -1; + + bits = b2n_sigbit(m); + size = ((CHUNK_MASK + bits) >> CHUNK_SHIFTS); + if (size == 0) + size = 1; + if (m->chunks > size) + if (b2n_resize(m, size)) + return -1; + + m->bits = bits; + m->dirty = 0; + return 0; } int -b2n_gcd (b2n_ptr e, b2n_ptr go, b2n_ptr ho) +b2n_gcd(b2n_ptr e, b2n_ptr go, b2n_ptr ho) { - b2n_t g, h; - - b2n_init (g); - b2n_init (h); - if (b2n_set (g, go)) - goto fail; - if (b2n_set (h, ho)) - goto fail; - - while (b2n_cmp_null (h)) - { - if (b2n_mod (g, g, h)) - goto fail; - B2N_SWAP (g, h); - } + b2n_t g, h; + + b2n_init(g); + b2n_init(h); + if (b2n_set(g, go)) + goto fail; + if (b2n_set(h, ho)) + goto fail; + + while (b2n_cmp_null(h)) { + if (b2n_mod(g, g, h)) + goto fail; + B2N_SWAP(g, h); + } - B2N_SWAP (e, g); + B2N_SWAP(e, g); - b2n_clear (g); - b2n_clear (h); - return 0; + b2n_clear(g); + b2n_clear(h); + return 0; fail: - b2n_clear (g); - b2n_clear (h); - return -1; + b2n_clear(g); + b2n_clear(h); + return -1; } int -b2n_mul_inv (b2n_ptr ga, b2n_ptr be, b2n_ptr p) +b2n_mul_inv(b2n_ptr ga, b2n_ptr be, b2n_ptr p) { - b2n_t a; + b2n_t a; - b2n_init (a); - if (b2n_set_ui (a, 1)) - goto fail; + b2n_init(a); + if (b2n_set_ui(a, 1)) + goto fail; - if (b2n_div_mod (ga, a, be, p)) - goto fail; + if (b2n_div_mod(ga, a, be, p)) + goto fail; - b2n_clear (a); - return 0; + b2n_clear(a); + return 0; - fail: - b2n_clear (a); - return -1; +fail: + b2n_clear(a); + return -1; } int -b2n_div_mod (b2n_ptr ga, b2n_ptr a, b2n_ptr be, b2n_ptr p) +b2n_div_mod(b2n_ptr ga, b2n_ptr a, b2n_ptr be, b2n_ptr p) { - b2n_t s0, s1, s2, q, r0, r1; - - /* There is no multiplicative inverse to Null. */ - if (!b2n_cmp_null (be)) - return b2n_set_null (ga); - - b2n_init (s0); - b2n_init (s1); - b2n_init (s2); - b2n_init (r0); - b2n_init (r1); - b2n_init (q); - - if (b2n_set (r0, p)) - goto fail; - if (b2n_set (r1, be)) - goto fail; - - if (b2n_set_null (s0)) - goto fail; - if (b2n_set (s1, a)) - goto fail; - - while (b2n_cmp_null (r1)) - { - if (b2n_div (q, r0, r0, r1)) - goto fail; - B2N_SWAP (r0, r1); - - if (b2n_mul (s2, q, s1)) - goto fail; - if (b2n_mod (s2, s2, p)) - goto fail; - if (b2n_sub (s2, s0, s2)) - goto fail; - - B2N_SWAP (s0, s1); - B2N_SWAP (s1, s2); - } - B2N_SWAP (ga, s0); - - b2n_clear (s0); - b2n_clear (s1); - b2n_clear (s2); - b2n_clear (r0); - b2n_clear (r1); - b2n_clear (q); - return 0; + b2n_t s0, s1, s2, q, r0, r1; + + /* There is no multiplicative inverse to Null. */ + if (!b2n_cmp_null(be)) + return b2n_set_null(ga); + + b2n_init(s0); + b2n_init(s1); + b2n_init(s2); + b2n_init(r0); + b2n_init(r1); + b2n_init(q); + + if (b2n_set(r0, p)) + goto fail; + if (b2n_set(r1, be)) + goto fail; + + if (b2n_set_null(s0)) + goto fail; + if (b2n_set(s1, a)) + goto fail; + + while (b2n_cmp_null(r1)) { + if (b2n_div(q, r0, r0, r1)) + goto fail; + B2N_SWAP(r0, r1); + + if (b2n_mul(s2, q, s1)) + goto fail; + if (b2n_mod(s2, s2, p)) + goto fail; + if (b2n_sub(s2, s0, s2)) + goto fail; + + B2N_SWAP(s0, s1); + B2N_SWAP(s1, s2); + } + B2N_SWAP(ga, s0); + + b2n_clear(s0); + b2n_clear(s1); + b2n_clear(s2); + b2n_clear(r0); + b2n_clear(r1); + b2n_clear(q); + return 0; fail: - b2n_clear (s0); - b2n_clear (s1); - b2n_clear (s2); - b2n_clear (r0); - b2n_clear (r1); - b2n_clear (q); - return -1; + b2n_clear(s0); + b2n_clear(s1); + b2n_clear(s2); + b2n_clear(r0); + b2n_clear(r1); + b2n_clear(q); + return -1; } /* @@ -854,33 +821,32 @@ fail: * If z is a square root, z + 1 is the other. */ int -b2n_trace (b2n_ptr ho, b2n_ptr a, b2n_ptr p) +b2n_trace(b2n_ptr ho, b2n_ptr a, b2n_ptr p) { - int i, m = b2n_sigbit (p) - 1; - b2n_t h; - - b2n_init (h); - if (b2n_set (h, a)) - goto fail; - - for (i = 0; i < m - 1; i++) - { - if (b2n_square (h, h)) - goto fail; - if (b2n_mod (h, h, p)) - goto fail; - - if (b2n_add (h, h, a)) - goto fail; - } - B2N_SWAP (ho, h); - - b2n_clear (h); - return 0; - - fail: - b2n_clear (h); - return -1; + int i, m = b2n_sigbit(p) - 1; + b2n_t h; + + b2n_init(h); + if (b2n_set(h, a)) + goto fail; + + for (i = 0; i < m - 1; i++) { + if (b2n_square(h, h)) + goto fail; + if (b2n_mod(h, h, p)) + goto fail; + + if (b2n_add(h, h, a)) + goto fail; + } + B2N_SWAP(ho, h); + + b2n_clear(h); + return 0; + +fail: + b2n_clear(h); + return -1; } /* @@ -888,38 +854,37 @@ b2n_trace (b2n_ptr ho, b2n_ptr a, b2n_ptr p) * irreduceable polynomial is odd. */ int -b2n_halftrace (b2n_ptr ho, b2n_ptr a, b2n_ptr p) +b2n_halftrace(b2n_ptr ho, b2n_ptr a, b2n_ptr p) { - int i, m = b2n_sigbit (p) - 1; - b2n_t h; - - b2n_init (h); - if (b2n_set (h, a)) - goto fail; - - for (i = 0; i < (m - 1) / 2; i++) - { - if (b2n_square (h, h)) - goto fail; - if (b2n_mod (h, h, p)) - goto fail; - if (b2n_square (h, h)) - goto fail; - if (b2n_mod (h, h, p)) - goto fail; - - if (b2n_add (h, h, a)) - goto fail; - } - - B2N_SWAP (ho, h); - - b2n_clear (h); - return 0; - - fail: - b2n_clear (h); - return -1; + int i, m = b2n_sigbit(p) - 1; + b2n_t h; + + b2n_init(h); + if (b2n_set(h, a)) + goto fail; + + for (i = 0; i < (m - 1) / 2; i++) { + if (b2n_square(h, h)) + goto fail; + if (b2n_mod(h, h, p)) + goto fail; + if (b2n_square(h, h)) + goto fail; + if (b2n_mod(h, h, p)) + goto fail; + + if (b2n_add(h, h, a)) + goto fail; + } + + B2N_SWAP(ho, h); + + b2n_clear(h); + return 0; + +fail: + b2n_clear(h); + return -1; } /* @@ -927,111 +892,107 @@ b2n_halftrace (b2n_ptr ho, b2n_ptr a, b2n_ptr p) * irreduceable polynomial. If m is odd, use the half trace. */ int -b2n_sqrt (b2n_ptr zo, b2n_ptr b, b2n_ptr ip) +b2n_sqrt(b2n_ptr zo, b2n_ptr b, b2n_ptr ip) { - int i, m = b2n_sigbit (ip) - 1; - b2n_t w, p, temp, z; - - if (!b2n_cmp_null (b)) - return b2n_set_null (z); - - if (m & 1) - return b2n_halftrace (zo, b, ip); - - b2n_init (z); - b2n_init (w); - b2n_init (p); - b2n_init (temp); - - do - { - if (b2n_random (p, m)) - goto fail; - if (b2n_set_null (z)) - goto fail; - if (b2n_set (w, p)) - goto fail; - - for (i = 1; i < m; i++) - { - if (b2n_square (z, z)) /* z**2 */ - goto fail; - if (b2n_mod (z, z, ip)) - goto fail; - - if (b2n_square (w, w)) /* w**2 */ - goto fail; - if (b2n_mod (w, w, ip)) - goto fail; - - if (b2n_mul (temp, w, b)) /* w**2 * b */ - goto fail; - if (b2n_mod (temp, temp, ip)) - goto fail; - if (b2n_add (z, z, temp)) /* z**2 + w**2 + b */ - goto fail; - - if (b2n_add (w, w, p)) /* w**2 + p */ - goto fail; + int i, m = b2n_sigbit(ip) - 1; + b2n_t w, p, temp, z; + + if (!b2n_cmp_null(b)) + return b2n_set_null(z); + + if (m & 1) + return b2n_halftrace(zo, b, ip); + + b2n_init(z); + b2n_init(w); + b2n_init(p); + b2n_init(temp); + + do { + if (b2n_random(p, m)) + goto fail; + if (b2n_set_null(z)) + goto fail; + if (b2n_set(w, p)) + goto fail; + + for (i = 1; i < m; i++) { + if (b2n_square(z, z)) /* z**2 */ + goto fail; + if (b2n_mod(z, z, ip)) + goto fail; + + if (b2n_square(w, w)) /* w**2 */ + goto fail; + if (b2n_mod(w, w, ip)) + goto fail; + + if (b2n_mul(temp, w, b)) /* w**2 * b */ + goto fail; + if (b2n_mod(temp, temp, ip)) + goto fail; + if (b2n_add(z, z, temp)) /* z**2 + w**2 + b */ + goto fail; + + if (b2n_add(w, w, p)) /* w**2 + p */ + goto fail; + } } - } - while (!b2n_cmp_null (w)); - - B2N_SWAP (zo, z); - - b2n_clear (w); - b2n_clear (p); - b2n_clear (temp); - b2n_clear (z); - return 0; - - fail: - b2n_clear (w); - b2n_clear (p); - b2n_clear (temp); - b2n_clear (z); - return -1; + while (!b2n_cmp_null(w)); + + B2N_SWAP(zo, z); + + b2n_clear(w); + b2n_clear(p); + b2n_clear(temp); + b2n_clear(z); + return 0; + +fail: + b2n_clear(w); + b2n_clear(p); + b2n_clear(temp); + b2n_clear(z); + return -1; } /* Exponentiation modulo a polynomial. */ int -b2n_exp_mod (b2n_ptr d, b2n_ptr b0, u_int32_t e, b2n_ptr p) +b2n_exp_mod(b2n_ptr d, b2n_ptr b0, u_int32_t e, b2n_ptr p) { - b2n_t u, b; - - b2n_init (u); - b2n_init (b); - if (b2n_set_ui (u, 1)) - goto fail; - if (b2n_mod (b, b0, p)) - goto fail; - - while (e) - { - if (e & 1) - { - if (b2n_mul (u, u, b)) - goto fail; - if (b2n_mod (u, u, p)) - goto fail; + b2n_t u, b; + + b2n_init(u); + b2n_init(b); + if (b2n_set_ui(u, 1)) + goto fail; + if (b2n_mod(b, b0, p)) + goto fail; + + while (e) { + if (e & 1) { + if (b2n_mul(u, u, b)) + goto fail; + if (b2n_mod(u, u, p)) + goto fail; + } + if (b2n_square(b, b)) + goto fail; + if (b2n_mod(b, b, p)) + goto fail; + e >>= 1; } - if (b2n_square (b, b)) - goto fail; - if (b2n_mod (b, b, p)) - goto fail; - e >>= 1; - } - - B2N_SWAP (d, u); - - b2n_clear (u); - b2n_clear (b); - return 0; - - fail: - b2n_clear (u); - b2n_clear (b); - return -1; + + B2N_SWAP(d, u); + + b2n_clear(u); + b2n_clear(b); + return 0; + +fail: + b2n_clear(u); + b2n_clear(b); + return -1; } /* @@ -1042,106 +1003,98 @@ b2n_exp_mod (b2n_ptr d, b2n_ptr b0, u_int32_t e, b2n_ptr p) /* Normal addition behaves as Z_{2**n} and not F_{2**n}. */ int -b2n_nadd (b2n_ptr d0, b2n_ptr a0, b2n_ptr b0) +b2n_nadd(b2n_ptr d0, b2n_ptr a0, b2n_ptr b0) { - int i, carry; - b2n_ptr a, b; - b2n_t d; - - if (!b2n_cmp_null (a0)) - return b2n_set (d0, b0); - - if (!b2n_cmp_null (b0)) - return b2n_set (d0, a0); - - b2n_init (d); - a = B2N_MAX (a0, b0); - b = B2N_MIN (a0, b0); - - if (b2n_resize (d, a->chunks + 1)) - { - b2n_clear (d); - return -1; - } - - for (carry = i = 0; i < b->chunks; i++) - { - d->limp[i] = a->limp[i] + b->limp[i] + carry; - carry = (d->limp[i] < a->limp[i] ? 1 : 0); - } - - for (; i < a->chunks && carry; i++) - { - d->limp[i] = a->limp[i] + carry; - carry = (d->limp[i] < a->limp[i] ? 1 : 0); - } - - if (i < a->chunks) - memcpy (d->limp + i, a->limp + i, CHUNK_BYTES * (a->chunks - i)); - - d->dirty = 1; - B2N_SWAP (d0, d); - - b2n_clear (d); - return 0; + int i, carry; + b2n_ptr a, b; + b2n_t d; + + if (!b2n_cmp_null(a0)) + return b2n_set(d0, b0); + + if (!b2n_cmp_null(b0)) + return b2n_set(d0, a0); + + b2n_init(d); + a = B2N_MAX(a0, b0); + b = B2N_MIN(a0, b0); + + if (b2n_resize(d, a->chunks + 1)) { + b2n_clear(d); + return -1; + } + for (carry = i = 0; i < b->chunks; i++) { + d->limp[i] = a->limp[i] + b->limp[i] + carry; + carry = (d->limp[i] < a->limp[i] ? 1 : 0); + } + + for (; i < a->chunks && carry; i++) { + d->limp[i] = a->limp[i] + carry; + carry = (d->limp[i] < a->limp[i] ? 1 : 0); + } + + if (i < a->chunks) + memcpy(d->limp + i, a->limp + i, CHUNK_BYTES * (a->chunks - i)); + + d->dirty = 1; + B2N_SWAP(d0, d); + + b2n_clear(d); + return 0; } /* Very special sub, a > b. */ int -b2n_nsub (b2n_ptr d0, b2n_ptr a, b2n_ptr b) +b2n_nsub(b2n_ptr d0, b2n_ptr a, b2n_ptr b) { - int i, carry; - b2n_t d; - - if (b2n_cmp (a, b) <= 0) - return b2n_set_null (d0); + int i, carry; + b2n_t d; - b2n_init (d); - if (b2n_resize (d, a->chunks)) - { - b2n_clear (d); - return -1; - } + if (b2n_cmp(a, b) <= 0) + return b2n_set_null(d0); - for (carry = i = 0; i < b->chunks; i++) - { - d->limp[i] = a->limp[i] - b->limp[i] - carry; - carry = (d->limp[i] > a->limp[i] ? 1 : 0); - } + b2n_init(d); + if (b2n_resize(d, a->chunks)) { + b2n_clear(d); + return -1; + } + for (carry = i = 0; i < b->chunks; i++) { + d->limp[i] = a->limp[i] - b->limp[i] - carry; + carry = (d->limp[i] > a->limp[i] ? 1 : 0); + } - for (; i < a->chunks && carry; i++) - { - d->limp[i] = a->limp[i] - carry; - carry = (d->limp[i] > a->limp[i] ? 1 : 0); - } + for (; i < a->chunks && carry; i++) { + d->limp[i] = a->limp[i] - carry; + carry = (d->limp[i] > a->limp[i] ? 1 : 0); + } - if (i < a->chunks) - memcpy (d->limp + i, a->limp + i, CHUNK_BYTES*(a->chunks - i)); + if (i < a->chunks) + memcpy(d->limp + i, a->limp + i, CHUNK_BYTES * (a->chunks - i)); - d->dirty = 1; + d->dirty = 1; - B2N_SWAP (d0, d); + B2N_SWAP(d0, d); - b2n_clear (d); - return 0; + b2n_clear(d); + return 0; } int -b2n_3mul (b2n_ptr d0, b2n_ptr e) +b2n_3mul(b2n_ptr d0, b2n_ptr e) { - b2n_t d; + b2n_t d; - b2n_init (d); - if (b2n_lshift (d, e, 1)) - goto fail; + b2n_init(d); + if (b2n_lshift(d, e, 1)) + goto fail; - if (b2n_nadd (d0, d, e)) - goto fail; + if (b2n_nadd(d0, d, e)) + goto fail; - b2n_clear (d); - return 0; + b2n_clear(d); + return 0; - fail: - b2n_clear (d); - return -1; +fail: + b2n_clear(d); + return -1; } diff --git a/sbin/isakmpd/math_2n.h b/sbin/isakmpd/math_2n.h index e8d43835e10..0515199cf59 100644 --- a/sbin/isakmpd/math_2n.h +++ b/sbin/isakmpd/math_2n.h @@ -1,5 +1,5 @@ -/* $OpenBSD: math_2n.h,v 1.6 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: math_2n.h,v 1.9 1999/04/17 23:20:32 niklas Exp $ */ +/* $OpenBSD: math_2n.h,v 1.7 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_2n.h,v 1.9 1999/04/17 23:20:32 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -39,7 +39,7 @@ * XXX - b2n_mask is only up to 32 bit at the moment. */ -#define USE_32BIT /* XXX - This obviously needs fixing */ +#define USE_32BIT /* XXX - This obviously needs fixing */ #ifdef USE_32BIT #define CHUNK_TYPE u_int32_t @@ -64,14 +64,14 @@ extern CHUNK_TYPE b2n_mask[CHUNK_BITS]; /* An element of GF(2**n), n = bits */ typedef struct { - u_int16_t chunks; - u_int16_t bits; - u_int8_t dirty; /* Sig bits are dirty */ - CHUNK_TYPE *limp; -} _b2n; + u_int16_t chunks; + u_int16_t bits; + u_int8_t dirty; /* Sig bits are dirty */ + CHUNK_TYPE *limp; +} _b2n; -typedef _b2n *b2n_ptr; -typedef _b2n b2n_t[1]; +typedef _b2n *b2n_ptr; +typedef _b2n b2n_t[1]; #define B2N_SET(x,y) do \ { \ @@ -95,38 +95,38 @@ while (0) #define B2N_MIN(x,y) ((x)->chunks > (y)->chunks ? (y) : (x)) #define B2N_MAX(x,y) ((x)->chunks > (y)->chunks ? (x) : (y)) -int b2n_3mul (b2n_ptr, b2n_ptr); -int b2n_add (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_cmp (b2n_ptr, b2n_ptr); -int b2n_cmp_null (b2n_ptr); -int b2n_div (b2n_ptr, b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_div_mod (b2n_ptr, b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_div_q (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_div_r (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_exp_mod (b2n_ptr, b2n_ptr, u_int32_t, b2n_ptr); -void b2n_init (b2n_ptr); -void b2n_clear (b2n_ptr); -int b2n_gcd (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_halftrace (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_lshift (b2n_ptr, b2n_ptr, unsigned int); -int b2n_mod (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_mul (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_mul_inv (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_nadd (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_nsub (b2n_ptr, b2n_ptr, b2n_ptr); -void b2n_print (b2n_ptr); -int b2n_random (b2n_ptr, u_int32_t); -int b2n_resize (b2n_ptr, unsigned int); -int b2n_rshift (b2n_ptr, b2n_ptr, unsigned int); -int b2n_set (b2n_ptr, b2n_ptr); -int b2n_set_null (b2n_ptr); -int b2n_set_str (b2n_ptr, char *); -int b2n_set_ui (b2n_ptr, unsigned int); -u_int32_t b2n_sigbit (b2n_ptr); -int b2n_snprint (char *, size_t, b2n_ptr); -int b2n_sqrt (b2n_ptr, b2n_ptr, b2n_ptr); -int b2n_square (b2n_ptr, b2n_ptr); +int b2n_3mul(b2n_ptr, b2n_ptr); +int b2n_add(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_cmp(b2n_ptr, b2n_ptr); +int b2n_cmp_null(b2n_ptr); +int b2n_div(b2n_ptr, b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_div_mod(b2n_ptr, b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_div_q(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_div_r(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_exp_mod(b2n_ptr, b2n_ptr, u_int32_t, b2n_ptr); +void b2n_init(b2n_ptr); +void b2n_clear(b2n_ptr); +int b2n_gcd(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_halftrace(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_lshift(b2n_ptr, b2n_ptr, unsigned int); +int b2n_mod(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_mul(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_mul_inv(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_nadd(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_nsub(b2n_ptr, b2n_ptr, b2n_ptr); +void b2n_print(b2n_ptr); +int b2n_random(b2n_ptr, u_int32_t); +int b2n_resize(b2n_ptr, unsigned int); +int b2n_rshift(b2n_ptr, b2n_ptr, unsigned int); +int b2n_set(b2n_ptr, b2n_ptr); +int b2n_set_null(b2n_ptr); +int b2n_set_str(b2n_ptr, char *); +int b2n_set_ui(b2n_ptr, unsigned int); +u_int32_t b2n_sigbit(b2n_ptr); +int b2n_snprint(char *, size_t, b2n_ptr); +int b2n_sqrt(b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_square(b2n_ptr, b2n_ptr); #define b2n_sub b2n_add -int b2n_trace (b2n_ptr, b2n_ptr, b2n_ptr); +int b2n_trace(b2n_ptr, b2n_ptr, b2n_ptr); -#endif /* _MATH_2N_H_ */ +#endif /* _MATH_2N_H_ */ diff --git a/sbin/isakmpd/math_ec2n.c b/sbin/isakmpd/math_ec2n.c index ce770cfefa7..5843ba1c8b3 100644 --- a/sbin/isakmpd/math_ec2n.c +++ b/sbin/isakmpd/math_ec2n.c @@ -1,5 +1,5 @@ -/* $OpenBSD: math_ec2n.c,v 1.9 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: math_ec2n.c,v 1.9 1999/04/20 09:23:31 niklas Exp $ */ +/* $OpenBSD: math_ec2n.c,v 1.10 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_ec2n.c,v 1.9 1999/04/20 09:23:31 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -39,356 +39,342 @@ #include "math_ec2n.h" void -ec2np_init (ec2np_ptr n) +ec2np_init(ec2np_ptr n) { - b2n_init (n->x); - b2n_init (n->y); - n->inf = 0; + b2n_init(n->x); + b2n_init(n->y); + n->inf = 0; } void -ec2np_clear (ec2np_ptr n) +ec2np_clear(ec2np_ptr n) { - b2n_clear (n->x); - b2n_clear (n->y); + b2n_clear(n->x); + b2n_clear(n->y); } int -ec2np_set (ec2np_ptr d, ec2np_ptr n) +ec2np_set(ec2np_ptr d, ec2np_ptr n) { - if (d == n) - return 0; + if (d == n) + return 0; - d->inf = n->inf; - if (b2n_set (d->x, n->x)) - return -1; - return b2n_set (d->y, n->y); + d->inf = n->inf; + if (b2n_set(d->x, n->x)) + return -1; + return b2n_set(d->y, n->y); } /* Group */ void -ec2ng_init (ec2ng_ptr n) +ec2ng_init(ec2ng_ptr n) { - b2n_init (n->a); - b2n_init (n->b); - b2n_init (n->p); + b2n_init(n->a); + b2n_init(n->b); + b2n_init(n->p); } void -ec2ng_clear (ec2ng_ptr n) +ec2ng_clear(ec2ng_ptr n) { - b2n_clear (n->a); - b2n_clear (n->b); - b2n_clear (n->p); + b2n_clear(n->a); + b2n_clear(n->b); + b2n_clear(n->p); } int -ec2ng_set (ec2ng_ptr d, ec2ng_ptr n) +ec2ng_set(ec2ng_ptr d, ec2ng_ptr n) { - if (b2n_set (d->a, n->a)) - return -1; - if (b2n_set (d->b, n->b)) - return -1; - return b2n_set (d->p, n->p); + if (b2n_set(d->a, n->a)) + return -1; + if (b2n_set(d->b, n->b)) + return -1; + return b2n_set(d->p, n->p); } /* Arithmetic functions */ int -ec2np_right (b2n_ptr n, ec2np_ptr p, ec2ng_ptr g) +ec2np_right(b2n_ptr n, ec2np_ptr p, ec2ng_ptr g) { - b2n_t temp; + b2n_t temp; - b2n_init (temp); + b2n_init(temp); - /* First calc x**3 + ax**2 + b */ - if (b2n_square (n, p->x)) - goto fail; - if (b2n_mod (n, n, g->p)) - goto fail; + /* First calc x**3 + ax**2 + b */ + if (b2n_square(n, p->x)) + goto fail; + if (b2n_mod(n, n, g->p)) + goto fail; - if (b2n_mul (temp, g->a, n)) /* a*x**2 */ - goto fail; - if (b2n_mod (temp, temp, g->p)) - goto fail; + if (b2n_mul(temp, g->a, n)) /* a*x**2 */ + goto fail; + if (b2n_mod(temp, temp, g->p)) + goto fail; - if (b2n_mul (n, n, p->x)) /* x**3 */ - goto fail; - if (b2n_mod (n, n, g->p)) - goto fail; + if (b2n_mul(n, n, p->x))/* x**3 */ + goto fail; + if (b2n_mod(n, n, g->p)) + goto fail; - if (b2n_add (n, n, temp)) - goto fail; - if (b2n_add (n, n, g->b)) - goto fail; + if (b2n_add(n, n, temp)) + goto fail; + if (b2n_add(n, n, g->b)) + goto fail; - b2n_clear (temp); - return 0; + b2n_clear(temp); + return 0; - fail: - b2n_clear (temp); - return -1; +fail: + b2n_clear(temp); + return -1; } int -ec2np_ison (ec2np_ptr p, ec2ng_ptr g) +ec2np_ison(ec2np_ptr p, ec2ng_ptr g) { - int res; + int res; - b2n_t x, y, temp; + b2n_t x, y, temp; - if (p->inf) - return 1; + if (p->inf) + return 1; - b2n_init (x); - b2n_init (y); - b2n_init (temp); + b2n_init(x); + b2n_init(y); + b2n_init(temp); - /* First calc x**3 + ax**2 + b */ - if (ec2np_right (x, p, g)) - goto fail; + /* First calc x**3 + ax**2 + b */ + if (ec2np_right(x, p, g)) + goto fail; - /* Now calc y**2 + xy */ - if (b2n_square (y, p->y)) - goto fail; - if (b2n_mod (y, y, g->p)) - goto fail; + /* Now calc y**2 + xy */ + if (b2n_square(y, p->y)) + goto fail; + if (b2n_mod(y, y, g->p)) + goto fail; - if (b2n_mul (temp, p->y, p->x)) - goto fail; - if (b2n_mod (temp, temp, g->p)) - goto fail; + if (b2n_mul(temp, p->y, p->x)) + goto fail; + if (b2n_mod(temp, temp, g->p)) + goto fail; - if (b2n_add (y, y, temp)) - goto fail; + if (b2n_add(y, y, temp)) + goto fail; - res = !b2n_cmp (x, y); + res = !b2n_cmp(x, y); - b2n_clear (x); - b2n_clear (y); - b2n_clear (temp); - return res; + b2n_clear(x); + b2n_clear(y); + b2n_clear(temp); + return res; - fail: - b2n_clear (x); - b2n_clear (y); - b2n_clear (temp); - return -1; +fail: + b2n_clear(x); + b2n_clear(y); + b2n_clear(temp); + return -1; } int -ec2np_find_y (ec2np_ptr p, ec2ng_ptr g) +ec2np_find_y(ec2np_ptr p, ec2ng_ptr g) { - b2n_t right; - - b2n_init (right); - - if (ec2np_right (right, p, g)) /* Right sight of equation */ - goto fail; - if (b2n_mul_inv (p->y, p->x, g->p)) - goto fail; - - if (b2n_square (p->y, p->y)) - goto fail; - if (b2n_mod (p->y, p->y, g->p)) - goto fail; - - if (b2n_mul (right, right, p->y)) /* x^-2 * right */ - goto fail; - if (b2n_mod (right, right, g->p)) - goto fail; - - if (b2n_sqrt (p->y, right, g->p)) /* Find root */ - goto fail; - if (b2n_mul (p->y, p->y, p->x)) - goto fail; - if (b2n_mod (p->y, p->y, g->p)) - goto fail; - - b2n_clear (right); - return 0; - - fail: - b2n_clear (right); - return -1; + b2n_t right; + + b2n_init(right); + + if (ec2np_right(right, p, g)) /* Right sight of equation */ + goto fail; + if (b2n_mul_inv(p->y, p->x, g->p)) + goto fail; + + if (b2n_square(p->y, p->y)) + goto fail; + if (b2n_mod(p->y, p->y, g->p)) + goto fail; + + if (b2n_mul(right, right, p->y)) /* x^-2 * right */ + goto fail; + if (b2n_mod(right, right, g->p)) + goto fail; + + if (b2n_sqrt(p->y, right, g->p)) /* Find root */ + goto fail; + if (b2n_mul(p->y, p->y, p->x)) + goto fail; + if (b2n_mod(p->y, p->y, g->p)) + goto fail; + + b2n_clear(right); + return 0; + +fail: + b2n_clear(right); + return -1; } int -ec2np_add (ec2np_ptr d, ec2np_ptr a, ec2np_ptr b, ec2ng_ptr g) +ec2np_add(ec2np_ptr d, ec2np_ptr a, ec2np_ptr b, ec2ng_ptr g) { - b2n_t lambda, temp; - ec2np_t pn; - - /* Check for Neutral Element */ - if (b->inf) - return ec2np_set (d, a); - if (a->inf) - return ec2np_set (d, b); - - if (!b2n_cmp (a->x, b->x) && (b2n_cmp (a->y, b->y) || !b2n_cmp_null (a->x))) - { - d->inf = 1; - if (b2n_set_null (d->x)) + b2n_t lambda, temp; + ec2np_t pn; + + /* Check for Neutral Element */ + if (b->inf) + return ec2np_set(d, a); + if (a->inf) + return ec2np_set(d, b); + + if (!b2n_cmp(a->x, b->x) && (b2n_cmp(a->y, b->y) || !b2n_cmp_null(a->x))) { + d->inf = 1; + if (b2n_set_null(d->x)) + return -1; + return b2n_set_null(d->y); + } + b2n_init(lambda); + b2n_init(temp); + ec2np_init(pn); + + if (b2n_cmp(a->x, b->x)) { + if (b2n_add(temp, a->x, b->x)) + goto fail; + if (b2n_add(lambda, a->y, b->y)) + goto fail; + if (b2n_div_mod(lambda, lambda, temp, g->p)) + goto fail; + + if (b2n_square(pn->x, lambda)) + goto fail; + if (b2n_mod(pn->x, pn->x, g->p)) + goto fail; + + if (b2n_add(pn->x, pn->x, lambda)) + goto fail; + if (b2n_add(pn->x, pn->x, g->a)) + goto fail; + if (b2n_add(pn->x, pn->x, a->x)) + goto fail; + if (b2n_add(pn->x, pn->x, b->x)) + goto fail; + } else { + if (b2n_div_mod(lambda, b->y, b->x, g->p)) + goto fail; + if (b2n_add(lambda, lambda, b->x)) + goto fail; + + if (b2n_square(pn->x, lambda)) + goto fail; + if (b2n_mod(pn->x, pn->x, g->p)) + goto fail; + if (b2n_add(pn->x, pn->x, lambda)) + goto fail; + if (b2n_add(pn->x, pn->x, g->a)) + goto fail; + } + + if (b2n_add(pn->y, b->x, pn->x)) + goto fail; + + if (b2n_mul(pn->y, pn->y, lambda)) + goto fail; + if (b2n_mod(pn->y, pn->y, g->p)) + goto fail; + + if (b2n_add(pn->y, pn->y, pn->x)) + goto fail; + if (b2n_add(pn->y, pn->y, b->y)) + goto fail; + + EC2NP_SWAP(d, pn); + + ec2np_clear(pn); + b2n_clear(lambda); + b2n_clear(temp); + return 0; + +fail: + ec2np_clear(pn); + b2n_clear(lambda); + b2n_clear(temp); return -1; - return b2n_set_null (d->y); - } - - b2n_init (lambda); - b2n_init (temp); - ec2np_init (pn); - - if (b2n_cmp (a->x, b->x)) - { - if (b2n_add (temp, a->x, b->x)) - goto fail; - if (b2n_add (lambda, a->y, b->y)) - goto fail; - if (b2n_div_mod (lambda, lambda, temp, g->p)) - goto fail; - - if (b2n_square (pn->x, lambda)) - goto fail; - if (b2n_mod (pn->x, pn->x, g->p)) - goto fail; - - if (b2n_add (pn->x, pn->x, lambda)) - goto fail; - if (b2n_add (pn->x, pn->x, g->a)) - goto fail; - if (b2n_add (pn->x, pn->x, a->x)) - goto fail; - if (b2n_add (pn->x, pn->x, b->x)) - goto fail; - } - else - { - if (b2n_div_mod (lambda, b->y, b->x, g->p)) - goto fail; - if (b2n_add (lambda, lambda, b->x)) - goto fail; - - if (b2n_square (pn->x, lambda)) - goto fail; - if (b2n_mod (pn->x, pn->x, g->p)) - goto fail; - if (b2n_add (pn->x, pn->x, lambda)) - goto fail; - if (b2n_add (pn->x, pn->x, g->a)) - goto fail; - } - - if (b2n_add (pn->y, b->x, pn->x)) - goto fail; - - if (b2n_mul (pn->y, pn->y, lambda)) - goto fail; - if (b2n_mod (pn->y, pn->y, g->p)) - goto fail; - - if (b2n_add (pn->y, pn->y, pn->x)) - goto fail; - if (b2n_add (pn->y, pn->y, b->y)) - goto fail; - - EC2NP_SWAP (d, pn); - - ec2np_clear (pn); - b2n_clear (lambda); - b2n_clear (temp); - return 0; - - fail: - ec2np_clear (pn); - b2n_clear (lambda); - b2n_clear (temp); - return -1; } int -ec2np_mul (ec2np_ptr d, ec2np_ptr a, b2n_ptr e, ec2ng_ptr g) +ec2np_mul(ec2np_ptr d, ec2np_ptr a, b2n_ptr e, ec2ng_ptr g) { - int i, j, bits, start; - b2n_t h, k; - ec2np_t q, mina; - - if (!b2n_cmp_null (e)) - { - d->inf = 1; - if (b2n_set_null (d->x)) - return -1; - return b2n_set_null (d->y); - } - - b2n_init (h); - b2n_init (k); - ec2np_init (q); - ec2np_init (mina); - - if (ec2np_set (q, a)) - goto fail; - - /* Create the point -a. */ - if (ec2np_set (mina, a)) - goto fail; - if (b2n_add (mina->y, mina->y, mina->x)) - goto fail; - - if (b2n_set (k, e)) - goto fail; - if (b2n_3mul (h, k)) - goto fail; - if (b2n_resize (k, h->chunks)) - goto fail; - - /* - * This is low level but can not be avoided, since we have to do single - * bit checks on h and k. - */ - bits = b2n_sigbit (h); - if ((bits & CHUNK_MASK) == 1) - { - start = ((CHUNK_MASK + bits) >> CHUNK_SHIFTS) - 2; - bits = CHUNK_BITS; - } - else - { - start = ((CHUNK_MASK + bits) >> CHUNK_SHIFTS) - 1; - bits = ((bits - 1) & CHUNK_MASK); - } - - /* - * This is the addition, subtraction method which is faster because - * we avoid one out of three additions (mean). - */ - for (i = start; i >= 0; i--) - for (j = (i == start ? bits : CHUNK_BITS) - 1; j >= 0; j--) - if (i > 0 || j > 0) - { - if (ec2np_add (q, q, q, g)) - goto fail; - if ((h->limp[i] & b2n_mask[j]) && !(k->limp[i] & b2n_mask[j])) - { - if (ec2np_add (q, q, a, g)) - goto fail; - } - else if (!(h->limp[i] & b2n_mask[j]) && (k->limp[i] & b2n_mask[j])) - if (ec2np_add (q, q, mina, g)) - goto fail; + int i, j, bits, start; + b2n_t h, k; + ec2np_t q, mina; + + if (!b2n_cmp_null(e)) { + d->inf = 1; + if (b2n_set_null(d->x)) + return -1; + return b2n_set_null(d->y); } + b2n_init(h); + b2n_init(k); + ec2np_init(q); + ec2np_init(mina); + + if (ec2np_set(q, a)) + goto fail; + + /* Create the point -a. */ + if (ec2np_set(mina, a)) + goto fail; + if (b2n_add(mina->y, mina->y, mina->x)) + goto fail; - EC2NP_SWAP (d, q); + if (b2n_set(k, e)) + goto fail; + if (b2n_3mul(h, k)) + goto fail; + if (b2n_resize(k, h->chunks)) + goto fail; - b2n_clear (k); - b2n_clear (h); - ec2np_clear (q); - ec2np_clear (mina); - return 0; + /* + * This is low level but can not be avoided, since we have to do single + * bit checks on h and k. + */ + bits = b2n_sigbit(h); + if ((bits & CHUNK_MASK) == 1) { + start = ((CHUNK_MASK + bits) >> CHUNK_SHIFTS) - 2; + bits = CHUNK_BITS; + } else { + start = ((CHUNK_MASK + bits) >> CHUNK_SHIFTS) - 1; + bits = ((bits - 1) & CHUNK_MASK); + } - fail: - b2n_clear (k); - b2n_clear (h); - ec2np_clear (q); - ec2np_clear (mina); - return -1; + /* + * This is the addition, subtraction method which is faster because + * we avoid one out of three additions (mean). + */ + for (i = start; i >= 0; i--) + for (j = (i == start ? bits : CHUNK_BITS) - 1; j >= 0; j--) + if (i > 0 || j > 0) { + if (ec2np_add(q, q, q, g)) + goto fail; + if ((h->limp[i] & b2n_mask[j]) && !(k->limp[i] & b2n_mask[j])) { + if (ec2np_add(q, q, a, g)) + goto fail; + } else if (!(h->limp[i] & b2n_mask[j]) && (k->limp[i] & b2n_mask[j])) + if (ec2np_add(q, q, mina, g)) + goto fail; + } + EC2NP_SWAP(d, q); + + b2n_clear(k); + b2n_clear(h); + ec2np_clear(q); + ec2np_clear(mina); + return 0; + +fail: + b2n_clear(k); + b2n_clear(h); + ec2np_clear(q); + ec2np_clear(mina); + return -1; } diff --git a/sbin/isakmpd/math_ec2n.h b/sbin/isakmpd/math_ec2n.h index dbd360f7ace..078eb4b19d9 100644 --- a/sbin/isakmpd/math_ec2n.h +++ b/sbin/isakmpd/math_ec2n.h @@ -1,5 +1,5 @@ -/* $OpenBSD: math_ec2n.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: math_ec2n.h,v 1.4 1999/04/17 23:20:37 niklas Exp $ */ +/* $OpenBSD: math_ec2n.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_ec2n.h,v 1.4 1999/04/17 23:20:37 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -35,9 +35,9 @@ /* Definitions for points on an elliptic curve */ typedef struct { - int inf; /* Are we the point at infinity ? */ - b2n_t x, y; -} _ec2n_point; + int inf; /* Are we the point at infinity ? */ + b2n_t x, y; +} _ec2n_point; typedef _ec2n_point *ec2np_ptr; typedef _ec2n_point ec2np_t[1]; @@ -54,9 +54,9 @@ typedef _ec2n_point ec2np_t[1]; } \ while (0) -void ec2np_init (ec2np_ptr); -void ec2np_clear (ec2np_ptr); -int ec2np_set (ec2np_ptr, ec2np_ptr); +void ec2np_init(ec2np_ptr); +void ec2np_clear(ec2np_ptr); +int ec2np_set(ec2np_ptr, ec2np_ptr); #define ec2np_set_x_ui(n, y) b2n_set_ui ((n)->x, y) #define ec2np_set_y_ui(n, x) b2n_set_ui ((n)->y, x) @@ -66,15 +66,15 @@ int ec2np_set (ec2np_ptr, ec2np_ptr); /* Definitions for the group to which the points to belong to. */ typedef struct { - b2n_t a, b, p; -} _ec2n_group; + b2n_t a, b, p; +} _ec2n_group; typedef _ec2n_group *ec2ng_ptr; typedef _ec2n_group ec2ng_t[1]; -void ec2ng_init (ec2ng_ptr); -void ec2ng_clear (ec2ng_ptr); -int ec2ng_set (ec2ng_ptr, ec2ng_ptr); +void ec2ng_init(ec2ng_ptr); +void ec2ng_clear(ec2ng_ptr); +int ec2ng_set(ec2ng_ptr, ec2ng_ptr); #define ec2ng_set_a_ui(n, x) b2n_set_ui ((n)->a, x) #define ec2ng_set_b_ui(n, x) b2n_set_ui ((n)->b, x) @@ -85,10 +85,10 @@ int ec2ng_set (ec2ng_ptr, ec2ng_ptr); /* Functions for computing on the elliptic group. */ -int ec2np_add (ec2np_ptr, ec2np_ptr, ec2np_ptr, ec2ng_ptr); -int ec2np_find_y (ec2np_ptr, ec2ng_ptr); -int ec2np_ison (ec2np_ptr, ec2ng_ptr); -int ec2np_mul (ec2np_ptr, ec2np_ptr, b2n_ptr, ec2ng_ptr); -int ec2np_right (b2n_ptr n, ec2np_ptr, ec2ng_ptr); +int ec2np_add(ec2np_ptr, ec2np_ptr, ec2np_ptr, ec2ng_ptr); +int ec2np_find_y(ec2np_ptr, ec2ng_ptr); +int ec2np_ison(ec2np_ptr, ec2ng_ptr); +int ec2np_mul(ec2np_ptr, ec2np_ptr, b2n_ptr, ec2ng_ptr); +int ec2np_right(b2n_ptr n, ec2np_ptr, ec2ng_ptr); -#endif /* _MATH_2N_H_ */ +#endif /* _MATH_2N_H_ */ diff --git a/sbin/isakmpd/math_group.c b/sbin/isakmpd/math_group.c index 4339dad392e..124a58b97d1 100644 --- a/sbin/isakmpd/math_group.c +++ b/sbin/isakmpd/math_group.c @@ -1,5 +1,5 @@ -/* $OpenBSD: math_group.c,v 1.20 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: math_group.c,v 1.25 2000/04/07 19:53:26 niklas Exp $ */ +/* $OpenBSD: math_group.c,v 1.21 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_group.c,v 1.25 2000/04/07 19:53:26 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -44,28 +44,28 @@ #include "math_mp.h" /* We do not want to export these definitions. */ -int modp_getlen (struct group *); -void modp_getraw (struct group *, math_mp_t, u_int8_t *); -int modp_setraw (struct group *, math_mp_t, u_int8_t *, int); -int modp_setrandom (struct group *, math_mp_t); -int modp_operation (struct group *, math_mp_t, math_mp_t, math_mp_t); - -int ec2n_getlen (struct group *); -void ec2n_getraw (struct group *, ec2np_ptr, u_int8_t *); -int ec2n_setraw (struct group *, ec2np_ptr, u_int8_t *, int); -int ec2n_setrandom (struct group *, ec2np_ptr); -int ec2n_operation (struct group *, ec2np_ptr, ec2np_ptr, ec2np_ptr); +int modp_getlen(struct group *); +void modp_getraw(struct group *, math_mp_t, u_int8_t *); +int modp_setraw(struct group *, math_mp_t, u_int8_t *, int); +int modp_setrandom(struct group *, math_mp_t); +int modp_operation(struct group *, math_mp_t, math_mp_t, math_mp_t); + +int ec2n_getlen(struct group *); +void ec2n_getraw(struct group *, ec2np_ptr, u_int8_t *); +int ec2n_setraw(struct group *, ec2np_ptr, u_int8_t *, int); +int ec2n_setrandom(struct group *, ec2np_ptr); +int ec2n_operation(struct group *, ec2np_ptr, ec2np_ptr, ec2np_ptr); struct ec2n_group { - ec2np_t gen; /* Generator */ - ec2ng_t grp; - ec2np_t a, b, c, d; + ec2np_t gen; /* Generator */ + ec2ng_t grp; + ec2np_t a, b, c, d; }; struct modp_group { - math_mp_t gen; /* Generator */ - math_mp_t p; /* Prime */ - math_mp_t a, b, c, d; + math_mp_t gen; /* Generator */ + math_mp_t p; /* Prime */ + math_mp_t a, b, c, d; }; /* @@ -102,172 +102,173 @@ struct modp_group { struct modp_dscr oakley_modp[] = { - { OAKLEY_GRP_1, 72, /* This group is insecure, only sufficient for DES */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_2, 82, /* This group is a bit better */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" - "FFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_5, 102, - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_14, 135, /* 2048 bit */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AACAA68FFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_15, 170, /* 3072 bit */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_16, 195, /* 4096 bit */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" - "FFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_17, 220, /* 6144 bit */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" - "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" - "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" - "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" - "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" - "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" - "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" - "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" - "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" - "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" - "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" - "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF", - "0x02" - }, - { OAKLEY_GRP_18, 250, /* 8192 bit */ - "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" - "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" - "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" - "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" - "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" - "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" - "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" - "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" - "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" - "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" - "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" - "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" - "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" - "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" - "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" - "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" - "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" - "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" - "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" - "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" - "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" - "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" - "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", - "0x02" - }, + {OAKLEY_GRP_1, 72, /* This group is insecure, only sufficient + * for DES */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_2, 82, /* This group is a bit better */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" + "FFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_5, 102, + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_14, 135, /* 2048 bit */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_15, 170, /* 3072 bit */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_16, 195, /* 4096 bit */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_17, 220, /* 6144 bit */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF", + "0x02" + }, + {OAKLEY_GRP_18, 250, /* 8192 bit */ + "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", + "0x02" + }, }; #ifdef USE_EC @@ -279,139 +280,140 @@ struct modp_dscr oakley_modp[] = */ struct ec2n_dscr oakley_ec2n[] = { - { OAKLEY_GRP_3, 76, /* This group is also considered insecure (P1363) */ - "0x0800000000000000000000004000000000000001", - "0x7b", - "0x00", - "0x7338f" }, - { OAKLEY_GRP_4, 91, - "0x020000000000000000000000000000200000000000000001", - "0x18", - "0x00", - "0x1ee9" }, + {OAKLEY_GRP_3, 76, /* This group is also considered insecure + * (P1363) */ + "0x0800000000000000000000004000000000000001", + "0x7b", + "0x00", + "0x7338f"}, + {OAKLEY_GRP_4, 91, + "0x020000000000000000000000000000200000000000000001", + "0x18", + "0x00", + "0x1ee9"}, }; -#endif /* USE_EC */ +#endif /* USE_EC */ /* XXX I want to get rid of the casting here. */ -struct group groups[] = { - { - MODP, OAKLEY_GRP_1, 0, &oakley_modp[0], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, - { - MODP, OAKLEY_GRP_2, 0, &oakley_modp[1], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, +struct group groups[] = { + { + MODP, OAKLEY_GRP_1, 0, &oakley_modp[0], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, + { + MODP, OAKLEY_GRP_2, 0, &oakley_modp[1], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, #ifdef USE_EC - { - EC2N, OAKLEY_GRP_3, 0, &oakley_ec2n[0], 0, 0, 0, 0, 0, - (int (*) (struct group *))ec2n_getlen, - (void (*) (struct group *, void *, u_int8_t *))ec2n_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))ec2n_setraw, - (int (*) (struct group *, void *))ec2n_setrandom, - (int (*) (struct group *, void *, void *, void *))ec2n_operation - }, - { - EC2N, OAKLEY_GRP_4, 0, &oakley_ec2n[1], 0, 0, 0, 0, 0, - (int (*) (struct group *))ec2n_getlen, - (void (*) (struct group *, void *, u_int8_t *))ec2n_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))ec2n_setraw, - (int (*) (struct group *, void *))ec2n_setrandom, - (int (*) (struct group *, void *, void *, void *))ec2n_operation - }, -#endif /* USE_EC */ - { - MODP, OAKLEY_GRP_5, 0, &oakley_modp[2], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, + { + EC2N, OAKLEY_GRP_3, 0, &oakley_ec2n[0], 0, 0, 0, 0, 0, + (int (*) (struct group *)) ec2n_getlen, + (void (*) (struct group *, void *, u_int8_t *)) ec2n_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) ec2n_setraw, + (int (*) (struct group *, void *)) ec2n_setrandom, + (int (*) (struct group *, void *, void *, void *)) ec2n_operation + }, + { + EC2N, OAKLEY_GRP_4, 0, &oakley_ec2n[1], 0, 0, 0, 0, 0, + (int (*) (struct group *)) ec2n_getlen, + (void (*) (struct group *, void *, u_int8_t *)) ec2n_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) ec2n_setraw, + (int (*) (struct group *, void *)) ec2n_setrandom, + (int (*) (struct group *, void *, void *, void *)) ec2n_operation + }, +#endif /* USE_EC */ + { + MODP, OAKLEY_GRP_5, 0, &oakley_modp[2], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, #ifdef USE_EC - /* XXX Higher EC2N group go here... */ -#endif /* USE_EC */ - /* XXX group 6 to 13 are not yet defined (draft-ike-ecc) */ - { - NOTYET, OAKLEY_GRP_6, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_7, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_8, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_9, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_10, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_11, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_12, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - NOTYET, OAKLEY_GRP_13, 0, NULL, 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL, NULL - }, - { - MODP, OAKLEY_GRP_14, 0, &oakley_modp[3], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, - { - MODP, OAKLEY_GRP_15, 0, &oakley_modp[4], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, - { - MODP, OAKLEY_GRP_16, 0, &oakley_modp[5], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, - { - MODP, OAKLEY_GRP_17, 0, &oakley_modp[6], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, - { - MODP, OAKLEY_GRP_18, 0, &oakley_modp[7], 0, 0, 0, 0, 0, - (int (*) (struct group *))modp_getlen, - (void (*) (struct group *, void *, u_int8_t *))modp_getraw, - (int (*) (struct group *, void *, u_int8_t *, int))modp_setraw, - (int (*) (struct group *, void *))modp_setrandom, - (int (*) (struct group *, void *, void *, void *))modp_operation - }, + /* XXX Higher EC2N group go here... */ +#endif /* USE_EC */ + /* XXX group 6 to 13 are not yet defined (draft-ike-ecc) */ + { + NOTYET, OAKLEY_GRP_6, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_7, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_8, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_9, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_10, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_11, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_12, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + NOTYET, OAKLEY_GRP_13, 0, NULL, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL + }, + { + MODP, OAKLEY_GRP_14, 0, &oakley_modp[3], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, + { + MODP, OAKLEY_GRP_15, 0, &oakley_modp[4], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, + { + MODP, OAKLEY_GRP_16, 0, &oakley_modp[5], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, + { + MODP, OAKLEY_GRP_17, 0, &oakley_modp[6], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, + { + MODP, OAKLEY_GRP_18, 0, &oakley_modp[7], 0, 0, 0, 0, 0, + (int (*) (struct group *)) modp_getlen, + (void (*) (struct group *, void *, u_int8_t *)) modp_getraw, + (int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw, + (int (*) (struct group *, void *)) modp_setrandom, + (int (*) (struct group *, void *, void *, void *)) modp_operation + }, }; /* @@ -420,437 +422,421 @@ struct group groups[] = { * and converting them to their native representation. */ void -group_init (void) +group_init(void) { - int i; + int i; - for (i = sizeof (groups) / sizeof (groups[0]) - 1; i >= 0; i--) - switch (groups[i].type) - { + for (i = sizeof(groups) / sizeof(groups[0]) - 1; i >= 0; i--) + switch (groups[i].type) { #ifdef USE_EC - case EC2N: /* Initialize an Elliptic Curve over GF(2**n) */ - ec2n_init (&groups[i]); - break; + case EC2N: /* Initialize an Elliptic Curve over GF(2**n) */ + ec2n_init(&groups[i]); + break; #endif - case MODP: /* Initialize an over GF(p) */ - modp_init (&groups[i]); - break; - - case NOTYET: /* Not yet assigned, drop silently */ - break; - - default: - log_print ("Unknown group type %d at index %d in group_init().", - groups[i].type, i); - break; - } -} + case MODP: /* Initialize an over GF(p) */ + modp_init(&groups[i]); + break; -struct group * -group_get (u_int32_t id) -{ - struct group *new, *clone; + case NOTYET: /* Not yet assigned, drop silently */ + break; - if (id < 1 || id > (sizeof (groups) / sizeof (groups[0]))) - { - log_print ("group_get: group ID (%u) out of range", id); - return 0; - } + default: + log_print("Unknown group type %d at index %d in group_init().", + groups[i].type, i); + break; + } +} - clone = &groups[id - 1]; +struct group * +group_get(u_int32_t id) +{ + struct group *new, *clone; - new = malloc (sizeof *new); - if (!new) - { - log_error ("group_get: malloc (%lu) failed", (unsigned long)sizeof *new); - return 0; - } + if (id < 1 || id > (sizeof(groups) / sizeof(groups[0]))) { + log_print("group_get: group ID (%u) out of range", id); + return 0; + } + clone = &groups[id - 1]; - switch (clone->type) - { + new = malloc(sizeof *new); + if (!new) { + log_error("group_get: malloc (%lu) failed", (unsigned long) sizeof *new); + return 0; + } + switch (clone->type) { #ifdef USE_EC - case EC2N: - new = ec2n_clone (new, clone); - break; + case EC2N: + new = ec2n_clone(new, clone); + break; #endif - case MODP: - new = modp_clone (new, clone); - break; - default: - log_print ("group_get: unknown group type %d", clone->type); - free (new); - return 0; - } - LOG_DBG ((LOG_MISC, 70, "group_get: returning %p of group %d", new, - new->id)); - return new; + case MODP: + new = modp_clone(new, clone); + break; + default: + log_print("group_get: unknown group type %d", clone->type); + free(new); + return 0; + } + LOG_DBG((LOG_MISC, 70, "group_get: returning %p of group %d", new, + new->id)); + return new; } void -group_free (struct group *grp) +group_free(struct group * grp) { - switch (grp->type) - { + switch (grp->type) { #ifdef USE_EC - case EC2N: - ec2n_free (grp); - break; + case EC2N: + ec2n_free(grp); + break; #endif - case MODP: - modp_free (grp); - break; - default: - log_print ("group_free: unknown group type %d", grp->type); - break; - } - free (grp); + case MODP: + modp_free(grp); + break; + default: + log_print("group_free: unknown group type %d", grp->type); + break; + } + free(grp); } -struct group * -modp_clone (struct group *new, struct group *clone) +struct group * +modp_clone(struct group * new, struct group * clone) { - struct modp_group *new_grp, *clone_grp = clone->group; - - new_grp = malloc (sizeof *new_grp); - if (!new_grp) - { - log_print ("modp_clone: malloc (%lu) failed", - (unsigned long)sizeof *new_grp); - free (new); - return 0; - } - - memcpy (new, clone, sizeof (struct group)); + struct modp_group *new_grp, *clone_grp = clone->group; + + new_grp = malloc(sizeof *new_grp); + if (!new_grp) { + log_print("modp_clone: malloc (%lu) failed", + (unsigned long) sizeof *new_grp); + free(new); + return 0; + } + memcpy(new, clone, sizeof(struct group)); - new->group = new_grp; + new->group = new_grp; #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_init_set (new_grp->p, clone_grp->p); - mpz_init_set (new_grp->gen, clone_grp->gen); + mpz_init_set(new_grp->p, clone_grp->p); + mpz_init_set(new_grp->gen, clone_grp->gen); - mpz_init (new_grp->a); - mpz_init (new_grp->b); - mpz_init (new_grp->c); + mpz_init(new_grp->a); + mpz_init(new_grp->b); + mpz_init(new_grp->c); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - new_grp->p = BN_dup (clone_grp->p); - new_grp->gen = BN_dup (clone_grp->gen); + new_grp->p = BN_dup(clone_grp->p); + new_grp->gen = BN_dup(clone_grp->gen); - new_grp->a = BN_new (); - new_grp->b = BN_new (); - new_grp->c = BN_new (); + new_grp->a = BN_new(); + new_grp->b = BN_new(); + new_grp->c = BN_new(); #endif - new->gen = new_grp->gen; - new->a = new_grp->a; - new->b = new_grp->b; - new->c = new_grp->c; + new->gen = new_grp->gen; + new->a = new_grp->a; + new->b = new_grp->b; + new->c = new_grp->c; - return new; + return new; } void -modp_free (struct group *old) +modp_free(struct group * old) { - struct modp_group *grp = old->group; + struct modp_group *grp = old->group; #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_clear (grp->p); - mpz_clear (grp->gen); - mpz_clear (grp->a); - mpz_clear (grp->b); - mpz_clear (grp->c); + mpz_clear(grp->p); + mpz_clear(grp->gen); + mpz_clear(grp->a); + mpz_clear(grp->b); + mpz_clear(grp->c); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - BN_clear_free (grp->p); - BN_clear_free (grp->gen); - BN_clear_free (grp->a); - BN_clear_free (grp->b); - BN_clear_free (grp->c); + BN_clear_free(grp->p); + BN_clear_free(grp->gen); + BN_clear_free(grp->a); + BN_clear_free(grp->b); + BN_clear_free(grp->c); #endif - free (grp); + free(grp); } void -modp_init (struct group *group) +modp_init(struct group * group) { - struct modp_dscr *dscr = (struct modp_dscr *)group->group; - struct modp_group *grp; + struct modp_dscr *dscr = (struct modp_dscr *) group->group; + struct modp_group *grp; - grp = malloc (sizeof *grp); - if (!grp) - log_fatal ("modp_init: malloc (%lu) failed", (unsigned long)sizeof *grp); + grp = malloc(sizeof *grp); + if (!grp) + log_fatal("modp_init: malloc (%lu) failed", (unsigned long) sizeof *grp); - group->bits = dscr->bits; + group->bits = dscr->bits; #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_init_set_str (grp->p, dscr->prime, 0); - mpz_init_set_str (grp->gen, dscr->gen, 0); + mpz_init_set_str(grp->p, dscr->prime, 0); + mpz_init_set_str(grp->gen, dscr->gen, 0); - mpz_init (grp->a); - mpz_init (grp->b); - mpz_init (grp->c); + mpz_init(grp->a); + mpz_init(grp->b); + mpz_init(grp->c); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - grp->p = BN_new (); - BN_hex2bn (&grp->p, dscr->prime + 2); - grp->gen = BN_new (); - BN_hex2bn (&grp->gen, dscr->gen + 2); - - grp->a = BN_new (); - grp->b = BN_new (); - grp->c = BN_new (); + grp->p = BN_new(); + BN_hex2bn(&grp->p, dscr->prime + 2); + grp->gen = BN_new(); + BN_hex2bn(&grp->gen, dscr->gen + 2); + + grp->a = BN_new(); + grp->b = BN_new(); + grp->c = BN_new(); #endif - group->gen = grp->gen; - group->a = grp->a; - group->b = grp->b; - group->c = grp->c; + group->gen = grp->gen; + group->a = grp->a; + group->b = grp->b; + group->c = grp->c; - group->group = grp; + group->group = grp; } #ifdef USE_EC -struct group * -ec2n_clone (struct group *new, struct group *clone) +struct group * +ec2n_clone(struct group * new, struct group * clone) { - struct ec2n_group *new_grp, *clone_grp = clone->group; - - new_grp = malloc (sizeof *new_grp); - if (!new_grp) - { - log_error ("ec2n_clone: malloc (%lu) failed", - (unsigned long)sizeof *new_grp); - free (new); - return 0; - } - - memcpy (new, clone, sizeof (struct group)); - - new->group = new_grp; - ec2ng_init (new_grp->grp); - ec2np_init (new_grp->gen); - ec2np_init (new_grp->a); - ec2np_init (new_grp->b); - ec2np_init (new_grp->c); - - if (ec2ng_set (new_grp->grp, clone_grp->grp)) - goto fail; - if (ec2np_set (new_grp->gen, clone_grp->gen)) - goto fail; - - new->gen = new_grp->gen; - new->a = new_grp->a; - new->b = new_grp->b; - new->c = new_grp->c; - new->d = ((ec2np_ptr)new->a)->x; - - return new; - - fail: - ec2ng_clear (new_grp->grp); - ec2np_clear (new_grp->gen); - ec2np_clear (new_grp->a); - ec2np_clear (new_grp->b); - ec2np_clear (new_grp->c); - free (new_grp); - free (new); - return 0; + struct ec2n_group *new_grp, *clone_grp = clone->group; + + new_grp = malloc(sizeof *new_grp); + if (!new_grp) { + log_error("ec2n_clone: malloc (%lu) failed", + (unsigned long) sizeof *new_grp); + free(new); + return 0; + } + memcpy(new, clone, sizeof(struct group)); + + new->group = new_grp; + ec2ng_init(new_grp->grp); + ec2np_init(new_grp->gen); + ec2np_init(new_grp->a); + ec2np_init(new_grp->b); + ec2np_init(new_grp->c); + + if (ec2ng_set(new_grp->grp, clone_grp->grp)) + goto fail; + if (ec2np_set(new_grp->gen, clone_grp->gen)) + goto fail; + + new->gen = new_grp->gen; + new->a = new_grp->a; + new->b = new_grp->b; + new->c = new_grp->c; + new->d = ((ec2np_ptr) new->a)->x; + + return new; + +fail: + ec2ng_clear(new_grp->grp); + ec2np_clear(new_grp->gen); + ec2np_clear(new_grp->a); + ec2np_clear(new_grp->b); + ec2np_clear(new_grp->c); + free(new_grp); + free(new); + return 0; } void -ec2n_free (struct group *old) +ec2n_free(struct group * old) { - struct ec2n_group *grp = old->group; + struct ec2n_group *grp = old->group; - ec2ng_clear (grp->grp); - ec2np_clear (grp->gen); - ec2np_clear (grp->a); - ec2np_clear (grp->b); - ec2np_clear (grp->c); + ec2ng_clear(grp->grp); + ec2np_clear(grp->gen); + ec2np_clear(grp->a); + ec2np_clear(grp->b); + ec2np_clear(grp->c); - free (grp); + free(grp); } void -ec2n_init (struct group *group) +ec2n_init(struct group * group) { - struct ec2n_dscr *dscr = (struct ec2n_dscr *)group->group; - struct ec2n_group *grp; - - grp = malloc (sizeof *grp); - if (!grp) - log_fatal ("ec2n_init: malloc (%lu) failed", (unsigned long)sizeof *grp); - - group->bits = dscr->bits; - - ec2ng_init (grp->grp); - ec2np_init (grp->gen); - ec2np_init (grp->a); - ec2np_init (grp->b); - ec2np_init (grp->c); - - if (ec2ng_set_p_str (grp->grp, dscr->polynomial)) - goto fail; - grp->grp->p->bits = b2n_sigbit (grp->grp->p); - if (ec2ng_set_a_str (grp->grp, dscr->a)) - goto fail; - if (ec2ng_set_b_str (grp->grp, dscr->b)) - goto fail; - - if (ec2np_set_x_str (grp->gen, dscr->gen_x)) - goto fail; - if (ec2np_find_y (grp->gen, grp->grp)) - goto fail; - - /* Sanity check */ - if (!ec2np_ison (grp->gen, grp->grp)) - log_fatal ("ec2n_init: generator is not on curve"); - - group->gen = grp->gen; - group->a = grp->a; - group->b = grp->b; - group->c = grp->c; - group->d = ((ec2np_ptr)group->a)->x; - - group->group = grp; - return; - - fail: - log_fatal ("ec2n_init: general failure"); + struct ec2n_dscr *dscr = (struct ec2n_dscr *) group->group; + struct ec2n_group *grp; + + grp = malloc(sizeof *grp); + if (!grp) + log_fatal("ec2n_init: malloc (%lu) failed", (unsigned long) sizeof *grp); + + group->bits = dscr->bits; + + ec2ng_init(grp->grp); + ec2np_init(grp->gen); + ec2np_init(grp->a); + ec2np_init(grp->b); + ec2np_init(grp->c); + + if (ec2ng_set_p_str(grp->grp, dscr->polynomial)) + goto fail; + grp->grp->p->bits = b2n_sigbit(grp->grp->p); + if (ec2ng_set_a_str(grp->grp, dscr->a)) + goto fail; + if (ec2ng_set_b_str(grp->grp, dscr->b)) + goto fail; + + if (ec2np_set_x_str(grp->gen, dscr->gen_x)) + goto fail; + if (ec2np_find_y(grp->gen, grp->grp)) + goto fail; + + /* Sanity check */ + if (!ec2np_ison(grp->gen, grp->grp)) + log_fatal("ec2n_init: generator is not on curve"); + + group->gen = grp->gen; + group->a = grp->a; + group->b = grp->b; + group->c = grp->c; + group->d = ((ec2np_ptr) group->a)->x; + + group->group = grp; + return; + +fail: + log_fatal("ec2n_init: general failure"); } -#endif /* USE_EC */ +#endif /* USE_EC */ int -modp_getlen (struct group *group) +modp_getlen(struct group * group) { - struct modp_group *grp = (struct modp_group *)group->group; + struct modp_group *grp = (struct modp_group *) group->group; - return mpz_sizeinoctets (grp->p); + return mpz_sizeinoctets(grp->p); } void -modp_getraw (struct group *grp, math_mp_t v, u_int8_t *d) +modp_getraw(struct group * grp, math_mp_t v, u_int8_t * d) { - mpz_getraw (d, v, grp->getlen (grp)); + mpz_getraw(d, v, grp->getlen(grp)); } int -modp_setraw (struct group *grp, math_mp_t d, u_int8_t *s, int l) +modp_setraw(struct group * grp, math_mp_t d, u_int8_t * s, int l) { - mpz_setraw (d, s, l); - return 0; + mpz_setraw(d, s, l); + return 0; } int -modp_setrandom (struct group *grp, math_mp_t d) +modp_setrandom(struct group * grp, math_mp_t d) { - int i, l = grp->getlen (grp); - u_int32_t tmp = 0; + int i, l = grp->getlen(grp); + u_int32_t tmp = 0; #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_set_ui (d, 0); + mpz_set_ui(d, 0); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - BN_set_word (d, 0); + BN_set_word(d, 0); #endif - for (i = 0; i < l; i++) - { - if (i % 4) - tmp = sysdep_random (); + for (i = 0; i < l; i++) { + if (i % 4) + tmp = sysdep_random(); #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_mul_2exp (d, d, 8); - mpz_add_ui (d, d, tmp & 0xFF); + mpz_mul_2exp(d, d, 8); + mpz_add_ui(d, d, tmp & 0xFF); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - BN_lshift (d, d, 8); - BN_add_word (d, tmp & 0xFF); + BN_lshift(d, d, 8); + BN_add_word(d, tmp & 0xFF); #endif - tmp >>= 8; - } - return 0; + tmp >>= 8; + } + return 0; } int -modp_operation (struct group *group, math_mp_t d, math_mp_t a, math_mp_t e) +modp_operation(struct group * group, math_mp_t d, math_mp_t a, math_mp_t e) { - struct modp_group *grp = (struct modp_group *)group->group; + struct modp_group *grp = (struct modp_group *) group->group; #if MP_FLAVOUR == MP_FLAVOUR_GMP - mpz_powm (d, a, e, grp->p); + mpz_powm(d, a, e, grp->p); #elif MP_FLAVOUR == MP_FLAVOUR_OPENSSL - BN_CTX *ctx = BN_CTX_new (); - BN_mod_exp (d, a, e, grp->p, ctx); - BN_CTX_free (ctx); + BN_CTX *ctx = BN_CTX_new(); + BN_mod_exp(d, a, e, grp->p, ctx); + BN_CTX_free(ctx); #endif - return 0; + return 0; } #ifdef USE_EC int -ec2n_getlen (struct group *group) +ec2n_getlen(struct group * group) { - struct ec2n_group *grp = (struct ec2n_group *)group->group; - int bits = b2n_sigbit (grp->grp->p) - 1; + struct ec2n_group *grp = (struct ec2n_group *) group->group; + int bits = b2n_sigbit(grp->grp->p) - 1; - return (7 + bits) >> 3; + return (7 + bits) >> 3; } void -ec2n_getraw (struct group *group, ec2np_ptr xo, u_int8_t *e) +ec2n_getraw(struct group * group, ec2np_ptr xo, u_int8_t * e) { - struct ec2n_group *grp = (struct ec2n_group *)group->group; - int chunks, bytes, i, j; - b2n_ptr x = xo->x; - CHUNK_TYPE tmp; - - bytes = b2n_sigbit (grp->grp->p) - 1; - chunks = (CHUNK_MASK + bytes) >> CHUNK_SHIFTS; - bytes = ((7 + (bytes & CHUNK_MASK)) >> 3); - - for (i = chunks - 1; i >= 0; i--) - { - tmp = (i >= x->chunks ? 0 : x->limp[i]); - for (j = (i == chunks - 1 ? bytes : CHUNK_BYTES) - 1; j >= 0; j--) - { - e[j] = tmp & 0xff; - tmp >>= 8; + struct ec2n_group *grp = (struct ec2n_group *) group->group; + int chunks, bytes, i, j; + b2n_ptr x = xo->x; + CHUNK_TYPE tmp; + + bytes = b2n_sigbit(grp->grp->p) - 1; + chunks = (CHUNK_MASK + bytes) >> CHUNK_SHIFTS; + bytes = ((7 + (bytes & CHUNK_MASK)) >> 3); + + for (i = chunks - 1; i >= 0; i--) { + tmp = (i >= x->chunks ? 0 : x->limp[i]); + for (j = (i == chunks - 1 ? bytes : CHUNK_BYTES) - 1; j >= 0; j--) { + e[j] = tmp & 0xff; + tmp >>= 8; + } + e += (i == chunks - 1 ? bytes : CHUNK_BYTES); } - e += (i == chunks - 1 ? bytes : CHUNK_BYTES); - } } int -ec2n_setraw (struct group *grp, ec2np_ptr out, u_int8_t *s, int l) +ec2n_setraw(struct group * grp, ec2np_ptr out, u_int8_t * s, int l) { - int len, bytes, i, j; - b2n_ptr outx = out->x; - CHUNK_TYPE tmp; - - len = (CHUNK_BYTES - 1 + l) / CHUNK_BYTES; - if (b2n_resize (outx, len)) - return -1; - - bytes = ((l - 1) % CHUNK_BYTES) + 1; - - for (i = len - 1; i >= 0; i--) - { - tmp = 0; - for (j = (i == len - 1 ? bytes : CHUNK_BYTES); j > 0; j--) - { - tmp <<= 8; - tmp |= *s++; + int len, bytes, i, j; + b2n_ptr outx = out->x; + CHUNK_TYPE tmp; + + len = (CHUNK_BYTES - 1 + l) / CHUNK_BYTES; + if (b2n_resize(outx, len)) + return -1; + + bytes = ((l - 1) % CHUNK_BYTES) + 1; + + for (i = len - 1; i >= 0; i--) { + tmp = 0; + for (j = (i == len - 1 ? bytes : CHUNK_BYTES); j > 0; j--) { + tmp <<= 8; + tmp |= *s++; + } + outx->limp[i] = tmp; } - outx->limp[i] = tmp; - } - return 0; + return 0; } int -ec2n_setrandom (struct group *group, ec2np_ptr x) +ec2n_setrandom(struct group * group, ec2np_ptr x) { - b2n_ptr d = x->x; - struct ec2n_group *grp = (struct ec2n_group *)group->group; + b2n_ptr d = x->x; + struct ec2n_group *grp = (struct ec2n_group *) group->group; - return b2n_random (d, b2n_sigbit (grp->grp->p) - 1); + return b2n_random(d, b2n_sigbit(grp->grp->p) - 1); } /* @@ -861,15 +847,15 @@ ec2n_setrandom (struct group *group, ec2np_ptr x) * set to zero. */ int -ec2n_operation (struct group *grp, ec2np_ptr d, ec2np_ptr a, ec2np_ptr e) +ec2n_operation(struct group * grp, ec2np_ptr d, ec2np_ptr a, ec2np_ptr e) { - b2n_ptr ex = e->x; - struct ec2n_group *group = (struct ec2n_group *)grp->group; + b2n_ptr ex = e->x; + struct ec2n_group *group = (struct ec2n_group *) grp->group; - if (a->y->chunks == 0) - if (ec2np_find_y (a, group->grp)) - return -1; + if (a->y->chunks == 0) + if (ec2np_find_y(a, group->grp)) + return -1; - return ec2np_mul (d, a, ex, group->grp); + return ec2np_mul(d, a, ex, group->grp); } -#endif /* USE_EC */ +#endif /* USE_EC */ diff --git a/sbin/isakmpd/math_group.h b/sbin/isakmpd/math_group.h index 2365f00f624..d5a19bcc76d 100644 --- a/sbin/isakmpd/math_group.h +++ b/sbin/isakmpd/math_group.h @@ -1,5 +1,5 @@ -/* $OpenBSD: math_group.h,v 1.9 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: math_group.h,v 1.7 1999/04/17 23:20:40 niklas Exp $ */ +/* $OpenBSD: math_group.h,v 1.10 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_group.h,v 1.7 1999/04/17 23:20:40 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -34,10 +34,10 @@ #define _MATH_GROUP_H_ enum groups { - MODP, /* F_p, Z modulo a prime */ - EC2N, /* Elliptic Curve over the Field GF(2**N) */ - ECP, /* Elliptic Curve over the Field Z_p */ - NOTYET /* Not yet assigned */ + MODP, /* F_p, Z modulo a prime */ + EC2N, /* Elliptic Curve over the Field GF(2**N) */ + ECP, /* Elliptic Curve over the Field Z_p */ + NOTYET /* Not yet assigned */ }; /* @@ -45,50 +45,50 @@ enum groups { */ struct group { - enum groups type; - int id; /* Group ID */ - int bits; /* Number of key bits provided by this group */ - void *group; - void *a, *b, *c, *d; - void *gen; /* Group Generator */ - int (*getlen) (struct group *); - void (*getraw) (struct group *, void *, u_int8_t *); - int (*setraw) (struct group *, void *, u_int8_t *, int); - int (*setrandom) (struct group *, void *); - int (*operation) (struct group *, void *, void *, void *); + enum groups type; + int id; /* Group ID */ + int bits; /* Number of key bits provided by this group */ + void *group; + void *a, *b, *c, *d; + void *gen; /* Group Generator */ + int (*getlen) (struct group *); + void (*getraw) (struct group *, void *, u_int8_t *); + int (*setraw) (struct group *, void *, u_int8_t *, int); + int (*setrandom) (struct group *, void *); + int (*operation) (struct group *, void *, void *, void *); }; /* Description of an Elliptic Group over GF(2**n) for Boot-Strapping */ struct ec2n_dscr { - int id; - int bits; /* Key Bits provided by this group */ - char *polynomial; /* Irreduceable polynomial */ - char *gen_x; /* X - Coord. of Generator */ - char *a, *b; /* Curve Parameters */ + int id; + int bits; /* Key Bits provided by this group */ + char *polynomial; /* Irreduceable polynomial */ + char *gen_x; /* X - Coord. of Generator */ + char *a, *b; /* Curve Parameters */ }; /* Description of F_p for Boot-Strapping */ struct modp_dscr { - int id; - int bits; /* Key Bits provided by this group */ - char *prime; /* Prime */ - char *gen; /* Generator */ + int id; + int bits; /* Key Bits provided by this group */ + char *prime; /* Prime */ + char *gen; /* Generator */ }; /* Prototypes */ -void group_init (void); -void group_free (struct group *); -struct group *group_get (u_int32_t); +void group_init(void); +void group_free(struct group *); +struct group *group_get(u_int32_t); -void ec2n_free (struct group *); -struct group *ec2n_clone (struct group *, struct group *); -void ec2n_init (struct group *); +void ec2n_free(struct group *); +struct group *ec2n_clone(struct group *, struct group *); +void ec2n_init(struct group *); -void modp_free (struct group *); -struct group *modp_clone (struct group *, struct group *); -void modp_init (struct group *); +void modp_free(struct group *); +struct group *modp_clone(struct group *, struct group *); +void modp_init(struct group *); -#endif /* _MATH_GROUP_H_ */ +#endif /* _MATH_GROUP_H_ */ diff --git a/sbin/isakmpd/math_mp.h b/sbin/isakmpd/math_mp.h index 6cb189ddfe9..ed554fc23a4 100644 --- a/sbin/isakmpd/math_mp.h +++ b/sbin/isakmpd/math_mp.h @@ -1,5 +1,5 @@ -/* $OpenBSD: math_mp.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: math_mp.h,v 1.4 2000/09/16 09:41:43 ho Exp $ */ +/* $OpenBSD: math_mp.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: math_mp.h,v 1.4 2000/09/16 09:41:43 ho Exp $ */ /* * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -53,4 +53,4 @@ typedef BIGNUM *math_mp_t; #endif -#endif /* _MATH_MP_H_ */ +#endif /* _MATH_MP_H_ */ diff --git a/sbin/isakmpd/message.c b/sbin/isakmpd/message.c index 9898ad69ca4..3f83c78cac0 100644 --- a/sbin/isakmpd/message.c +++ b/sbin/isakmpd/message.c @@ -1,5 +1,5 @@ -/* $OpenBSD: message.c,v 1.70 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ +/* $OpenBSD: message.c,v 1.71 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -66,55 +66,57 @@ #endif /* A local set datatype, coincidentally fd_set suits our purpose fine. */ -typedef fd_set set; +typedef fd_set set; #define ISSET FD_ISSET #define SET FD_SET #define ZERO FD_ZERO -static int message_check_duplicate (struct message *); -static int message_encrypt (struct message *); -static int message_index_payload (struct message *, struct payload *, u_int8_t, - u_int8_t *); -static int message_parse_transform (struct message *, struct payload *, - u_int8_t, u_int8_t *); -static int message_validate_attribute (struct message *, struct payload *); -static int message_validate_cert (struct message *, struct payload *); -static int message_validate_cert_req (struct message *, struct payload *); -static int message_validate_delete (struct message *, struct payload *); -static int message_validate_hash (struct message *, struct payload *); -static int message_validate_id (struct message *, struct payload *); -static int message_validate_key_exch (struct message *, struct payload *); -static int message_validate_nonce (struct message *, struct payload *); -static int message_validate_notify (struct message *, struct payload *); -static int message_validate_proposal (struct message *, struct payload *); -static int message_validate_sa (struct message *, struct payload *); -static int message_validate_sig (struct message *, struct payload *); -static int message_validate_transform (struct message *, struct payload *); -static int message_validate_vendor (struct message *, struct payload *); - -static void message_packet_log (struct message *); - -static int (*message_validate_payload[]) (struct message *, struct payload *) = +static int message_check_duplicate(struct message *); +static int message_encrypt(struct message *); +static int +message_index_payload(struct message *, struct payload *, u_int8_t, + u_int8_t *); +static int +message_parse_transform(struct message *, struct payload *, + u_int8_t, u_int8_t *); +static int message_validate_attribute(struct message *, struct payload *); +static int message_validate_cert(struct message *, struct payload *); +static int message_validate_cert_req(struct message *, struct payload *); +static int message_validate_delete(struct message *, struct payload *); +static int message_validate_hash(struct message *, struct payload *); +static int message_validate_id(struct message *, struct payload *); +static int message_validate_key_exch(struct message *, struct payload *); +static int message_validate_nonce(struct message *, struct payload *); +static int message_validate_notify(struct message *, struct payload *); +static int message_validate_proposal(struct message *, struct payload *); +static int message_validate_sa(struct message *, struct payload *); +static int message_validate_sig(struct message *, struct payload *); +static int message_validate_transform(struct message *, struct payload *); +static int message_validate_vendor(struct message *, struct payload *); + +static void message_packet_log(struct message *); + +static int (*message_validate_payload[]) (struct message *, struct payload *) = { - message_validate_sa, message_validate_proposal, message_validate_transform, - message_validate_key_exch, message_validate_id, message_validate_cert, - message_validate_cert_req, message_validate_hash, message_validate_sig, - message_validate_nonce, message_validate_notify, message_validate_delete, - message_validate_vendor, message_validate_attribute + message_validate_sa, message_validate_proposal, message_validate_transform, + message_validate_key_exch, message_validate_id, message_validate_cert, + message_validate_cert_req, message_validate_hash, message_validate_sig, + message_validate_nonce, message_validate_notify, message_validate_delete, + message_validate_vendor, message_validate_attribute }; static struct field *fields[] = { - isakmp_sa_fld, isakmp_prop_fld, isakmp_transform_fld, isakmp_ke_fld, - isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld, - isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld, - isakmp_vendor_fld, isakmp_attribute_fld + isakmp_sa_fld, isakmp_prop_fld, isakmp_transform_fld, isakmp_ke_fld, + isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld, + isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld, + isakmp_vendor_fld, isakmp_attribute_fld }; static u_int16_t min_payload_lengths[] = { - 0, ISAKMP_SA_SZ, ISAKMP_PROP_SZ, ISAKMP_TRANSFORM_SZ, ISAKMP_KE_SZ, - ISAKMP_ID_SZ, ISAKMP_CERT_SZ, ISAKMP_CERTREQ_SZ, ISAKMP_HASH_SZ, - ISAKMP_SIG_SZ, ISAKMP_NONCE_SZ, ISAKMP_NOTIFY_SZ, ISAKMP_DELETE_SZ, - ISAKMP_VENDOR_SZ, ISAKMP_ATTRIBUTE_SZ + 0, ISAKMP_SA_SZ, ISAKMP_PROP_SZ, ISAKMP_TRANSFORM_SZ, ISAKMP_KE_SZ, + ISAKMP_ID_SZ, ISAKMP_CERT_SZ, ISAKMP_CERTREQ_SZ, ISAKMP_HASH_SZ, + ISAKMP_SIG_SZ, ISAKMP_NONCE_SZ, ISAKMP_NOTIFY_SZ, ISAKMP_DELETE_SZ, + ISAKMP_VENDOR_SZ, ISAKMP_ATTRIBUTE_SZ }; /* @@ -131,42 +133,40 @@ static u_int32_t last_xf_no; * segment buffer sized SZ, copied from BUF if given. */ struct message * -message_alloc (struct transport *t, u_int8_t *buf, size_t sz) +message_alloc(struct transport * t, u_int8_t * buf, size_t sz) { - struct message *msg; - int i; - - /* - * We use calloc(3) because it zeroes the structure which we rely on in - * message_free when determining what sub-allocations to free. - */ - msg = (struct message *)calloc (1, sizeof *msg); - if (!msg) - return 0; - msg->iov = calloc (1, sizeof *msg->iov); - if (!msg->iov) - { - message_free (msg); - return 0; - } - msg->iov[0].iov_len = sz; - msg->iov[0].iov_base = malloc (sz); - if (!msg->iov[0].iov_base) - { - message_free (msg); - return 0; - } - msg->iovlen = 1; - if (buf) - memcpy (msg->iov[0].iov_base, buf, sz); - msg->nextp = (u_int8_t *)msg->iov[0].iov_base + ISAKMP_HDR_NEXT_PAYLOAD_OFF; - msg->transport = t; - transport_reference (t); - for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) - TAILQ_INIT (&msg->payload[i]); - TAILQ_INIT (&msg->post_send); - LOG_DBG ((LOG_MESSAGE, 90, "message_alloc: allocated %p", msg)); - return msg; + struct message *msg; + int i; + + /* + * We use calloc(3) because it zeroes the structure which we rely on in + * message_free when determining what sub-allocations to free. + */ + msg = (struct message *) calloc(1, sizeof *msg); + if (!msg) + return 0; + msg->iov = calloc(1, sizeof *msg->iov); + if (!msg->iov) { + message_free(msg); + return 0; + } + msg->iov[0].iov_len = sz; + msg->iov[0].iov_base = malloc(sz); + if (!msg->iov[0].iov_base) { + message_free(msg); + return 0; + } + msg->iovlen = 1; + if (buf) + memcpy(msg->iov[0].iov_base, buf, sz); + msg->nextp = (u_int8_t *) msg->iov[0].iov_base + ISAKMP_HDR_NEXT_PAYLOAD_OFF; + msg->transport = t; + transport_reference(t); + for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) + TAILQ_INIT(&msg->payload[i]); + TAILQ_INIT(&msg->post_send); + LOG_DBG((LOG_MESSAGE, 90, "message_alloc: allocated %p", msg)); + return msg; } /* @@ -174,62 +174,59 @@ message_alloc (struct transport *t, u_int8_t *buf, size_t sz) * ISAKMP header as the first segment. */ struct message * -message_alloc_reply (struct message *msg) +message_alloc_reply(struct message * msg) { - struct message *reply; - - reply = message_alloc (msg->transport, 0, ISAKMP_HDR_SZ); - reply->exchange = msg->exchange; - reply->isakmp_sa = msg->isakmp_sa; - if (msg->isakmp_sa) - sa_reference (msg->isakmp_sa); - return reply; + struct message *reply; + + reply = message_alloc(msg->transport, 0, ISAKMP_HDR_SZ); + reply->exchange = msg->exchange; + reply->isakmp_sa = msg->isakmp_sa; + if (msg->isakmp_sa) + sa_reference(msg->isakmp_sa); + return reply; } /* Free up all resources used by the MSG message. */ void -message_free (struct message *msg) +message_free(struct message * msg) { - u_int32_t i; - struct payload *payload, *next; - - LOG_DBG ((LOG_MESSAGE, 20, "message_free: freeing %p", msg)); - if (!msg) - return; - if (msg->orig && msg->orig != (u_int8_t *)msg->iov[0].iov_base) - free (msg->orig); - if (msg->iov) - { - for (i = 0; i < msg->iovlen; i++) - if (msg->iov[i].iov_base) - free (msg->iov[i].iov_base); - free (msg->iov); - } - if (msg->retrans) - timer_remove_event (msg->retrans); - for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) - for (payload = TAILQ_FIRST (&msg->payload[i]); payload; payload = next) - { - next = TAILQ_NEXT (payload, link); - free (payload); - } - while (TAILQ_FIRST (&msg->post_send) != 0) - TAILQ_REMOVE (&msg->post_send, TAILQ_FIRST (&msg->post_send), link); - - /* If we are on the send queue, remove us from there. */ - if (msg->flags & MSG_IN_TRANSIT) - { - if (msg->flags & MSG_PRIORITIZED) - TAILQ_REMOVE (&msg->transport->prio_sendq, msg, link); - else - TAILQ_REMOVE (&msg->transport->sendq, msg, link); - } - transport_release (msg->transport); - - if (msg->isakmp_sa) - sa_release (msg->isakmp_sa); - - free (msg); + u_int32_t i; + struct payload *payload, *next; + + LOG_DBG((LOG_MESSAGE, 20, "message_free: freeing %p", msg)); + if (!msg) + return; + if (msg->orig && msg->orig != (u_int8_t *) msg->iov[0].iov_base) + free(msg->orig); + if (msg->iov) { + for (i = 0; i < msg->iovlen; i++) + if (msg->iov[i].iov_base) + free(msg->iov[i].iov_base); + free(msg->iov); + } + if (msg->retrans) + timer_remove_event(msg->retrans); + for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) + for (payload = TAILQ_FIRST(&msg->payload[i]); payload; payload = next) { + next = TAILQ_NEXT(payload, link); + free(payload); + } + while (TAILQ_FIRST(&msg->post_send) != 0) + TAILQ_REMOVE(&msg->post_send, TAILQ_FIRST(&msg->post_send), link); + + /* If we are on the send queue, remove us from there. */ + if (msg->flags & MSG_IN_TRANSIT) { + if (msg->flags & MSG_PRIORITIZED) + TAILQ_REMOVE(&msg->transport->prio_sendq, msg, link); + else + TAILQ_REMOVE(&msg->transport->sendq, msg, link); + } + transport_release(msg->transport); + + if (msg->isakmp_sa) + sa_release(msg->isakmp_sa); + + free(msg); } /* @@ -241,106 +238,91 @@ message_free (struct message *msg) * parsed payloads. */ static int -message_parse_payloads (struct message *msg, struct payload *p, u_int8_t next, - u_int8_t *buf, set *accepted_payloads, - int (*func) (struct message *, struct payload *, - u_int8_t, u_int8_t *)) +message_parse_payloads(struct message * msg, struct payload * p, u_int8_t next, + u_int8_t * buf, set * accepted_payloads, + int (*func) (struct message *, struct payload *, + u_int8_t, u_int8_t *)) { - u_int8_t payload; - u_int16_t len; - int sz = 0; - - do - { - LOG_DBG ((LOG_MESSAGE, 50, - "message_parse_payloads: offset %ld payload %s", - (long)(buf - (u_int8_t *)msg->iov[0].iov_base), - constant_name (isakmp_payload_cst, next))); - - /* Does this payload's header fit? */ - if (buf + ISAKMP_GEN_SZ - > (u_int8_t *)msg->iov[0].iov_base + msg->iov[0].iov_len) - { - log_print ("message_parse_payloads: short message"); - message_drop (msg, ISAKMP_NOTIFY_UNEQUAL_PAYLOAD_LENGTHS, 0, 1, 1); - return -1; - } - - /* Ponder on the payload that is at BUF... */ - payload = next; - - /* Look at the next payload's type. */ - next = GET_ISAKMP_GEN_NEXT_PAYLOAD (buf); - if (next >= ISAKMP_PAYLOAD_RESERVED_MIN && - next <= ISAKMP_PAYLOAD_RESERVED_MAX) - { - log_print ("message_parse_payloads: invalid next payload type %d " - "in payload of type %d", next, payload); - message_drop (msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); - return -1; - } - - /* Reserved fields in ISAKMP messages should be zero. */ - if (GET_ISAKMP_GEN_RESERVED (buf) != 0) - { - log_print ("message_parse_payloads: reserved field non-zero: %x", - GET_ISAKMP_GEN_RESERVED (buf)); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - /* - * Decode and validate the payload length field. - */ - len = GET_ISAKMP_GEN_LENGTH (buf); - - if ((payload < ISAKMP_PAYLOAD_RESERVED_MIN) - && (len < min_payload_lengths[payload])) - { - log_print ("message_parse_payloads: payload too short: %u", len); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - if (buf + len > (u_int8_t *)msg->iov[0].iov_base + msg->iov[0].iov_len) - { - log_print ("message_parse_payloads: payload too long: %u", len); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - /* Ignore private payloads. */ - if (next >= ISAKMP_PAYLOAD_PRIVATE_MIN) - { - LOG_DBG ((LOG_MESSAGE, 30, - "message_parse_payloads: private next payload type %d " - "in payload of type %d ignored", next, payload)); - goto next_payload; - } - - /* - * Check if the current payload is one of the accepted ones at this - * stage. - */ - if (!ISSET (payload, accepted_payloads)) - { - log_print ("message_parse_payloads: payload type %d unexpected", - payload); - message_drop (msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); - return -1; - } - - /* Call the payload handler specified by the caller. */ - if (func (msg, p, payload, buf)) - return -1; - - next_payload: - /* Advance to next payload. */ - buf += len; - sz += len; - } - while (next != ISAKMP_PAYLOAD_NONE); - return sz; + u_int8_t payload; + u_int16_t len; + int sz = 0; + + do { + LOG_DBG((LOG_MESSAGE, 50, + "message_parse_payloads: offset %ld payload %s", + (long) (buf - (u_int8_t *) msg->iov[0].iov_base), + constant_name(isakmp_payload_cst, next))); + + /* Does this payload's header fit? */ + if (buf + ISAKMP_GEN_SZ + > (u_int8_t *) msg->iov[0].iov_base + msg->iov[0].iov_len) { + log_print("message_parse_payloads: short message"); + message_drop(msg, ISAKMP_NOTIFY_UNEQUAL_PAYLOAD_LENGTHS, 0, 1, 1); + return -1; + } + /* Ponder on the payload that is at BUF... */ + payload = next; + + /* Look at the next payload's type. */ + next = GET_ISAKMP_GEN_NEXT_PAYLOAD(buf); + if (next >= ISAKMP_PAYLOAD_RESERVED_MIN && + next <= ISAKMP_PAYLOAD_RESERVED_MAX) { + log_print("message_parse_payloads: invalid next payload type %d " + "in payload of type %d", next, payload); + message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); + return -1; + } + /* Reserved fields in ISAKMP messages should be zero. */ + if (GET_ISAKMP_GEN_RESERVED(buf) != 0) { + log_print("message_parse_payloads: reserved field non-zero: %x", + GET_ISAKMP_GEN_RESERVED(buf)); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* + * Decode and validate the payload length field. + */ + len = GET_ISAKMP_GEN_LENGTH(buf); + + if ((payload < ISAKMP_PAYLOAD_RESERVED_MIN) + && (len < min_payload_lengths[payload])) { + log_print("message_parse_payloads: payload too short: %u", len); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + if (buf + len > (u_int8_t *) msg->iov[0].iov_base + msg->iov[0].iov_len) { + log_print("message_parse_payloads: payload too long: %u", len); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* Ignore private payloads. */ + if (next >= ISAKMP_PAYLOAD_PRIVATE_MIN) { + LOG_DBG((LOG_MESSAGE, 30, + "message_parse_payloads: private next payload type %d " + "in payload of type %d ignored", next, payload)); + goto next_payload; + } + /* + * Check if the current payload is one of the accepted ones at this + * stage. + */ + if (!ISSET(payload, accepted_payloads)) { + log_print("message_parse_payloads: payload type %d unexpected", + payload); + message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); + return -1; + } + /* Call the payload handler specified by the caller. */ + if (func(msg, p, payload, buf)) + return -1; + +next_payload: + /* Advance to next payload. */ + buf += len; + sz += len; + } + while (next != ISAKMP_PAYLOAD_NONE); + return sz; } /* @@ -350,109 +332,103 @@ message_parse_payloads (struct message *msg, struct payload *p, u_int8_t next, * generic payload header. */ static int -message_parse_proposal (struct message *msg, struct payload *p, - u_int8_t payload, u_int8_t *buf) +message_parse_proposal(struct message * msg, struct payload * p, + u_int8_t payload, u_int8_t * buf) { - set payload_set; - - /* Put the proposal into the proposal bucket. */ - message_index_payload (msg, p, payload, buf); - - ZERO (&payload_set); - SET (ISAKMP_PAYLOAD_TRANSFORM, &payload_set); - if (message_parse_payloads (msg, - TAILQ_LAST (&msg->payload - [ISAKMP_PAYLOAD_PROPOSAL], - payload_head), - ISAKMP_PAYLOAD_TRANSFORM, - buf + ISAKMP_PROP_SPI_OFF - + GET_ISAKMP_PROP_SPI_SZ (buf), - &payload_set, message_parse_transform) == -1) - return -1; - - return 0; + set payload_set; + + /* Put the proposal into the proposal bucket. */ + message_index_payload(msg, p, payload, buf); + + ZERO(&payload_set); + SET(ISAKMP_PAYLOAD_TRANSFORM, &payload_set); + if (message_parse_payloads(msg, + TAILQ_LAST(&msg->payload + [ISAKMP_PAYLOAD_PROPOSAL], + payload_head), + ISAKMP_PAYLOAD_TRANSFORM, + buf + ISAKMP_PROP_SPI_OFF + + GET_ISAKMP_PROP_SPI_SZ(buf), + &payload_set, message_parse_transform) == -1) + return -1; + + return 0; } static int -message_parse_transform (struct message *msg, struct payload *p, - u_int8_t payload, u_int8_t *buf) +message_parse_transform(struct message * msg, struct payload * p, + u_int8_t payload, u_int8_t * buf) { - /* Put the transform into the transform bucket. */ - message_index_payload (msg, p, payload, buf); + /* Put the transform into the transform bucket. */ + message_index_payload(msg, p, payload, buf); - LOG_DBG ((LOG_MESSAGE, 50, "Transform %d's attributes", - GET_ISAKMP_TRANSFORM_NO (buf))); + LOG_DBG((LOG_MESSAGE, 50, "Transform %d's attributes", + GET_ISAKMP_TRANSFORM_NO(buf))); #ifdef USE_DEBUG - attribute_map (buf + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (buf) - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - msg->exchange->doi->debug_attribute, msg); + attribute_map(buf + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(buf) - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + msg->exchange->doi->debug_attribute, msg); #endif - return 0; + return 0; } /* Validate the attribute payload P in message MSG. */ static int -message_validate_attribute (struct message *msg, struct payload *p) +message_validate_attribute(struct message * msg, struct payload * p) { #ifdef USE_ISAKMP_CFG - /* If we don't have an exchange yet, create one. */ - if (!msg->exchange) - { - if (zero_test ((u_int8_t *)msg->iov[0].iov_base - + ISAKMP_HDR_MESSAGE_ID_OFF, ISAKMP_HDR_MESSAGE_ID_LEN)) - msg->exchange = exchange_setup_p1 (msg, IPSEC_DOI_IPSEC); - else - msg->exchange = exchange_setup_p2 (msg, IPSEC_DOI_IPSEC); - if (!msg->exchange) - { - log_print ("message_validate_attribute: can not create exchange"); - message_free (msg); - return -1; - } - } + /* If we don't have an exchange yet, create one. */ + if (!msg->exchange) { + if (zero_test((u_int8_t *) msg->iov[0].iov_base + + ISAKMP_HDR_MESSAGE_ID_OFF, ISAKMP_HDR_MESSAGE_ID_LEN)) + msg->exchange = exchange_setup_p1(msg, IPSEC_DOI_IPSEC); + else + msg->exchange = exchange_setup_p2(msg, IPSEC_DOI_IPSEC); + if (!msg->exchange) { + log_print("message_validate_attribute: can not create exchange"); + message_free(msg); + return -1; + } + } #endif - return 0; + return 0; } /* Validate the certificate payload P in message MSG. */ static int -message_validate_cert (struct message *msg, struct payload *p) +message_validate_cert(struct message * msg, struct payload * p) { - if (GET_ISAKMP_CERT_ENCODING (p->p) >= ISAKMP_CERTENC_RESERVED_MIN) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_CERT_ENCODING, 0, 1, 1); - return -1; - } - return 0; + if (GET_ISAKMP_CERT_ENCODING(p->p) >= ISAKMP_CERTENC_RESERVED_MIN) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_CERT_ENCODING, 0, 1, 1); + return -1; + } + return 0; } /* Validate the certificate request payload P in message MSG. */ static int -message_validate_cert_req (struct message *msg, struct payload *p) +message_validate_cert_req(struct message * msg, struct payload * p) { - struct cert_handler *cert; - size_t len = GET_ISAKMP_GEN_LENGTH (p->p)- ISAKMP_CERTREQ_AUTHORITY_OFF; - - if (GET_ISAKMP_CERTREQ_TYPE (p->p) >= ISAKMP_CERTENC_RESERVED_MIN) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_CERT_ENCODING, 0, 1, 1); - return -1; - } - - /* - * Check the certificate types we support and if an acceptable authority - * is included in the payload check if it can be decoded - */ - cert = cert_get (GET_ISAKMP_CERTREQ_TYPE (p->p)); - if (!cert - || (len && !cert->certreq_validate (p->p + ISAKMP_CERTREQ_AUTHORITY_OFF, - len))) - { - message_drop (msg, ISAKMP_NOTIFY_CERT_TYPE_UNSUPPORTED, 0, 1, 1); - return -1; - } - return 0; + struct cert_handler *cert; + size_t len = GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_CERTREQ_AUTHORITY_OFF; + + if (GET_ISAKMP_CERTREQ_TYPE(p->p) >= ISAKMP_CERTENC_RESERVED_MIN) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_CERT_ENCODING, 0, 1, 1); + return -1; + } + /* + * Check the certificate types we support and if an acceptable authority + * is included in the payload check if it can be decoded + */ + cert = cert_get(GET_ISAKMP_CERTREQ_TYPE(p->p)); + if (!cert + || (len && !cert->certreq_validate(p->p + ISAKMP_CERTREQ_AUTHORITY_OFF, + len))) { + message_drop(msg, ISAKMP_NOTIFY_CERT_TYPE_UNSUPPORTED, 0, 1, 1); + return -1; + } + return 0; } /* @@ -460,94 +436,83 @@ message_validate_cert_req (struct message *msg, struct payload *p) * an exchange if we do not have one already. */ static int -message_validate_delete (struct message *msg, struct payload *p) +message_validate_delete(struct message * msg, struct payload * p) { - u_int8_t proto = GET_ISAKMP_DELETE_PROTO (p->p); - struct doi *doi; - struct sa *sa, *isakmp_sa; - struct sockaddr *dst, *dst_isa; - u_int32_t nspis = GET_ISAKMP_DELETE_NSPIS (p->p); - u_int8_t *spis = (u_int8_t *)p->p + ISAKMP_DELETE_SPI_OFF; - u_int32_t i; - char *addr; - - doi = doi_lookup (GET_ISAKMP_DELETE_DOI (p->p)); - if (!doi) - { - log_print ("message_validate_delete: DOI not supported"); - message_free (msg); - return -1; - } - - /* If we don't have an exchange yet, create one. */ - if (!msg->exchange) - { - if (zero_test ((u_int8_t *)msg->iov[0].iov_base - + ISAKMP_HDR_MESSAGE_ID_OFF, ISAKMP_HDR_MESSAGE_ID_LEN)) - msg->exchange = exchange_setup_p1 (msg, doi->id); - else - msg->exchange = exchange_setup_p2 (msg, doi->id); - if (!msg->exchange) - { - log_print ("message_validate_delete: can not create exchange"); - message_free (msg); - return -1; - } - } - - if (proto != ISAKMP_PROTO_ISAKMP && doi->validate_proto (proto)) - { - log_print ("message_validate_delete: protocol not supported"); - message_free (msg); - return -1; - } - - /* Validate the SPIs. */ - for (i = 0; i < nspis; i++) - { - /* Get ISAKMP SA protecting this message. */ - isakmp_sa = msg->isakmp_sa; - if (!isakmp_sa) - { - /* XXX should not happen? */ - log_print ("message_validate_delete: invalid spi " - "(no valid ISAKMP SA found)"); - message_free (msg); - return -1; - } - isakmp_sa->transport->vtbl->get_dst (isakmp_sa->transport, &dst_isa); - - /* Get SA to be deleted. */ - msg->transport->vtbl->get_dst (msg->transport, &dst); - if (proto == ISAKMP_PROTO_ISAKMP) - sa = sa_lookup_isakmp_sa (dst, spis + i * ISAKMP_HDR_COOKIES_LEN); - else - sa = ipsec_sa_lookup (dst, ((u_int32_t *)spis)[i], proto); - if (!sa) - { - LOG_DBG ((LOG_MESSAGE, 50, "message_validate_delete: invalid spi " - "(no valid SA found)")); - message_free (msg); - return -1; - } - sa->transport->vtbl->get_dst (sa->transport, &dst); - - /* Destination addresses must match. */ - if (dst->sa_family != dst_isa->sa_family || - memcmp (sockaddr_addrdata (dst_isa), sockaddr_addrdata (dst), - sockaddr_addrlen (dst))) - { - sockaddr2text (dst_isa, &addr, 0); - - log_print ("message_validate_delete: invalid spi " - "(illegal delete request from %s)", addr); - free (addr); - message_free (msg); - return -1; - } - } - - return 0; + u_int8_t proto = GET_ISAKMP_DELETE_PROTO(p->p); + struct doi *doi; + struct sa *sa, *isakmp_sa; + struct sockaddr *dst, *dst_isa; + u_int32_t nspis = GET_ISAKMP_DELETE_NSPIS(p->p); + u_int8_t *spis = (u_int8_t *) p->p + ISAKMP_DELETE_SPI_OFF; + u_int32_t i; + char *addr; + + doi = doi_lookup(GET_ISAKMP_DELETE_DOI(p->p)); + if (!doi) { + log_print("message_validate_delete: DOI not supported"); + message_free(msg); + return -1; + } + /* If we don't have an exchange yet, create one. */ + if (!msg->exchange) { + if (zero_test((u_int8_t *) msg->iov[0].iov_base + + ISAKMP_HDR_MESSAGE_ID_OFF, ISAKMP_HDR_MESSAGE_ID_LEN)) + msg->exchange = exchange_setup_p1(msg, doi->id); + else + msg->exchange = exchange_setup_p2(msg, doi->id); + if (!msg->exchange) { + log_print("message_validate_delete: can not create exchange"); + message_free(msg); + return -1; + } + } + if (proto != ISAKMP_PROTO_ISAKMP && doi->validate_proto(proto)) { + log_print("message_validate_delete: protocol not supported"); + message_free(msg); + return -1; + } + /* Validate the SPIs. */ + for (i = 0; i < nspis; i++) { + /* Get ISAKMP SA protecting this message. */ + isakmp_sa = msg->isakmp_sa; + if (!isakmp_sa) { + /* XXX should not happen? */ + log_print("message_validate_delete: invalid spi " + "(no valid ISAKMP SA found)"); + message_free(msg); + return -1; + } + isakmp_sa->transport->vtbl->get_dst(isakmp_sa->transport, &dst_isa); + + /* Get SA to be deleted. */ + msg->transport->vtbl->get_dst(msg->transport, &dst); + if (proto == ISAKMP_PROTO_ISAKMP) + sa = sa_lookup_isakmp_sa(dst, spis + i * ISAKMP_HDR_COOKIES_LEN); + else + sa = ipsec_sa_lookup(dst, ((u_int32_t *) spis)[i], proto); + if (!sa) { + LOG_DBG((LOG_MESSAGE, 50, "message_validate_delete: invalid spi " + "(no valid SA found)")); + message_free(msg); + return -1; + } + sa->transport->vtbl->get_dst(sa->transport, &dst); + + /* Destination addresses must match. */ + if (dst->sa_family != dst_isa->sa_family || + memcmp(sockaddr_addrdata(dst_isa), sockaddr_addrdata(dst), + sockaddr_addrlen(dst))) { + sockaddr2text(dst_isa, &addr, 0); + + log_print("message_validate_delete: invalid spi " + "(illegal delete request from %s)", addr); + free(addr); + message_free(msg); + return -1; + } + } + + return 0; } /* @@ -556,165 +521,146 @@ message_validate_delete (struct message *msg, struct payload *p) * except INFORMATIONAL. This should be actually done here. */ static int -message_validate_hash (struct message *msg, struct payload *p) +message_validate_hash(struct message * msg, struct payload * p) { - struct sa *isakmp_sa = msg->isakmp_sa; - struct ipsec_sa *isa; - struct hash *hash; - struct payload *hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); - struct prf *prf; - u_int8_t *comp_hash, *rest; - u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; - size_t rest_len; - - if (msg->exchange) /* active exchange validates hash payload. */ - return 0; - - if (isakmp_sa == NULL) - { - log_print ("message_validate_hash: invalid hash information"); - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); - return -1; - } - - isa = isakmp_sa->data; - hash = hash_get (isa->hash); - - if (hash == NULL) - { - log_print ("message_validate_hash: invalid hash information"); - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); - return -1; - } - - /* If no SKEYID_a, we can not do anything (should not happen). */ - if (!isa->skeyid_a) - { - log_print ("message_validate_hash: invalid hash information"); - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); - return -1; - } - - /* Allocate the prf and start calculating our HASH(1). */ - LOG_DBG_BUF ((LOG_MISC, 90, "message_validate_hash: SKEYID_a", isa->skeyid_a, - isa->skeyid_len)); - prf = prf_alloc (isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); - if (!prf) - { - message_free (msg); - return -1; - } - - comp_hash = (u_int8_t *)malloc (hash->hashsize); - if (!comp_hash) - { - log_error ("message_validate_hash: malloc (%lu) failed", - (unsigned long)hash->hashsize); - prf_free (prf); - message_free (msg); - return -1; - } - - /* This is not an active exchange. */ - GET_ISAKMP_HDR_MESSAGE_ID (msg->iov[0].iov_base, message_id); - - prf->Init (prf->prfctx); - LOG_DBG_BUF ((LOG_MISC, 90, "message_validate_hash: message_id", - message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); - prf->Update (prf->prfctx, message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - rest = hashp->p + GET_ISAKMP_GEN_LENGTH (hashp->p); - rest_len = (GET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base) - - (rest - (u_int8_t*)msg->iov[0].iov_base)); - LOG_DBG_BUF ((LOG_MISC, 90, "message_validate_hash: payloads after HASH(1)", - rest, rest_len)); - prf->Update (prf->prfctx, rest, rest_len); - prf->Final (comp_hash, prf->prfctx); - prf_free (prf); - - if (memcmp (hashp->p + ISAKMP_HASH_DATA_OFF, comp_hash, hash->hashsize)) - { - log_print ("message_validate_hash: invalid hash value for %s payload", - TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_DELETE]) - ? "DELETE" : "NOTIFY"); - message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); - free (comp_hash); - return -1; - } - free (comp_hash); - - /* Mark the HASH as handled. */ - hashp->flags |= PL_MARK; - - return 0; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa; + struct hash *hash; + struct payload *hashp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_HASH]); + struct prf *prf; + u_int8_t *comp_hash, *rest; + u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; + size_t rest_len; + + if (msg->exchange) /* active exchange validates hash payload. */ + return 0; + + if (isakmp_sa == NULL) { + log_print("message_validate_hash: invalid hash information"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); + return -1; + } + isa = isakmp_sa->data; + hash = hash_get(isa->hash); + + if (hash == NULL) { + log_print("message_validate_hash: invalid hash information"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); + return -1; + } + /* If no SKEYID_a, we can not do anything (should not happen). */ + if (!isa->skeyid_a) { + log_print("message_validate_hash: invalid hash information"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); + return -1; + } + /* Allocate the prf and start calculating our HASH(1). */ + LOG_DBG_BUF((LOG_MISC, 90, "message_validate_hash: SKEYID_a", isa->skeyid_a, + isa->skeyid_len)); + prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); + if (!prf) { + message_free(msg); + return -1; + } + comp_hash = (u_int8_t *) malloc(hash->hashsize); + if (!comp_hash) { + log_error("message_validate_hash: malloc (%lu) failed", + (unsigned long) hash->hashsize); + prf_free(prf); + message_free(msg); + return -1; + } + /* This is not an active exchange. */ + GET_ISAKMP_HDR_MESSAGE_ID(msg->iov[0].iov_base, message_id); + + prf->Init(prf->prfctx); + LOG_DBG_BUF((LOG_MISC, 90, "message_validate_hash: message_id", + message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update(prf->prfctx, message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + rest = hashp->p + GET_ISAKMP_GEN_LENGTH(hashp->p); + rest_len = (GET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base) + - (rest - (u_int8_t *) msg->iov[0].iov_base)); + LOG_DBG_BUF((LOG_MISC, 90, "message_validate_hash: payloads after HASH(1)", + rest, rest_len)); + prf->Update(prf->prfctx, rest, rest_len); + prf->Final(comp_hash, prf->prfctx); + prf_free(prf); + + if (memcmp(hashp->p + ISAKMP_HASH_DATA_OFF, comp_hash, hash->hashsize)) { + log_print("message_validate_hash: invalid hash value for %s payload", + TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_DELETE]) + ? "DELETE" : "NOTIFY"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + free(comp_hash); + return -1; + } + free(comp_hash); + + /* Mark the HASH as handled. */ + hashp->flags |= PL_MARK; + + return 0; } /* Validate the identification payload P in message MSG. */ static int -message_validate_id (struct message *msg, struct payload *p) +message_validate_id(struct message * msg, struct payload * p) { - struct exchange *exchange = msg->exchange; - size_t len = GET_ISAKMP_GEN_LENGTH (p->p); - - if (!exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_id: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - if (exchange->doi - && exchange->doi->validate_id_information (GET_ISAKMP_ID_TYPE (p->p), - p->p + ISAKMP_ID_DOI_DATA_OFF, - p->p + ISAKMP_ID_DATA_OFF, - len - ISAKMP_ID_DATA_OFF, - exchange)) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION, 0, 1, 1); - return -1; - } - return 0; + struct exchange *exchange = msg->exchange; + size_t len = GET_ISAKMP_GEN_LENGTH(p->p); + + if (!exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_id: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + if (exchange->doi + && exchange->doi->validate_id_information(GET_ISAKMP_ID_TYPE(p->p), + p->p + ISAKMP_ID_DOI_DATA_OFF, + p->p + ISAKMP_ID_DATA_OFF, + len - ISAKMP_ID_DATA_OFF, + exchange)) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION, 0, 1, 1); + return -1; + } + return 0; } /* Validate the key exchange payload P in message MSG. */ static int -message_validate_key_exch (struct message *msg, struct payload *p) +message_validate_key_exch(struct message * msg, struct payload * p) { - struct exchange *exchange = msg->exchange; - size_t len = GET_ISAKMP_GEN_LENGTH (p->p); - - if (!exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_key_exch: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - if (exchange->doi - && exchange->doi->validate_key_information (p->p + ISAKMP_KE_DATA_OFF, - len - ISAKMP_KE_DATA_OFF)) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_KEY_INFORMATION, 0, 1, 1); - return -1; - } - return 0; + struct exchange *exchange = msg->exchange; + size_t len = GET_ISAKMP_GEN_LENGTH(p->p); + + if (!exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_key_exch: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + if (exchange->doi + && exchange->doi->validate_key_information(p->p + ISAKMP_KE_DATA_OFF, + len - ISAKMP_KE_DATA_OFF)) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_KEY_INFORMATION, 0, 1, 1); + return -1; + } + return 0; } /* Validate the nonce payload P in message MSG. */ static int -message_validate_nonce (struct message *msg, struct payload *p) +message_validate_nonce(struct message * msg, struct payload * p) { - if (!msg->exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_nonce: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - /* Nonces require no specific validation. */ - return 0; + if (!msg->exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_nonce: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* Nonces require no specific validation. */ + return 0; } /* @@ -722,97 +668,84 @@ message_validate_nonce (struct message *msg, struct payload *p) * an exchange if we do not have one already. */ static int -message_validate_notify (struct message *msg, struct payload *p) +message_validate_notify(struct message * msg, struct payload * p) { - u_int8_t proto = GET_ISAKMP_NOTIFY_PROTO (p->p); - u_int16_t type = GET_ISAKMP_NOTIFY_MSG_TYPE (p->p); - struct doi *doi; - - doi = doi_lookup (GET_ISAKMP_NOTIFY_DOI (p->p)); - if (!doi) - { - log_print ("message_validate_notify: DOI not supported"); - message_free (msg); - return -1; - } - - /* If we don't have an exchange yet, create one. */ - if (!msg->exchange) - { - if (zero_test ((u_int8_t *)msg->iov[0].iov_base - + ISAKMP_HDR_MESSAGE_ID_OFF, ISAKMP_HDR_MESSAGE_ID_LEN)) - msg->exchange = exchange_setup_p1 (msg, doi->id); - else - msg->exchange = exchange_setup_p2 (msg, doi->id); - if (!msg->exchange) - { - log_print ("message_validate_notify: can not create exchange"); - message_free (msg); - return -1; - } - } - - if (proto != ISAKMP_PROTO_ISAKMP && doi->validate_proto (proto)) - { - log_print ("message_validate_notify: protocol not supported"); - message_free (msg); - return -1; - } - - /* XXX Validate the SPI. */ - - if (type < ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE - || (type >= ISAKMP_NOTIFY_RESERVED_MIN - && type < ISAKMP_NOTIFY_PRIVATE_MIN) - || (type >= ISAKMP_NOTIFY_STATUS_RESERVED1_MIN - && type <= ISAKMP_NOTIFY_STATUS_RESERVED1_MAX) - || (type >= ISAKMP_NOTIFY_STATUS_DOI_MIN - && type <= ISAKMP_NOTIFY_STATUS_DOI_MAX - && doi->validate_notification (type)) - || type >= ISAKMP_NOTIFY_STATUS_RESERVED2_MIN) - { - log_print ("message_validate_notify: message type not supported"); - message_free (msg); - return -1; - } - return 0; + u_int8_t proto = GET_ISAKMP_NOTIFY_PROTO(p->p); + u_int16_t type = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p); + struct doi *doi; + + doi = doi_lookup(GET_ISAKMP_NOTIFY_DOI(p->p)); + if (!doi) { + log_print("message_validate_notify: DOI not supported"); + message_free(msg); + return -1; + } + /* If we don't have an exchange yet, create one. */ + if (!msg->exchange) { + if (zero_test((u_int8_t *) msg->iov[0].iov_base + + ISAKMP_HDR_MESSAGE_ID_OFF, ISAKMP_HDR_MESSAGE_ID_LEN)) + msg->exchange = exchange_setup_p1(msg, doi->id); + else + msg->exchange = exchange_setup_p2(msg, doi->id); + if (!msg->exchange) { + log_print("message_validate_notify: can not create exchange"); + message_free(msg); + return -1; + } + } + if (proto != ISAKMP_PROTO_ISAKMP && doi->validate_proto(proto)) { + log_print("message_validate_notify: protocol not supported"); + message_free(msg); + return -1; + } + /* XXX Validate the SPI. */ + + if (type < ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE + || (type >= ISAKMP_NOTIFY_RESERVED_MIN + && type < ISAKMP_NOTIFY_PRIVATE_MIN) + || (type >= ISAKMP_NOTIFY_STATUS_RESERVED1_MIN + && type <= ISAKMP_NOTIFY_STATUS_RESERVED1_MAX) + || (type >= ISAKMP_NOTIFY_STATUS_DOI_MIN + && type <= ISAKMP_NOTIFY_STATUS_DOI_MAX + && doi->validate_notification(type)) + || type >= ISAKMP_NOTIFY_STATUS_RESERVED2_MIN) { + log_print("message_validate_notify: message type not supported"); + message_free(msg); + return -1; + } + return 0; } /* Validate the proposal payload P in message MSG. */ static int -message_validate_proposal (struct message *msg, struct payload *p) +message_validate_proposal(struct message * msg, struct payload * p) { - u_int8_t proto = GET_ISAKMP_PROP_PROTO (p->p); - u_int8_t *sa = p->context->p; - - if (!msg->exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_proposal: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - if (proto != ISAKMP_PROTO_ISAKMP - && msg->exchange->doi->validate_proto (proto)) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_PROTOCOL_ID, 0, 1, 1); - return -1; - } - - /* Check that we get monotonically increasing proposal IDs per SA. */ - if (sa != last_sa) - last_sa = sa; - else if (GET_ISAKMP_PROP_NO (p->p) < last_prop_no) - { - message_drop (msg, ISAKMP_NOTIFY_BAD_PROPOSAL_SYNTAX, 0, 1, 1); - return -1; - } - last_prop_no = GET_ISAKMP_PROP_NO (p->p); - - /* XXX Validate the SPI, and other syntactic things. */ - - return 0; + u_int8_t proto = GET_ISAKMP_PROP_PROTO(p->p); + u_int8_t *sa = p->context->p; + + if (!msg->exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_proposal: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + if (proto != ISAKMP_PROTO_ISAKMP + && msg->exchange->doi->validate_proto(proto)) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_PROTOCOL_ID, 0, 1, 1); + return -1; + } + /* Check that we get monotonically increasing proposal IDs per SA. */ + if (sa != last_sa) + last_sa = sa; + else if (GET_ISAKMP_PROP_NO(p->p) < last_prop_no) { + message_drop(msg, ISAKMP_NOTIFY_BAD_PROPOSAL_SYNTAX, 0, 1, 1); + return -1; + } + last_prop_no = GET_ISAKMP_PROP_NO(p->p); + + /* XXX Validate the SPI, and other syntactic things. */ + + return 0; } /* @@ -827,190 +760,165 @@ message_validate_proposal (struct message *msg, struct payload *p) * first due to the IANA assigned payload number? */ static int -message_validate_sa (struct message *msg, struct payload *p) +message_validate_sa(struct message * msg, struct payload * p) { - set payload_set; - size_t len; - u_int32_t doi_id; - struct exchange *exchange = msg->exchange; - u_int8_t *pkt = msg->iov[0].iov_base; - - doi_id = GET_ISAKMP_SA_DOI (p->p); - if (!doi_lookup (doi_id)) - { - log_print ("message_validate_sa: DOI not supported"); - message_drop (msg, ISAKMP_NOTIFY_DOI_NOT_SUPPORTED, 0, 1, 1); - return -1; - } - - /* - * It's time to figure out what SA this message is about. If it is - * already set, then we are creating a new phase 1 SA. Otherwise, lookup - * the SA using the cookies and the message ID. If we cannot find - * it, and the phase 1 SA is ready, setup a phase 2 SA. - */ - if (!exchange) - { - if (zero_test (pkt + ISAKMP_HDR_RCOOKIE_OFF, ISAKMP_HDR_RCOOKIE_LEN)) - exchange = exchange_setup_p1 (msg, doi_id); - else if (msg->isakmp_sa->flags & SA_FLAG_READY) - exchange = exchange_setup_p2 (msg, doi_id); - else - { - /* XXX What to do here? */ - message_free (msg); - return -1; - } - if (!exchange) - { - /* XXX Log? */ - message_free (msg); - return -1; - } - } - msg->exchange = exchange; - - /* - * Create a struct sa for each SA payload handed to us unless we are the - * initiator where we only will count them. - */ - if (exchange->initiator) - { - /* XXX Count SA payloads. */ - } - else if (sa_create (exchange, msg->transport)) - { - /* XXX Remove exchange if we just created it? */ - message_free (msg); - return -1; - } - - if (exchange->phase == 1) - { - msg->isakmp_sa = TAILQ_FIRST (&exchange->sa_list); - if (msg->isakmp_sa) - sa_reference (msg->isakmp_sa); - } - - /* - * Let the DOI validate the situation, at the same time it tells us what - * the length of the situation field is. - */ - if (exchange->doi->validate_situation (p->p + ISAKMP_SA_SIT_OFF, &len, - GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SA_SIT_OFF)) - { - log_print ("message_validate_sa: situation not supported"); - message_drop (msg, ISAKMP_NOTIFY_SITUATION_NOT_SUPPORTED, 0, 1, 1); - return -1; - } - - /* Reset the fields we base our proposal & transform number checks on. */ - last_sa = last_prop = 0; - last_prop_no = last_xf_no = 0; - - /* Go through the PROPOSAL payloads. */ - ZERO (&payload_set); - SET (ISAKMP_PAYLOAD_PROPOSAL, &payload_set); - if (message_parse_payloads (msg, p, ISAKMP_PAYLOAD_PROPOSAL, - p->p + ISAKMP_SA_SIT_OFF + len, &payload_set, - message_parse_proposal) == -1) - return -1; - - return 0; + set payload_set; + size_t len; + u_int32_t doi_id; + struct exchange *exchange = msg->exchange; + u_int8_t *pkt = msg->iov[0].iov_base; + + doi_id = GET_ISAKMP_SA_DOI(p->p); + if (!doi_lookup(doi_id)) { + log_print("message_validate_sa: DOI not supported"); + message_drop(msg, ISAKMP_NOTIFY_DOI_NOT_SUPPORTED, 0, 1, 1); + return -1; + } + /* + * It's time to figure out what SA this message is about. If it is + * already set, then we are creating a new phase 1 SA. Otherwise, lookup + * the SA using the cookies and the message ID. If we cannot find + * it, and the phase 1 SA is ready, setup a phase 2 SA. + */ + if (!exchange) { + if (zero_test(pkt + ISAKMP_HDR_RCOOKIE_OFF, ISAKMP_HDR_RCOOKIE_LEN)) + exchange = exchange_setup_p1(msg, doi_id); + else if (msg->isakmp_sa->flags & SA_FLAG_READY) + exchange = exchange_setup_p2(msg, doi_id); + else { + /* XXX What to do here? */ + message_free(msg); + return -1; + } + if (!exchange) { + /* XXX Log? */ + message_free(msg); + return -1; + } + } + msg->exchange = exchange; + + /* + * Create a struct sa for each SA payload handed to us unless we are the + * initiator where we only will count them. + */ + if (exchange->initiator) { + /* XXX Count SA payloads. */ + } else if (sa_create(exchange, msg->transport)) { + /* XXX Remove exchange if we just created it? */ + message_free(msg); + return -1; + } + if (exchange->phase == 1) { + msg->isakmp_sa = TAILQ_FIRST(&exchange->sa_list); + if (msg->isakmp_sa) + sa_reference(msg->isakmp_sa); + } + /* + * Let the DOI validate the situation, at the same time it tells us what + * the length of the situation field is. + */ + if (exchange->doi->validate_situation(p->p + ISAKMP_SA_SIT_OFF, &len, + GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_SA_SIT_OFF)) { + log_print("message_validate_sa: situation not supported"); + message_drop(msg, ISAKMP_NOTIFY_SITUATION_NOT_SUPPORTED, 0, 1, 1); + return -1; + } + /* + * Reset the fields we base our proposal & transform number checks + * on. + */ + last_sa = last_prop = 0; + last_prop_no = last_xf_no = 0; + + /* Go through the PROPOSAL payloads. */ + ZERO(&payload_set); + SET(ISAKMP_PAYLOAD_PROPOSAL, &payload_set); + if (message_parse_payloads(msg, p, ISAKMP_PAYLOAD_PROPOSAL, + p->p + ISAKMP_SA_SIT_OFF + len, &payload_set, + message_parse_proposal) == -1) + return -1; + + return 0; } /* Validate the signature payload P in message MSG. */ static int -message_validate_sig (struct message *msg, struct payload *p) +message_validate_sig(struct message * msg, struct payload * p) { - if (!msg->exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_sig: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - /* XXX Not implemented yet. */ - return 0; + if (!msg->exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_sig: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* XXX Not implemented yet. */ + return 0; } /* Validate the transform payload P in message MSG. */ static int -message_validate_transform (struct message *msg, struct payload *p) +message_validate_transform(struct message * msg, struct payload * p) { - u_int8_t proto = GET_ISAKMP_PROP_PROTO (p->context->p); - u_int8_t *prop = p->context->p; - - if (!msg->exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_transform: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - if (msg->exchange->doi - ->validate_transform_id (proto, GET_ISAKMP_TRANSFORM_ID (p->p))) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_TRANSFORM_ID, 0, 1, 1); - return -1; - } - - /* Check that the reserved field is zero. */ - if (!zero_test (p->p + ISAKMP_TRANSFORM_RESERVED_OFF, - ISAKMP_TRANSFORM_RESERVED_LEN)) - { - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - /* - * Check that we get monotonically increasing transform numbers per proposal. - */ - if (prop != last_prop) - last_prop = prop; - else if (GET_ISAKMP_TRANSFORM_NO (p->p) <= last_xf_no) - { - message_drop (msg, ISAKMP_NOTIFY_BAD_PROPOSAL_SYNTAX, 0, 1, 1); - return -1; - } - last_xf_no = GET_ISAKMP_TRANSFORM_NO (p->p); - - /* Validate the attributes. */ - if (attribute_map (p->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (p->p) - - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - msg->exchange->doi->validate_attribute, msg)) - { - message_drop (msg, ISAKMP_NOTIFY_ATTRIBUTES_NOT_SUPPORTED, 0, 1, 1); - return -1; - } - - return 0; + u_int8_t proto = GET_ISAKMP_PROP_PROTO(p->context->p); + u_int8_t *prop = p->context->p; + + if (!msg->exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_transform: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + if (msg->exchange->doi + ->validate_transform_id(proto, GET_ISAKMP_TRANSFORM_ID(p->p))) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_TRANSFORM_ID, 0, 1, 1); + return -1; + } + /* Check that the reserved field is zero. */ + if (!zero_test(p->p + ISAKMP_TRANSFORM_RESERVED_OFF, + ISAKMP_TRANSFORM_RESERVED_LEN)) { + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* + * Check that we get monotonically increasing transform numbers per proposal. + */ + if (prop != last_prop) + last_prop = prop; + else if (GET_ISAKMP_TRANSFORM_NO(p->p) <= last_xf_no) { + message_drop(msg, ISAKMP_NOTIFY_BAD_PROPOSAL_SYNTAX, 0, 1, 1); + return -1; + } + last_xf_no = GET_ISAKMP_TRANSFORM_NO(p->p); + + /* Validate the attributes. */ + if (attribute_map(p->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(p->p) + - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + msg->exchange->doi->validate_attribute, msg)) { + message_drop(msg, ISAKMP_NOTIFY_ATTRIBUTES_NOT_SUPPORTED, 0, 1, 1); + return -1; + } + return 0; } /* Validate the vendor payload P in message MSG. */ static int -message_validate_vendor (struct message *msg, struct payload *p) +message_validate_vendor(struct message * msg, struct payload * p) { - if (!msg->exchange) - { - /* We should have an exchange at this point. */ - log_print ("message_validate_vendor: payload out of sequence"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - return -1; - } - - /* Vendor IDs are only allowed in phase 1. */ - if (msg->exchange->phase != 1) - { - message_drop (msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); - return -1; - } - - LOG_DBG ((LOG_MESSAGE, 40, "message_validate_vendor: vendor ID seen")); - return 0; + if (!msg->exchange) { + /* We should have an exchange at this point. */ + log_print("message_validate_vendor: payload out of sequence"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* Vendor IDs are only allowed in phase 1. */ + if (msg->exchange->phase != 1) { + message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); + return -1; + } + LOG_DBG((LOG_MESSAGE, 40, "message_validate_vendor: vendor ID seen")); + return 0; } /* @@ -1020,20 +928,20 @@ message_validate_vendor (struct message *msg, struct payload *p) * node so we can go from transforms -> payloads -> SAs. */ static int -message_index_payload (struct message *msg, struct payload *p, - u_int8_t payload, u_int8_t *buf) +message_index_payload(struct message * msg, struct payload * p, + u_int8_t payload, u_int8_t * buf) { - struct payload *payload_node; - - /* Put the payload pointer into the right bucket. */ - payload_node = malloc (sizeof *payload_node); - if (!payload_node) - return -1; - payload_node->p = buf; - payload_node->context = p; - payload_node->flags = 0; - TAILQ_INSERT_TAIL (&msg->payload[payload], payload_node, link); - return 0; + struct payload *payload_node; + + /* Put the payload pointer into the right bucket. */ + payload_node = malloc(sizeof *payload_node); + if (!payload_node) + return -1; + payload_node->p = buf; + payload_node->context = p; + payload_node->flags = 0; + TAILQ_INSERT_TAIL(&msg->payload[payload], payload_node, link); + return 0; } /* @@ -1043,45 +951,44 @@ message_index_payload (struct message *msg, struct payload *p, * computed message length (i.e. without padding) in msg->iov[0].iov_len. */ static int -message_sort_payloads (struct message *msg, u_int8_t next) +message_sort_payloads(struct message * msg, u_int8_t next) { - set payload_set; - int i, sz; - - ZERO (&payload_set); - for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) - if (i != ISAKMP_PAYLOAD_PROPOSAL && i != ISAKMP_PAYLOAD_TRANSFORM) - SET (i, &payload_set); - sz = - message_parse_payloads (msg, 0, next, - (u_int8_t *)msg->iov[0].iov_base + ISAKMP_HDR_SZ, - &payload_set, message_index_payload); - if (sz == -1) - return -1; - msg->iov[0].iov_len = ISAKMP_HDR_SZ + sz; - SET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base, ISAKMP_HDR_SZ + sz); - return 0; + set payload_set; + int i, sz; + + ZERO(&payload_set); + for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) + if (i != ISAKMP_PAYLOAD_PROPOSAL && i != ISAKMP_PAYLOAD_TRANSFORM) + SET(i, &payload_set); + sz = + message_parse_payloads(msg, 0, next, + (u_int8_t *) msg->iov[0].iov_base + ISAKMP_HDR_SZ, + &payload_set, message_index_payload); + if (sz == -1) + return -1; + msg->iov[0].iov_len = ISAKMP_HDR_SZ + sz; + SET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base, ISAKMP_HDR_SZ + sz); + return 0; } /* Run all the generic payload tests that the drafts specify. */ static int -message_validate_payloads (struct message *msg) +message_validate_payloads(struct message * msg) { - int i; - struct payload *p; - - for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) - for (p = TAILQ_FIRST (&msg->payload[i]); p; p = TAILQ_NEXT (p, link)) - { - LOG_DBG ((LOG_MESSAGE, 60, - "message_validate_payloads: " - "payload %s at %p of message %p", - constant_name (isakmp_payload_cst, i), p->p, msg)); - field_dump_payload (fields[i - ISAKMP_PAYLOAD_SA], p->p); - if (message_validate_payload[i - ISAKMP_PAYLOAD_SA] (msg, p)) - return -1; - } - return 0; + int i; + struct payload *p; + + for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_RESERVED_MIN; i++) + for (p = TAILQ_FIRST(&msg->payload[i]); p; p = TAILQ_NEXT(p, link)) { + LOG_DBG((LOG_MESSAGE, 60, + "message_validate_payloads: " + "payload %s at %p of message %p", + constant_name(isakmp_payload_cst, i), p->p, msg)); + field_dump_payload(fields[i - ISAKMP_PAYLOAD_SA], p->p); + if (message_validate_payload[i - ISAKMP_PAYLOAD_SA] (msg, p)) + return -1; + } + return 0; } /* @@ -1090,390 +997,342 @@ message_validate_payloads (struct message *msg) * the exchange this message, MSG, is part of, and feed it there. */ int -message_recv (struct message *msg) +message_recv(struct message * msg) { - u_int8_t *buf = msg->iov[0].iov_base; - size_t sz = msg->iov[0].iov_len; - u_int8_t exch_type; - int setup_isakmp_sa, msgid_is_zero; - u_int8_t flags; - struct keystate *ks = 0; - struct proto tmp_proto; - struct sa tmp_sa; - - /* Messages shorter than an ISAKMP header are bad. */ - if (sz < ISAKMP_HDR_SZ || sz != GET_ISAKMP_HDR_LENGTH (buf)) - { - log_print ("message_recv: bad message length"); - message_drop (msg, ISAKMP_NOTIFY_UNEQUAL_PAYLOAD_LENGTHS, 0, 1, 1); - return -1; - } - + u_int8_t *buf = msg->iov[0].iov_base; + size_t sz = msg->iov[0].iov_len; + u_int8_t exch_type; + int setup_isakmp_sa, msgid_is_zero; + u_int8_t flags; + struct keystate *ks = 0; + struct proto tmp_proto; + struct sa tmp_sa; + + /* Messages shorter than an ISAKMP header are bad. */ + if (sz < ISAKMP_HDR_SZ || sz != GET_ISAKMP_HDR_LENGTH(buf)) { + log_print("message_recv: bad message length"); + message_drop(msg, ISAKMP_NOTIFY_UNEQUAL_PAYLOAD_LENGTHS, 0, 1, 1); + return -1; + } #ifdef USE_DEBUG - /* Possibly dump a raw hex image of the message to the log channel. */ - message_dump_raw ("message_recv", msg, LOG_MESSAGE); + /* Possibly dump a raw hex image of the message to the log channel. */ + message_dump_raw("message_recv", msg, LOG_MESSAGE); #endif - /* - * If the responder cookie is zero, this is a request to setup an ISAKMP SA. - * Otherwise the cookies should refer to an existing ISAKMP SA. - * - * XXX This is getting ugly, please reread later to see if it can be made - * nicer. - */ - setup_isakmp_sa = zero_test (buf + ISAKMP_HDR_RCOOKIE_OFF, - ISAKMP_HDR_RCOOKIE_LEN); - if (setup_isakmp_sa) - { - /* - * This might be a retransmission of a former ISAKMP SA setup message. - * If so, just drop it. - * XXX Must we really look in both the SA and exchange pools? - */ - if (exchange_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF) - || sa_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF)) - { - /* - * XXX Later we should differentiate between retransmissions and - * potential replay attacks. - */ - LOG_DBG ((LOG_MESSAGE, 90, - "message_recv: dropping setup for existing SA")); - message_free (msg); - return -1; - } - } - else - { - msg->isakmp_sa = sa_lookup_by_header (buf, 0); - if (msg->isakmp_sa) - sa_reference (msg->isakmp_sa); - - /* - * If we cannot find an ISAKMP SA out of the cookies, this is either - * a responder's first reply, and we need to upgrade our exchange, - * or it's just plain invalid cookies. - */ - if (!msg->isakmp_sa) - { - msg->exchange - = exchange_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF); - if (msg->exchange && msg->exchange->phase == 1 - && zero_test (msg->exchange->cookies + ISAKMP_HDR_RCOOKIE_OFF, - ISAKMP_HDR_RCOOKIE_LEN)) - exchange_upgrade_p1 (msg); - else - { - log_print ("message_recv: invalid cookie(s) %08x%08x %08x%08x", - decode_32 (buf + ISAKMP_HDR_ICOOKIE_OFF), - decode_32 (buf + ISAKMP_HDR_ICOOKIE_OFF + 4), - decode_32 (buf + ISAKMP_HDR_RCOOKIE_OFF), - decode_32 (buf + ISAKMP_HDR_RCOOKIE_OFF + 4)); - tmp_proto.sa = &tmp_sa; - tmp_sa.doi = doi_lookup (ISAKMP_DOI_ISAKMP); - tmp_proto.proto = ISAKMP_PROTO_ISAKMP; - tmp_proto.spi_sz[1] = ISAKMP_HDR_COOKIES_LEN; - tmp_proto.spi[1] = buf + ISAKMP_HDR_COOKIES_OFF; - message_drop (msg, ISAKMP_NOTIFY_INVALID_COOKIE, &tmp_proto, 1, - 1); - return -1; - } + /* + * If the responder cookie is zero, this is a request to setup an ISAKMP SA. + * Otherwise the cookies should refer to an existing ISAKMP SA. + * + * XXX This is getting ugly, please reread later to see if it can be made + * nicer. + */ + setup_isakmp_sa = zero_test(buf + ISAKMP_HDR_RCOOKIE_OFF, + ISAKMP_HDR_RCOOKIE_LEN); + if (setup_isakmp_sa) { + /* + * This might be a retransmission of a former ISAKMP SA setup message. + * If so, just drop it. + * XXX Must we really look in both the SA and exchange pools? + */ + if (exchange_lookup_from_icookie(buf + ISAKMP_HDR_ICOOKIE_OFF) + || sa_lookup_from_icookie(buf + ISAKMP_HDR_ICOOKIE_OFF)) { + /* + * XXX Later we should differentiate between retransmissions and + * potential replay attacks. + */ + LOG_DBG((LOG_MESSAGE, 90, + "message_recv: dropping setup for existing SA")); + message_free(msg); + return -1; + } + } else { + msg->isakmp_sa = sa_lookup_by_header(buf, 0); + if (msg->isakmp_sa) + sa_reference(msg->isakmp_sa); + + /* + * If we cannot find an ISAKMP SA out of the cookies, this is either + * a responder's first reply, and we need to upgrade our exchange, + * or it's just plain invalid cookies. + */ + if (!msg->isakmp_sa) { + msg->exchange + = exchange_lookup_from_icookie(buf + ISAKMP_HDR_ICOOKIE_OFF); + if (msg->exchange && msg->exchange->phase == 1 + && zero_test(msg->exchange->cookies + ISAKMP_HDR_RCOOKIE_OFF, + ISAKMP_HDR_RCOOKIE_LEN)) + exchange_upgrade_p1(msg); + else { + log_print("message_recv: invalid cookie(s) %08x%08x %08x%08x", + decode_32(buf + ISAKMP_HDR_ICOOKIE_OFF), + decode_32(buf + ISAKMP_HDR_ICOOKIE_OFF + 4), + decode_32(buf + ISAKMP_HDR_RCOOKIE_OFF), + decode_32(buf + ISAKMP_HDR_RCOOKIE_OFF + 4)); + tmp_proto.sa = &tmp_sa; + tmp_sa.doi = doi_lookup(ISAKMP_DOI_ISAKMP); + tmp_proto.proto = ISAKMP_PROTO_ISAKMP; + tmp_proto.spi_sz[1] = ISAKMP_HDR_COOKIES_LEN; + tmp_proto.spi[1] = buf + ISAKMP_HDR_COOKIES_OFF; + message_drop(msg, ISAKMP_NOTIFY_INVALID_COOKIE, &tmp_proto, 1, + 1); + return -1; + } #if 0 - msg->isakmp_sa - = sa_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF); - if (msg->isakmp_sa) - sa_isakmp_upgrade (msg); + msg->isakmp_sa + = sa_lookup_from_icookie(buf + ISAKMP_HDR_ICOOKIE_OFF); + if (msg->isakmp_sa) + sa_isakmp_upgrade(msg); #endif + } + msg->exchange = exchange_lookup(buf, 1); + } + + if (message_check_duplicate(msg)) + return -1; + + if (GET_ISAKMP_HDR_NEXT_PAYLOAD(buf) >= ISAKMP_PAYLOAD_RESERVED_MIN) { + log_print("message_recv: " + "invalid payload type %d in ISAKMP header " + "(check passphrases, if applicable and in Phase 1)", + GET_ISAKMP_HDR_NEXT_PAYLOAD(buf)); + message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); + return -1; + } + /* Validate that the message is of version 1.0. */ + if (ISAKMP_VERSION_MAJOR(GET_ISAKMP_HDR_VERSION(buf)) != 1) { + log_print("message_recv: invalid version major %d", + ISAKMP_VERSION_MAJOR(GET_ISAKMP_HDR_VERSION(buf))); + message_drop(msg, ISAKMP_NOTIFY_INVALID_MAJOR_VERSION, 0, 1, 1); + return -1; + } + if (ISAKMP_VERSION_MINOR(GET_ISAKMP_HDR_VERSION(buf)) != 0) { + log_print("message_recv: invalid version minor %d", + ISAKMP_VERSION_MINOR(GET_ISAKMP_HDR_VERSION(buf))); + message_drop(msg, ISAKMP_NOTIFY_INVALID_MINOR_VERSION, 0, 1, 1); + return -1; + } + /* + * Validate the exchange type. If it's a DOI-specified exchange wait until + * after all payloads have been seen for the validation as the SA payload + * might not yet have been parsed, thus the DOI might be unknown. + */ + exch_type = GET_ISAKMP_HDR_EXCH_TYPE(buf); + if (exch_type == ISAKMP_EXCH_NONE + || (exch_type >= ISAKMP_EXCH_FUTURE_MIN && + exch_type <= ISAKMP_EXCH_FUTURE_MAX) + || (setup_isakmp_sa && exch_type >= ISAKMP_EXCH_DOI_MIN)) { + log_print("message_recv: invalid exchange type %s", + constant_name(isakmp_exch_cst, exch_type)); + message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, 1); + return -1; + } + /* + * Check for unrecognized flags, or the encryption flag when we don't + * have an ISAKMP SA to decrypt with. + */ + flags = GET_ISAKMP_HDR_FLAGS(buf); + if (flags + & ~(ISAKMP_FLAGS_ENC | ISAKMP_FLAGS_COMMIT | ISAKMP_FLAGS_AUTH_ONLY)) { + log_print("message_recv: invalid flags 0x%x", + GET_ISAKMP_HDR_FLAGS(buf)); + message_drop(msg, ISAKMP_NOTIFY_INVALID_FLAGS, 0, 1, 1); + return -1; + } + /* + * If we are about to setup an ISAKMP SA, the message ID must be + * zero. + */ + msgid_is_zero = zero_test(buf + ISAKMP_HDR_MESSAGE_ID_OFF, + ISAKMP_HDR_MESSAGE_ID_LEN); + if (setup_isakmp_sa && !msgid_is_zero) { + log_print("message_recv: invalid message id"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_MESSAGE_ID, 0, 1, 1); + return -1; + } + if (!setup_isakmp_sa && msgid_is_zero) { + /* + * XXX Very likely redundant, look at the else clause of the + * if (setup_isakmp_sa) statement above. + */ + msg->exchange = exchange_lookup(buf, 0); + if (!msg->exchange) { + log_print("message_recv: phase 1 message after ISAKMP SA is ready"); + message_free(msg); + return -1; + } else if (msg->exchange->last_sent) { + LOG_DBG((LOG_MESSAGE, 80, + "message_recv: resending last message from phase 1")); + message_send(msg->exchange->last_sent); + } + } + if (flags & ISAKMP_FLAGS_ENC) { + if (!msg->isakmp_sa) { + LOG_DBG((LOG_MISC, 10, + "message_recv: no isakmp_sa for encrypted message")); + message_free(msg); + return -1; + } + /* Decrypt rest of message using a DOI-specified IV. */ + ks = msg->isakmp_sa->doi->get_keystate(msg); + if (!ks) { + message_free(msg); + return -1; + } + msg->orig = malloc(sz); + if (!msg->orig) { + message_free(msg); + free(ks); + return -1; + } + memcpy(msg->orig, buf, sz); + crypto_decrypt(ks, buf + ISAKMP_HDR_SZ, sz - ISAKMP_HDR_SZ); + } else + msg->orig = buf; + msg->orig_sz = sz; + + /* IKE packet capture */ + message_packet_log(msg); + + /* + * Check the overall payload structure at the same time as indexing them by + * type. + */ + if (GET_ISAKMP_HDR_NEXT_PAYLOAD(buf) != ISAKMP_PAYLOAD_NONE + && message_sort_payloads(msg, GET_ISAKMP_HDR_NEXT_PAYLOAD(buf))) { + if (ks) + free(ks); + return -1; + } + /* + * Run generic payload tests now. If anything fails these checks, the + * message needs either to be retained for later duplicate checks or + * freed entirely. + * XXX Should SAs and even transports be cleaned up then too? + */ + if (message_validate_payloads(msg)) { + if (ks) + free(ks); + return -1; + } + /* + * If we have not found an exchange by now something is definitely + * wrong. + */ + if (!msg->exchange) { + log_print("message_recv: no exchange"); + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + if (ks) + free(ks); + return -1; + } + /* + * Now we can validate DOI-specific exchange types. If we have no SA + * DOI-specific exchange types are definitely wrong. + */ + if (exch_type >= ISAKMP_EXCH_DOI_MIN && exch_type <= ISAKMP_EXCH_DOI_MAX + && msg->exchange->doi->validate_exchange(exch_type)) { + log_print("message_recv: invalid DOI exchange type %d", exch_type); + message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, 1); + if (ks) + free(ks); + return -1; + } + /* Make sure the IV we used gets saved in the proper SA. */ + if (ks) { + if (!msg->exchange->keystate) { + msg->exchange->keystate = ks; + msg->exchange->crypto = ks->xf; + } else + free(ks); } - msg->exchange = exchange_lookup (buf, 1); - } - - if (message_check_duplicate (msg)) - return -1; - - if (GET_ISAKMP_HDR_NEXT_PAYLOAD (buf) >= ISAKMP_PAYLOAD_RESERVED_MIN) - { - log_print ("message_recv: " - "invalid payload type %d in ISAKMP header " - "(check passphrases, if applicable and in Phase 1)", - GET_ISAKMP_HDR_NEXT_PAYLOAD (buf)); - message_drop (msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); - return -1; - } - - /* Validate that the message is of version 1.0. */ - if (ISAKMP_VERSION_MAJOR (GET_ISAKMP_HDR_VERSION (buf)) != 1) - { - log_print ("message_recv: invalid version major %d", - ISAKMP_VERSION_MAJOR (GET_ISAKMP_HDR_VERSION (buf))); - message_drop (msg, ISAKMP_NOTIFY_INVALID_MAJOR_VERSION, 0, 1, 1); - return -1; - } - - if (ISAKMP_VERSION_MINOR (GET_ISAKMP_HDR_VERSION (buf)) != 0) - { - log_print ("message_recv: invalid version minor %d", - ISAKMP_VERSION_MINOR (GET_ISAKMP_HDR_VERSION (buf))); - message_drop (msg, ISAKMP_NOTIFY_INVALID_MINOR_VERSION, 0, 1, 1); - return -1; - } - - /* - * Validate the exchange type. If it's a DOI-specified exchange wait until - * after all payloads have been seen for the validation as the SA payload - * might not yet have been parsed, thus the DOI might be unknown. - */ - exch_type = GET_ISAKMP_HDR_EXCH_TYPE (buf); - if (exch_type == ISAKMP_EXCH_NONE - || (exch_type >= ISAKMP_EXCH_FUTURE_MIN && - exch_type <= ISAKMP_EXCH_FUTURE_MAX) - || (setup_isakmp_sa && exch_type >= ISAKMP_EXCH_DOI_MIN)) - { - log_print ("message_recv: invalid exchange type %s", - constant_name (isakmp_exch_cst, exch_type)); - message_drop (msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, 1); - return -1; - } - - /* - * Check for unrecognized flags, or the encryption flag when we don't - * have an ISAKMP SA to decrypt with. - */ - flags = GET_ISAKMP_HDR_FLAGS (buf); - if (flags - & ~(ISAKMP_FLAGS_ENC | ISAKMP_FLAGS_COMMIT | ISAKMP_FLAGS_AUTH_ONLY)) - { - log_print ("message_recv: invalid flags 0x%x", - GET_ISAKMP_HDR_FLAGS (buf)); - message_drop (msg, ISAKMP_NOTIFY_INVALID_FLAGS, 0, 1, 1); - return -1; - } - - /* If we are about to setup an ISAKMP SA, the message ID must be zero. */ - msgid_is_zero = zero_test (buf + ISAKMP_HDR_MESSAGE_ID_OFF, - ISAKMP_HDR_MESSAGE_ID_LEN); - if (setup_isakmp_sa && !msgid_is_zero) - { - log_print ("message_recv: invalid message id"); - message_drop (msg, ISAKMP_NOTIFY_INVALID_MESSAGE_ID, 0, 1, 1); - return -1; - } - - if (!setup_isakmp_sa && msgid_is_zero) - { - /* - * XXX Very likely redundant, look at the else clause of the - * if (setup_isakmp_sa) statement above. - */ - msg->exchange = exchange_lookup (buf, 0); - if (!msg->exchange) - { - log_print ("message_recv: phase 1 message after ISAKMP SA is ready"); - message_free (msg); - return -1; - } - else if (msg->exchange->last_sent) - { - LOG_DBG ((LOG_MESSAGE, 80, - "message_recv: resending last message from phase 1")); - message_send (msg->exchange->last_sent); - } - } - - if (flags & ISAKMP_FLAGS_ENC) - { - if (!msg->isakmp_sa) - { - LOG_DBG ((LOG_MISC, 10, - "message_recv: no isakmp_sa for encrypted message")); - message_free (msg); - return -1; - } - - /* Decrypt rest of message using a DOI-specified IV. */ - ks = msg->isakmp_sa->doi->get_keystate (msg); - if (!ks) - { - message_free (msg); - return -1; - } - msg->orig = malloc (sz); - if (!msg->orig) - { - message_free (msg); - free (ks); - return -1; - } - memcpy (msg->orig, buf, sz); - crypto_decrypt (ks, buf + ISAKMP_HDR_SZ, sz - ISAKMP_HDR_SZ); - } - else - msg->orig = buf; - msg->orig_sz = sz; - - /* IKE packet capture */ - message_packet_log (msg); - - /* - * Check the overall payload structure at the same time as indexing them by - * type. - */ - if (GET_ISAKMP_HDR_NEXT_PAYLOAD (buf) != ISAKMP_PAYLOAD_NONE - && message_sort_payloads (msg, GET_ISAKMP_HDR_NEXT_PAYLOAD (buf))) - { - if (ks) - free (ks); - return -1; - } - - /* - * Run generic payload tests now. If anything fails these checks, the - * message needs either to be retained for later duplicate checks or - * freed entirely. - * XXX Should SAs and even transports be cleaned up then too? - */ - if (message_validate_payloads (msg)) - { - if (ks) - free (ks); - return -1; - } - - /* If we have not found an exchange by now something is definitely wrong. */ - if (!msg->exchange) - { - log_print ("message_recv: no exchange"); - message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); - if (ks) - free (ks); - return -1; - } - - /* - * Now we can validate DOI-specific exchange types. If we have no SA - * DOI-specific exchange types are definitely wrong. - */ - if (exch_type >= ISAKMP_EXCH_DOI_MIN && exch_type <= ISAKMP_EXCH_DOI_MAX - && msg->exchange->doi->validate_exchange (exch_type)) - { - log_print ("message_recv: invalid DOI exchange type %d", exch_type); - message_drop (msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, 1); - if (ks) - free (ks); - return -1; - } - - /* Make sure the IV we used gets saved in the proper SA. */ - if (ks) - { - if (!msg->exchange->keystate) - { - msg->exchange->keystate = ks; - msg->exchange->crypto = ks->xf; - } - else - free (ks); - } - - /* Handle the flags. */ - if (flags & ISAKMP_FLAGS_ENC) - msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; - if ((msg->exchange->flags & EXCHANGE_FLAG_COMMITTED) == 0 - && (flags & ISAKMP_FLAGS_COMMIT)) - msg->exchange->flags |= EXCHANGE_FLAG_HE_COMMITTED; - - /* Require encryption as soon as we have the keystate for it. */ - if ((flags & ISAKMP_FLAGS_ENC) == 0 && - (msg->exchange->phase == 2 || msg->exchange->keystate)) - { - log_print ("message_recv: cleartext phase %d message", - msg->exchange->phase); - message_drop (msg, ISAKMP_NOTIFY_INVALID_FLAGS, 0, 1, 1); - return -1; - } - - /* OK let the exchange logic do the rest. */ - exchange_run (msg); - - return 0; + /* Handle the flags. */ + if (flags & ISAKMP_FLAGS_ENC) + msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT; + if ((msg->exchange->flags & EXCHANGE_FLAG_COMMITTED) == 0 + && (flags & ISAKMP_FLAGS_COMMIT)) + msg->exchange->flags |= EXCHANGE_FLAG_HE_COMMITTED; + + /* Require encryption as soon as we have the keystate for it. */ + if ((flags & ISAKMP_FLAGS_ENC) == 0 && + (msg->exchange->phase == 2 || msg->exchange->keystate)) { + log_print("message_recv: cleartext phase %d message", + msg->exchange->phase); + message_drop(msg, ISAKMP_NOTIFY_INVALID_FLAGS, 0, 1, 1); + return -1; + } + /* OK let the exchange logic do the rest. */ + exchange_run(msg); + + return 0; } void -message_send_expire (struct message *msg) +message_send_expire(struct message * msg) { - msg->retrans = 0; + msg->retrans = 0; - message_send (msg); + message_send(msg); } /* Queue up message MSG for transmittal. */ void -message_send (struct message *msg) +message_send(struct message * msg) { - struct exchange *exchange = msg->exchange; - struct message *m; - struct msg_head *q; - - /* Remove retransmissions on this message */ - if (msg->retrans) - { - timer_remove_event (msg->retrans); - msg->retrans = 0; - } - - /* IKE packet capture */ - message_packet_log (msg); - - /* - * If the ISAKMP SA has set up encryption, encrypt the message. - * However, in a retransmit, it is already encrypted. - */ - if ((msg->flags & MSG_ENCRYPTED) == 0 - && exchange->flags & EXCHANGE_FLAG_ENCRYPT) - { - if (!exchange->keystate) - { - exchange->keystate = exchange->doi->get_keystate (msg); - exchange->crypto = exchange->keystate->xf; - exchange->flags |= EXCHANGE_FLAG_ENCRYPT; - } - - if (message_encrypt (msg)) - { - /* XXX Log. */ - return; - } - } - - /* Keep the COMMIT bit on. */ - if (exchange->flags & EXCHANGE_FLAG_COMMITTED) - SET_ISAKMP_HDR_FLAGS (msg->iov[0].iov_base, - GET_ISAKMP_HDR_FLAGS (msg->iov[0].iov_base) - | ISAKMP_FLAGS_COMMIT); + struct exchange *exchange = msg->exchange; + struct message *m; + struct msg_head *q; + + /* Remove retransmissions on this message */ + if (msg->retrans) { + timer_remove_event(msg->retrans); + msg->retrans = 0; + } + /* IKE packet capture */ + message_packet_log(msg); + + /* + * If the ISAKMP SA has set up encryption, encrypt the message. + * However, in a retransmit, it is already encrypted. + */ + if ((msg->flags & MSG_ENCRYPTED) == 0 + && exchange->flags & EXCHANGE_FLAG_ENCRYPT) { + if (!exchange->keystate) { + exchange->keystate = exchange->doi->get_keystate(msg); + exchange->crypto = exchange->keystate->xf; + exchange->flags |= EXCHANGE_FLAG_ENCRYPT; + } + if (message_encrypt(msg)) { + /* XXX Log. */ + return; + } + } + /* Keep the COMMIT bit on. */ + if (exchange->flags & EXCHANGE_FLAG_COMMITTED) + SET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base, + GET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base) + | ISAKMP_FLAGS_COMMIT); #ifdef USE_DEBUG - message_dump_raw ("message_send", msg, LOG_MESSAGE); + message_dump_raw("message_send", msg, LOG_MESSAGE); #endif - msg->flags |= MSG_IN_TRANSIT; - exchange->in_transit = msg; - - /* - * If we get a retransmission of a message before our response - * has left the queue, don't queue it again, as it will result - * in a circular list. - */ - q = msg->flags & MSG_PRIORITIZED ? &msg->transport->prio_sendq : - &msg->transport->sendq; - - for (m = TAILQ_FIRST (q); m; m = TAILQ_NEXT (m, link)) - if (m == msg) - { - LOG_DBG ((LOG_MESSAGE, 60, - "message_send: msg %p already on sendq %p", m, q)); - return; - } - - TAILQ_INSERT_TAIL (q, msg, link); + msg->flags |= MSG_IN_TRANSIT; + exchange->in_transit = msg; + + /* + * If we get a retransmission of a message before our response + * has left the queue, don't queue it again, as it will result + * in a circular list. + */ + q = msg->flags & MSG_PRIORITIZED ? &msg->transport->prio_sendq : + &msg->transport->sendq; + + for (m = TAILQ_FIRST(q); m; m = TAILQ_NEXT(m, link)) + if (m == msg) { + LOG_DBG((LOG_MESSAGE, 60, + "message_send: msg %p already on sendq %p", m, q)); + return; + } + TAILQ_INSERT_TAIL(q, msg, link); } /* @@ -1482,20 +1341,20 @@ message_send (struct message *msg) * identifying the exchange. */ void -message_setup_header (struct message *msg, u_int8_t exchange, u_int8_t flags, - u_int8_t *msg_id) +message_setup_header(struct message * msg, u_int8_t exchange, u_int8_t flags, + u_int8_t * msg_id) { - u_int8_t *buf = msg->iov[0].iov_base; - - SET_ISAKMP_HDR_ICOOKIE (buf, msg->exchange->cookies); - SET_ISAKMP_HDR_RCOOKIE (buf, - msg->exchange->cookies + ISAKMP_HDR_ICOOKIE_LEN); - SET_ISAKMP_HDR_NEXT_PAYLOAD (buf, ISAKMP_PAYLOAD_NONE); - SET_ISAKMP_HDR_VERSION (buf, ISAKMP_VERSION_MAKE (1, 0)); - SET_ISAKMP_HDR_EXCH_TYPE (buf, exchange); - SET_ISAKMP_HDR_FLAGS (buf, flags); - SET_ISAKMP_HDR_MESSAGE_ID (buf, msg_id); - SET_ISAKMP_HDR_LENGTH (buf, msg->iov[0].iov_len); + u_int8_t *buf = msg->iov[0].iov_base; + + SET_ISAKMP_HDR_ICOOKIE(buf, msg->exchange->cookies); + SET_ISAKMP_HDR_RCOOKIE(buf, + msg->exchange->cookies + ISAKMP_HDR_ICOOKIE_LEN); + SET_ISAKMP_HDR_NEXT_PAYLOAD(buf, ISAKMP_PAYLOAD_NONE); + SET_ISAKMP_HDR_VERSION(buf, ISAKMP_VERSION_MAKE(1, 0)); + SET_ISAKMP_HDR_EXCH_TYPE(buf, exchange); + SET_ISAKMP_HDR_FLAGS(buf, flags); + SET_ISAKMP_HDR_MESSAGE_ID(buf, msg_id); + SET_ISAKMP_HDR_LENGTH(buf, msg->iov[0].iov_len); } /* @@ -1507,66 +1366,64 @@ message_setup_header (struct message *msg, u_int8_t exchange, u_int8_t flags, * XXX We might want to resize the iov array several slots at a time. */ int -message_add_payload (struct message *msg, u_int8_t payload, u_int8_t *buf, - size_t sz, int link) +message_add_payload(struct message * msg, u_int8_t payload, u_int8_t * buf, + size_t sz, int link) { - struct iovec *new_iov; - struct payload *payload_node; - - payload_node = calloc (1, sizeof *payload_node); - if (!payload_node) - { - log_error ("message_add_payload: calloc (1, %lu) failed", - (unsigned long)sizeof *payload_node); - return -1; - } - new_iov - = (struct iovec *)realloc (msg->iov, (msg->iovlen + 1) * sizeof *msg->iov); - if (!new_iov) - { - log_error ("message_add_payload: realloc (%p, %lu) failed", msg->iov, - (msg->iovlen + 1) * (unsigned long)sizeof *msg->iov); - free (payload_node); - return -1; - } - msg->iov = new_iov; - new_iov[msg->iovlen].iov_base = buf; - new_iov[msg->iovlen].iov_len = sz; - msg->iovlen++; - if (link) - *msg->nextp = payload; - msg->nextp = buf + ISAKMP_GEN_NEXT_PAYLOAD_OFF; - *msg->nextp = ISAKMP_PAYLOAD_NONE; - SET_ISAKMP_GEN_RESERVED (buf, 0); - SET_ISAKMP_GEN_LENGTH (buf, sz); - SET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base, - GET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base) + sz); - - /* - * For the sake of exchange_validate we index the payloads even in outgoing - * messages, however context and flags are uninteresting in this situation. - */ - payload_node->p = buf; - TAILQ_INSERT_TAIL (&msg->payload[payload], payload_node, link); - return 0; + struct iovec *new_iov; + struct payload *payload_node; + + payload_node = calloc(1, sizeof *payload_node); + if (!payload_node) { + log_error("message_add_payload: calloc (1, %lu) failed", + (unsigned long) sizeof *payload_node); + return -1; + } + new_iov + = (struct iovec *) realloc(msg->iov, (msg->iovlen + 1) * sizeof *msg->iov); + if (!new_iov) { + log_error("message_add_payload: realloc (%p, %lu) failed", msg->iov, + (msg->iovlen + 1) * (unsigned long) sizeof *msg->iov); + free(payload_node); + return -1; + } + msg->iov = new_iov; + new_iov[msg->iovlen].iov_base = buf; + new_iov[msg->iovlen].iov_len = sz; + msg->iovlen++; + if (link) + *msg->nextp = payload; + msg->nextp = buf + ISAKMP_GEN_NEXT_PAYLOAD_OFF; + *msg->nextp = ISAKMP_PAYLOAD_NONE; + SET_ISAKMP_GEN_RESERVED(buf, 0); + SET_ISAKMP_GEN_LENGTH(buf, sz); + SET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base, + GET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base) + sz); + + /* + * For the sake of exchange_validate we index the payloads even in outgoing + * messages, however context and flags are uninteresting in this situation. + */ + payload_node->p = buf; + TAILQ_INSERT_TAIL(&msg->payload[payload], payload_node, link); + return 0; } /* XXX Move up when ready. */ struct info_args { - char discr; - u_int32_t doi; - u_int8_t proto; - u_int16_t spi_sz; - union { - struct { - u_int16_t msg_type; - u_int8_t *spi; - } n; - struct { - u_int16_t nspis; - u_int8_t *spis; - } d; - } u; + char discr; + u_int32_t doi; + u_int8_t proto; + u_int16_t spi_sz; + union { + struct { + u_int16_t msg_type; + u_int8_t *spi; + } n; + struct { + u_int16_t nspis; + u_int8_t *spis; + } d; + } u; }; /* @@ -1581,127 +1438,117 @@ struct info_args { * status value? */ void -message_send_notification (struct message *msg, struct sa *isakmp_sa, - u_int16_t notify, struct proto *proto, - int incoming) +message_send_notification(struct message * msg, struct sa * isakmp_sa, + u_int16_t notify, struct proto * proto, + int incoming) { - struct info_args args; - struct sa *doi_sa = proto ? proto->sa : isakmp_sa; - - args.discr = 'N'; - args.doi = doi_sa ? doi_sa->doi->id : ISAKMP_DOI_ISAKMP; - args.proto = proto ? proto->proto : ISAKMP_PROTO_ISAKMP; - args.spi_sz = proto ? proto->spi_sz[incoming] : 0; - args.u.n.msg_type = notify; - args.u.n.spi = proto ? proto->spi[incoming] : 0; - if (isakmp_sa && (isakmp_sa->flags & SA_FLAG_READY)) - exchange_establish_p2 (isakmp_sa, ISAKMP_EXCH_INFO, 0, &args, 0 ,0); - else - exchange_establish_p1 (msg->transport, ISAKMP_EXCH_INFO, - msg->exchange - ? msg->exchange->doi->id : ISAKMP_DOI_ISAKMP, - 0, &args, 0, 0); + struct info_args args; + struct sa *doi_sa = proto ? proto->sa : isakmp_sa; + + args.discr = 'N'; + args.doi = doi_sa ? doi_sa->doi->id : ISAKMP_DOI_ISAKMP; + args.proto = proto ? proto->proto : ISAKMP_PROTO_ISAKMP; + args.spi_sz = proto ? proto->spi_sz[incoming] : 0; + args.u.n.msg_type = notify; + args.u.n.spi = proto ? proto->spi[incoming] : 0; + if (isakmp_sa && (isakmp_sa->flags & SA_FLAG_READY)) + exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO, 0, &args, 0, 0); + else + exchange_establish_p1(msg->transport, ISAKMP_EXCH_INFO, + msg->exchange + ? msg->exchange->doi->id : ISAKMP_DOI_ISAKMP, + 0, &args, 0, 0); } /* Send a DELETE inside an informational exchange for each protocol in SA. */ void -message_send_delete (struct sa *sa) +message_send_delete(struct sa * sa) { - struct info_args args; - struct proto *proto; - struct sa *isakmp_sa; - struct sockaddr *dst; - - sa->transport->vtbl->get_dst (sa->transport, &dst); - isakmp_sa = sa_isakmp_lookup_by_peer (dst, sysdep_sa_len (dst)); - if (!isakmp_sa) - { - /* - * XXX We ought to setup an ISAKMP SA with our peer here and send - * the DELETE over that one. - */ - return; - } - - args.discr = 'D'; - args.doi = sa->doi->id; - args.u.d.nspis = 1; - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - args.proto = proto->proto; - args.spi_sz = proto->spi_sz[1]; - args.u.d.spis = proto->spi[1]; - exchange_establish_p2 (isakmp_sa, ISAKMP_EXCH_INFO, 0, &args, 0 ,0); - } + struct info_args args; + struct proto *proto; + struct sa *isakmp_sa; + struct sockaddr *dst; + + sa->transport->vtbl->get_dst(sa->transport, &dst); + isakmp_sa = sa_isakmp_lookup_by_peer(dst, sysdep_sa_len(dst)); + if (!isakmp_sa) { + /* + * XXX We ought to setup an ISAKMP SA with our peer here and send + * the DELETE over that one. + */ + return; + } + args.discr = 'D'; + args.doi = sa->doi->id; + args.u.d.nspis = 1; + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + args.proto = proto->proto; + args.spi_sz = proto->spi_sz[1]; + args.u.d.spis = proto->spi[1]; + exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO, 0, &args, 0, 0); + } } /* Build the informational message into MSG. */ int -message_send_info (struct message *msg) +message_send_info(struct message * msg) { - u_int8_t *buf; - size_t sz; - struct info_args *args = msg->extra; - u_int8_t payload; - - /* Let the DOI get the first hand on the message. */ - if (msg->exchange->doi->informational_pre_hook) - if (msg->exchange->doi->informational_pre_hook (msg)) - return -1; - - sz = (args->discr == 'N' ? ISAKMP_NOTIFY_SPI_OFF + args->spi_sz - : ISAKMP_DELETE_SPI_OFF + args->u.d.nspis * args->spi_sz); - buf = calloc (1, sz); - if (!buf) - { - log_error ("message_send_info: calloc (1, %lu) failed", (unsigned long)sz); - message_free (msg); - return -1; - } - - switch (args->discr) - { - case 'N': - /* Build the NOTIFY payload. */ - payload = ISAKMP_PAYLOAD_NOTIFY; - SET_ISAKMP_NOTIFY_DOI (buf, args->doi); - SET_ISAKMP_NOTIFY_PROTO (buf, args->proto); - SET_ISAKMP_NOTIFY_SPI_SZ (buf, args->spi_sz); - SET_ISAKMP_NOTIFY_MSG_TYPE (buf, args->u.n.msg_type); - memcpy (buf + ISAKMP_NOTIFY_SPI_OFF, args->u.n.spi, args->spi_sz); - break; - - case 'D': - default: /* Silence GCC. */ - /* Build the DELETE payload. */ - payload = ISAKMP_PAYLOAD_DELETE; - SET_ISAKMP_DELETE_DOI (buf, args->doi); - SET_ISAKMP_DELETE_PROTO (buf, args->proto); - SET_ISAKMP_DELETE_SPI_SZ (buf, args->spi_sz); - SET_ISAKMP_DELETE_NSPIS (buf, args->u.d.nspis); - memcpy (buf + ISAKMP_DELETE_SPI_OFF, args->u.d.spis, - args->u.d.nspis * args->spi_sz); - msg->flags |= MSG_PRIORITIZED; - break; - } - - if (message_add_payload (msg, payload, buf, sz, 1)) - { - free (buf); - message_free (msg); - return -1; - } - - /* Let the DOI get the last hand on the message. */ - if (msg->exchange->doi->informational_post_hook) - if (msg->exchange->doi->informational_post_hook (msg)) - { - message_free (msg); - return -1; - } + u_int8_t *buf; + size_t sz; + struct info_args *args = msg->extra; + u_int8_t payload; + + /* Let the DOI get the first hand on the message. */ + if (msg->exchange->doi->informational_pre_hook) + if (msg->exchange->doi->informational_pre_hook(msg)) + return -1; + + sz = (args->discr == 'N' ? ISAKMP_NOTIFY_SPI_OFF + args->spi_sz + : ISAKMP_DELETE_SPI_OFF + args->u.d.nspis * args->spi_sz); + buf = calloc(1, sz); + if (!buf) { + log_error("message_send_info: calloc (1, %lu) failed", (unsigned long) sz); + message_free(msg); + return -1; + } + switch (args->discr) { + case 'N': + /* Build the NOTIFY payload. */ + payload = ISAKMP_PAYLOAD_NOTIFY; + SET_ISAKMP_NOTIFY_DOI(buf, args->doi); + SET_ISAKMP_NOTIFY_PROTO(buf, args->proto); + SET_ISAKMP_NOTIFY_SPI_SZ(buf, args->spi_sz); + SET_ISAKMP_NOTIFY_MSG_TYPE(buf, args->u.n.msg_type); + memcpy(buf + ISAKMP_NOTIFY_SPI_OFF, args->u.n.spi, args->spi_sz); + break; + + case 'D': + default: /* Silence GCC. */ + /* Build the DELETE payload. */ + payload = ISAKMP_PAYLOAD_DELETE; + SET_ISAKMP_DELETE_DOI(buf, args->doi); + SET_ISAKMP_DELETE_PROTO(buf, args->proto); + SET_ISAKMP_DELETE_SPI_SZ(buf, args->spi_sz); + SET_ISAKMP_DELETE_NSPIS(buf, args->u.d.nspis); + memcpy(buf + ISAKMP_DELETE_SPI_OFF, args->u.d.spis, + args->u.d.nspis * args->spi_sz); + msg->flags |= MSG_PRIORITIZED; + break; + } - return 0; + if (message_add_payload(msg, payload, buf, sz, 1)) { + free(buf); + message_free(msg); + return -1; + } + /* Let the DOI get the last hand on the message. */ + if (msg->exchange->doi->informational_post_hook) + if (msg->exchange->doi->informational_post_hook(msg)) { + message_free(msg); + return -1; + } + return 0; } /* @@ -1711,45 +1558,42 @@ message_send_info (struct message *msg) * set, free the message when ready with it. */ void -message_drop (struct message *msg, int notify, struct proto *proto, - int incoming, int clean) +message_drop(struct message * msg, int notify, struct proto * proto, + int incoming, int clean) { - struct transport *t = msg->transport; - struct sockaddr *dst; - char *address; - short port = 0; - - t->vtbl->get_dst (t, &dst); - if (sockaddr2text (dst, &address, 0)) - { - log_error ("message_drop: sockaddr2text () failed"); - address = 0; - } - - switch (dst->sa_family) - { - case AF_INET: - port = ((struct sockaddr_in *)dst)->sin_port; - break; - case AF_INET6: - port = ((struct sockaddr_in6 *)dst)->sin6_port; - break; - default: - log_print ("message_drop: unknown protocol family %d", dst->sa_family); - } - - log_print ("dropped message from %s port %d due to notification type %s", - address ? address : "<unknown>", htons (port), - constant_name (isakmp_notify_cst, notify)); - - if (address) - free (address); - - /* If specified, return a notification. */ - if (notify) - message_send_notification (msg, msg->isakmp_sa, notify, proto, incoming); - if (clean) - message_free (msg); + struct transport *t = msg->transport; + struct sockaddr *dst; + char *address; + short port = 0; + + t->vtbl->get_dst(t, &dst); + if (sockaddr2text(dst, &address, 0)) { + log_error("message_drop: sockaddr2text () failed"); + address = 0; + } + switch (dst->sa_family) { + case AF_INET: + port = ((struct sockaddr_in *) dst)->sin_port; + break; + case AF_INET6: + port = ((struct sockaddr_in6 *) dst)->sin6_port; + break; + default: + log_print("message_drop: unknown protocol family %d", dst->sa_family); + } + + log_print("dropped message from %s port %d due to notification type %s", + address ? address : "<unknown>", htons(port), + constant_name(isakmp_notify_cst, notify)); + + if (address) + free(address); + + /* If specified, return a notification. */ + if (notify) + message_send_notification(msg, msg->isakmp_sa, notify, proto, incoming); + if (clean) + message_free(msg); } /* @@ -1757,57 +1601,51 @@ message_drop (struct message *msg, int notify, struct proto *proto, * as we can without resorting to per-payload handling. */ void -message_dump_raw (char *header, struct message *msg, int class) +message_dump_raw(char *header, struct message * msg, int class) { - u_int32_t i, j, k = 0; - char buf[80], *p = buf; - - LOG_DBG ((class, 70, "%s: message %p", header, msg)); - field_dump_payload (isakmp_hdr_fld, msg->iov[0].iov_base); - for (i = 0; i < msg->iovlen; i++) - for (j = 0; j < msg->iov[i].iov_len; j++) - { - snprintf (p, sizeof buf - (int)(p - buf), "%02x", - ((u_int8_t *)msg->iov[i].iov_base)[j]); - p += 2; - if (++k % 32 == 0) - { - *p = '\0'; - LOG_DBG ((class, 70, "%s: %s", header, buf)); - p = buf; - } - else if (k % 4 == 0) - *p++ = ' '; - } - *p = '\0'; - if (p != buf) - LOG_DBG ((class, 70, "%s: %s", header, buf)); + u_int32_t i, j, k = 0; + char buf[80], *p = buf; + + LOG_DBG((class, 70, "%s: message %p", header, msg)); + field_dump_payload(isakmp_hdr_fld, msg->iov[0].iov_base); + for (i = 0; i < msg->iovlen; i++) + for (j = 0; j < msg->iov[i].iov_len; j++) { + snprintf(p, sizeof buf - (int) (p - buf), "%02x", + ((u_int8_t *) msg->iov[i].iov_base)[j]); + p += 2; + if (++k % 32 == 0) { + *p = '\0'; + LOG_DBG((class, 70, "%s: %s", header, buf)); + p = buf; + } else if (k % 4 == 0) + *p++ = ' '; + } + *p = '\0'; + if (p != buf) + LOG_DBG((class, 70, "%s: %s", header, buf)); } static void -message_packet_log (struct message *msg) +message_packet_log(struct message * msg) { #ifdef USE_DEBUG - struct sockaddr *src, *dst; - - /* Don't log retransmissions. Redundant for incoming packets... */ - if (msg->xmits > 0) - return; - - /* Figure out direction. */ - if (msg->exchange && msg->exchange->initiator ^ (msg->exchange->step % 2)) - { - msg->transport->vtbl->get_src (msg->transport, &src); - msg->transport->vtbl->get_dst (msg->transport, &dst); - } - else - { - msg->transport->vtbl->get_src (msg->transport, &dst); - msg->transport->vtbl->get_dst (msg->transport, &src); - } - - log_packet_iov (src, dst, msg->iov, msg->iovlen); -#endif /* USE_DEBUG */ + struct sockaddr *src, *dst; + + /* Don't log retransmissions. Redundant for incoming packets... */ + if (msg->xmits > 0) + return; + + /* Figure out direction. */ + if (msg->exchange && msg->exchange->initiator ^ (msg->exchange->step % 2)) { + msg->transport->vtbl->get_src(msg->transport, &src); + msg->transport->vtbl->get_dst(msg->transport, &dst); + } else { + msg->transport->vtbl->get_src(msg->transport, &dst); + msg->transport->vtbl->get_dst(msg->transport, &src); + } + + log_packet_iov(src, dst, msg->iov, msg->iovlen); +#endif /* USE_DEBUG */ } /* @@ -1817,56 +1655,54 @@ message_packet_log (struct message *msg) * we encrypt. */ static int -message_encrypt (struct message *msg) +message_encrypt(struct message * msg) { - struct exchange *exchange = msg->exchange; - size_t i, sz = 0; - u_int8_t *buf; - - /* If no payloads, nothing to do. */ - if (msg->iovlen == 1) - return 0; - - /* - * For encryption we need to put all payloads together in a single buffer. - * This buffer should be padded to the current crypto transform's blocksize. - */ - for (i = 1; i < msg->iovlen; i++) - sz += msg->iov[i].iov_len; - sz = ((sz + exchange->crypto->blocksize - 1) / exchange->crypto->blocksize) - * exchange->crypto->blocksize; - buf = realloc (msg->iov[1].iov_base, sz); - if (!buf) - { - log_error ("message_encrypt: realloc (%p, %lu) failed", - msg->iov[1].iov_base, (unsigned long)sz); - return -1; - } - msg->iov[1].iov_base = buf; - for (i = 2; i < msg->iovlen; i++) - { - memcpy (buf + msg->iov[1].iov_len, msg->iov[i].iov_base, - msg->iov[i].iov_len); - msg->iov[1].iov_len += msg->iov[i].iov_len; - free (msg->iov[i].iov_base); - } - - /* Pad with zeroes. */ - memset (buf + msg->iov[1].iov_len, '\0', sz - msg->iov[1].iov_len); - msg->iov[1].iov_len = sz; - msg->iovlen = 2; - - SET_ISAKMP_HDR_FLAGS (msg->iov[0].iov_base, - GET_ISAKMP_HDR_FLAGS (msg->iov[0].iov_base) - | ISAKMP_FLAGS_ENC); - SET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base, ISAKMP_HDR_SZ + sz); - crypto_encrypt (exchange->keystate, buf, msg->iov[1].iov_len); - msg->flags |= MSG_ENCRYPTED; - - /* Update the IV so we can decrypt the next incoming message. */ - crypto_update_iv (exchange->keystate); - - return 0; + struct exchange *exchange = msg->exchange; + size_t i, sz = 0; + u_int8_t *buf; + + /* If no payloads, nothing to do. */ + if (msg->iovlen == 1) + return 0; + + /* + * For encryption we need to put all payloads together in a single buffer. + * This buffer should be padded to the current crypto transform's blocksize. + */ + for (i = 1; i < msg->iovlen; i++) + sz += msg->iov[i].iov_len; + sz = ((sz + exchange->crypto->blocksize - 1) / exchange->crypto->blocksize) + * exchange->crypto->blocksize; + buf = realloc(msg->iov[1].iov_base, sz); + if (!buf) { + log_error("message_encrypt: realloc (%p, %lu) failed", + msg->iov[1].iov_base, (unsigned long) sz); + return -1; + } + msg->iov[1].iov_base = buf; + for (i = 2; i < msg->iovlen; i++) { + memcpy(buf + msg->iov[1].iov_len, msg->iov[i].iov_base, + msg->iov[i].iov_len); + msg->iov[1].iov_len += msg->iov[i].iov_len; + free(msg->iov[i].iov_base); + } + + /* Pad with zeroes. */ + memset(buf + msg->iov[1].iov_len, '\0', sz - msg->iov[1].iov_len); + msg->iov[1].iov_len = sz; + msg->iovlen = 2; + + SET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base, + GET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base) + | ISAKMP_FLAGS_ENC); + SET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base, ISAKMP_HDR_SZ + sz); + crypto_encrypt(exchange->keystate, buf, msg->iov[1].iov_len); + msg->flags |= MSG_ENCRYPTED; + + /* Update the IV so we can decrypt the next incoming message. */ + crypto_update_iv(exchange->keystate); + + return 0; } /* @@ -1874,77 +1710,70 @@ message_encrypt (struct message *msg) * this specific SA. */ static int -message_check_duplicate (struct message *msg) +message_check_duplicate(struct message * msg) { - struct exchange *exchange = msg->exchange; - size_t sz = msg->iov[0].iov_len; - u_int8_t *pkt = msg->iov[0].iov_base; - - /* If no SA has been found, we cannot test, thus it's good. */ - if (!exchange) - return 0; - - LOG_DBG ((LOG_MESSAGE, 90, "message_check_duplicate: last_received %p", - exchange->last_received)); - if (exchange->last_received) - { - LOG_DBG_BUF ((LOG_MESSAGE, 95, - "message_check_duplicate: last_received", - exchange->last_received->orig, - exchange->last_received->orig_sz)); - /* Is it a duplicate, lose the new one. */ - if (sz == exchange->last_received->orig_sz - && memcmp (pkt, exchange->last_received->orig, sz) == 0) - { - LOG_DBG ((LOG_MESSAGE, 80, - "message_check_duplicate: dropping dup")); - - /* - * Retransmit if the previos sent message was the last of an - * exchange, otherwise just wait for the ordinary retransmission. - */ - if (exchange->last_sent && (exchange->last_sent->flags & MSG_LAST)) - message_send (exchange->last_sent); - message_free (msg); - return -1; - } - } - - /* - * As this new message is an indication that state is moving forward - * at the peer, remove the retransmit timer on our last message. - */ - if (exchange->last_sent) - { - if (exchange->last_sent == exchange->in_transit) - { - if (exchange->in_transit->flags & MSG_PRIORITIZED) - TAILQ_REMOVE (&exchange->in_transit->transport->prio_sendq, - exchange->in_transit, link); - else - TAILQ_REMOVE (&exchange->in_transit->transport->sendq, - exchange->in_transit, link); - exchange->in_transit = 0; - } - message_free (exchange->last_sent); - exchange->last_sent = 0; - } - - return 0; + struct exchange *exchange = msg->exchange; + size_t sz = msg->iov[0].iov_len; + u_int8_t *pkt = msg->iov[0].iov_base; + + /* If no SA has been found, we cannot test, thus it's good. */ + if (!exchange) + return 0; + + LOG_DBG((LOG_MESSAGE, 90, "message_check_duplicate: last_received %p", + exchange->last_received)); + if (exchange->last_received) { + LOG_DBG_BUF((LOG_MESSAGE, 95, + "message_check_duplicate: last_received", + exchange->last_received->orig, + exchange->last_received->orig_sz)); + /* Is it a duplicate, lose the new one. */ + if (sz == exchange->last_received->orig_sz + && memcmp(pkt, exchange->last_received->orig, sz) == 0) { + LOG_DBG((LOG_MESSAGE, 80, + "message_check_duplicate: dropping dup")); + + /* + * Retransmit if the previos sent message was the last of an + * exchange, otherwise just wait for the ordinary retransmission. + */ + if (exchange->last_sent && (exchange->last_sent->flags & MSG_LAST)) + message_send(exchange->last_sent); + message_free(msg); + return -1; + } + } + /* + * As this new message is an indication that state is moving forward + * at the peer, remove the retransmit timer on our last message. + */ + if (exchange->last_sent) { + if (exchange->last_sent == exchange->in_transit) { + if (exchange->in_transit->flags & MSG_PRIORITIZED) + TAILQ_REMOVE(&exchange->in_transit->transport->prio_sendq, + exchange->in_transit, link); + else + TAILQ_REMOVE(&exchange->in_transit->transport->sendq, + exchange->in_transit, link); + exchange->in_transit = 0; + } + message_free(exchange->last_sent); + exchange->last_sent = 0; + } + return 0; } /* Helper to message_negotiate_sa. */ static INLINE struct payload * -step_transform (struct payload *tp, struct payload **propp, - struct payload **sap) +step_transform(struct payload * tp, struct payload ** propp, + struct payload ** sap) { - tp = TAILQ_NEXT (tp, link); - if (tp) - { - *propp = tp->context; - *sap = (*propp)->context; - } - return tp; + tp = TAILQ_NEXT(tp, link); + if (tp) { + *propp = tp->context; + *sap = (*propp)->context; + } + return tp; } /* @@ -1952,172 +1781,173 @@ step_transform (struct payload *tp, struct payload **propp, * SA payload) we accept as a full protection suite. */ int -message_negotiate_sa (struct message *msg, - int (*validate) (struct exchange *, struct sa *, - struct sa *)) +message_negotiate_sa(struct message * msg, + int (*validate) (struct exchange *, struct sa *, + struct sa *)) { - struct payload *tp, *propp, *sap, *next_tp = 0, *next_propp, *next_sap; - struct payload *saved_tp = 0, *saved_propp = 0, *saved_sap = 0; - struct sa *sa; - struct proto *proto; - int suite_ok_so_far = 0; - struct exchange *exchange = msg->exchange; - - /* - * This algorithm is a weird bottom-up thing... mostly due to the - * payload links pointing upwards. - * - * The algorithm goes something like this: - * Foreach transform - * If transform is compatible - * Remember that this protocol can work - * Skip to last transform of this protocol - * If next transform belongs to a new protocol inside the same suite - * If no transform was found for the current protocol - * Forget all earlier transforms for protocols in this suite - * Skip to last transform of this suite - * If next transform belongs to a new suite - * If the current protocol had an OK transform - * Skip to the last transform of this SA - * If the next transform belongs to a new SA - * If no transforms have been chosen - * Issue a NO_PROPOSAL_CHOSEN notification - */ - - sa = TAILQ_FIRST (&exchange->sa_list); - for (tp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); tp; - tp = next_tp) - { - propp = tp->context; - sap = propp->context; - sap->flags |= PL_MARK; - next_tp = step_transform (tp, &next_propp, &next_sap); - - /* For each transform, see if it is compatible. */ - if (!attribute_map (tp->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (tp->p) - - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - exchange->doi->is_attribute_incompatible, msg)) - { - LOG_DBG ((LOG_NEGOTIATION, 30, - "message_negotiate_sa: " - "transform %d proto %d proposal %d ok", - GET_ISAKMP_TRANSFORM_NO (tp->p), - GET_ISAKMP_PROP_PROTO (propp->p), - GET_ISAKMP_PROP_NO (propp->p))); - if (sa_add_transform (sa, tp, exchange->initiator, &proto)) - goto cleanup; - suite_ok_so_far = 1; - - saved_tp = next_tp; - saved_propp = next_propp; - saved_sap = next_sap; - /* Skip to last transform of this protocol proposal. */ - while ((next_tp = step_transform (tp, &next_propp, &next_sap)) - && next_propp == propp) - tp = next_tp; - } - - retry_transform: - /* - * Figure out if we will be looking at a new protocol proposal - * inside the current protection suite. - */ - if (next_tp && propp != next_propp && sap == next_sap - && (GET_ISAKMP_PROP_NO (propp->p) - == GET_ISAKMP_PROP_NO (next_propp->p))) - { - if (!suite_ok_so_far) - { - LOG_DBG ((LOG_NEGOTIATION, 30, - "message_negotiate_sa: proto %d proposal %d failed", - GET_ISAKMP_PROP_PROTO (propp->p), - GET_ISAKMP_PROP_NO (propp->p))); - /* Remove potentially succeeded choices from the SA. */ - while (TAILQ_FIRST (&sa->protos)) - TAILQ_REMOVE (&sa->protos, TAILQ_FIRST (&sa->protos), link); - - /* Skip to the last transform of this protection suite. */ - while ((next_tp = step_transform (tp, &next_propp, &next_sap)) - && (GET_ISAKMP_PROP_NO (next_propp->p) - == GET_ISAKMP_PROP_NO (propp->p)) - && next_sap == sap) - tp = next_tp; - } - suite_ok_so_far = 0; - } - - /* Figure out if we will be looking at a new protection suite. */ - if (!next_tp - || (propp != next_propp - && (GET_ISAKMP_PROP_NO (propp->p) - != GET_ISAKMP_PROP_NO (next_propp->p))) - || sap != next_sap) - { - /* - * Check if the suite we just considered was OK, if so we check - * it against the accepted ones. - */ - if (suite_ok_so_far) - { - if (!validate || validate (exchange, sa, msg->isakmp_sa)) - { - LOG_DBG ((LOG_NEGOTIATION, 30, - "message_negotiate_sa: proposal %d succeeded", - GET_ISAKMP_PROP_NO (propp->p))); - - /* Skip to the last transform of this SA. */ - while ((next_tp - = step_transform (tp, &next_propp, &next_sap)) - && next_sap == sap) - tp = next_tp; + struct payload *tp, *propp, *sap, *next_tp = 0, *next_propp, *next_sap; + struct payload *saved_tp = 0, *saved_propp = 0, *saved_sap = 0; + struct sa *sa; + struct proto *proto; + int suite_ok_so_far = 0; + struct exchange *exchange = msg->exchange; + + /* + * This algorithm is a weird bottom-up thing... mostly due to the + * payload links pointing upwards. + * + * The algorithm goes something like this: + * Foreach transform + * If transform is compatible + * Remember that this protocol can work + * Skip to last transform of this protocol + * If next transform belongs to a new protocol inside the same suite + * If no transform was found for the current protocol + * Forget all earlier transforms for protocols in this suite + * Skip to last transform of this suite + * If next transform belongs to a new suite + * If the current protocol had an OK transform + * Skip to the last transform of this SA + * If the next transform belongs to a new SA + * If no transforms have been chosen + * Issue a NO_PROPOSAL_CHOSEN notification + */ + + sa = TAILQ_FIRST(&exchange->sa_list); + for (tp = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); tp; + tp = next_tp) { + propp = tp->context; + sap = propp->context; + sap->flags |= PL_MARK; + next_tp = step_transform(tp, &next_propp, &next_sap); + + /* For each transform, see if it is compatible. */ + if (!attribute_map(tp->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(tp->p) + - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + exchange->doi->is_attribute_incompatible, msg)) { + LOG_DBG((LOG_NEGOTIATION, 30, + "message_negotiate_sa: " + "transform %d proto %d proposal %d ok", + GET_ISAKMP_TRANSFORM_NO(tp->p), + GET_ISAKMP_PROP_PROTO(propp->p), + GET_ISAKMP_PROP_NO(propp->p))); + if (sa_add_transform(sa, tp, exchange->initiator, &proto)) + goto cleanup; + suite_ok_so_far = 1; + + saved_tp = next_tp; + saved_propp = next_propp; + saved_sap = next_sap; + /* Skip to last transform of this protocol proposal. */ + while ((next_tp = step_transform(tp, &next_propp, &next_sap)) + && next_propp == propp) + tp = next_tp; + } +retry_transform: + /* + * Figure out if we will be looking at a new protocol proposal + * inside the current protection suite. + */ + if (next_tp && propp != next_propp && sap == next_sap + && (GET_ISAKMP_PROP_NO(propp->p) + == GET_ISAKMP_PROP_NO(next_propp->p))) { + if (!suite_ok_so_far) { + LOG_DBG((LOG_NEGOTIATION, 30, + "message_negotiate_sa: proto %d proposal %d failed", + GET_ISAKMP_PROP_PROTO(propp->p), + GET_ISAKMP_PROP_NO(propp->p))); + /* + * Remove potentially succeeded choices from + * the SA. + */ + while (TAILQ_FIRST(&sa->protos)) + TAILQ_REMOVE(&sa->protos, TAILQ_FIRST(&sa->protos), link); + + /* + * Skip to the last transform of this + * protection suite. + */ + while ((next_tp = step_transform(tp, &next_propp, &next_sap)) + && (GET_ISAKMP_PROP_NO(next_propp->p) + == GET_ISAKMP_PROP_NO(propp->p)) + && next_sap == sap) + tp = next_tp; + } + suite_ok_so_far = 0; + } + /* + * Figure out if we will be looking at a new protection + * suite. + */ + if (!next_tp + || (propp != next_propp + && (GET_ISAKMP_PROP_NO(propp->p) + != GET_ISAKMP_PROP_NO(next_propp->p))) + || sap != next_sap) { + /* + * Check if the suite we just considered was OK, if so we check + * it against the accepted ones. + */ + if (suite_ok_so_far) { + if (!validate || validate(exchange, sa, msg->isakmp_sa)) { + LOG_DBG((LOG_NEGOTIATION, 30, + "message_negotiate_sa: proposal %d succeeded", + GET_ISAKMP_PROP_NO(propp->p))); + + /* + * Skip to the last transform of this + * SA. + */ + while ((next_tp + = step_transform(tp, &next_propp, &next_sap)) + && next_sap == sap) + tp = next_tp; + } else { + /* Backtrack. */ + LOG_DBG((LOG_NEGOTIATION, 30, + "message_negotiate_sa: proposal %d failed", + GET_ISAKMP_PROP_NO(propp->p))); + next_tp = saved_tp; + next_propp = saved_propp; + next_sap = saved_sap; + suite_ok_so_far = 0; + + /* + * Remove potentially succeeded + * choices from the SA. + */ + while (TAILQ_FIRST(&sa->protos)) + TAILQ_REMOVE(&sa->protos, TAILQ_FIRST(&sa->protos), + link); + goto retry_transform; + } + } } - else - { - /* Backtrack. */ - LOG_DBG ((LOG_NEGOTIATION, 30, - "message_negotiate_sa: proposal %d failed", - GET_ISAKMP_PROP_NO (propp->p))); - next_tp = saved_tp; - next_propp = saved_propp; - next_sap = saved_sap; - suite_ok_so_far = 0; - - /* Remove potentially succeeded choices from the SA. */ - while (TAILQ_FIRST (&sa->protos)) - TAILQ_REMOVE (&sa->protos, TAILQ_FIRST (&sa->protos), - link); - goto retry_transform; + /* Have we walked all the proposals of an SA? */ + if (!next_tp || sap != next_sap) { + if (!suite_ok_so_far) { + /* + * XXX We cannot possibly call this a drop... seeing we just turn + * down one of the offers, can we? I suggest renaming + * message_drop to something else. + */ + log_print("message_negotiate_sa: no compatible proposal found"); + message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); + } + sa = TAILQ_NEXT(sa, next); } - } - } - - /* Have we walked all the proposals of an SA? */ - if (!next_tp || sap != next_sap) - { - if (!suite_ok_so_far) - { - /* - * XXX We cannot possibly call this a drop... seeing we just turn - * down one of the offers, can we? I suggest renaming - * message_drop to something else. - */ - log_print ("message_negotiate_sa: no compatible proposal found"); - message_drop (msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN, 0, 1, 0); - } - sa = TAILQ_NEXT (sa, next); - } - } - return 0; - - cleanup: - /* - * Remove potentially succeeded choices from the SA. - * XXX Do we leak struct protos and related data here? - */ - while (TAILQ_FIRST (&sa->protos)) - TAILQ_REMOVE (&sa->protos, TAILQ_FIRST (&sa->protos), link); - return -1; + } + return 0; + +cleanup: + /* + * Remove potentially succeeded choices from the SA. + * XXX Do we leak struct protos and related data here? + */ + while (TAILQ_FIRST(&sa->protos)) + TAILQ_REMOVE(&sa->protos, TAILQ_FIRST(&sa->protos), link); + return -1; } /* @@ -2125,248 +1955,228 @@ message_negotiate_sa (struct message *msg, * found in the exchange MSG is part of.. */ int -message_add_sa_payload (struct message *msg) +message_add_sa_payload(struct message * msg) { - struct exchange *exchange = msg->exchange; - u_int8_t *sa_buf, *saved_nextp_sa, *saved_nextp_prop; - size_t sa_len, extra_sa_len; - int i, nprotos = 0; - struct proto *proto; - u_int8_t **transforms = 0, **proposals = 0; - size_t *transform_lens = 0, *proposal_lens = 0; - struct sa *sa; - struct doi *doi = exchange->doi; - u_int8_t *spi = 0; - size_t spi_sz; - - /* - * Generate SA payloads. - */ - for (sa = TAILQ_FIRST (&exchange->sa_list); sa; - sa = TAILQ_NEXT (sa, next)) - { - /* Setup a SA payload. */ - sa_len = ISAKMP_SA_SIT_OFF + doi->situation_size (); - extra_sa_len = 0; - sa_buf = malloc (sa_len); - if (!sa_buf) - { - log_error ("message_add_sa_payload: malloc (%lu) failed", - (unsigned long)sa_len); - goto cleanup; - } - - SET_ISAKMP_SA_DOI (sa_buf, doi->id); - doi->setup_situation (sa_buf); - - /* Count transforms. */ - nprotos = 0; - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - nprotos++; - - /* Allocate transient transform and proposal payload/size vectors. */ - transforms = calloc (nprotos, sizeof *transforms); - if (!transforms) - { - log_error ("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, - (unsigned long)sizeof *transforms); - goto cleanup; - } - - transform_lens = calloc (nprotos, sizeof *transform_lens); - if (!transform_lens) - { - log_error ("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, - (unsigned long)sizeof *transform_lens); - goto cleanup; - } - - proposals = calloc (nprotos, sizeof *proposals); - if (!proposals) - { - log_error ("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, - (unsigned long)sizeof *proposals); - goto cleanup; - } - - proposal_lens = calloc (nprotos, sizeof *proposal_lens); - if (!proposal_lens) - { - log_error ("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, - (unsigned long)sizeof *proposal_lens); - goto cleanup; - } - - /* Pick out the chosen transforms. */ - for (proto = TAILQ_FIRST (&sa->protos), i = 0; proto; - proto = TAILQ_NEXT (proto, link), i++) - { - transform_lens[i] = GET_ISAKMP_GEN_LENGTH (proto->chosen->p); - transforms[i] = malloc (transform_lens[i]); - if (!transforms[i]) - { - log_error ("message_add_sa_payload: malloc (%lu) failed", - (unsigned long)transform_lens[i]); - goto cleanup; - } - - /* Get incoming SPI from application. */ - if (doi->get_spi) - { - spi = doi->get_spi (&spi_sz, - GET_ISAKMP_PROP_PROTO (proto->chosen - ->context->p), - msg); - if (spi_sz && !spi) - goto cleanup; - proto->spi[1] = spi; - proto->spi_sz[1] = spi_sz; - } - else - spi_sz = 0; - - proposal_lens[i] = ISAKMP_PROP_SPI_OFF + spi_sz; - proposals[i] = malloc (proposal_lens[i]); - if (!proposals[i]) - { - log_error ("message_add_sa_payload: malloc (%lu) failed", - (unsigned long)proposal_lens[i]); - goto cleanup; - } - - memcpy (transforms[i], proto->chosen->p, transform_lens[i]); - memcpy (proposals[i], proto->chosen->context->p, - ISAKMP_PROP_SPI_OFF); - SET_ISAKMP_PROP_NTRANSFORMS (proposals[i], 1); - SET_ISAKMP_PROP_SPI_SZ (proposals[i], spi_sz); - if (spi_sz) - memcpy (proposals[i] + ISAKMP_PROP_SPI_OFF, spi, spi_sz); - extra_sa_len += proposal_lens[i] + transform_lens[i]; - } - - /* - * Add the payloads. As this is a SA, we need to recompute the - * lengths of the payloads containing others. We also need to - * reset these payload's "next payload type" field. - */ - if (message_add_payload (msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1)) - goto cleanup; - SET_ISAKMP_GEN_LENGTH (sa_buf, sa_len + extra_sa_len); - sa_buf = 0; - - saved_nextp_sa = msg->nextp; - for (proto = TAILQ_FIRST (&sa->protos), i = 0; proto; - proto = TAILQ_NEXT (proto, link), i++) - { - if (message_add_payload (msg, ISAKMP_PAYLOAD_PROPOSAL, proposals[i], - proposal_lens[i], i > 1)) - goto cleanup; - SET_ISAKMP_GEN_LENGTH (proposals[i], - proposal_lens[i] + transform_lens[i]); - proposals[i] = 0; - - saved_nextp_prop = msg->nextp; - if (message_add_payload (msg, ISAKMP_PAYLOAD_TRANSFORM, - transforms[i], transform_lens[i], 0)) - goto cleanup; - msg->nextp = saved_nextp_prop; - transforms[i] = 0; - } - msg->nextp = saved_nextp_sa; - - /* Free the temporary allocations made above. */ - free (transforms); - free (transform_lens); - free (proposals); - free (proposal_lens); - } - return 0; - - cleanup: - if (sa_buf) - free (sa_buf); - for (i = 0; i < nprotos; i++) - { - if (transforms[i]) - free (transforms[i]); - if (proposals[i]) - free (proposals[i]); - } - if (transforms) - free (transforms); - if (transform_lens) - free (transform_lens); - if (proposals) - free (proposals); - if (proposal_lens) - free (proposal_lens); - return -1; + struct exchange *exchange = msg->exchange; + u_int8_t *sa_buf, *saved_nextp_sa, *saved_nextp_prop; + size_t sa_len, extra_sa_len; + int i, nprotos = 0; + struct proto *proto; + u_int8_t **transforms = 0, **proposals = 0; + size_t *transform_lens = 0, *proposal_lens = 0; + struct sa *sa; + struct doi *doi = exchange->doi; + u_int8_t *spi = 0; + size_t spi_sz; + + /* + * Generate SA payloads. + */ + for (sa = TAILQ_FIRST(&exchange->sa_list); sa; + sa = TAILQ_NEXT(sa, next)) { + /* Setup a SA payload. */ + sa_len = ISAKMP_SA_SIT_OFF + doi->situation_size(); + extra_sa_len = 0; + sa_buf = malloc(sa_len); + if (!sa_buf) { + log_error("message_add_sa_payload: malloc (%lu) failed", + (unsigned long) sa_len); + goto cleanup; + } + SET_ISAKMP_SA_DOI(sa_buf, doi->id); + doi->setup_situation(sa_buf); + + /* Count transforms. */ + nprotos = 0; + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) + nprotos++; + + /* + * Allocate transient transform and proposal payload/size + * vectors. + */ + transforms = calloc(nprotos, sizeof *transforms); + if (!transforms) { + log_error("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, + (unsigned long) sizeof *transforms); + goto cleanup; + } + transform_lens = calloc(nprotos, sizeof *transform_lens); + if (!transform_lens) { + log_error("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, + (unsigned long) sizeof *transform_lens); + goto cleanup; + } + proposals = calloc(nprotos, sizeof *proposals); + if (!proposals) { + log_error("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, + (unsigned long) sizeof *proposals); + goto cleanup; + } + proposal_lens = calloc(nprotos, sizeof *proposal_lens); + if (!proposal_lens) { + log_error("message_add_sa_payload: calloc (%d, %lu) failed", nprotos, + (unsigned long) sizeof *proposal_lens); + goto cleanup; + } + /* Pick out the chosen transforms. */ + for (proto = TAILQ_FIRST(&sa->protos), i = 0; proto; + proto = TAILQ_NEXT(proto, link), i++) { + transform_lens[i] = GET_ISAKMP_GEN_LENGTH(proto->chosen->p); + transforms[i] = malloc(transform_lens[i]); + if (!transforms[i]) { + log_error("message_add_sa_payload: malloc (%lu) failed", + (unsigned long) transform_lens[i]); + goto cleanup; + } + /* Get incoming SPI from application. */ + if (doi->get_spi) { + spi = doi->get_spi(&spi_sz, + GET_ISAKMP_PROP_PROTO(proto->chosen + ->context->p), + msg); + if (spi_sz && !spi) + goto cleanup; + proto->spi[1] = spi; + proto->spi_sz[1] = spi_sz; + } else + spi_sz = 0; + + proposal_lens[i] = ISAKMP_PROP_SPI_OFF + spi_sz; + proposals[i] = malloc(proposal_lens[i]); + if (!proposals[i]) { + log_error("message_add_sa_payload: malloc (%lu) failed", + (unsigned long) proposal_lens[i]); + goto cleanup; + } + memcpy(transforms[i], proto->chosen->p, transform_lens[i]); + memcpy(proposals[i], proto->chosen->context->p, + ISAKMP_PROP_SPI_OFF); + SET_ISAKMP_PROP_NTRANSFORMS(proposals[i], 1); + SET_ISAKMP_PROP_SPI_SZ(proposals[i], spi_sz); + if (spi_sz) + memcpy(proposals[i] + ISAKMP_PROP_SPI_OFF, spi, spi_sz); + extra_sa_len += proposal_lens[i] + transform_lens[i]; + } + + /* + * Add the payloads. As this is a SA, we need to recompute the + * lengths of the payloads containing others. We also need to + * reset these payload's "next payload type" field. + */ + if (message_add_payload(msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1)) + goto cleanup; + SET_ISAKMP_GEN_LENGTH(sa_buf, sa_len + extra_sa_len); + sa_buf = 0; + + saved_nextp_sa = msg->nextp; + for (proto = TAILQ_FIRST(&sa->protos), i = 0; proto; + proto = TAILQ_NEXT(proto, link), i++) { + if (message_add_payload(msg, ISAKMP_PAYLOAD_PROPOSAL, proposals[i], + proposal_lens[i], i > 1)) + goto cleanup; + SET_ISAKMP_GEN_LENGTH(proposals[i], + proposal_lens[i] + transform_lens[i]); + proposals[i] = 0; + + saved_nextp_prop = msg->nextp; + if (message_add_payload(msg, ISAKMP_PAYLOAD_TRANSFORM, + transforms[i], transform_lens[i], 0)) + goto cleanup; + msg->nextp = saved_nextp_prop; + transforms[i] = 0; + } + msg->nextp = saved_nextp_sa; + + /* Free the temporary allocations made above. */ + free(transforms); + free(transform_lens); + free(proposals); + free(proposal_lens); + } + return 0; + +cleanup: + if (sa_buf) + free(sa_buf); + for (i = 0; i < nprotos; i++) { + if (transforms[i]) + free(transforms[i]); + if (proposals[i]) + free(proposals[i]); + } + if (transforms) + free(transforms); + if (transform_lens) + free(transform_lens); + if (proposals) + free(proposals); + if (proposal_lens) + free(proposal_lens); + return -1; } /* * Return a copy of MSG's constants starting from OFFSET and stash the size * in SZP. It is the callers responsibility to free this up. */ -u_int8_t * -message_copy (struct message *msg, size_t offset, size_t *szp) +u_int8_t * +message_copy(struct message * msg, size_t offset, size_t * szp) { - int skip = 0; - size_t i, sz = 0; - ssize_t start = -1; - u_int8_t *buf, *p; - - /* Calculate size of message and where we want to start to copy. */ - for (i = 1; i < msg->iovlen; i++) - { - sz += msg->iov[i].iov_len; - if (sz <= offset) - skip = i; - else if (start < 0) - start = offset - (sz - msg->iov[i].iov_len); - } - - /* Allocate and copy. */ - *szp = sz - offset; - buf = malloc (*szp); - if (!buf) - return 0; - p = buf; - for (i = skip + 1; i < msg->iovlen; i++) - { - memcpy (p, (u_int8_t *)msg->iov[i].iov_base + start, - msg->iov[i].iov_len - start); - p += msg->iov[i].iov_len - start; - start = 0; - } - return buf; + int skip = 0; + size_t i, sz = 0; + ssize_t start = -1; + u_int8_t *buf, *p; + + /* Calculate size of message and where we want to start to copy. */ + for (i = 1; i < msg->iovlen; i++) { + sz += msg->iov[i].iov_len; + if (sz <= offset) + skip = i; + else if (start < 0) + start = offset - (sz - msg->iov[i].iov_len); + } + + /* Allocate and copy. */ + *szp = sz - offset; + buf = malloc(*szp); + if (!buf) + return 0; + p = buf; + for (i = skip + 1; i < msg->iovlen; i++) { + memcpy(p, (u_int8_t *) msg->iov[i].iov_base + start, + msg->iov[i].iov_len - start); + p += msg->iov[i].iov_len - start; + start = 0; + } + return buf; } /* Register a post-send function POST_SEND with message MSG. */ int -message_register_post_send (struct message *msg, - void (*post_send) (struct message *)) +message_register_post_send(struct message * msg, + void (*post_send) (struct message *)) { - struct post_send *node; - - node = malloc (sizeof *node); - if (!node) - return -1; - node->func = post_send; - TAILQ_INSERT_TAIL (&msg->post_send, node, link); - return 0; + struct post_send *node; + + node = malloc(sizeof *node); + if (!node) + return -1; + node->func = post_send; + TAILQ_INSERT_TAIL(&msg->post_send, node, link); + return 0; } /* Run the post-send functions of message MSG. */ void -message_post_send (struct message *msg) +message_post_send(struct message * msg) { - struct post_send *node; - - while ((node = TAILQ_FIRST (&msg->post_send)) != 0) - { - TAILQ_REMOVE (&msg->post_send, node, link); - node->func (msg); - free (node); - } + struct post_send *node; + + while ((node = TAILQ_FIRST(&msg->post_send)) != 0) { + TAILQ_REMOVE(&msg->post_send, node, link); + node->func(msg); + free(node); + } } diff --git a/sbin/isakmpd/message.h b/sbin/isakmpd/message.h index 3cb2153336a..45fdfb30835 100644 --- a/sbin/isakmpd/message.h +++ b/sbin/isakmpd/message.h @@ -1,5 +1,5 @@ -/* $OpenBSD: message.h,v 1.17 2003/11/06 16:12:07 ho Exp $ */ -/* $EOM: message.h,v 1.51 2000/10/10 12:36:39 provos Exp $ */ +/* $OpenBSD: message.h,v 1.18 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: message.h,v 1.51 2000/10/10 12:36:39 provos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -48,19 +48,19 @@ struct sa; struct transport; struct payload { - /* Link all payloads of the same type through here. */ - TAILQ_ENTRY (payload) link; + /* Link all payloads of the same type through here. */ + TAILQ_ENTRY(payload) link; - /* The pointer to the actual payload data. */ - u_int8_t *p; + /* The pointer to the actual payload data. */ + u_int8_t *p; - /* - * A pointer to the parent payload, used for proposal and transform payloads. - */ - struct payload *context; + /* + * A pointer to the parent payload, used for proposal and transform payloads. + */ + struct payload *context; - /* Payload flags described below. */ - int flags; + /* Payload flags described below. */ + int flags; }; /* Payload flags. */ @@ -73,73 +73,73 @@ struct payload { /* A post-send chain of functions to be called. */ struct post_send { - /* Link to the next function in the chain. */ - TAILQ_ENTRY (post_send) link; + /* Link to the next function in the chain. */ + TAILQ_ENTRY(post_send) link; - /* The actual function. */ - void (*func) (struct message *); + /* The actual function. */ + void (*func) (struct message *); }; struct message { - /* Link message in send queues via this link. */ - TAILQ_ENTRY (message) link; - - /* Message flags described below. */ - u_int flags; - - /* - * This is the transport the message either arrived on or will be sent to. - */ - struct transport *transport; - - /* - * This is the ISAKMP SA protecting this message. - * XXX Needs to be redone to some keystate pointer or something. - */ - struct sa *isakmp_sa; - - /* This is the exchange where this message appears. */ - struct exchange *exchange; - - /* - * A segmented buffer structure holding the messages raw contents. On input - * only segment 0 will be filled, holding all of the message. On output, as - * long as the message body is unencrypted each segment will be one payload, - * after encryption segment 0 will be the unencrypted header, and segment 1 - * will be the encrypted payloads, all of them. - */ - struct iovec *iov; - - /* The segment count. */ - u_int iovlen; - - /* Pointer to the last "next payload" field. */ - u_int8_t *nextp; - - /* "Smart" pointers to each payload, sorted by type. */ - TAILQ_HEAD (payload_head, payload) payload[ISAKMP_PAYLOAD_RESERVED_MIN]; - - /* Number of times this message has been sent. */ - int xmits; - - /* The timeout event causing retransmission of this message. */ - struct event *retrans; - - /* The (possibly encrypted) message text, used for duplicate testing. */ - u_int8_t *orig; - size_t orig_sz; - - /* - * Extra baggage needed to travel with the message. Used transiently - * in context sensitive ways. - */ - void *extra; - - /* - * Hooks for stuff needed to be done after the message has gone out to - * the wire. - */ - TAILQ_HEAD (post_send_head, post_send) post_send; + /* Link message in send queues via this link. */ + TAILQ_ENTRY(message) link; + + /* Message flags described below. */ + u_int flags; + + /* + * This is the transport the message either arrived on or will be sent to. + */ + struct transport *transport; + + /* + * This is the ISAKMP SA protecting this message. + * XXX Needs to be redone to some keystate pointer or something. + */ + struct sa *isakmp_sa; + + /* This is the exchange where this message appears. */ + struct exchange *exchange; + + /* + * A segmented buffer structure holding the messages raw contents. On input + * only segment 0 will be filled, holding all of the message. On output, as + * long as the message body is unencrypted each segment will be one payload, + * after encryption segment 0 will be the unencrypted header, and segment 1 + * will be the encrypted payloads, all of them. + */ + struct iovec *iov; + + /* The segment count. */ + u_int iovlen; + + /* Pointer to the last "next payload" field. */ + u_int8_t *nextp; + + /* "Smart" pointers to each payload, sorted by type. */ + TAILQ_HEAD(payload_head, payload) payload[ISAKMP_PAYLOAD_RESERVED_MIN]; + + /* Number of times this message has been sent. */ + int xmits; + + /* The timeout event causing retransmission of this message. */ + struct event *retrans; + + /* The (possibly encrypted) message text, used for duplicate testing. */ + u_int8_t *orig; + size_t orig_sz; + + /* + * Extra baggage needed to travel with the message. Used transiently + * in context sensitive ways. + */ + void *extra; + + /* + * Hooks for stuff needed to be done after the message has gone out to + * the wire. + */ + TAILQ_HEAD(post_send_head, post_send) post_send; }; /* Message flags. */ @@ -160,31 +160,33 @@ struct message { /* This message should be kept on the prioritized sendq. */ #define MSG_PRIORITIZED 8 -TAILQ_HEAD (msg_head, message); - -extern int message_add_payload (struct message *, u_int8_t, u_int8_t *, - size_t, int); -extern int message_add_sa_payload (struct message *); -extern struct message *message_alloc (struct transport *, u_int8_t *, size_t); -extern struct message *message_alloc_reply (struct message *); -extern u_int8_t *message_copy (struct message *, size_t, size_t *); -extern void message_drop (struct message *, int, struct proto *, int, int); -extern void message_dump_raw (char *, struct message *, int); -extern void message_free (struct message *); -extern int message_negotiate_sa (struct message *, - int (*) (struct exchange *, struct sa *, - struct sa *)); -extern int message_recv (struct message *); -extern int message_register_post_send (struct message *, - void (*) (struct message *)); -extern void message_post_send (struct message *); -extern void message_send (struct message *); -extern void message_send_expire (struct message *); -extern void message_send_delete (struct sa *); -extern int message_send_info (struct message *); -extern void message_send_notification (struct message *, struct sa *, - u_int16_t, struct proto *, int); -extern void message_setup_header (struct message *, u_int8_t, u_int8_t, - u_int8_t *); - -#endif /* _MESSAGE_H_ */ +TAILQ_HEAD(msg_head, message); + +extern int +message_add_payload(struct message *, u_int8_t, u_int8_t *, + size_t, int); +extern int message_add_sa_payload(struct message *); +extern struct message *message_alloc(struct transport *, u_int8_t *, size_t); +extern struct message *message_alloc_reply(struct message *); +extern u_int8_t *message_copy(struct message *, size_t, size_t *); +extern void message_drop(struct message *, int, struct proto *, int, int); +extern void message_dump_raw(char *, struct message *, int); +extern void message_free(struct message *); +extern int +message_negotiate_sa(struct message *, + int (*) (struct exchange *, struct sa *, + struct sa *)); + extern int message_recv(struct message *); + extern int message_register_post_send(struct message *, + void (*) (struct message *)); + extern void message_post_send(struct message *); + extern void message_send(struct message *); + extern void message_send_expire(struct message *); + extern void message_send_delete(struct sa *); + extern int message_send_info(struct message *); + extern void message_send_notification(struct message *, struct sa *, + u_int16_t, struct proto *, int); + extern void message_setup_header(struct message *, u_int8_t, u_int8_t, + u_int8_t *); + +#endif /* _MESSAGE_H_ */ diff --git a/sbin/isakmpd/monitor.c b/sbin/isakmpd/monitor.c index a4517e1d9fb..7afaa27c2df 100644 --- a/sbin/isakmpd/monitor.c +++ b/sbin/isakmpd/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.18 2004/04/07 22:45:49 ho Exp $ */ +/* $OpenBSD: monitor.c,v 1.19 2004/04/15 18:39:26 deraadt Exp $ */ /* * Copyright (c) 2003 Håkan Olsson. All rights reserved. @@ -52,37 +52,36 @@ #include "policy.h" #include "util.h" -struct monitor_state -{ - pid_t pid; - int s; - char root[MAXPATHLEN]; -} m_state; +struct monitor_state { + pid_t pid; + int s; + char root[MAXPATHLEN]; +} m_state; volatile sig_atomic_t sigchlded = 0; volatile sig_atomic_t monitor_sighupped = 0; extern volatile sig_atomic_t sigtermed; static volatile sig_atomic_t cur_state = STATE_INIT; -extern char *ui_fifo; +extern char *ui_fifo; /* Private functions. */ -int m_write_int32 (int, int32_t); -int m_write_raw (int, char *, size_t); -int m_read_int32 (int, int32_t *); -int m_read_raw (int, char *, size_t); -void m_flush (int); - -static void m_priv_getfd (int); -static void m_priv_getsocket (int); -static void m_priv_setsockopt (int); -static void m_priv_bind (int); -static void m_priv_mkfifo (int); -static int m_priv_local_sanitize_path (char *, size_t, int); -static int m_priv_check_sockopt (int, int); -static int m_priv_check_bind (const struct sockaddr *, socklen_t); -static void m_priv_increase_state (int); -static void m_priv_test_state (int); +int m_write_int32(int, int32_t); +int m_write_raw(int, char *, size_t); +int m_read_int32(int, int32_t *); +int m_read_raw(int, char *, size_t); +void m_flush(int); + +static void m_priv_getfd(int); +static void m_priv_getsocket(int); +static void m_priv_setsockopt(int); +static void m_priv_bind(int); +static void m_priv_mkfifo(int); +static int m_priv_local_sanitize_path(char *, size_t, int); +static int m_priv_check_sockopt(int, int); +static int m_priv_check_bind(const struct sockaddr *, socklen_t); +static void m_priv_increase_state(int); +static void m_priv_test_state(int); /* * Public functions, unprivileged. @@ -90,428 +89,401 @@ static void m_priv_test_state (int); /* Setup monitor context, fork, drop child privs. */ pid_t -monitor_init (void) +monitor_init(void) { - struct passwd *pw; - int p[2]; - memset (&m_state, 0, sizeof m_state); + struct passwd *pw; + int p[2]; + + memset(&m_state, 0, sizeof m_state); - if (socketpair (AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) != 0) - log_fatal ("monitor_init: socketpair() failed"); + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) != 0) + log_fatal("monitor_init: socketpair() failed"); - pw = getpwnam (ISAKMPD_PRIVSEP_USER); - if (pw == NULL) - log_fatal ("monitor_init: getpwnam(\"%s\") failed", - ISAKMPD_PRIVSEP_USER); + pw = getpwnam(ISAKMPD_PRIVSEP_USER); + if (pw == NULL) + log_fatal("monitor_init: getpwnam(\"%s\") failed", + ISAKMPD_PRIVSEP_USER); - m_state.pid = fork (); - m_state.s = p[m_state.pid ? 1 : 0]; - strlcpy (m_state.root, pw->pw_dir, sizeof m_state.root); + m_state.pid = fork(); + m_state.s = p[m_state.pid ? 1 : 0]; + strlcpy(m_state.root, pw->pw_dir, sizeof m_state.root); - LOG_DBG ((LOG_SYSDEP, 30, "monitor_init: pid %d my fd %d", m_state.pid, + LOG_DBG((LOG_SYSDEP, 30, "monitor_init: pid %d my fd %d", m_state.pid, m_state.s)); - /* The child process should drop privileges now. */ - if (!m_state.pid) - { - if (chroot (pw->pw_dir) != 0 || chdir("/") != 0) - log_fatal ("monitor_init: chroot failed"); + /* The child process should drop privileges now. */ + if (!m_state.pid) { + if (chroot(pw->pw_dir) != 0 || chdir("/") != 0) + log_fatal("monitor_init: chroot failed"); - if (setgid (pw->pw_gid) != 0) - log_fatal ("monitor_init: setgid(%d) failed", pw->pw_gid); + if (setgid(pw->pw_gid) != 0) + log_fatal("monitor_init: setgid(%d) failed", pw->pw_gid); - if (setuid (pw->pw_uid) != 0) - log_fatal ("monitor_init: setuid(%d) failed", pw->pw_uid); + if (setuid(pw->pw_uid) != 0) + log_fatal("monitor_init: setuid(%d) failed", pw->pw_uid); - LOG_DBG ((LOG_MISC, 10, - "monitor_init: privileges dropped for child process")); - } - else - { - setproctitle ("monitor [priv]"); - } + LOG_DBG((LOG_MISC, 10, + "monitor_init: privileges dropped for child process")); + } else { + setproctitle("monitor [priv]"); + } - return m_state.pid; + return m_state.pid; } int -monitor_open (const char *path, int flags, mode_t mode) +monitor_open(const char *path, int flags, mode_t mode) { - int fd, mode32 = (int32_t) mode; - int32_t err; - char realpath[MAXPATHLEN]; - - if (path[0] == '/') - strlcpy (realpath, path, sizeof realpath); - else - snprintf (realpath, sizeof realpath, "%s/%s", m_state.root, path); - - /* Write data to priv process. */ - if (m_write_int32 (m_state.s, MONITOR_GET_FD)) - goto errout; - - if (m_write_raw (m_state.s, realpath, strlen (realpath) + 1)) - goto errout; - - if (m_write_int32 (m_state.s, flags)) - goto errout; - - if (m_write_int32 (m_state.s, mode32)) - goto errout; - - if (m_read_int32 (m_state.s, &err)) - goto errout; - - if (err != 0) - { - errno = (int)err; - return -1; - } - - /* Wait for response. */ - fd = mm_receive_fd (m_state.s); - if (fd < 0) - { - log_error ("monitor_open: mm_receive_fd () failed: %s", - strerror (errno)); - return -1; - } - - return fd; - - errout: - log_error ("monitor_open: problem talking to privileged process"); - return -1; + int fd, mode32 = (int32_t) mode; + int32_t err; + char realpath[MAXPATHLEN]; + + if (path[0] == '/') + strlcpy(realpath, path, sizeof realpath); + else + snprintf(realpath, sizeof realpath, "%s/%s", m_state.root, path); + + /* Write data to priv process. */ + if (m_write_int32(m_state.s, MONITOR_GET_FD)) + goto errout; + + if (m_write_raw(m_state.s, realpath, strlen(realpath) + 1)) + goto errout; + + if (m_write_int32(m_state.s, flags)) + goto errout; + + if (m_write_int32(m_state.s, mode32)) + goto errout; + + if (m_read_int32(m_state.s, &err)) + goto errout; + + if (err != 0) { + errno = (int) err; + return -1; + } + /* Wait for response. */ + fd = mm_receive_fd(m_state.s); + if (fd < 0) { + log_error("monitor_open: mm_receive_fd () failed: %s", + strerror(errno)); + return -1; + } + return fd; + +errout: + log_error("monitor_open: problem talking to privileged process"); + return -1; } FILE * -monitor_fopen (const char *path, const char *mode) +monitor_fopen(const char *path, const char *mode) { - FILE *fp; - int fd, flags = 0, mask, saved_errno; - - /* Only the child process is supposed to run this. */ - if (m_state.pid) - log_fatal ("[priv] bad call to monitor_fopen"); - - switch (mode[0]) - { - case 'r': - flags = (mode[1] == '+' ? O_RDWR : O_RDONLY); - break; - case 'w': - flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT | O_TRUNC; - break; - case 'a': - flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT | O_APPEND; - break; - default: - log_fatal ("monitor_fopen: bad call"); - } - - mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - - fd = monitor_open (path, flags, mask); - if (fd < 0) - return NULL; - - /* Got the fd, attach a FILE * to it. */ - fp = fdopen (fd, mode); - if (!fp) - { - log_error ("monitor_fopen: fdopen() failed"); - saved_errno = errno; - close (fd); - errno = saved_errno; - return NULL; - } - - return fp; + FILE *fp; + int fd, flags = 0, mask, saved_errno; + + /* Only the child process is supposed to run this. */ + if (m_state.pid) + log_fatal("[priv] bad call to monitor_fopen"); + + switch (mode[0]) { + case 'r': + flags = (mode[1] == '+' ? O_RDWR : O_RDONLY); + break; + case 'w': + flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT | O_TRUNC; + break; + case 'a': + flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT | O_APPEND; + break; + default: + log_fatal("monitor_fopen: bad call"); + } + + mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + + fd = monitor_open(path, flags, mask); + if (fd < 0) + return NULL; + + /* Got the fd, attach a FILE * to it. */ + fp = fdopen(fd, mode); + if (!fp) { + log_error("monitor_fopen: fdopen() failed"); + saved_errno = errno; + close(fd); + errno = saved_errno; + return NULL; + } + return fp; } int -monitor_stat (const char *path, struct stat *sb) +monitor_stat(const char *path, struct stat *sb) { - int fd, r, saved_errno; - - /* O_NONBLOCK is needed for stat'ing fifos. */ - fd = monitor_open (path, O_RDONLY | O_NONBLOCK, 0); - if (fd < 0) - return -1; - - r = fstat (fd, sb); - saved_errno = errno; - close (fd); - errno = saved_errno; - return r; + int fd, r, saved_errno; + + /* O_NONBLOCK is needed for stat'ing fifos. */ + fd = monitor_open(path, O_RDONLY | O_NONBLOCK, 0); + if (fd < 0) + return -1; + + r = fstat(fd, sb); + saved_errno = errno; + close(fd); + errno = saved_errno; + return r; } int -monitor_socket (int domain, int type, int protocol) +monitor_socket(int domain, int type, int protocol) { - int s; - int32_t err; + int s; + int32_t err; - if (m_write_int32 (m_state.s, MONITOR_GET_SOCKET)) - goto errout; + if (m_write_int32(m_state.s, MONITOR_GET_SOCKET)) + goto errout; - if (m_write_int32 (m_state.s, (int32_t)domain)) - goto errout; + if (m_write_int32(m_state.s, (int32_t) domain)) + goto errout; - if (m_write_int32 (m_state.s, (int32_t)type)) - goto errout; + if (m_write_int32(m_state.s, (int32_t) type)) + goto errout; - if (m_write_int32 (m_state.s, (int32_t)protocol)) - goto errout; + if (m_write_int32(m_state.s, (int32_t) protocol)) + goto errout; - if (m_read_int32 (m_state.s, &err)) - goto errout; + if (m_read_int32(m_state.s, &err)) + goto errout; - if (err != 0) - { - errno = (int)err; - return -1; - } - - /* Read result. */ - s = mm_receive_fd (m_state.s); - if (s < 0) - { - log_error ("monitor_socket: mm_receive_fd () failed: %s", - strerror (errno)); - return -1; - } - - return s; + if (err != 0) { + errno = (int) err; + return -1; + } + /* Read result. */ + s = mm_receive_fd(m_state.s); + if (s < 0) { + log_error("monitor_socket: mm_receive_fd () failed: %s", + strerror(errno)); + return -1; + } + return s; - errout: - log_error ("monitor_socket: problem talking to privileged process"); - return -1; +errout: + log_error("monitor_socket: problem talking to privileged process"); + return -1; } int -monitor_setsockopt (int s, int level, int optname, const void *optval, - socklen_t optlen) +monitor_setsockopt(int s, int level, int optname, const void *optval, + socklen_t optlen) { - int32_t ret, err; + int32_t ret, err; - if (m_write_int32 (m_state.s, MONITOR_SETSOCKOPT)) - goto errout; - if (mm_send_fd (m_state.s, s)) - goto errout; + if (m_write_int32(m_state.s, MONITOR_SETSOCKOPT)) + goto errout; + if (mm_send_fd(m_state.s, s)) + goto errout; - if (m_write_int32 (m_state.s, (int32_t)level)) - goto errout; - if (m_write_int32 (m_state.s, (int32_t)optname)) - goto errout; - if (m_write_int32 (m_state.s, (int32_t)optlen)) - goto errout; - if (m_write_raw (m_state.s, (char *)optval, (size_t)optlen)) - goto errout; + if (m_write_int32(m_state.s, (int32_t) level)) + goto errout; + if (m_write_int32(m_state.s, (int32_t) optname)) + goto errout; + if (m_write_int32(m_state.s, (int32_t) optlen)) + goto errout; + if (m_write_raw(m_state.s, (char *) optval, (size_t) optlen)) + goto errout; - if (m_read_int32 (m_state.s, &err)) - goto errout; + if (m_read_int32(m_state.s, &err)) + goto errout; - if (err != 0) - errno = (int)err; + if (err != 0) + errno = (int) err; - if (m_read_int32 (m_state.s, &ret)) - goto errout; + if (m_read_int32(m_state.s, &ret)) + goto errout; - return (int)ret; + return (int) ret; - errout: - log_print ("monitor_setsockopt: read/write error"); - return -1; +errout: + log_print("monitor_setsockopt: read/write error"); + return -1; } int -monitor_bind (int s, const struct sockaddr *name, socklen_t namelen) +monitor_bind(int s, const struct sockaddr *name, socklen_t namelen) { - int32_t ret, err; + int32_t ret, err; - if (m_write_int32 (m_state.s, MONITOR_BIND)) - goto errout; - if (mm_send_fd (m_state.s, s)) - goto errout; + if (m_write_int32(m_state.s, MONITOR_BIND)) + goto errout; + if (mm_send_fd(m_state.s, s)) + goto errout; - if (m_write_int32 (m_state.s, (int32_t)namelen)) - goto errout; - if (m_write_raw (m_state.s, (char *)name, (size_t)namelen)) - goto errout; + if (m_write_int32(m_state.s, (int32_t) namelen)) + goto errout; + if (m_write_raw(m_state.s, (char *) name, (size_t) namelen)) + goto errout; - if (m_read_int32 (m_state.s, &err)) - goto errout; + if (m_read_int32(m_state.s, &err)) + goto errout; - if (err != 0) - errno = (int)err; + if (err != 0) + errno = (int) err; - if (m_read_int32 (m_state.s, &ret)) - goto errout; + if (m_read_int32(m_state.s, &ret)) + goto errout; - return (int)ret; + return (int) ret; - errout: - log_print ("monitor_bind: read/write error"); - return -1; +errout: + log_print("monitor_bind: read/write error"); + return -1; } int -monitor_mkfifo (const char *path, mode_t mode) +monitor_mkfifo(const char *path, mode_t mode) { - int32_t ret, err; - char realpath[MAXPATHLEN]; + int32_t ret, err; + char realpath[MAXPATHLEN]; - /* Only the child process is supposed to run this. */ - if (m_state.pid) - log_fatal ("[priv] bad call to monitor_mkfifo"); + /* Only the child process is supposed to run this. */ + if (m_state.pid) + log_fatal("[priv] bad call to monitor_mkfifo"); - if (path[0] == '/') - strlcpy (realpath, path, sizeof realpath); - else - snprintf (realpath, sizeof realpath, "%s/%s", m_state.root, path); + if (path[0] == '/') + strlcpy(realpath, path, sizeof realpath); + else + snprintf(realpath, sizeof realpath, "%s/%s", m_state.root, path); - if (m_write_int32 (m_state.s, MONITOR_MKFIFO)) - goto errout; + if (m_write_int32(m_state.s, MONITOR_MKFIFO)) + goto errout; - if (m_write_raw (m_state.s, realpath, strlen (realpath) + 1)) - goto errout; + if (m_write_raw(m_state.s, realpath, strlen(realpath) + 1)) + goto errout; - ret = (int32_t)mode; - if (m_write_int32 (m_state.s, ret)) - goto errout; + ret = (int32_t) mode; + if (m_write_int32(m_state.s, ret)) + goto errout; - if (m_read_int32 (m_state.s, &err)) - goto errout; + if (m_read_int32(m_state.s, &err)) + goto errout; - if (err != 0) - errno = (int)err; + if (err != 0) + errno = (int) err; - if (m_read_int32 (m_state.s, &ret)) - goto errout; + if (m_read_int32(m_state.s, &ret)) + goto errout; - return (int)ret; + return (int) ret; - errout: - log_print ("monitor_mkfifo: read/write error"); - return -1; +errout: + log_print("monitor_mkfifo: read/write error"); + return -1; } struct monitor_dirents * -monitor_opendir (const char *path) +monitor_opendir(const char *path) { - char *buf, *cp; - size_t bufsize; - int fd, nbytes, entries; - long base; - struct stat sb; - struct dirent *dp; - struct monitor_dirents *direntries; - - fd = monitor_open (path, 0, O_RDONLY); - if (fd < 0) - { - log_error ("monitor_opendir: opendir(\"%s\") failed", path); - return NULL; - } - - /* Now build a list with all dirents from fd. */ - if (fstat (fd, &sb) < 0) - { - (void)close (fd); - return NULL; - } - - if (!S_ISDIR (sb.st_mode)) - { - (void)close (fd); - errno = EACCES; - return NULL; - } - - bufsize = sb.st_size; - if (bufsize < sb.st_blksize) - bufsize = sb.st_blksize; - - buf = calloc (bufsize, sizeof (char)); - if (buf == NULL) - { - (void)close (fd); - errno = EACCES; - return NULL; - } - - nbytes = getdirentries (fd, buf, bufsize, &base); - if (nbytes <= 0) - { - (void)close (fd); - free (buf); - errno = EACCES; - return NULL; - } - (void)close (fd); - - for (entries = 0, cp = buf; cp < buf + nbytes; ) - { - dp = (struct dirent *)cp; - cp += dp->d_reclen; - entries++; - } - - direntries = calloc (1, sizeof (struct monitor_dirents)); - if (direntries == NULL) - { - free (buf); - errno = EACCES; - return NULL; - } - - direntries->dirents = calloc (entries + 1, sizeof (struct dirent *)); - if (direntries->dirents == NULL) - { - free (buf); - free (direntries); - errno = EACCES; - return NULL; - } - direntries->current = 0; - - for (entries = 0, cp = buf; cp < buf + nbytes; ) - { - dp = (struct dirent *)cp; - direntries->dirents[entries++] = dp; - cp += dp->d_reclen; - } - direntries->dirents[entries] = NULL; - - return direntries; + char *buf, *cp; + size_t bufsize; + int fd, nbytes, entries; + long base; + struct stat sb; + struct dirent *dp; + struct monitor_dirents *direntries; + + fd = monitor_open(path, 0, O_RDONLY); + if (fd < 0) { + log_error("monitor_opendir: opendir(\"%s\") failed", path); + return NULL; + } + /* Now build a list with all dirents from fd. */ + if (fstat(fd, &sb) < 0) { + (void) close(fd); + return NULL; + } + if (!S_ISDIR(sb.st_mode)) { + (void) close(fd); + errno = EACCES; + return NULL; + } + bufsize = sb.st_size; + if (bufsize < sb.st_blksize) + bufsize = sb.st_blksize; + + buf = calloc(bufsize, sizeof(char)); + if (buf == NULL) { + (void) close(fd); + errno = EACCES; + return NULL; + } + nbytes = getdirentries(fd, buf, bufsize, &base); + if (nbytes <= 0) { + (void) close(fd); + free(buf); + errno = EACCES; + return NULL; + } + (void) close(fd); + + for (entries = 0, cp = buf; cp < buf + nbytes;) { + dp = (struct dirent *) cp; + cp += dp->d_reclen; + entries++; + } + + direntries = calloc(1, sizeof(struct monitor_dirents)); + if (direntries == NULL) { + free(buf); + errno = EACCES; + return NULL; + } + direntries->dirents = calloc(entries + 1, sizeof(struct dirent *)); + if (direntries->dirents == NULL) { + free(buf); + free(direntries); + errno = EACCES; + return NULL; + } + direntries->current = 0; + + for (entries = 0, cp = buf; cp < buf + nbytes;) { + dp = (struct dirent *) cp; + direntries->dirents[entries++] = dp; + cp += dp->d_reclen; + } + direntries->dirents[entries] = NULL; + + return direntries; } struct dirent * -monitor_readdir (struct monitor_dirents *direntries) +monitor_readdir(struct monitor_dirents *direntries) { - if (direntries->dirents[direntries->current] != NULL) - return direntries->dirents[direntries->current++]; + if (direntries->dirents[direntries->current] != NULL) + return direntries->dirents[direntries->current++]; - return NULL; + return NULL; } int -monitor_closedir (struct monitor_dirents *direntries) +monitor_closedir(struct monitor_dirents *direntries) { - free (direntries->dirents); - free (direntries); + free(direntries->dirents); + free(direntries); - return 0; + return 0; } void -monitor_init_done (void) +monitor_init_done(void) { - if (m_write_int32 (m_state.s, MONITOR_INIT_DONE)) - log_print ("monitor_init_done: read/write error"); + if (m_write_int32(m_state.s, MONITOR_INIT_DONE)) + log_print("monitor_init_done: read/write error"); - return; + return; } /* @@ -520,425 +492,395 @@ monitor_init_done (void) /* Help functions for monitor_loop(). */ static void -monitor_got_sigchld (int sig) +monitor_got_sigchld(int sig) { - sigchlded = 1; + sigchlded = 1; } static void sig_pass_to_chld(int sig) { - int oerrno = errno; + int oerrno = errno; - if (m_state.pid != -1) - kill(m_state.pid, sig); - errno = oerrno; + if (m_state.pid != -1) + kill(m_state.pid, sig); + errno = oerrno; } /* This function is where the privileged process waits(loops) indefinitely. */ void -monitor_loop (int debugging) +monitor_loop(int debugging) { - pid_t pid; - fd_set *fds; - size_t fdsn; - int n, maxfd; - - if (!debugging) - log_to (0); - - maxfd = m_state.s + 1; - - fdsn = howmany (maxfd, NFDBITS) * sizeof (fd_mask); - fds = (fd_set *)malloc (fdsn); - if (!fds) - { - kill (m_state.pid, SIGTERM); - log_fatal ("monitor_loop: malloc (%u) failed", fdsn); - return; - } - - /* If the child dies, we should shutdown also. */ - signal (SIGCHLD, monitor_got_sigchld); - - /* SIGHUP, SIGUSR1 and SIGUSR2 will be forwarded to child. */ - signal (SIGHUP, sig_pass_to_chld); - signal (SIGUSR1, sig_pass_to_chld); - signal (SIGUSR2, sig_pass_to_chld); - - while (cur_state < STATE_QUIT) - { - /* - * Currently, there is no need for us to hang around if the child - * is in the process of shutting down. - */ - if (sigtermed || sigchlded) - { - if (sigtermed) - kill (m_state.pid, SIGTERM); - - if (sigchlded) - { - do - { - pid = waitpid (m_state.pid, &n, WNOHANG); + pid_t pid; + fd_set *fds; + size_t fdsn; + int n, maxfd; + + if (!debugging) + log_to(0); + + maxfd = m_state.s + 1; + + fdsn = howmany(maxfd, NFDBITS) * sizeof(fd_mask); + fds = (fd_set *) malloc(fdsn); + if (!fds) { + kill(m_state.pid, SIGTERM); + log_fatal("monitor_loop: malloc (%u) failed", fdsn); + return; + } + /* If the child dies, we should shutdown also. */ + signal(SIGCHLD, monitor_got_sigchld); + + /* SIGHUP, SIGUSR1 and SIGUSR2 will be forwarded to child. */ + signal(SIGHUP, sig_pass_to_chld); + signal(SIGUSR1, sig_pass_to_chld); + signal(SIGUSR2, sig_pass_to_chld); + + while (cur_state < STATE_QUIT) { + /* + * Currently, there is no need for us to hang around if the child + * is in the process of shutting down. + */ + if (sigtermed || sigchlded) { + if (sigtermed) + kill(m_state.pid, SIGTERM); + + if (sigchlded) { + do { + pid = waitpid(m_state.pid, &n, WNOHANG); + } + while (pid == -1 && errno == EINTR); + + if (pid == m_state.pid && (WIFEXITED(n) || + WIFSIGNALED(n))) + m_priv_increase_state(STATE_QUIT); + } + break; } - while (pid == -1 && errno == EINTR); + if (monitor_sighupped) { + kill(m_state.pid, SIGHUP); + monitor_sighupped = 0; + } + memset(fds, 0, fdsn); + FD_SET(m_state.s, fds); + + n = select(maxfd, fds, NULL, NULL, NULL); + if (n == -1) { + if (errno != EINTR) { + log_error("select"); + sleep(1); + } + } else if (n) + if (FD_ISSET(m_state.s, fds)) { + int32_t msgcode; + if (m_read_int32(m_state.s, &msgcode)) + m_flush(m_state.s); + else + switch (msgcode) { + case MONITOR_GET_FD: + m_priv_getfd(m_state.s); + break; + + case MONITOR_GET_SOCKET: + LOG_DBG((LOG_MISC, 80, "%s: MONITOR_GET_SOCKET", __func__)); + m_priv_test_state(STATE_INIT); + m_priv_getsocket(m_state.s); + break; + + case MONITOR_SETSOCKOPT: + LOG_DBG((LOG_MISC, 80, "%s: MONITOR_SETSOCKOPT", __func__)); + m_priv_test_state(STATE_INIT); + m_priv_setsockopt(m_state.s); + break; + + case MONITOR_BIND: + LOG_DBG((LOG_MISC, 80, "%s: MONITOR_BIND", __func__)); + m_priv_test_state(STATE_INIT); + m_priv_bind(m_state.s); + break; + + case MONITOR_MKFIFO: + LOG_DBG((LOG_MISC, 80, "%s: MONITOR_MKFIFO", __func__)); + m_priv_test_state(STATE_INIT); + m_priv_mkfifo(m_state.s); + break; + + case MONITOR_INIT_DONE: + LOG_DBG((LOG_MISC, 80, "%s: MONITOR_INIT_DONE", __func__)); + m_priv_test_state(STATE_INIT); + m_priv_increase_state(STATE_RUNNING); + break; + + case MONITOR_SHUTDOWN: + LOG_DBG((LOG_MISC, 80, "%s: MONITOR_SHUTDOWN", __func__)); + m_priv_increase_state(STATE_QUIT); + break; + + default: + log_print("monitor_loop: got unknown code %d", msgcode); + } + } + } - if (pid == m_state.pid && (WIFEXITED (n) || WIFSIGNALED (n))) - m_priv_increase_state (STATE_QUIT); - } + free(fds); + exit(0); +} - break; +/* Privileged: called by monitor_loop. */ +static void +m_priv_getfd(int s) +{ + char path[MAXPATHLEN]; + int32_t v, err; + int flags; + mode_t mode; + + /* + * We expect the following data on the socket: + * u_int32_t pathlen + * <variable> path + * u_int32_t flags + * u_int32_t mode + */ + + if (m_read_raw(s, path, MAXPATHLEN)) + goto errout; + + if (m_read_int32(s, &v)) + goto errout; + flags = (int) v; + + if (m_read_int32(s, &v)) + goto errout; + mode = (mode_t) v; + + if (m_priv_local_sanitize_path(path, sizeof path, flags) != 0) { + err = EACCES; + v = -1; + } else { + err = 0; + v = (int32_t) open(path, flags, mode); + if (v < 0) + err = (int32_t) errno; } - if (monitor_sighupped) - { - kill (m_state.pid, SIGHUP); - monitor_sighupped = 0; - } + if (m_write_int32(s, err)) + goto errout; - memset (fds, 0, fdsn); - FD_SET (m_state.s, fds); - - n = select (maxfd, fds, NULL, NULL, NULL); - if (n == -1) - { - if (errno != EINTR) - { - log_error ("select"); - sleep (1); - } + if (v > 0 && mm_send_fd(s, v)) { + close(v); + goto errout; } - else if (n) - if (FD_ISSET (m_state.s, fds)) - { - int32_t msgcode; - if (m_read_int32 (m_state.s, &msgcode)) - m_flush (m_state.s); - else - switch (msgcode) - { - case MONITOR_GET_FD: - m_priv_getfd (m_state.s); - break; - - case MONITOR_GET_SOCKET: - LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_GET_SOCKET", __func__)); - m_priv_test_state (STATE_INIT); - m_priv_getsocket (m_state.s); - break; - - case MONITOR_SETSOCKOPT: - LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_SETSOCKOPT", __func__)); - m_priv_test_state (STATE_INIT); - m_priv_setsockopt (m_state.s); - break; - - case MONITOR_BIND: - LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_BIND", __func__)); - m_priv_test_state (STATE_INIT); - m_priv_bind (m_state.s); - break; - - case MONITOR_MKFIFO: - LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_MKFIFO", __func__)); - m_priv_test_state (STATE_INIT); - m_priv_mkfifo (m_state.s); - break; - - case MONITOR_INIT_DONE: - LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_INIT_DONE", __func__)); - m_priv_test_state (STATE_INIT); - m_priv_increase_state (STATE_RUNNING); - break; - - case MONITOR_SHUTDOWN: - LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_SHUTDOWN", __func__)); - m_priv_increase_state (STATE_QUIT); - break; - - default: - log_print ("monitor_loop: got unknown code %d", msgcode); - } - } - } + close(v); + return; - free (fds); - exit (0); +errout: + log_error("m_priv_getfd: read/write operation failed"); + return; } /* Privileged: called by monitor_loop. */ static void -m_priv_getfd (int s) +m_priv_getsocket(int s) { - char path[MAXPATHLEN]; - int32_t v, err; - int flags; - mode_t mode; - - /* - * We expect the following data on the socket: - * u_int32_t pathlen - * <variable> path - * u_int32_t flags - * u_int32_t mode - */ - - if (m_read_raw (s, path, MAXPATHLEN)) - goto errout; - - if (m_read_int32 (s, &v)) - goto errout; - flags = (int)v; - - if (m_read_int32 (s, &v)) - goto errout; - mode = (mode_t)v; - - if (m_priv_local_sanitize_path (path, sizeof path, flags) != 0) - { - err = EACCES; - v = -1; - } - else - { - err = 0; - v = (int32_t)open (path, flags, mode); - if (v < 0) - err = (int32_t)errno; - } - - if (m_write_int32 (s, err)) - goto errout; - - if (v > 0 && mm_send_fd (s, v)) - { - close (v); - goto errout; - } - close (v); - return; - - errout: - log_error ("m_priv_getfd: read/write operation failed"); - return; -} + int domain, type, protocol; + int32_t v, err; -/* Privileged: called by monitor_loop. */ -static void -m_priv_getsocket (int s) -{ - int domain, type, protocol; - int32_t v, err; - - if (m_read_int32 (s, &v)) - goto errout; - domain = (int)v; - - if (m_read_int32 (s, &v)) - goto errout; - type = (int)v; - - if (m_read_int32 (s, &v)) - goto errout; - protocol = (int)v; - - err = 0; - v = (int32_t)socket (domain, type, protocol); - if (v < 0) - err = (int32_t)errno; - - if (m_write_int32 (s, err)) - goto errout; - - if (v > 0 && mm_send_fd (s, v)) - { - close (v); - goto errout; - } - close (v); - return; - - errout: - log_error ("m_priv_getsocket: read/write operation failed"); - return; + if (m_read_int32(s, &v)) + goto errout; + domain = (int) v; + + if (m_read_int32(s, &v)) + goto errout; + type = (int) v; + + if (m_read_int32(s, &v)) + goto errout; + protocol = (int) v; + + err = 0; + v = (int32_t) socket(domain, type, protocol); + if (v < 0) + err = (int32_t) errno; + + if (m_write_int32(s, err)) + goto errout; + + if (v > 0 && mm_send_fd(s, v)) { + close(v); + goto errout; + } + close(v); + return; + +errout: + log_error("m_priv_getsocket: read/write operation failed"); + return; } /* Privileged: called by monitor_loop. */ static void -m_priv_setsockopt (int s) +m_priv_setsockopt(int s) { - int sock, level, optname; - char *optval = 0; - socklen_t optlen; - int32_t v, err; - - sock = mm_receive_fd (s); - if (sock < 0) - goto errout; - - if (m_read_int32 (s, &level)) - goto errout; - - if (m_read_int32 (s, &optname)) - goto errout; - - if (m_read_int32 (s, &optlen)) - goto errout; - - optval = (char *)malloc (optlen); - if (!optval) - goto errout; - - if (m_read_raw (s, optval, optlen)) - goto errout; - - if (m_priv_check_sockopt (level, optname) != 0) - { - err = EACCES; - v = -1; - } - else - { - err = 0; - v = (int32_t) setsockopt (sock, level, optname, optval, optlen); - if (v < 0) - err = (int32_t)errno; - } - - close (sock); - sock = -1; - - if (m_write_int32 (s, err)) - goto errout; - - if (m_write_int32 (s, v)) - goto errout; - - free (optval); - return; - - errout: - log_print ("m_priv_setsockopt: read/write error"); - if (optval) - free (optval); - if (sock >= 0) - close (sock); - return; + int sock, level, optname; + char *optval = 0; + socklen_t optlen; + int32_t v, err; + + sock = mm_receive_fd(s); + if (sock < 0) + goto errout; + + if (m_read_int32(s, &level)) + goto errout; + + if (m_read_int32(s, &optname)) + goto errout; + + if (m_read_int32(s, &optlen)) + goto errout; + + optval = (char *) malloc(optlen); + if (!optval) + goto errout; + + if (m_read_raw(s, optval, optlen)) + goto errout; + + if (m_priv_check_sockopt(level, optname) != 0) { + err = EACCES; + v = -1; + } else { + err = 0; + v = (int32_t) setsockopt(sock, level, optname, optval, optlen); + if (v < 0) + err = (int32_t) errno; + } + + close(sock); + sock = -1; + + if (m_write_int32(s, err)) + goto errout; + + if (m_write_int32(s, v)) + goto errout; + + free(optval); + return; + +errout: + log_print("m_priv_setsockopt: read/write error"); + if (optval) + free(optval); + if (sock >= 0) + close(sock); + return; } /* Privileged: called by monitor_loop. */ static void -m_priv_bind (int s) +m_priv_bind(int s) { - int sock; - struct sockaddr *name = 0; - socklen_t namelen; - int32_t v, err; - - sock = mm_receive_fd (s); - if (sock < 0) - goto errout; - - if (m_read_int32 (s, &v)) - goto errout; - namelen = (socklen_t)v; - - name = (struct sockaddr *)malloc (namelen); - if (!name) - goto errout; - - if (m_read_raw (s, (char *)name, (size_t)namelen)) - goto errout; - - if (m_priv_check_bind (name, namelen) != 0) - { - err = EACCES; - v = -1; - } - else - { - err = 0; - v = (int32_t)bind (sock, name, namelen); - if (v < 0) - { - log_error ("m_priv_bind: bind(%d,%p,%d) returned %d", - sock, name, namelen, v); - err = (int32_t)errno; - } - } - - close (sock); - sock = -1; - - if (m_write_int32 (s, err)) - goto errout; - - if (m_write_int32 (s, v)) - goto errout; - - free (name); - return; - - errout: - log_print ("m_priv_bind: read/write error"); - if (name) - free (name); - if (sock >= 0) - close (sock); - return; + int sock; + struct sockaddr *name = 0; + socklen_t namelen; + int32_t v, err; + + sock = mm_receive_fd(s); + if (sock < 0) + goto errout; + + if (m_read_int32(s, &v)) + goto errout; + namelen = (socklen_t) v; + + name = (struct sockaddr *) malloc(namelen); + if (!name) + goto errout; + + if (m_read_raw(s, (char *) name, (size_t) namelen)) + goto errout; + + if (m_priv_check_bind(name, namelen) != 0) { + err = EACCES; + v = -1; + } else { + err = 0; + v = (int32_t) bind(sock, name, namelen); + if (v < 0) { + log_error("m_priv_bind: bind(%d,%p,%d) returned %d", + sock, name, namelen, v); + err = (int32_t) errno; + } + } + + close(sock); + sock = -1; + + if (m_write_int32(s, err)) + goto errout; + + if (m_write_int32(s, v)) + goto errout; + + free(name); + return; + +errout: + log_print("m_priv_bind: read/write error"); + if (name) + free(name); + if (sock >= 0) + close(sock); + return; } /* Privileged: called by monitor_loop. */ static void -m_priv_mkfifo (int s) +m_priv_mkfifo(int s) { - char path[MAXPATHLEN]; - mode_t mode; - int32_t v, err; - - if (m_read_raw (s, path, MAXPATHLEN)) - goto errout; - - if (m_read_int32 (s, &v)) - goto errout; - mode = (mode_t)v; - - /* - * ui_fifo is set before creation of the unpriv'ed child. So path should - * exactly match ui_fifo. It's also restricted to /var/run. - */ - if (m_priv_local_sanitize_path (path, sizeof path, O_RDWR) != 0 || - strncmp (ui_fifo, path, strlen (ui_fifo))) - { - err = EACCES; - v = -1; - } - else - { - unlink (path); /* XXX See ui.c:ui_init() */ - - err = 0; - v = (int32_t)mkfifo (path, mode); - if (v) - { - log_error ("m_priv_mkfifo: mkfifo(\"%s\", %o) failed", path, mode); - err = (int32_t)errno; + char path[MAXPATHLEN]; + mode_t mode; + int32_t v, err; + + if (m_read_raw(s, path, MAXPATHLEN)) + goto errout; + + if (m_read_int32(s, &v)) + goto errout; + mode = (mode_t) v; + + /* + * ui_fifo is set before creation of the unpriv'ed child. So path + * should exactly match ui_fifo. It's also restricted to /var/run. + */ + if (m_priv_local_sanitize_path(path, sizeof path, O_RDWR) != 0 || + strncmp(ui_fifo, path, strlen(ui_fifo))) { + err = EACCES; + v = -1; + } else { + unlink(path); /* XXX See ui.c:ui_init() */ + + err = 0; + v = (int32_t) mkfifo(path, mode); + if (v) { + log_error("m_priv_mkfifo: mkfifo(\"%s\", %o) failed", path, mode); + err = (int32_t) errno; + } } - } - if (m_write_int32 (s, err)) - goto errout; + if (m_write_int32(s, err)) + goto errout; - if (m_write_int32 (s, v)) - goto errout; + if (m_write_int32(s, v)) + goto errout; - return; + return; - errout: - log_print ("m_priv_mkfifo: read/write error"); - return; +errout: + log_print("m_priv_mkfifo: read/write error"); + return; } /* @@ -947,206 +889,193 @@ m_priv_mkfifo (int s) /* Write a 32-bit value to a socket. */ int -m_write_int32 (int s, int32_t value) +m_write_int32(int s, int32_t value) { - u_int32_t v; - memcpy (&v, &value, sizeof v); - return (write (s, &v, sizeof v) == -1); + u_int32_t v; + memcpy(&v, &value, sizeof v); + return (write(s, &v, sizeof v) == -1); } /* Write a number of bytes of data to a socket. */ int -m_write_raw (int s, char *data, size_t dlen) +m_write_raw(int s, char *data, size_t dlen) { - if (m_write_int32 (s, (int32_t)dlen)) - return 1; - return (write (s, data, dlen) == -1); + if (m_write_int32(s, (int32_t) dlen)) + return 1; + return (write(s, data, dlen) == -1); } int -m_read_int32 (int s, int32_t *value) +m_read_int32(int s, int32_t *value) { - u_int32_t v; - if (read (s, &v, sizeof v) != sizeof v) - return 1; - memcpy (value, &v, sizeof v); - return 0; + u_int32_t v; + if (read(s, &v, sizeof v) != sizeof v) + return 1; + memcpy(value, &v, sizeof v); + return 0; } int -m_read_raw (int s, char *data, size_t maxlen) +m_read_raw(int s, char *data, size_t maxlen) { - u_int32_t v; - int r; - if (m_read_int32 (s, &v)) - return 1; - if (v > maxlen) - return 1; - r = read (s, data, v); - return (r == -1); + u_int32_t v; + int r; + if (m_read_int32(s, &v)) + return 1; + if (v > maxlen) + return 1; + r = read(s, data, v); + return (r == -1); } /* Drain all available input on a socket. */ void -m_flush (int s) +m_flush(int s) { - u_int8_t tmp; - int one = 1; + u_int8_t tmp; + int one = 1; - ioctl (s, FIONBIO, &one); /* Non-blocking */ - while (read (s, &tmp, 1) > 0) ; - ioctl (s, FIONBIO, 0); /* Blocking */ + ioctl(s, FIONBIO, &one);/* Non-blocking */ + while (read(s, &tmp, 1) > 0); + ioctl(s, FIONBIO, 0); /* Blocking */ } /* Check that path/mode is permitted. */ static int -m_priv_local_sanitize_path (char *path, size_t pmax, int flags) +m_priv_local_sanitize_path(char *path, size_t pmax, int flags) { - char *p; - - /* - * We only permit paths starting with - * /etc/isakmpd/ (read only) - * /var/run/ (rw) - */ - - if (strlen (path) < strlen ("/var/run/")) - goto bad_path; - - /* Any path containing '..' is invalid. */ - for (p = path; *p && (p - path) < (int)pmax; p++) - if (*p == '.' && *(p + 1) == '.') - goto bad_path; - - /* For any write-mode, only a few paths are permitted. */ - if ((flags & O_ACCMODE) != O_RDONLY) - { - if (strncmp ("/var/run/", path, strlen ("/var/run/")) == 0) - return 0; - goto bad_path; - } - - /* Any other path is read-only. */ - if (strncmp (ISAKMPD_ROOT, path, strlen (ISAKMPD_ROOT)) == 0 || - strncmp ("/var/run/", path, strlen ("/var/run/")) == 0) - return 0; - - bad_path: - log_print ("m_priv_local_sanitize_path: illegal path \"%.1023s\", " - "replaced with \"/dev/null\"", path); - strlcpy (path, "/dev/null", pmax); - return 1; + char *p; + + /* + * We only permit paths starting with + * /etc/isakmpd/ (read only) + * /var/run/ (rw) + */ + + if (strlen(path) < strlen("/var/run/")) + goto bad_path; + + /* Any path containing '..' is invalid. */ + for (p = path; *p && (p - path) < (int) pmax; p++) + if (*p == '.' && *(p + 1) == '.') + goto bad_path; + + /* For any write-mode, only a few paths are permitted. */ + if ((flags & O_ACCMODE) != O_RDONLY) { + if (strncmp("/var/run/", path, strlen("/var/run/")) == 0) + return 0; + goto bad_path; + } + /* Any other path is read-only. */ + if (strncmp(ISAKMPD_ROOT, path, strlen(ISAKMPD_ROOT)) == 0 || + strncmp("/var/run/", path, strlen("/var/run/")) == 0) + return 0; + +bad_path: + log_print("m_priv_local_sanitize_path: illegal path \"%.1023s\", " + "replaced with \"/dev/null\"", path); + strlcpy(path, "/dev/null", pmax); + return 1; } /* Check setsockopt */ static int -m_priv_check_sockopt (int level, int name) +m_priv_check_sockopt(int level, int name) { - switch (level) - { - /* These are allowed */ - case SOL_SOCKET: - case IPPROTO_IP: - case IPPROTO_IPV6: - break; - - default: - log_print ("m_priv_check_sockopt: Illegal level %d", level); - return 1; - } - - switch (name) - { - /* These are allowed */ - case SO_REUSEPORT: - case SO_REUSEADDR: - case IP_AUTH_LEVEL: - case IP_ESP_TRANS_LEVEL: - case IP_ESP_NETWORK_LEVEL: - case IP_IPCOMP_LEVEL: - case IPV6_AUTH_LEVEL: - case IPV6_ESP_TRANS_LEVEL: - case IPV6_ESP_NETWORK_LEVEL: - case IPV6_IPCOMP_LEVEL: - break; - - default: - log_print ("m_priv_check_sockopt: Illegal option name %d", name); - return 1; - } - - return 0; + switch (level) { + /* These are allowed */ + case SOL_SOCKET: + case IPPROTO_IP: + case IPPROTO_IPV6: + break; + + default: + log_print("m_priv_check_sockopt: Illegal level %d", level); + return 1; + } + + switch (name) { + /* These are allowed */ + case SO_REUSEPORT: + case SO_REUSEADDR: + case IP_AUTH_LEVEL: + case IP_ESP_TRANS_LEVEL: + case IP_ESP_NETWORK_LEVEL: + case IP_IPCOMP_LEVEL: + case IPV6_AUTH_LEVEL: + case IPV6_ESP_TRANS_LEVEL: + case IPV6_ESP_NETWORK_LEVEL: + case IPV6_IPCOMP_LEVEL: + break; + + default: + log_print("m_priv_check_sockopt: Illegal option name %d", name); + return 1; + } + + return 0; } /* Check bind */ static int -m_priv_check_bind (const struct sockaddr *sa, socklen_t salen) +m_priv_check_bind(const struct sockaddr *sa, socklen_t salen) { - in_port_t port; - - if (sa == NULL) - { - log_print ("NULL address"); - return 1; - } - - if (sysdep_sa_len ((struct sockaddr *)sa) != salen) - { - log_print ("Length mismatch: %d %d", - (int) sysdep_sa_len ((struct sockaddr *)sa), (int) salen); - return 1; - } - - switch (sa->sa_family) - { - case AF_INET: - if (salen != sizeof (struct sockaddr_in)) - { - log_print ("Invalid inet address length"); - return 1; - } - port = ((const struct sockaddr_in *)sa)->sin_port; - break; - case AF_INET6: - if (salen != sizeof (struct sockaddr_in6)) - { - log_print ("Invalid inet6 address length"); - return 1; - } - port = ((const struct sockaddr_in6 *)sa)->sin6_port; - break; - default: - log_print ("Unknown address family"); - return 1; - } + in_port_t port; - port = ntohs(port); + if (sa == NULL) { + log_print("NULL address"); + return 1; + } + if (sysdep_sa_len((struct sockaddr *) sa) != salen) { + log_print("Length mismatch: %d %d", + (int) sysdep_sa_len((struct sockaddr *) sa), (int) salen); + return 1; + } + switch (sa->sa_family) { + case AF_INET: + if (salen != sizeof(struct sockaddr_in)) { + log_print("Invalid inet address length"); + return 1; + } + port = ((const struct sockaddr_in *) sa)->sin_port; + break; + case AF_INET6: + if (salen != sizeof(struct sockaddr_in6)) { + log_print("Invalid inet6 address length"); + return 1; + } + port = ((const struct sockaddr_in6 *) sa)->sin6_port; + break; + default: + log_print("Unknown address family"); + return 1; + } - if (port != ISAKMP_PORT_DEFAULT && port < 1024) - { - log_print ("Disallowed port %u", port); - return 1; - } + port = ntohs(port); - return 0; + if (port != ISAKMP_PORT_DEFAULT && port < 1024) { + log_print("Disallowed port %u", port); + return 1; + } + return 0; } - + /* Increase state into less permissive mode */ static void -m_priv_increase_state (int state) +m_priv_increase_state(int state) { - if (state <= cur_state) - log_print ("m_priv_increase_state: attempt to decrase state or match " - "current state"); - if (state < STATE_INIT || state > STATE_QUIT) - log_print ("m_priv_increase_state: attempt to switch to invalid state"); - cur_state = state; + if (state <= cur_state) + log_print("m_priv_increase_state: attempt to decrase state or match " + "current state"); + if (state < STATE_INIT || state > STATE_QUIT) + log_print("m_priv_increase_state: attempt to switch to invalid state"); + cur_state = state; } static void -m_priv_test_state (int state) +m_priv_test_state(int state) { - if (cur_state != state) - log_print ("m_priv_test_state: Illegal state: %d != %d", cur_state, state); - return; + if (cur_state != state) + log_print("m_priv_test_state: Illegal state: %d != %d", cur_state, state); + return; } diff --git a/sbin/isakmpd/monitor.h b/sbin/isakmpd/monitor.h index b76af5318ed..2d20f5eb0f0 100644 --- a/sbin/isakmpd/monitor.h +++ b/sbin/isakmpd/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.7 2004/03/19 14:04:43 hshoexer Exp $ */ +/* $OpenBSD: monitor.h,v 1.8 2004/04/15 18:39:26 deraadt Exp $ */ /* * Copyright (c) 2003 Håkan Olsson. All rights reserved. @@ -38,15 +38,14 @@ #define ISAKMP_PORT_DEFAULT 500 -enum monitor_reqtypes -{ - MONITOR_GET_FD, - MONITOR_GET_SOCKET, - MONITOR_SETSOCKOPT, - MONITOR_BIND, - MONITOR_MKFIFO, - MONITOR_INIT_DONE, - MONITOR_SHUTDOWN +enum monitor_reqtypes { + MONITOR_GET_FD, + MONITOR_GET_SOCKET, + MONITOR_SETSOCKOPT, + MONITOR_BIND, + MONITOR_MKFIFO, + MONITOR_INIT_DONE, + MONITOR_SHUTDOWN }; enum priv_state { @@ -55,31 +54,30 @@ enum priv_state { STATE_QUIT /* shutting down */ }; -struct monitor_dirents -{ - int current; - struct dirent **dirents; +struct monitor_dirents { + int current; + struct dirent **dirents; }; -pid_t monitor_init (void); -void monitor_loop (int); +pid_t monitor_init(void); +void monitor_loop(int); -int mm_send_fd (int, int); -int mm_receive_fd (int); +int mm_send_fd(int, int); +int mm_receive_fd(int); -FILE *monitor_fopen (const char *, const char *); -int monitor_open (const char *, int, mode_t); -int monitor_stat (const char *, struct stat *); -int monitor_socket (int, int, int); -int monitor_setsockopt (int, int, int, const void *, socklen_t); -int monitor_bind (int, const struct sockaddr *, socklen_t); -int monitor_mkfifo (const char *, mode_t); -struct monitor_dirents *monitor_opendir (const char *); -struct dirent *monitor_readdir (struct monitor_dirents *); -int monitor_closedir (struct monitor_dirents *); -void monitor_init_done (void); +FILE *monitor_fopen(const char *, const char *); +int monitor_open(const char *, int, mode_t); +int monitor_stat(const char *, struct stat *); +int monitor_socket(int, int, int); +int monitor_setsockopt(int, int, int, const void *, socklen_t); +int monitor_bind(int, const struct sockaddr *, socklen_t); +int monitor_mkfifo(const char *, mode_t); +struct monitor_dirents *monitor_opendir(const char *); +struct dirent *monitor_readdir(struct monitor_dirents *); +int monitor_closedir(struct monitor_dirents *); +void monitor_init_done(void); -#else /* !USE_PRIVSEP */ +#else /* !USE_PRIVSEP */ #define monitor_fopen fopen #define monitor_open open @@ -92,5 +90,5 @@ void monitor_init_done (void); #define monitor_readdir readdir #define monitor_closedir closedir -#endif /* USE_PRIVSEP */ -#endif /* _MONITOR_H_ */ +#endif /* USE_PRIVSEP */ +#endif /* _MONITOR_H_ */ diff --git a/sbin/isakmpd/monitor_fdpass.c b/sbin/isakmpd/monitor_fdpass.c index 14370205349..0a1e3065c4d 100644 --- a/sbin/isakmpd/monitor_fdpass.c +++ b/sbin/isakmpd/monitor_fdpass.c @@ -32,81 +32,73 @@ #include "monitor.h" int -mm_send_fd (int socket, int fd) +mm_send_fd(int socket, int fd) { - struct msghdr msg; - char tmp[CMSG_SPACE (sizeof (int))]; - struct cmsghdr *cmsg; - struct iovec vec; - char ch = '\0'; - ssize_t n; + struct msghdr msg; + char tmp[CMSG_SPACE(sizeof(int))], ch = '\0'; + struct cmsghdr *cmsg; + struct iovec vec; + ssize_t n; - memset (&msg, 0, sizeof msg); - msg.msg_control = (caddr_t)tmp; - msg.msg_controllen = CMSG_LEN (sizeof (int)); - cmsg = CMSG_FIRSTHDR (&msg); - cmsg->cmsg_len = CMSG_LEN (sizeof (int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA (cmsg) = fd; + memset(&msg, 0, sizeof msg); + msg.msg_control = (caddr_t) tmp; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *) CMSG_DATA(cmsg) = fd; - vec.iov_base = &ch; - vec.iov_len = 1; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; + vec.iov_base = &ch; + vec.iov_len = 1; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; - if ((n = sendmsg (socket, &msg, 0)) == -1) - { - log_error ("%s: sendmsg(%d)", __func__, fd); - return -1; - } - if (n != 1) - { - log_error ("%s: sendmsg: expected sent 1 got %ld", __func__, (long)n); - return -1; - } - return 0; + if ((n = sendmsg(socket, &msg, 0)) == -1) { + log_error("%s: sendmsg(%d)", __func__, fd); + return -1; + } + if (n != 1) { + log_error("%s: sendmsg: expected sent 1 got %ld", + __func__, (long) n); + return -1; + } + return 0; } int -mm_receive_fd (int socket) +mm_receive_fd(int socket) { - struct msghdr msg; - char tmp[CMSG_SPACE (sizeof (int))]; - struct cmsghdr *cmsg; - struct iovec vec; - ssize_t n; - char ch; - int fd; + struct msghdr msg; + char tmp[CMSG_SPACE(sizeof(int))], ch; + struct cmsghdr *cmsg; + struct iovec vec; + ssize_t n; + int fd; - memset (&msg, 0, sizeof msg); - vec.iov_base = &ch; - vec.iov_len = 1; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; - msg.msg_control = tmp; - msg.msg_controllen = sizeof tmp; + memset(&msg, 0, sizeof msg); + vec.iov_base = &ch; + vec.iov_len = 1; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_control = tmp; + msg.msg_controllen = sizeof tmp; - if ((n = recvmsg (socket, &msg, 0)) == -1) - { - log_error ("%s: recvmsg", __func__); - return -1; - } - if (n != 1) - { - log_error ("%s: recvmsg: expected received 1 got %ld", __func__, - (long)n); - return -1; - } - - cmsg = CMSG_FIRSTHDR (&msg); - if (cmsg->cmsg_type != SCM_RIGHTS) - { - log_error ("%s: expected type %d got %d", __func__, SCM_RIGHTS, - cmsg->cmsg_type); - return -1; - } - fd = (*(int *)CMSG_DATA (cmsg)); - - return fd; + if ((n = recvmsg(socket, &msg, 0)) == -1) { + log_error("%s: recvmsg", __func__); + return -1; + } + if (n != 1) { + log_error("%s: recvmsg: expected received 1 got %ld", __func__, + (long) n); + return -1; + } + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_type != SCM_RIGHTS) { + log_error("%s: expected type %d got %d", __func__, SCM_RIGHTS, + cmsg->cmsg_type); + return -1; + } + fd = (*(int *) CMSG_DATA(cmsg)); + return fd; } diff --git a/sbin/isakmpd/pf_key_v2.c b/sbin/isakmpd/pf_key_v2.c index debe23d2f66..cc243b8d05a 100644 --- a/sbin/isakmpd/pf_key_v2.c +++ b/sbin/isakmpd/pf_key_v2.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pf_key_v2.c,v 1.139 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */ +/* $OpenBSD: pf_key_v2.c,v 1.140 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -75,10 +75,10 @@ #endif #define IN6_IS_ADDR_FULL(a) \ - ((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffff) \ - && (*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffff) \ - && (*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffff) \ - && (*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffff)) + ((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffff) && \ + (*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffff) && \ + (*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffff) && \ + (*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffff)) #define ADDRESS_MAX sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" @@ -87,27 +87,27 @@ */ #define PF_KEY_V2_CHUNK 8 #define PF_KEY_V2_ROUND(x) \ - (((x) + PF_KEY_V2_CHUNK - 1) & ~(PF_KEY_V2_CHUNK - 1)) + (((x) + PF_KEY_V2_CHUNK - 1) & ~(PF_KEY_V2_CHUNK - 1)) /* How many microseconds we will wait for a reply from the PF_KEY socket. */ #define PF_KEY_REPLY_TIMEOUT 1000 struct pf_key_v2_node { - TAILQ_ENTRY (pf_key_v2_node) link; - void *seg; - size_t sz; - int cnt; - u_int16_t type; - u_int8_t flags; + TAILQ_ENTRY(pf_key_v2_node) link; + void *seg; + size_t sz; + int cnt; + u_int16_t type; + u_int8_t flags; }; -TAILQ_HEAD (pf_key_v2_msg, pf_key_v2_node); +TAILQ_HEAD(pf_key_v2_msg, pf_key_v2_node); #define PF_KEY_V2_NODE_MALLOCED 1 #define PF_KEY_V2_NODE_MARK 2 /* Used to derive "unique" connection identifiers. */ -int connection_seq = 0; +int connection_seq = 0; #ifdef KAME /* @@ -115,159 +115,158 @@ int connection_seq = 0; * GETSPI creating the larval SA. */ struct pf_key_v2_sa_seq { - TAILQ_ENTRY (pf_key_v2_sa_seq) link; - u_int8_t *spi; - size_t sz; - u_int8_t proto; - struct sockaddr *dst; - int dstlen; - u_int32_t seq; + TAILQ_ENTRY(pf_key_v2_sa_seq) link; + u_int8_t *spi; + size_t sz; + u_int8_t proto; + struct sockaddr *dst; + int dstlen; + u_int32_t seq; }; -TAILQ_HEAD (, pf_key_v2_sa_seq) pf_key_v2_sa_seq_map; +TAILQ_HEAD(, pf_key_v2_sa_seq) pf_key_v2_sa_seq_map; #endif #ifndef KAME -static u_int8_t *pf_key_v2_convert_id (u_int8_t *, int, size_t *, int *); -#endif -static struct pf_key_v2_msg *pf_key_v2_call (struct pf_key_v2_msg *); -static struct pf_key_v2_node *pf_key_v2_find_ext (struct pf_key_v2_msg *, - u_int16_t); -static void pf_key_v2_notify (struct pf_key_v2_msg *); -static struct pf_key_v2_msg *pf_key_v2_read (u_int32_t); -static u_int32_t pf_key_v2_seq (void); -static u_int32_t pf_key_v2_write (struct pf_key_v2_msg *); -static int pf_key_v2_remove_conf (char *); -static int pf_key_v2_conf_refhandle (int, char *); +static u_int8_t *pf_key_v2_convert_id(u_int8_t *, int, size_t *, int *); +#endif +static struct pf_key_v2_msg *pf_key_v2_call(struct pf_key_v2_msg *); +static struct pf_key_v2_node *pf_key_v2_find_ext(struct pf_key_v2_msg *, + u_int16_t); +static void pf_key_v2_notify(struct pf_key_v2_msg *); +static struct pf_key_v2_msg *pf_key_v2_read(u_int32_t); +static u_int32_t pf_key_v2_seq(void); +static u_int32_t pf_key_v2_write(struct pf_key_v2_msg *); +static int pf_key_v2_remove_conf(char *); +static int pf_key_v2_conf_refhandle(int, char *); #ifdef SADB_X_ASKPOLICY -static int pf_key_v2_conf_refinc (int, char *); +static int pf_key_v2_conf_refinc(int, char *); #endif /* The socket to use for PF_KEY interactions. */ -static int pf_key_v2_socket; +static int pf_key_v2_socket; #ifdef KAME static int -pf_key_v2_register_sa_seq (u_int8_t *spi, size_t sz, u_int8_t proto, - struct sockaddr *dst, int dstlen, u_int32_t seq) +pf_key_v2_register_sa_seq(u_int8_t *spi, size_t sz, u_int8_t proto, + struct sockaddr *dst, int dstlen, u_int32_t seq) { - struct pf_key_v2_sa_seq *node = 0; - - node = malloc (sizeof *node); - if (!node) - goto cleanup; - memset (node, '0', sizeof *node); - node->spi = malloc (sz); - if (!node->spi) - goto cleanup; - node->dst = malloc (sysdep_sa_len (dst)); - if (!node->dst) - goto cleanup; - memcpy (node->dst, dst, sysdep_sa_len (dst)); - node->dstlen = sysdep_sa_len (dst); - memcpy (node->spi, spi, sz); - node->sz = sz; - node->proto = proto; - node->seq = seq; - TAILQ_INSERT_TAIL (&pf_key_v2_sa_seq_map, node, link); - return 1; - - cleanup: - if (node->dst) - free (node->dst); - if (node) - free (node); - return 0; + struct pf_key_v2_sa_seq *node = 0; + + node = malloc(sizeof *node); + if (!node) + goto cleanup; + memset(node, '0', sizeof *node); + node->spi = malloc(sz); + if (!node->spi) + goto cleanup; + node->dst = malloc(sysdep_sa_len(dst)); + if (!node->dst) + goto cleanup; + memcpy(node->dst, dst, sysdep_sa_len(dst)); + node->dstlen = sysdep_sa_len(dst); + memcpy(node->spi, spi, sz); + node->sz = sz; + node->proto = proto; + node->seq = seq; + TAILQ_INSERT_TAIL(&pf_key_v2_sa_seq_map, node, link); + return 1; + +cleanup: + if (node->dst) + free(node->dst); + if (node) + free(node); + return 0; } static u_int32_t -pf_key_v2_seq_by_sa (u_int8_t *spi, size_t sz, u_int8_t proto, - struct sockaddr *dst, int dstlen) +pf_key_v2_seq_by_sa(u_int8_t *spi, size_t sz, u_int8_t proto, + struct sockaddr *dst, int dstlen) { - struct pf_key_v2_sa_seq *node; - - for (node = TAILQ_FIRST (&pf_key_v2_sa_seq_map); node; - node = TAILQ_NEXT (node, link)) - if (node->proto == proto - && node->sz == sz && memcmp (node->spi, spi, sz) == 0 - && node->dstlen == sysdep_sa_len (dst) - && memcmp (node->dst, dst, sysdep_sa_len (dst)) == 0) - return node->seq; - return 0; + struct pf_key_v2_sa_seq *node; + + for (node = TAILQ_FIRST(&pf_key_v2_sa_seq_map); node; + node = TAILQ_NEXT(node, link)) + if (node->proto == proto && + node->sz == sz && memcmp(node->spi, spi, sz) == 0 && + node->dstlen == sysdep_sa_len(dst) && + memcmp(node->dst, dst, sysdep_sa_len(dst)) == 0) + return node->seq; + return 0; } #endif static struct pf_key_v2_msg * -pf_key_v2_msg_new (struct sadb_msg *msg, int flags) +pf_key_v2_msg_new(struct sadb_msg *msg, int flags) { - struct pf_key_v2_node *node = 0; - struct pf_key_v2_msg *ret; - - node = malloc (sizeof *node); - if (!node) - goto cleanup; - ret = malloc (sizeof *ret); - if (!ret) - goto cleanup; - TAILQ_INIT (ret); - node->seg = msg; - node->sz = sizeof *msg; - node->type = 0; - node->cnt = 1; - node->flags = flags; - TAILQ_INSERT_HEAD (ret, node, link); - return ret; - - cleanup: - if (node) - free (node); - return 0; + struct pf_key_v2_node *node = 0; + struct pf_key_v2_msg *ret; + + node = malloc(sizeof *node); + if (!node) + goto cleanup; + ret = malloc(sizeof *ret); + if (!ret) + goto cleanup; + TAILQ_INIT(ret); + node->seg = msg; + node->sz = sizeof *msg; + node->type = 0; + node->cnt = 1; + node->flags = flags; + TAILQ_INSERT_HEAD(ret, node, link); + return ret; + +cleanup: + if (node) + free(node); + return 0; } /* Add a SZ sized segment SEG to the PF_KEY message MSG. */ static int -pf_key_v2_msg_add (struct pf_key_v2_msg *msg, struct sadb_ext *ext, int flags) +pf_key_v2_msg_add(struct pf_key_v2_msg *msg, struct sadb_ext *ext, int flags) { - struct pf_key_v2_node *node; - - node = malloc (sizeof *node); - if (!node) - return -1; - node->seg = ext; - node->sz = ext->sadb_ext_len * PF_KEY_V2_CHUNK; - node->type = ext->sadb_ext_type; - node->flags = flags; - TAILQ_FIRST (msg)->cnt++; - TAILQ_INSERT_TAIL (msg, node, link); - return 0; + struct pf_key_v2_node *node; + + node = malloc(sizeof *node); + if (!node) + return -1; + node->seg = ext; + node->sz = ext->sadb_ext_len * PF_KEY_V2_CHUNK; + node->type = ext->sadb_ext_type; + node->flags = flags; + TAILQ_FIRST(msg)->cnt++; + TAILQ_INSERT_TAIL(msg, node, link); + return 0; } /* Deallocate the PF_KEY message MSG. */ static void -pf_key_v2_msg_free (struct pf_key_v2_msg *msg) +pf_key_v2_msg_free(struct pf_key_v2_msg *msg) { - struct pf_key_v2_node *np; - - np = TAILQ_FIRST (msg); - while (np) - { - TAILQ_REMOVE (msg, np, link); - if (np->flags & PF_KEY_V2_NODE_MALLOCED) - free (np->seg); - free (np); - np = TAILQ_FIRST (msg); - } - free (msg); + struct pf_key_v2_node *np; + + np = TAILQ_FIRST(msg); + while (np) { + TAILQ_REMOVE(msg, np, link); + if (np->flags & PF_KEY_V2_NODE_MALLOCED) + free(np->seg); + free(np); + np = TAILQ_FIRST(msg); + } + free(msg); } /* Just return a new sequence number. */ static u_int32_t -pf_key_v2_seq (void) +pf_key_v2_seq(void) { - static u_int32_t seq = 0; + static u_int32_t seq = 0; - return ++seq; + return ++seq; } /* @@ -276,221 +275,201 @@ pf_key_v2_seq (void) * messages up until both the PID and the sequence number match. */ static struct pf_key_v2_msg * -pf_key_v2_read (u_int32_t seq) +pf_key_v2_read(u_int32_t seq) { - ssize_t n; - u_int8_t *buf = 0; - struct pf_key_v2_msg *ret = 0; - struct sadb_msg *msg; - struct sadb_msg hdr; - struct sadb_ext *ext; - struct timeval tv; - fd_set *fds; - - while (1) - { - /* - * If this is a read of a reply we should actually expect the reply to - * get lost as PF_KEY is an unreliable service per the specs. - * Currently we do this by setting a short timeout, and if it is not - * readable in that time, we fail the read. - */ - if (seq) - { - fds = calloc (howmany (pf_key_v2_socket + 1, NFDBITS), - sizeof (fd_mask)); - if (!fds) - { - log_error ("pf_key_v2_read: calloc (%lu, %lu) failed", - (unsigned long)howmany (pf_key_v2_socket + 1, - NFDBITS), - (unsigned long)sizeof (fd_mask)); - goto cleanup; - } - FD_SET (pf_key_v2_socket, fds); - tv.tv_sec = 0; - tv.tv_usec = PF_KEY_REPLY_TIMEOUT; - n = select (pf_key_v2_socket + 1, fds, 0, 0, &tv); - free (fds); - if (n == -1) - { - log_error ("pf_key_v2_read: select (%d, fds, 0, 0, &tv) failed", - pf_key_v2_socket + 1); - goto cleanup; - } - if (!n) - { - log_print ("pf_key_v2_read: no reply from PF_KEY"); - goto cleanup; - } - } - n = recv (pf_key_v2_socket, &hdr, sizeof hdr, MSG_PEEK); - if (n == -1) - { - log_error ("pf_key_v2_read: recv (%d, ...) failed", - pf_key_v2_socket); - goto cleanup; - } - if (n != sizeof hdr) - { - log_error ("pf_key_v2_read: recv (%d, ...) returned short packet " - "(%lu bytes)", pf_key_v2_socket, (unsigned long)n); - goto cleanup; + ssize_t n; + u_int8_t *buf = 0; + struct pf_key_v2_msg *ret = 0; + struct sadb_msg *msg; + struct sadb_msg hdr; + struct sadb_ext *ext; + struct timeval tv; + fd_set *fds; + + while (1) { + /* + * If this is a read of a reply we should actually expect the reply to + * get lost as PF_KEY is an unreliable service per the specs. + * Currently we do this by setting a short timeout, and if it is not + * readable in that time, we fail the read. + */ + if (seq) { + fds = calloc(howmany(pf_key_v2_socket + 1, NFDBITS), + sizeof(fd_mask)); + if (!fds) { + log_error("pf_key_v2_read: calloc (%lu, %lu) failed", + (unsigned long) howmany(pf_key_v2_socket + 1, + NFDBITS), + (unsigned long) sizeof(fd_mask)); + goto cleanup; + } + FD_SET(pf_key_v2_socket, fds); + tv.tv_sec = 0; + tv.tv_usec = PF_KEY_REPLY_TIMEOUT; + n = select(pf_key_v2_socket + 1, fds, 0, 0, &tv); + free(fds); + if (n == -1) { + log_error("pf_key_v2_read: select (%d, fds, 0, " + "0, &tv) failed", + pf_key_v2_socket + 1); + goto cleanup; + } + if (!n) { + log_print("pf_key_v2_read: no reply from PF_KEY"); + goto cleanup; + } + } + n = recv(pf_key_v2_socket, &hdr, sizeof hdr, MSG_PEEK); + if (n == -1) { + log_error("pf_key_v2_read: recv (%d, ...) failed", + pf_key_v2_socket); + goto cleanup; + } + if (n != sizeof hdr) { + log_error("pf_key_v2_read: recv (%d, ...) " + "returned short packet (%lu bytes)", + pf_key_v2_socket, (unsigned long) n); + goto cleanup; + } + n = hdr.sadb_msg_len * PF_KEY_V2_CHUNK; + buf = malloc(n); + if (!buf) { + log_error("pf_key_v2_read: malloc (%lu) failed", + (unsigned long) n); + goto cleanup; + } + n = read(pf_key_v2_socket, buf, n); + if (n == -1) { + log_error("pf_key_v2_read: read (%d, ...) failed", + pf_key_v2_socket); + goto cleanup; + } + if (n != hdr.sadb_msg_len * PF_KEY_V2_CHUNK) { + log_print("pf_key_v2_read: read (%d, ...) " + "returned short packet (%lu bytes)", + pf_key_v2_socket, (unsigned long) n); + goto cleanup; + } + LOG_DBG_BUF((LOG_SYSDEP, 80, "pf_key_v2_read: msg", buf, n)); + + /* We drop all messages that is not what we expect. */ + msg = (struct sadb_msg *) buf; + if (msg->sadb_msg_version != PF_KEY_V2 || + (msg->sadb_msg_pid != 0 && + msg->sadb_msg_pid != (u_int32_t) getpid())) { + if (seq) { + free(buf); + buf = 0; + continue; + } else { + LOG_DBG((LOG_SYSDEP, 90, + "pf_key_v2_read:" + "bad version (%d) or PID (%d, mine is %ld), ignored", + msg->sadb_msg_version, msg->sadb_msg_pid, + (long) getpid())); + goto cleanup; + } + } + /* Parse the message. */ + ret = pf_key_v2_msg_new(msg, PF_KEY_V2_NODE_MALLOCED); + if (!ret) + goto cleanup; + buf = 0; + for (ext = (struct sadb_ext *) (msg + 1); + (u_int8_t *) ext - (u_int8_t *) msg < + msg->sadb_msg_len * PF_KEY_V2_CHUNK; + ext = (struct sadb_ext *) ((u_int8_t *) ext + + ext->sadb_ext_len * PF_KEY_V2_CHUNK)) + pf_key_v2_msg_add(ret, ext, 0); + + /* + * If the message is not the one we are waiting for, queue it + * up. + */ + if (seq && (msg->sadb_msg_pid != (u_int32_t) getpid() || + msg->sadb_msg_seq != seq)) { + gettimeofday(&tv, 0); + timer_add_event("pf_key_v2_notify", + (void (*) (void *)) pf_key_v2_notify, ret, &tv); + ret = 0; + continue; + } + return ret; } - n = hdr.sadb_msg_len * PF_KEY_V2_CHUNK; - buf = malloc (n); - if (!buf) - { - log_error ("pf_key_v2_read: malloc (%lu) failed", (unsigned long)n); - goto cleanup; - } +cleanup: + if (buf) + free(buf); + if (ret) + pf_key_v2_msg_free(ret); + return 0; +} - n = read (pf_key_v2_socket, buf, n); - if (n == -1) - { - log_error ("pf_key_v2_read: read (%d, ...) failed", - pf_key_v2_socket); - goto cleanup; +/* Write the message in PMSG to the PF_KEY socket. */ +u_int32_t +pf_key_v2_write(struct pf_key_v2_msg *pmsg) +{ + struct iovec *iov = 0; + ssize_t n; + size_t len; + int i, cnt = TAILQ_FIRST(pmsg)->cnt; + char header[80]; + struct sadb_msg *msg = TAILQ_FIRST(pmsg)->seg; + struct pf_key_v2_node *np = TAILQ_FIRST(pmsg); + + iov = (struct iovec *) malloc(cnt * sizeof *iov); + if (!iov) { + log_error("pf_key_v2_write: malloc (%lu) failed", + cnt * (unsigned long) sizeof *iov); + return 0; } - - if (n != hdr.sadb_msg_len * PF_KEY_V2_CHUNK) - { - log_print ("pf_key_v2_read: read (%d, ...) returned short packet " - "(%lu bytes)", pf_key_v2_socket, (unsigned long)n); - goto cleanup; + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_errno = 0; + msg->sadb_msg_reserved = 0; + msg->sadb_msg_pid = getpid(); + if (!msg->sadb_msg_seq) + msg->sadb_msg_seq = pf_key_v2_seq(); + + /* Compute the iovec segments as well as the message length. */ + len = 0; + for (i = 0; i < cnt; i++) { + iov[i].iov_base = np->seg; + len += iov[i].iov_len = np->sz; + + /* + * XXX One can envision setting specific extension fields, like + * *_reserved ones here. For now we require them to be set by the + * caller. + */ + + np = TAILQ_NEXT(np, link); } + msg->sadb_msg_len = len / PF_KEY_V2_CHUNK; - LOG_DBG_BUF ((LOG_SYSDEP, 80, "pf_key_v2_read: msg", buf, n)); - - /* We drop all messages that is not what we expect. */ - msg = (struct sadb_msg *)buf; - if (msg->sadb_msg_version != PF_KEY_V2 - || (msg->sadb_msg_pid != 0 - && msg->sadb_msg_pid != (u_int32_t)getpid ())) - { - if (seq) - { - free (buf); - buf = 0; - continue; - } - else - { - LOG_DBG ((LOG_SYSDEP, 90, - "pf_key_v2_read:" - "bad version (%d) or PID (%d, mine is %ld), ignored", - msg->sadb_msg_version, msg->sadb_msg_pid, - (long)getpid ())); - goto cleanup; - } + for (i = 0; i < cnt; i++) { + snprintf(header, sizeof header, "pf_key_v2_write: iov[%d]", i); + LOG_DBG_BUF((LOG_SYSDEP, 80, header, (u_int8_t *) iov[i].iov_base, + iov[i].iov_len)); } - /* Parse the message. */ - ret = pf_key_v2_msg_new (msg, PF_KEY_V2_NODE_MALLOCED); - if (!ret) - goto cleanup; - buf = 0; - for (ext = (struct sadb_ext *)(msg + 1); - (u_int8_t *)ext - (u_int8_t *)msg - < msg->sadb_msg_len * PF_KEY_V2_CHUNK; - ext = (struct sadb_ext *)((u_int8_t *)ext - + ext->sadb_ext_len * PF_KEY_V2_CHUNK)) - pf_key_v2_msg_add (ret, ext, 0); - - /* If the message is not the one we are waiting for, queue it up. */ - if (seq && (msg->sadb_msg_pid != (u_int32_t)getpid () - || msg->sadb_msg_seq != seq)) - { - gettimeofday (&tv, 0); - timer_add_event ("pf_key_v2_notify", - (void (*) (void *))pf_key_v2_notify, ret, &tv); - ret = 0; - continue; + n = writev(pf_key_v2_socket, iov, cnt); + if (n == -1) { + log_error("pf_key_v2_write: writev (%d, %p, %d) failed", + pf_key_v2_socket, iov, cnt); + goto cleanup; } + if ((size_t) n != len) { + log_error("pf_key_v2_write: writev (%d, ...) returned prematurely " + "(%lu)", pf_key_v2_socket, (unsigned long) n); + goto cleanup; + } + free(iov); + return msg->sadb_msg_seq; - return ret; - } - - cleanup: - if (buf) - free (buf); - if (ret) - pf_key_v2_msg_free (ret); - return 0; -} - -/* Write the message in PMSG to the PF_KEY socket. */ -u_int32_t -pf_key_v2_write (struct pf_key_v2_msg *pmsg) -{ - struct iovec *iov = 0; - ssize_t n; - size_t len; - int i, cnt = TAILQ_FIRST (pmsg)->cnt; - char header[80]; - struct sadb_msg *msg = TAILQ_FIRST (pmsg)->seg; - struct pf_key_v2_node *np = TAILQ_FIRST (pmsg); - - iov = (struct iovec *)malloc (cnt * sizeof *iov); - if (!iov) - { - log_error ("pf_key_v2_write: malloc (%lu) failed", - cnt * (unsigned long)sizeof *iov); - return 0; - } - - msg->sadb_msg_version = PF_KEY_V2; - msg->sadb_msg_errno = 0; - msg->sadb_msg_reserved = 0; - msg->sadb_msg_pid = getpid (); - if (!msg->sadb_msg_seq) - msg->sadb_msg_seq = pf_key_v2_seq (); - - /* Compute the iovec segments as well as the message length. */ - len = 0; - for (i = 0; i < cnt; i++) - { - iov[i].iov_base = np->seg; - len += iov[i].iov_len = np->sz; - - /* - * XXX One can envision setting specific extension fields, like - * *_reserved ones here. For now we require them to be set by the - * caller. - */ - - np = TAILQ_NEXT (np, link); - } - msg->sadb_msg_len = len / PF_KEY_V2_CHUNK; - - for (i = 0; i < cnt; i++) - { - snprintf (header, sizeof header, "pf_key_v2_write: iov[%d]", i); - LOG_DBG_BUF ((LOG_SYSDEP, 80, header, (u_int8_t *)iov[i].iov_base, - iov[i].iov_len)); - } - - n = writev (pf_key_v2_socket, iov, cnt); - if (n == -1) - { - log_error ("pf_key_v2_write: writev (%d, %p, %d) failed", - pf_key_v2_socket, iov, cnt); - goto cleanup; - } - if ((size_t)n != len) - { - log_error ("pf_key_v2_write: writev (%d, ...) returned prematurely " - "(%lu)", pf_key_v2_socket, (unsigned long)n); - goto cleanup; - } - free (iov); - return msg->sadb_msg_seq; - - cleanup: - if (iov) - free (iov); - return 0; +cleanup: + if (iov) + free(iov); + return 0; } /* @@ -498,27 +477,27 @@ pf_key_v2_write (struct pf_key_v2_msg *pmsg) * it to the caller. */ static struct pf_key_v2_msg * -pf_key_v2_call (struct pf_key_v2_msg *msg) +pf_key_v2_call(struct pf_key_v2_msg *msg) { - u_int32_t seq; + u_int32_t seq; - seq = pf_key_v2_write (msg); - if (!seq) - return 0; - return pf_key_v2_read (seq); + seq = pf_key_v2_write(msg); + if (!seq) + return 0; + return pf_key_v2_read(seq); } /* Find the TYPE extension in MSG. Return zero if none found. */ static struct pf_key_v2_node * -pf_key_v2_find_ext (struct pf_key_v2_msg *msg, u_int16_t type) +pf_key_v2_find_ext(struct pf_key_v2_msg *msg, u_int16_t type) { - struct pf_key_v2_node *ext; + struct pf_key_v2_node *ext; - for (ext = TAILQ_NEXT (TAILQ_FIRST (msg), link); ext; - ext = TAILQ_NEXT (ext, link)) - if (ext->type == type) - return ext; - return 0; + for (ext = TAILQ_NEXT(TAILQ_FIRST(msg), link); ext; + ext = TAILQ_NEXT(ext, link)) + if (ext->type == type) + return ext; + return 0; } /* @@ -526,106 +505,98 @@ pf_key_v2_find_ext (struct pf_key_v2_msg *msg, u_int16_t type) * Return -1 for failure and -2 if no notifies will show up. */ int -pf_key_v2_open (void) +pf_key_v2_open(void) { - int fd = -1, err; - struct sadb_msg msg; - struct pf_key_v2_msg *regmsg = 0, *ret = 0; - - /* Open the socket we use to speak to IPsec. */ - pf_key_v2_socket = -1; - fd = monitor_socket (PF_KEY, SOCK_RAW, PF_KEY_V2); - if (fd == -1) - { - log_error ("pf_key_v2_open: " - "socket (PF_KEY, SOCK_RAW, PF_KEY_V2) failed"); - goto cleanup; - } - pf_key_v2_socket = fd; - - /* Register it to get ESP and AH acquires from the kernel. */ - msg.sadb_msg_seq = 0; - msg.sadb_msg_type = SADB_REGISTER; - msg.sadb_msg_satype = SADB_SATYPE_ESP; - regmsg = pf_key_v2_msg_new (&msg, 0); - if (!regmsg) - goto cleanup; - ret = pf_key_v2_call (regmsg); - pf_key_v2_msg_free (regmsg); - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - log_print ("pf_key_v2_open: REGISTER: %s", strerror (err)); - goto cleanup; - } - - /* XXX Register the accepted transforms. */ - - pf_key_v2_msg_free (ret); - ret = 0; - - msg.sadb_msg_seq = 0; - msg.sadb_msg_type = SADB_REGISTER; - msg.sadb_msg_satype = SADB_SATYPE_AH; - regmsg = pf_key_v2_msg_new (&msg, 0); - if (!regmsg) - goto cleanup; - ret = pf_key_v2_call (regmsg); - pf_key_v2_msg_free (regmsg); - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - log_print ("pf_key_v2_open: REGISTER: %s", strerror (err)); - goto cleanup; - } - - /* XXX Register the accepted transforms. */ - - pf_key_v2_msg_free (ret); - ret = 0; + int fd = -1, err; + struct sadb_msg msg; + struct pf_key_v2_msg *regmsg = 0, *ret = 0; + + /* Open the socket we use to speak to IPsec. */ + pf_key_v2_socket = -1; + fd = monitor_socket(PF_KEY, SOCK_RAW, PF_KEY_V2); + if (fd == -1) { + log_error("pf_key_v2_open: " + "socket (PF_KEY, SOCK_RAW, PF_KEY_V2) failed"); + goto cleanup; + } + pf_key_v2_socket = fd; + + /* Register it to get ESP and AH acquires from the kernel. */ + msg.sadb_msg_seq = 0; + msg.sadb_msg_type = SADB_REGISTER; + msg.sadb_msg_satype = SADB_SATYPE_ESP; + regmsg = pf_key_v2_msg_new(&msg, 0); + if (!regmsg) + goto cleanup; + ret = pf_key_v2_call(regmsg); + pf_key_v2_msg_free(regmsg); + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); + goto cleanup; + } + /* XXX Register the accepted transforms. */ + + pf_key_v2_msg_free(ret); + ret = 0; + + msg.sadb_msg_seq = 0; + msg.sadb_msg_type = SADB_REGISTER; + msg.sadb_msg_satype = SADB_SATYPE_AH; + regmsg = pf_key_v2_msg_new(&msg, 0); + if (!regmsg) + goto cleanup; + ret = pf_key_v2_call(regmsg); + pf_key_v2_msg_free(regmsg); + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); + goto cleanup; + } + /* XXX Register the accepted transforms. */ + + pf_key_v2_msg_free(ret); + ret = 0; #ifdef SADB_X_SATYPE_IPCOMP - msg.sadb_msg_seq = 0; - msg.sadb_msg_type = SADB_REGISTER; - msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; - regmsg = pf_key_v2_msg_new (&msg, 0); - if (!regmsg) - goto cleanup; - ret = pf_key_v2_call (regmsg); - pf_key_v2_msg_free (regmsg); - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - log_print ("pf_key_v2_open: REGISTER: %s", strerror (err)); - goto cleanup; - } - - /* XXX Register the accepted transforms. */ - - pf_key_v2_msg_free (ret); + msg.sadb_msg_seq = 0; + msg.sadb_msg_type = SADB_REGISTER; + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + regmsg = pf_key_v2_msg_new(&msg, 0); + if (!regmsg) + goto cleanup; + ret = pf_key_v2_call(regmsg); + pf_key_v2_msg_free(regmsg); + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); + goto cleanup; + } + /* XXX Register the accepted transforms. */ + + pf_key_v2_msg_free(ret); #endif /* SADB_X_SATYPE_IPCOMP */ #ifdef KAME - TAILQ_INIT (&pf_key_v2_sa_seq_map); + TAILQ_INIT(&pf_key_v2_sa_seq_map); #endif - return fd; - - cleanup: - if (pf_key_v2_socket != -1) - { - close (pf_key_v2_socket); - pf_key_v2_socket = -1; - } - if (ret) - pf_key_v2_msg_free (ret); - return -1; + return fd; + +cleanup: + if (pf_key_v2_socket != -1) { + close(pf_key_v2_socket); + pf_key_v2_socket = -1; + } + if (ret) + pf_key_v2_msg_free(ret); + return -1; } /* @@ -633,231 +604,217 @@ pf_key_v2_open (void) * SRC, SRCLEN, DST & DSTLEN. Stash the SPI size in SZ. */ u_int8_t * -pf_key_v2_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, - struct sockaddr *dst, u_int32_t seq) +pf_key_v2_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src, + struct sockaddr *dst, u_int32_t seq) { - struct sadb_msg msg; - struct sadb_sa *sa; - struct sadb_address *addr = 0; - struct sadb_spirange spirange; - struct pf_key_v2_msg *getspi = 0, *ret = 0; - struct pf_key_v2_node *ext; - u_int8_t *spi = 0; - int len, err; + struct sadb_msg msg; + struct sadb_sa *sa; + struct sadb_address *addr = 0; + struct sadb_spirange spirange; + struct pf_key_v2_msg *getspi = 0, *ret = 0; + struct pf_key_v2_node *ext; + u_int8_t *spi = 0; + int len, err; #ifdef KAME - struct sadb_x_sa2 ssa2; + struct sadb_x_sa2 ssa2; #endif - msg.sadb_msg_type = SADB_GETSPI; - switch (proto) - { - case IPSEC_PROTO_IPSEC_ESP: - msg.sadb_msg_satype = SADB_SATYPE_ESP; - break; - case IPSEC_PROTO_IPSEC_AH: - msg.sadb_msg_satype = SADB_SATYPE_AH; - break; + msg.sadb_msg_type = SADB_GETSPI; + switch (proto) { + case IPSEC_PROTO_IPSEC_ESP: + msg.sadb_msg_satype = SADB_SATYPE_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + msg.sadb_msg_satype = SADB_SATYPE_AH; + break; #ifdef SADB_X_SATYPE_IPCOMP - case IPSEC_PROTO_IPCOMP: - msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; - break; + case IPSEC_PROTO_IPCOMP: + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + break; #endif - default: - log_print ("pf_key_v2_get_spi: invalid proto %d", proto); - goto cleanup; - } + default: + log_print("pf_key_v2_get_spi: invalid proto %d", proto); + goto cleanup; + } - /* Set the sequence number from the ACQUIRE message. */ - msg.sadb_msg_seq = seq; - getspi = pf_key_v2_msg_new (&msg, 0); - if (!getspi) - goto cleanup; + /* Set the sequence number from the ACQUIRE message. */ + msg.sadb_msg_seq = seq; + getspi = pf_key_v2_msg_new(&msg, 0); + if (!getspi) + goto cleanup; #ifdef KAME - memset (&ssa2, 0, sizeof ssa2); - ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; - ssa2.sadb_x_sa2_mode = 0; - if (pf_key_v2_msg_add (getspi, (struct sadb_ext *)&ssa2, 0) == -1) - goto cleanup; + memset(&ssa2, 0, sizeof ssa2); + ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; + ssa2.sadb_x_sa2_mode = 0; + if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) & ssa2, 0) == -1) + goto cleanup; #endif - /* Setup the ADDRESS extensions. */ - len = sizeof (struct sadb_address) + PF_KEY_V2_ROUND (sysdep_sa_len (src)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + /* Setup the ADDRESS extensions. */ + len = sizeof(struct sadb_address) + PF_KEY_V2_ROUND(sysdep_sa_len(src)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, src, sysdep_sa_len (src)); - switch (((struct sockaddr *)(addr + 1))->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; - } - if (pf_key_v2_msg_add (getspi, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - len = sizeof (struct sadb_address) + PF_KEY_V2_ROUND (sysdep_sa_len (dst)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + memcpy(addr + 1, src, sysdep_sa_len(src)); + switch (((struct sockaddr *) (addr + 1))->sa_family) { + case AF_INET: + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; + } + if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + len = sizeof(struct sadb_address) + PF_KEY_V2_ROUND(sysdep_sa_len(dst)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, dst, sysdep_sa_len (dst)); - switch (((struct sockaddr *)(addr + 1))->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; - } - if (pf_key_v2_msg_add (getspi, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - /* Setup the SPIRANGE extension. */ - spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; - spirange.sadb_spirange_len = sizeof spirange / PF_KEY_V2_CHUNK; - if (proto == IPSEC_PROTO_IPCOMP) - { - spirange.sadb_spirange_min = CPI_RESERVED_MAX + 1; - spirange.sadb_spirange_max = CPI_PRIVATE_MIN - 1; - } - else - { - spirange.sadb_spirange_min = IPSEC_SPI_LOW; - spirange.sadb_spirange_max = 0xffffffff; - } - spirange.sadb_spirange_reserved = 0; - if (pf_key_v2_msg_add (getspi, (struct sadb_ext *)&spirange, 0) == -1) - goto cleanup; - - ret = pf_key_v2_call (getspi); - pf_key_v2_msg_free (getspi); - getspi = 0; - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - log_print ("pf_key_v2_get_spi: GETSPI: %s", strerror (err)); - goto cleanup; - } - - ext = pf_key_v2_find_ext (ret, SADB_EXT_SA); - if (!ext) - { - log_print ("pf_key_v2_get_spi: no SA extension found"); - goto cleanup; - } - sa = ext->seg; - - /* IPCOMP CPIs are only 16 bits long. */ - *sz = (proto == IPSEC_PROTO_IPCOMP) ? sizeof (u_int16_t) - : sizeof sa->sadb_sa_spi; - spi = malloc (*sz); - if (!spi) - goto cleanup; - /* XXX This is ugly. */ - if (proto == IPSEC_PROTO_IPCOMP) - { - u_int32_t tspi = ntohl (sa->sadb_sa_spi); - *(u_int16_t *)spi = htons ((u_int16_t)tspi); - } - else - memcpy (spi, &sa->sadb_sa_spi, *sz); + addr->sadb_address_reserved = 0; + memcpy(addr + 1, dst, sysdep_sa_len(dst)); + switch (((struct sockaddr *) (addr + 1))->sa_family) { + case AF_INET: + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; + } + if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + /* Setup the SPIRANGE extension. */ + spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; + spirange.sadb_spirange_len = sizeof spirange / PF_KEY_V2_CHUNK; + if (proto == IPSEC_PROTO_IPCOMP) { + spirange.sadb_spirange_min = CPI_RESERVED_MAX + 1; + spirange.sadb_spirange_max = CPI_PRIVATE_MIN - 1; + } else { + spirange.sadb_spirange_min = IPSEC_SPI_LOW; + spirange.sadb_spirange_max = 0xffffffff; + } + spirange.sadb_spirange_reserved = 0; + if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) & spirange, 0) == -1) + goto cleanup; + + ret = pf_key_v2_call(getspi); + pf_key_v2_msg_free(getspi); + getspi = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + log_print("pf_key_v2_get_spi: GETSPI: %s", strerror(err)); + goto cleanup; + } + ext = pf_key_v2_find_ext(ret, SADB_EXT_SA); + if (!ext) { + log_print("pf_key_v2_get_spi: no SA extension found"); + goto cleanup; + } + sa = ext->seg; + + /* IPCOMP CPIs are only 16 bits long. */ + *sz = (proto == IPSEC_PROTO_IPCOMP) ? sizeof(u_int16_t) + : sizeof sa->sadb_sa_spi; + spi = malloc(*sz); + if (!spi) + goto cleanup; + /* XXX This is ugly. */ + if (proto == IPSEC_PROTO_IPCOMP) { + u_int32_t tspi = ntohl(sa->sadb_sa_spi); + *(u_int16_t *) spi = htons((u_int16_t) tspi); + } else + memcpy(spi, &sa->sadb_sa_spi, *sz); #ifdef KAME - if (!pf_key_v2_register_sa_seq (spi, *sz, proto, dst, sysdep_sa_len (dst), - ((struct sadb_msg *)(TAILQ_FIRST (ret)->seg)) - ->sadb_msg_seq)) - goto cleanup; + if (!pf_key_v2_register_sa_seq(spi, *sz, proto, dst, sysdep_sa_len(dst), + ((struct sadb_msg *) (TAILQ_FIRST(ret)->seg))->sadb_msg_seq)) + goto cleanup; #endif - pf_key_v2_msg_free (ret); - - LOG_DBG_BUF ((LOG_SYSDEP, 50, "pf_key_v2_get_spi: spi", spi, *sz)); - - return spi; - - cleanup: - if (spi) - free (spi); - if (addr) - free (addr); - if (getspi) - pf_key_v2_msg_free (getspi); - if (ret) - pf_key_v2_msg_free (ret); - return 0; + pf_key_v2_msg_free(ret); + + LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_spi: spi", spi, *sz)); + return spi; + +cleanup: + if (spi) + free(spi); + if (addr) + free(addr); + if (getspi) + pf_key_v2_msg_free(getspi); + if (ret) + pf_key_v2_msg_free(ret); + return 0; } static void -pf_key_v2_setup_sockaddr (void *res, struct sockaddr *src, - struct sockaddr *dst, in_port_t port, int ingress) +pf_key_v2_setup_sockaddr(void *res, struct sockaddr *src, + struct sockaddr *dst, in_port_t port, int ingress) { - struct sockaddr_in *ip4_sa; - struct sockaddr_in6 *ip6_sa; - u_int8_t *p; - - switch (src->sa_family) - { - case AF_INET: - ip4_sa = (struct sockaddr_in *)res; - ip4_sa->sin_family = AF_INET; + struct sockaddr_in *ip4_sa; + struct sockaddr_in6 *ip6_sa; + u_int8_t *p; + + switch (src->sa_family) { + case AF_INET: + ip4_sa = (struct sockaddr_in *) res; + ip4_sa->sin_family = AF_INET; #ifndef USE_OLD_SOCKADDR - ip4_sa->sin_len = sizeof *ip4_sa; -#endif - ip4_sa->sin_port = port; - if (dst) - p = (u_int8_t *)(ingress - ? &((struct sockaddr_in *)src)->sin_addr.s_addr - : &((struct sockaddr_in *)dst)->sin_addr.s_addr); - else - p = (u_int8_t *)&((struct sockaddr_in *)src)->sin_addr.s_addr; - ip4_sa->sin_addr.s_addr = *((in_addr_t *)p); - break; - - case AF_INET6: - ip6_sa = (struct sockaddr_in6 *)res; - ip6_sa->sin6_family = AF_INET6; + ip4_sa->sin_len = sizeof *ip4_sa; +#endif + ip4_sa->sin_port = port; + if (dst) + p = (u_int8_t *) (ingress ? + &((struct sockaddr_in *)src)->sin_addr.s_addr : + &((struct sockaddr_in *)dst)->sin_addr.s_addr); + else + p = (u_int8_t *)&((struct sockaddr_in *)src)->sin_addr.s_addr; + ip4_sa->sin_addr.s_addr = *((in_addr_t *) p); + break; + + case AF_INET6: + ip6_sa = (struct sockaddr_in6 *) res; + ip6_sa->sin6_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - ip6_sa->sin6_len = sizeof *ip6_sa; -#endif - ip6_sa->sin6_port = port; - if (dst) - p = (u_int8_t *)(ingress - ? &((struct sockaddr_in6 *)src)->sin6_addr.s6_addr - : &((struct sockaddr_in6 *)dst)->sin6_addr.s6_addr); - else - p = (u_int8_t *)&((struct sockaddr_in6 *)src)->sin6_addr.s6_addr; - memcpy (ip6_sa->sin6_addr.s6_addr, p, sizeof (struct in6_addr)); - break; - - default: - log_print ("pf_key_v2_setup_sockaddr: unknown family %d\n", - src->sa_family); - break; - } + ip6_sa->sin6_len = sizeof *ip6_sa; +#endif + ip6_sa->sin6_port = port; + if (dst) + p = (u_int8_t *) (ingress ? + &((struct sockaddr_in6 *)src)->sin6_addr.s6_addr : + &((struct sockaddr_in6 *)dst)->sin6_addr.s6_addr); + else + p = (u_int8_t *)&((struct sockaddr_in6 *)src)->sin6_addr.s6_addr; + memcpy(ip6_sa->sin6_addr.s6_addr, p, sizeof(struct in6_addr)); + break; + + default: + log_print("pf_key_v2_setup_sockaddr: unknown family %d\n", + src->sa_family); + break; + } } /* @@ -866,860 +823,834 @@ pf_key_v2_setup_sockaddr (void *res, struct sockaddr *src, * parameters for the incoming SA, and cleared otherwise. */ int -pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, - struct sa *isakmp_sa) +pf_key_v2_set_spi(struct sa *sa, struct proto *proto, int incoming, + struct sa *isakmp_sa) { - struct sadb_msg msg; - struct sadb_sa ssa; - struct sadb_lifetime *life = 0; - struct sadb_address *addr = 0; - struct sadb_key *key = 0; - struct sadb_ident *sid = 0; - struct sockaddr *src, *dst; - struct pf_key_v2_msg *update = 0, *ret = 0; - struct ipsec_proto *iproto = proto->data; - size_t len; - int keylen, hashlen, err; + struct sadb_msg msg; + struct sadb_sa ssa; + struct sadb_lifetime *life = 0; + struct sadb_address *addr = 0; + struct sadb_key *key = 0; + struct sadb_ident *sid = 0; + struct sockaddr *src, *dst; + struct pf_key_v2_msg *update = 0, *ret = 0; + struct ipsec_proto *iproto = proto->data; + size_t len; + int keylen, hashlen, err; #ifndef KAME - u_int8_t *pp; - int idtype; -#else /* KAME */ - struct sadb_x_sa2 ssa2; + u_int8_t *pp; + int idtype; +#else /* KAME */ + struct sadb_x_sa2 ssa2; #endif #if defined (SADB_X_CREDTYPE_NONE) || defined (SADB_X_AUTHTYPE_NONE) - struct ipsec_sa *isa = sa->data; - struct sadb_x_cred *cred; - struct sadb_protocol flowtype, tprotocol; + struct ipsec_sa *isa = sa->data; + struct sadb_x_cred *cred; + struct sadb_protocol flowtype, tprotocol; #endif #ifdef USE_DEBUG - char *addr_str; + char *addr_str; #endif - msg.sadb_msg_type = incoming ? SADB_UPDATE : SADB_ADD; - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_ESP: - msg.sadb_msg_satype = SADB_SATYPE_ESP; - keylen = ipsec_esp_enckeylength (proto); - hashlen = ipsec_esp_authkeylength (proto); + msg.sadb_msg_type = incoming ? SADB_UPDATE : SADB_ADD; + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_ESP: + msg.sadb_msg_satype = SADB_SATYPE_ESP; + keylen = ipsec_esp_enckeylength(proto); + hashlen = ipsec_esp_authkeylength(proto); - switch (proto->id) - { - case IPSEC_ESP_DES: - case IPSEC_ESP_DES_IV32: - case IPSEC_ESP_DES_IV64: - ssa.sadb_sa_encrypt = SADB_EALG_DESCBC; - break; + switch (proto->id) { + case IPSEC_ESP_DES: + case IPSEC_ESP_DES_IV32: + case IPSEC_ESP_DES_IV64: + ssa.sadb_sa_encrypt = SADB_EALG_DESCBC; + break; - case IPSEC_ESP_3DES: - ssa.sadb_sa_encrypt = SADB_EALG_3DESCBC; - break; + case IPSEC_ESP_3DES: + ssa.sadb_sa_encrypt = SADB_EALG_3DESCBC; + break; #ifdef SADB_X_EALG_AES - case IPSEC_ESP_AES: - /* case IPSEC_ESP_AES_128_CTR: */ - ssa.sadb_sa_encrypt = SADB_X_EALG_AES; - break; + case IPSEC_ESP_AES: + /* case IPSEC_ESP_AES_128_CTR: */ + ssa.sadb_sa_encrypt = SADB_X_EALG_AES; + break; #endif #ifdef SADB_X_EALG_CAST - case IPSEC_ESP_CAST: - ssa.sadb_sa_encrypt = SADB_X_EALG_CAST; - break; + case IPSEC_ESP_CAST: + ssa.sadb_sa_encrypt = SADB_X_EALG_CAST; + break; #endif #ifdef SADB_X_EALG_BLF - case IPSEC_ESP_BLOWFISH: - ssa.sadb_sa_encrypt = SADB_X_EALG_BLF; - break; + case IPSEC_ESP_BLOWFISH: + ssa.sadb_sa_encrypt = SADB_X_EALG_BLF; + break; #endif - default: - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_set_spi: unknown encryption algorithm %d", - proto->id)); - return -1; - } + default: + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_set_spi: unknown encryption algorithm %d", + proto->id)); + return -1; + } - switch (iproto->auth) - { - case IPSEC_AUTH_HMAC_MD5: + switch (iproto->auth) { + case IPSEC_AUTH_HMAC_MD5: #ifdef SADB_AALG_MD5HMAC96 - ssa.sadb_sa_auth = SADB_AALG_MD5HMAC96; + ssa.sadb_sa_auth = SADB_AALG_MD5HMAC96; #else - ssa.sadb_sa_auth = SADB_AALG_MD5HMAC; + ssa.sadb_sa_auth = SADB_AALG_MD5HMAC; #endif - break; + break; - case IPSEC_AUTH_HMAC_SHA: + case IPSEC_AUTH_HMAC_SHA: #ifdef SADB_AALG_SHA1HMAC96 - ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC96; + ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC96; #else - ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC; + ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC; #endif - break; + break; #ifndef KAME - case IPSEC_AUTH_HMAC_RIPEMD: + case IPSEC_AUTH_HMAC_RIPEMD: #ifdef SADB_X_AALG_RIPEMD160HMAC96 - ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC96; + ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC96; #elif defined (SADB_X_AALG_RIPEMD160HMAC) - ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC; + ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC; #elif defined (SADB_X_AALG_RIPEMD160) - ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160; + ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160; #else - ssa.sadb_sa_auth = SADB_AALG_RIPEMD160HMAC; + ssa.sadb_sa_auth = SADB_AALG_RIPEMD160HMAC; #endif - break; + break; #endif #ifdef SADB_X_AALG_SHA2_256 - case IPSEC_AUTH_HMAC_SHA2_256: - ssa.sadb_sa_auth = SADB_X_AALG_SHA2_256; - break; + case IPSEC_AUTH_HMAC_SHA2_256: + ssa.sadb_sa_auth = SADB_X_AALG_SHA2_256; + break; #endif #ifdef SADB_X_AALG_SHA2_384 - case IPSEC_AUTH_HMAC_SHA2_384: - ssa.sadb_sa_auth = SADB_X_AALG_SHA2_384; - break; + case IPSEC_AUTH_HMAC_SHA2_384: + ssa.sadb_sa_auth = SADB_X_AALG_SHA2_384; + break; #endif #ifdef SADB_X_AALG_SHA2_512 - case IPSEC_AUTH_HMAC_SHA2_512: - ssa.sadb_sa_auth = SADB_X_AALG_SHA2_512; - break; + case IPSEC_AUTH_HMAC_SHA2_512: + ssa.sadb_sa_auth = SADB_X_AALG_SHA2_512; + break; #endif - case IPSEC_AUTH_DES_MAC: - case IPSEC_AUTH_KPDK: - /* XXX We should be supporting KPDK */ - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_set_spi: unknown authentication algorithm %d", - iproto->auth)); - return -1; + case IPSEC_AUTH_DES_MAC: + case IPSEC_AUTH_KPDK: + /* XXX We should be supporting KPDK */ + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_set_spi: unknown authentication algorithm %d", + iproto->auth)); + return -1; - default: - ssa.sadb_sa_auth = SADB_AALG_NONE; - } - break; + default: + ssa.sadb_sa_auth = SADB_AALG_NONE; + } + break; - case IPSEC_PROTO_IPSEC_AH: - msg.sadb_msg_satype = SADB_SATYPE_AH; - hashlen = ipsec_ah_keylength (proto); - keylen = 0; + case IPSEC_PROTO_IPSEC_AH: + msg.sadb_msg_satype = SADB_SATYPE_AH; + hashlen = ipsec_ah_keylength(proto); + keylen = 0; - ssa.sadb_sa_encrypt = SADB_EALG_NONE; - switch (proto->id) - { - case IPSEC_AH_MD5: + ssa.sadb_sa_encrypt = SADB_EALG_NONE; + switch (proto->id) { + case IPSEC_AH_MD5: #ifdef SADB_AALG_MD5HMAC96 - ssa.sadb_sa_auth = SADB_AALG_MD5HMAC96; + ssa.sadb_sa_auth = SADB_AALG_MD5HMAC96; #else - ssa.sadb_sa_auth = SADB_AALG_MD5HMAC; + ssa.sadb_sa_auth = SADB_AALG_MD5HMAC; #endif - break; + break; - case IPSEC_AH_SHA: + case IPSEC_AH_SHA: #ifdef SADB_AALG_SHA1HMAC96 - ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC96; + ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC96; #else - ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC; + ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC; #endif - break; + break; #ifndef KAME - case IPSEC_AH_RIPEMD: + case IPSEC_AH_RIPEMD: #ifdef SADB_X_AALG_RIPEMD160HMAC96 - ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC96; + ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC96; #elif defined (SADB_X_AALG_RIPEMD160HMAC) - ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC; + ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC; #elif defined (SADB_X_AALG_RIPEMD160) - ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160; + ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160; #else - ssa.sadb_sa_auth = SADB_AALG_RIPEMD160HMAC; + ssa.sadb_sa_auth = SADB_AALG_RIPEMD160HMAC; #endif - break; + break; #endif #ifdef SADB_X_AALG_SHA2_256 - case IPSEC_AH_SHA2_256: - ssa.sadb_sa_auth = SADB_X_AALG_SHA2_256; - break; + case IPSEC_AH_SHA2_256: + ssa.sadb_sa_auth = SADB_X_AALG_SHA2_256; + break; #endif #ifdef SADB_X_AALG_SHA2_384 - case IPSEC_AH_SHA2_384: - ssa.sadb_sa_auth = SADB_X_AALG_SHA2_384; - break; + case IPSEC_AH_SHA2_384: + ssa.sadb_sa_auth = SADB_X_AALG_SHA2_384; + break; #endif #ifdef SADB_X_AALG_SHA2_512 - case IPSEC_AH_SHA2_512: - ssa.sadb_sa_auth = SADB_X_AALG_SHA2_512; - break; + case IPSEC_AH_SHA2_512: + ssa.sadb_sa_auth = SADB_X_AALG_SHA2_512; + break; #endif - default: - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_set_spi: unknown authentication algorithm %d", - proto->id)); - goto cleanup; - } - break; + default: + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_set_spi: unknown authentication algorithm %d", + proto->id)); + goto cleanup; + } + break; #ifdef SADB_X_SATYPE_IPCOMP - case IPSEC_PROTO_IPCOMP: - msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; - ssa.sadb_sa_auth = SADB_AALG_NONE; - keylen = 0; - hashlen = 0; - - /* Put compression algorithm type in the sadb_sa_encrypt field. */ - switch (proto->id) - { + case IPSEC_PROTO_IPCOMP: + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + ssa.sadb_sa_auth = SADB_AALG_NONE; + keylen = 0; + hashlen = 0; + + /* + * Put compression algorithm type in the sadb_sa_encrypt + * field. + */ + switch (proto->id) { #ifdef SADB_X_CALG_OUI - case IPSEC_IPCOMP_OUI: - ssa.sadb_sa_encrypt = SADB_X_CALG_OUI; - break; + case IPSEC_IPCOMP_OUI: + ssa.sadb_sa_encrypt = SADB_X_CALG_OUI; + break; #endif #ifdef SADB_X_CALG_DEFLATE - case IPSEC_IPCOMP_DEFLATE: - ssa.sadb_sa_encrypt = SADB_X_CALG_DEFLATE; - break; + case IPSEC_IPCOMP_DEFLATE: + ssa.sadb_sa_encrypt = SADB_X_CALG_DEFLATE; + break; #endif #ifdef SADB_X_CALG_LZS - case IPSEC_IPCOMP_LZS: - ssa.sadb_sa_encrypt = SADB_X_CALG_LZS; - break; + case IPSEC_IPCOMP_LZS: + ssa.sadb_sa_encrypt = SADB_X_CALG_LZS; + break; #endif #ifdef SADB_X_CALG_V42BIS - case IPSEC_IPCOMP_V42BIS: - ssa.sadb_sa_encrypt = SADB_X_CALG_V42BIS; - break; + case IPSEC_IPCOMP_V42BIS: + ssa.sadb_sa_encrypt = SADB_X_CALG_V42BIS; + break; #endif - default: - break; - } - break; + default: + break; + } + break; #endif /* SADB_X_SATYPE_IPCOMP */ - default: - log_print ("pf_key_v2_set_spi: invalid proto %d", proto->proto); - goto cleanup; - } - if (incoming) - sa->transport->vtbl->get_src (sa->transport, &dst); - else - sa->transport->vtbl->get_dst (sa->transport, &dst); + default: + log_print("pf_key_v2_set_spi: invalid proto %d", proto->proto); + goto cleanup; + } + if (incoming) + sa->transport->vtbl->get_src(sa->transport, &dst); + else + sa->transport->vtbl->get_dst(sa->transport, &dst); #ifdef KAME - msg.sadb_msg_seq - = (incoming ? pf_key_v2_seq_by_sa (proto->spi[incoming], - sizeof ssa.sadb_sa_spi, proto->proto, - dst, sysdep_sa_len (dst)) - : 0); + msg.sadb_msg_seq = (incoming ? + pf_key_v2_seq_by_sa(proto->spi[incoming], sizeof ssa.sadb_sa_spi, + proto->proto, dst, sysdep_sa_len(dst)) : 0); #else - msg.sadb_msg_seq = sa->seq; + msg.sadb_msg_seq = sa->seq; #endif - update = pf_key_v2_msg_new (&msg, 0); - if (!update) - goto cleanup; + update = pf_key_v2_msg_new(&msg, 0); + if (!update) + goto cleanup; #ifdef KAME - memset (&ssa2, 0, sizeof ssa2); - ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; + memset(&ssa2, 0, sizeof ssa2); + ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; #if defined (LINUX_IPSEC) - if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) - ssa2.sadb_x_sa2_mode = IPSEC_MODE_TUNNEL; - else - ssa2.sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT; + if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) + ssa2.sadb_x_sa2_mode = IPSEC_MODE_TUNNEL; + else + ssa2.sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT; #else - ssa2.sadb_x_sa2_mode = 0; + ssa2.sadb_x_sa2_mode = 0; #endif - if (pf_key_v2_msg_add (update, (struct sadb_ext *)&ssa2, 0) == -1) - goto cleanup; + if (pf_key_v2_msg_add(update, (struct sadb_ext *) & ssa2, 0) == -1) + goto cleanup; #endif - /* Setup the rest of the SA extension. */ - ssa.sadb_sa_exttype = SADB_EXT_SA; - ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; - if (proto->spi_sz[incoming] == 2) /* IPCOMP uses 16bit CPIs. */ - ssa.sadb_sa_spi = htonl (proto->spi[incoming][0] << 8 - | proto->spi[incoming][1]); - else - memcpy (&ssa.sadb_sa_spi, proto->spi[incoming], sizeof ssa.sadb_sa_spi); - ssa.sadb_sa_replay - = conf_get_str ("General", "Shared-SADB") ? 0 : iproto->replay_window; - ssa.sadb_sa_state = SADB_SASTATE_MATURE; + /* Setup the rest of the SA extension. */ + ssa.sadb_sa_exttype = SADB_EXT_SA; + ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; + if (proto->spi_sz[incoming] == 2) /* IPCOMP uses 16bit CPIs. */ + ssa.sadb_sa_spi = htonl(proto->spi[incoming][0] << 8 | + proto->spi[incoming][1]); + else + memcpy(&ssa.sadb_sa_spi, proto->spi[incoming], + sizeof ssa.sadb_sa_spi); + ssa.sadb_sa_replay = conf_get_str("General", "Shared-SADB") ? 0 : + iproto->replay_window; + ssa.sadb_sa_state = SADB_SASTATE_MATURE; #ifdef SADB_X_SAFLAGS_TUNNEL - ssa.sadb_sa_flags - = iproto->encap_mode == IPSEC_ENCAP_TUNNEL ? SADB_X_SAFLAGS_TUNNEL : 0; + ssa.sadb_sa_flags = iproto->encap_mode == IPSEC_ENCAP_TUNNEL ? + SADB_X_SAFLAGS_TUNNEL : 0; #else - ssa.sadb_sa_flags = 0; + ssa.sadb_sa_flags = 0; #endif - if (pf_key_v2_msg_add (update, (struct sadb_ext *)&ssa, 0) == -1) - goto cleanup; - - if (sa->seconds || sa->kilobytes) - { - /* Setup the hard limits. */ - life = malloc (sizeof *life); - if (!life) - goto cleanup; - life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK; - life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; - life->sadb_lifetime_allocations = 0; - life->sadb_lifetime_bytes = sa->kilobytes * 1024; - /* - * XXX I am not sure which one is best in security respect. Maybe the - * RFCs actually mandate what a lifetime really is. - */ + if (pf_key_v2_msg_add(update, (struct sadb_ext *) & ssa, 0) == -1) + goto cleanup; + + if (sa->seconds || sa->kilobytes) { + /* Setup the hard limits. */ + life = malloc(sizeof *life); + if (!life) + goto cleanup; + life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK; + life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; + life->sadb_lifetime_allocations = 0; + life->sadb_lifetime_bytes = sa->kilobytes * 1024; + /* + * XXX I am not sure which one is best in security respect. Maybe the + * RFCs actually mandate what a lifetime really is. + */ #if 0 - life->sadb_lifetime_addtime = 0; - life->sadb_lifetime_usetime = sa->seconds; + life->sadb_lifetime_addtime = 0; + life->sadb_lifetime_usetime = sa->seconds; #else - life->sadb_lifetime_addtime = sa->seconds; - life->sadb_lifetime_usetime = 0; -#endif - if (pf_key_v2_msg_add (update, (struct sadb_ext *)life, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - life = 0; - - /* - * Setup the soft limits, we use 90 % of the hard ones. - * XXX A configurable ratio would be better. - */ - life = malloc (sizeof *life); - if (!life) - goto cleanup; - life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK; - life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; - life->sadb_lifetime_allocations = 0; - life->sadb_lifetime_bytes = sa->kilobytes * 1024 * 9 / 10; - /* - * XXX I am not sure which one is best in security respect. Maybe the - * RFCs actually mandate what a lifetime really is. - */ + life->sadb_lifetime_addtime = sa->seconds; + life->sadb_lifetime_usetime = 0; +#endif + if (pf_key_v2_msg_add(update, (struct sadb_ext *) life, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + life = 0; + + /* + * Setup the soft limits, we use 90 % of the hard ones. + * XXX A configurable ratio would be better. + */ + life = malloc(sizeof *life); + if (!life) + goto cleanup; + life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK; + life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; + life->sadb_lifetime_allocations = 0; + life->sadb_lifetime_bytes = sa->kilobytes * 1024 * 9 / 10; + /* + * XXX I am not sure which one is best in security respect. Maybe the + * RFCs actually mandate what a lifetime really is. + */ #if 0 - life->sadb_lifetime_addtime = 0; - life->sadb_lifetime_usetime = sa->seconds * 9 / 10; + life->sadb_lifetime_addtime = 0; + life->sadb_lifetime_usetime = sa->seconds * 9 / 10; #else - life->sadb_lifetime_addtime = sa->seconds * 9 / 10; - life->sadb_lifetime_usetime = 0; + life->sadb_lifetime_addtime = sa->seconds * 9 / 10; + life->sadb_lifetime_usetime = 0; #endif - if (pf_key_v2_msg_add (update, (struct sadb_ext *)life, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - life = 0; - } - - /* - * Setup the ADDRESS extensions. - */ - if (incoming) - sa->transport->vtbl->get_dst (sa->transport, &src); - else - sa->transport->vtbl->get_src (sa->transport, &src); - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (src)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; -#ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; -#endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, src, sysdep_sa_len (src)); - switch (((struct sockaddr *)(addr + 1))->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; - } - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (dst)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + if (pf_key_v2_msg_add(update, (struct sadb_ext *) life, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + life = 0; + } + /* + * Setup the ADDRESS extensions. + */ + if (incoming) + sa->transport->vtbl->get_dst(sa->transport, &src); + else + sa->transport->vtbl->get_src(sa->transport, &src); + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(src)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, dst, sysdep_sa_len (dst)); - switch (((struct sockaddr *)(addr + 1))->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; - } - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; + addr->sadb_address_reserved = 0; + memcpy(addr + 1, src, sysdep_sa_len(src)); + switch (((struct sockaddr *) (addr + 1))->sa_family) { + case AF_INET: + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; + } + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; -#if 0 - /* XXX I am not sure about what to do here just yet. */ - if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) - { - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (dst)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(dst)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, dst, sysdep_sa_len (dst)); - switch (((struct sockaddr *)(addr + 1))->sa_family) - { + addr->sadb_address_reserved = 0; + memcpy(addr + 1, dst, sysdep_sa_len(dst)); + switch (((struct sockaddr *) (addr + 1))->sa_family) { case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; } - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + #if 0 - msg->em_odst = msg->em_dst; - msg->em_osrc = msg->em_src; -#endif - } + /* XXX I am not sure about what to do here just yet. */ + if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) { + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(dst)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; +#ifndef __OpenBSD__ + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; +#endif + addr->sadb_address_reserved = 0; + memcpy(addr + 1, dst, sysdep_sa_len(dst)); + switch (((struct sockaddr *) (addr + 1))->sa_family) { + case AF_INET: + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; + } + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; +#if 0 + msg->em_odst = msg->em_dst; + msg->em_osrc = msg->em_src; #endif - - if (proto->proto != IPSEC_PROTO_IPCOMP) - { - /* Setup the KEY extensions. */ - if (hashlen) - { - len = sizeof *key + PF_KEY_V2_ROUND (hashlen); - key = malloc (len); - if (!key) - goto cleanup; - key->sadb_key_exttype = SADB_EXT_KEY_AUTH; - key->sadb_key_len = len / PF_KEY_V2_CHUNK; - key->sadb_key_bits = hashlen * 8; - key->sadb_key_reserved = 0; - memcpy (key + 1, - iproto->keymat[incoming] - + (proto->proto == IPSEC_PROTO_IPSEC_ESP ? keylen : 0), - hashlen); - if (pf_key_v2_msg_add (update, (struct sadb_ext *)key, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - key = 0; } +#endif - if (keylen) - { - len = sizeof *key + PF_KEY_V2_ROUND (keylen); - key = malloc (len); - if (!key) - goto cleanup; - key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; - key->sadb_key_len = len / PF_KEY_V2_CHUNK; - key->sadb_key_bits = keylen * 8; - key->sadb_key_reserved = 0; - memcpy (key + 1, iproto->keymat[incoming], keylen); - if (pf_key_v2_msg_add (update, (struct sadb_ext *)key, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - key = 0; + if (proto->proto != IPSEC_PROTO_IPCOMP) { + /* Setup the KEY extensions. */ + if (hashlen) { + len = sizeof *key + PF_KEY_V2_ROUND(hashlen); + key = malloc(len); + if (!key) + goto cleanup; + key->sadb_key_exttype = SADB_EXT_KEY_AUTH; + key->sadb_key_len = len / PF_KEY_V2_CHUNK; + key->sadb_key_bits = hashlen * 8; + key->sadb_key_reserved = 0; + memcpy(key + 1, + iproto->keymat[incoming] + + (proto->proto == IPSEC_PROTO_IPSEC_ESP ? keylen : 0), + hashlen); + if (pf_key_v2_msg_add(update, (struct sadb_ext *) key, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + key = 0; + } + if (keylen) { + len = sizeof *key + PF_KEY_V2_ROUND(keylen); + key = malloc(len); + if (!key) + goto cleanup; + key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; + key->sadb_key_len = len / PF_KEY_V2_CHUNK; + key->sadb_key_bits = keylen * 8; + key->sadb_key_reserved = 0; + memcpy(key + 1, iproto->keymat[incoming], keylen); + if (pf_key_v2_msg_add(update, (struct sadb_ext *) key, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + key = 0; + } } - } - #ifndef KAME - /* Setup identity extensions. */ - if (isakmp_sa->id_i) - { - pp = pf_key_v2_convert_id (isakmp_sa->id_i, isakmp_sa->id_i_len, - &len, &idtype); - if (!pp) - goto nosid; - - sid = calloc (PF_KEY_V2_ROUND (len + 1) + sizeof *sid, sizeof (u_int8_t)); - if (!sid) - { - free (pp); - goto cleanup; + /* Setup identity extensions. */ + if (isakmp_sa->id_i) { + pp = pf_key_v2_convert_id(isakmp_sa->id_i, isakmp_sa->id_i_len, + &len, &idtype); + if (!pp) + goto nosid; + + sid = calloc(PF_KEY_V2_ROUND(len + 1) + sizeof *sid, sizeof(u_int8_t)); + if (!sid) { + free(pp); + goto cleanup; + } + sid->sadb_ident_type = idtype; + sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(len + 1) / PF_KEY_V2_CHUNK; + if ((isakmp_sa->initiator && !incoming) || + (!isakmp_sa->initiator && incoming)) + sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; + else + sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; + + memcpy(sid + 1, pp, len); + free(pp); + + if (pf_key_v2_msg_add(update, (struct sadb_ext *) sid, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + sid = 0; + +nosid: + if (sid) + free(sid); + sid = 0; } - - sid->sadb_ident_type = idtype; - sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) - + PF_KEY_V2_ROUND (len + 1) / PF_KEY_V2_CHUNK; - if ((isakmp_sa->initiator && !incoming) - || (!isakmp_sa->initiator && incoming)) - sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; - else - sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; - - memcpy (sid + 1, pp, len); - free (pp); - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)sid, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - sid = 0; - - nosid: - if (sid) - free (sid); - sid = 0; - } - - if (isakmp_sa->id_r) - { - pp = pf_key_v2_convert_id (isakmp_sa->id_r, isakmp_sa->id_r_len, - &len, &idtype); - if (!pp) - goto nodid; - - sid = calloc (PF_KEY_V2_ROUND (len + 1) + sizeof *sid, sizeof (u_int8_t)); - if (!sid) - { - free (pp); - goto cleanup; + if (isakmp_sa->id_r) { + pp = pf_key_v2_convert_id(isakmp_sa->id_r, isakmp_sa->id_r_len, + &len, &idtype); + if (!pp) + goto nodid; + + sid = calloc(PF_KEY_V2_ROUND(len + 1) + sizeof *sid, sizeof(u_int8_t)); + if (!sid) { + free(pp); + goto cleanup; + } + sid->sadb_ident_type = idtype; + sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(len + 1) / PF_KEY_V2_CHUNK; + if ((isakmp_sa->initiator && !incoming) || + (!isakmp_sa->initiator && incoming)) + sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; + else + sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; + + memcpy(sid + 1, pp, len); + free(pp); + + if (pf_key_v2_msg_add(update, (struct sadb_ext *) sid, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + sid = 0; + +nodid: + if (sid) + free(sid); + sid = 0; } - - sid->sadb_ident_type = idtype; - sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) - + PF_KEY_V2_ROUND (len + 1) / PF_KEY_V2_CHUNK; - if ((isakmp_sa->initiator && !incoming) - || (!isakmp_sa->initiator && incoming)) - sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; - else - sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; - - memcpy (sid + 1, pp, len); - free (pp); - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)sid, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - sid = 0; - - nodid: - if (sid) - free (sid); - sid = 0; - } #endif /* KAME */ #ifdef SADB_X_CREDTYPE_NONE - /* - * Send received credentials to the kernel. We don't bother with - * our credentials, since the process either knows them (if it specified - * them with setsockopt()), or has no business looking at them (e.g., - * system wide certs). - */ - if (isakmp_sa->recv_cert) - { - switch (isakmp_sa->recv_certtype) - { - case ISAKMP_CERTENC_NONE: - /* Nothing to be done here. */ - break; + /* + * Send received credentials to the kernel. We don't bother with + * our credentials, since the process either knows them (if it specified + * them with setsockopt()), or has no business looking at them (e.g., + * system wide certs). + */ + if (isakmp_sa->recv_cert) { + switch (isakmp_sa->recv_certtype) { + case ISAKMP_CERTENC_NONE: + /* Nothing to be done here. */ + break; #if defined (USE_KEYNOTE) && defined (SADB_X_EXT_REMOTE_CREDENTIALS) - case ISAKMP_CERTENC_KEYNOTE: - len = strlen (isakmp_sa->recv_cert); - cred = calloc (PF_KEY_V2_ROUND (len) + sizeof *cred, - sizeof (u_int8_t)); - if (!cred) - goto cleanup; - - cred->sadb_x_cred_len = ((sizeof *cred) / PF_KEY_V2_CHUNK) + - PF_KEY_V2_ROUND (len) / PF_KEY_V2_CHUNK; - cred->sadb_x_cred_exttype = SADB_X_EXT_REMOTE_CREDENTIALS; - cred->sadb_x_cred_type = SADB_X_CREDTYPE_KEYNOTE; - memcpy (cred + 1, isakmp_sa->recv_cert, len); - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)cred, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - break; -#endif /* USE_KEYNOTE */ + case ISAKMP_CERTENC_KEYNOTE: + len = strlen(isakmp_sa->recv_cert); + cred = calloc(PF_KEY_V2_ROUND(len) + sizeof *cred, + sizeof(u_int8_t)); + if (!cred) + goto cleanup; + + cred->sadb_x_cred_len = ((sizeof *cred) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(len) / PF_KEY_V2_CHUNK; + cred->sadb_x_cred_exttype = SADB_X_EXT_REMOTE_CREDENTIALS; + cred->sadb_x_cred_type = SADB_X_CREDTYPE_KEYNOTE; + memcpy(cred + 1, isakmp_sa->recv_cert, len); + + if (pf_key_v2_msg_add(update, (struct sadb_ext *) cred, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + break; +#endif /* USE_KEYNOTE */ #if defined (USE_X509) && defined (SADB_X_EXT_REMOTE_CREDENTIALS) - case ISAKMP_CERTENC_X509_SIG: - { - u_int8_t *data; - u_int32_t datalen; - struct cert_handler *handler; - - /* We do it this way to avoid weird includes. */ - handler = cert_get (ISAKMP_CERTENC_X509_SIG); - if (!handler) - break; - handler->cert_serialize (isakmp_sa->recv_cert, &data, &datalen); - if (!data) - break; - - len = datalen; - cred = calloc (PF_KEY_V2_ROUND (len) + sizeof *cred, - sizeof (u_int8_t)); - if (!cred) - { - free (data); - goto cleanup; - } - - cred->sadb_x_cred_len = ((sizeof *cred) / PF_KEY_V2_CHUNK) + - PF_KEY_V2_ROUND (len) / PF_KEY_V2_CHUNK; - cred->sadb_x_cred_exttype = SADB_X_EXT_REMOTE_CREDENTIALS; - cred->sadb_x_cred_type = SADB_X_CREDTYPE_X509; - memcpy (cred + 1, data, len); - free (data); - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)cred, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - } - break; + case ISAKMP_CERTENC_X509_SIG: + { + u_int8_t *data; + u_int32_t datalen; + struct cert_handler *handler; + + /* We do it this way to avoid weird includes. */ + handler = cert_get(ISAKMP_CERTENC_X509_SIG); + if (!handler) + break; + handler->cert_serialize(isakmp_sa->recv_cert, + &data, &datalen); + if (!data) + break; + + len = datalen; + cred = calloc(PF_KEY_V2_ROUND(len) + sizeof *cred, + sizeof(u_int8_t)); + if (!cred) { + free(data); + goto cleanup; + } + cred->sadb_x_cred_len = + ((sizeof *cred) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(len) / PF_KEY_V2_CHUNK; + cred->sadb_x_cred_exttype = + SADB_X_EXT_REMOTE_CREDENTIALS; + cred->sadb_x_cred_type = SADB_X_CREDTYPE_X509; + memcpy(cred + 1, data, len); + free(data); + + if (pf_key_v2_msg_add(update, (struct sadb_ext *) cred, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + } + break; #endif /* USE_X509 */ + } } - } #endif /* SADB_X_CREDTYPE_NONE */ #ifdef SADB_X_AUTHTYPE_NONE - /* - * Tell the kernel what the peer used to authenticate, unless it was a - * passphrase. - */ - if (isakmp_sa->recv_key) - { - u_int8_t *data; - - /* - * If it's a private key, we shouldn't pass it to the kernel for - * processes to see; successful authentication of Phase 1 implies - * that the process already knew the passphrase. On the other hand, - * we don't want to reveal to processes any system-wide passphrases - * used for authentication with remote systems. Same reason we don't - * send up the key (private or passphrase) we used to authenticate - * with the peer. - */ - if (isakmp_sa->recv_keytype == ISAKMP_KEY_PASSPHRASE) - goto doneauth; - - key_serialize (isakmp_sa->recv_keytype, ISAKMP_KEYTYPE_PUBLIC, - isakmp_sa->recv_key, &data, &len); - if (!data) - goto cleanup; - - cred = calloc (PF_KEY_V2_ROUND (len) + sizeof *cred, sizeof (u_int8_t)); - if (!cred) - { - free (data); - goto cleanup; - } + /* + * Tell the kernel what the peer used to authenticate, unless it was a + * passphrase. + */ + if (isakmp_sa->recv_key) { + u_int8_t *data; + + /* + * If it's a private key, we shouldn't pass it to the kernel for + * processes to see; successful authentication of Phase 1 implies + * that the process already knew the passphrase. On the other hand, + * we don't want to reveal to processes any system-wide passphrases + * used for authentication with remote systems. Same reason we don't + * send up the key (private or passphrase) we used to authenticate + * with the peer. + */ + if (isakmp_sa->recv_keytype == ISAKMP_KEY_PASSPHRASE) + goto doneauth; + + key_serialize(isakmp_sa->recv_keytype, ISAKMP_KEYTYPE_PUBLIC, + isakmp_sa->recv_key, &data, &len); + if (!data) + goto cleanup; + + cred = calloc(PF_KEY_V2_ROUND(len) + sizeof *cred, sizeof(u_int8_t)); + if (!cred) { + free(data); + goto cleanup; + } + cred->sadb_x_cred_len = ((sizeof *cred) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(len) / PF_KEY_V2_CHUNK; + cred->sadb_x_cred_exttype = SADB_X_EXT_REMOTE_AUTH; + memcpy(cred + 1, data, len); + free(data); - cred->sadb_x_cred_len = ((sizeof *cred) / PF_KEY_V2_CHUNK) + - PF_KEY_V2_ROUND (len) / PF_KEY_V2_CHUNK; - cred->sadb_x_cred_exttype = SADB_X_EXT_REMOTE_AUTH; - memcpy (cred + 1, data, len); - free (data); + switch (isakmp_sa->recv_keytype) { + case ISAKMP_KEY_RSA: + cred->sadb_x_cred_type = SADB_X_AUTHTYPE_RSA; + break; - switch (isakmp_sa->recv_keytype) - { - case ISAKMP_KEY_RSA: - cred->sadb_x_cred_type = SADB_X_AUTHTYPE_RSA; - break; + default: + log_print("pf_key_v2_set_spi: unknown received key type %d", + isakmp_sa->recv_keytype); + free(cred); + goto cleanup; + } - default: - log_print ("pf_key_v2_set_spi: unknown received key type %d", - isakmp_sa->recv_keytype); - free (cred); - goto cleanup; + if (pf_key_v2_msg_add(update, (struct sadb_ext *) cred, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; } - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)cred, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - } - doneauth: -#endif /* SADB_X_AUTHTYPE_NONE */ +doneauth: +#endif /* SADB_X_AUTHTYPE_NONE */ #ifdef SADB_X_EXT_FLOW_TYPE - /* Setup the flow type extension. */ - bzero (&flowtype, sizeof flowtype); - flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; - flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK; - flowtype.sadb_protocol_direction - = incoming ? IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)&flowtype, 0) == -1) - goto cleanup; - - bzero (&tprotocol, sizeof tprotocol); - tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; - tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK; - tprotocol.sadb_protocol_proto = isa->tproto; - - if (pf_key_v2_msg_add (update, (struct sadb_ext *)&tprotocol, 0) == -1) - goto cleanup; - - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (isa->src_net)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = - incoming ? SADB_X_EXT_DST_FLOW : SADB_X_EXT_SRC_FLOW; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, isa->src_net, 0, isa->sport, 0); - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = - incoming ? SADB_X_EXT_DST_MASK : SADB_X_EXT_SRC_MASK; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, isa->src_mask, 0, - isa->sport ? 0xffff : 0, 0); - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = - incoming ? SADB_X_EXT_SRC_FLOW : SADB_X_EXT_DST_FLOW; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, isa->dst_net, 0, isa->dport, 0); - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = - incoming ? SADB_X_EXT_SRC_MASK : SADB_X_EXT_DST_MASK; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, isa->dst_mask, 0, - isa->dport ? 0xffff : 0, 0); - if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; + /* Setup the flow type extension. */ + bzero(&flowtype, sizeof flowtype); + flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; + flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK; + flowtype.sadb_protocol_direction = incoming ? + IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; + + if (pf_key_v2_msg_add(update, (struct sadb_ext *) & flowtype, 0) == -1) + goto cleanup; + + bzero(&tprotocol, sizeof tprotocol); + tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; + tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK; + tprotocol.sadb_protocol_proto = isa->tproto; + + if (pf_key_v2_msg_add(update, (struct sadb_ext *) & tprotocol, 0) == -1) + goto cleanup; + + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(isa->src_net)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = incoming ? + SADB_X_EXT_DST_FLOW : SADB_X_EXT_SRC_FLOW; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, isa->src_net, 0, isa->sport, 0); + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = + incoming ? SADB_X_EXT_DST_MASK : SADB_X_EXT_SRC_MASK; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, isa->src_mask, 0, + isa->sport ? 0xffff : 0, 0); + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = incoming ? + SADB_X_EXT_SRC_FLOW : SADB_X_EXT_DST_FLOW; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, isa->dst_net, 0, isa->dport, 0); + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = + incoming ? SADB_X_EXT_SRC_MASK : SADB_X_EXT_DST_MASK; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, isa->dst_mask, 0, + isa->dport ? 0xffff : 0, 0); + if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; #endif /* SADB_X_EXT_FLOW_TYPE */ - /* XXX Here can sensitivity extensions be setup. */ + /* XXX Here can sensitivity extensions be setup. */ #ifdef USE_DEBUG - if (sockaddr2text (dst, &addr_str, 0)) - addr_str = 0; + if (sockaddr2text(dst, &addr_str, 0)) + addr_str = 0; - LOG_DBG ((LOG_SYSDEP, 10, "pf_key_v2_set_spi: satype %d dst %s SPI 0x%x", + LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_set_spi: satype %d dst %s SPI 0x%x", msg.sadb_msg_satype, addr_str ? addr_str : "unknown", - ntohl (ssa.sadb_sa_spi))); - - if (addr_str) - free (addr_str); -#endif /* USE_DEBUG */ - - /* - * Although PF_KEY knows about expirations, it is unreliable per the specs - * thus we need to do them inside isakmpd as well. - */ - if (sa->seconds) - if (sa_setup_expirations (sa)) - goto cleanup; - - ret = pf_key_v2_call (update); - pf_key_v2_msg_free (update); - update = 0; - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - pf_key_v2_msg_free (ret); - ret = 0; - - /* - * If we are doing an addition into an SADB shared with our peer, errors - * here are to be expected as the peer will already have created the SA, - * and can thus be ignored. - */ - if (err && !(msg.sadb_msg_type == SADB_ADD - && conf_get_str ("General", "Shared-SADB"))) - { - log_print ("pf_key_v2_set_spi: %s: %s", - msg.sadb_msg_type == SADB_ADD ? "ADD" : "UPDATE", - strerror (err)); - goto cleanup; - } - - LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_set_spi: done")); - - return 0; - - cleanup: - if (sid) - free (sid); - if (addr) - free (addr); - if (life) - free (life); - if (key) - free (key); - if (update) - pf_key_v2_msg_free (update); - if (ret) - pf_key_v2_msg_free (ret); - return -1; + ntohl(ssa.sadb_sa_spi))); + + if (addr_str) + free(addr_str); +#endif /* USE_DEBUG */ + + /* + * Although PF_KEY knows about expirations, it is unreliable per the specs + * thus we need to do them inside isakmpd as well. + */ + if (sa->seconds) + if (sa_setup_expirations(sa)) + goto cleanup; + + ret = pf_key_v2_call(update); + pf_key_v2_msg_free(update); + update = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + pf_key_v2_msg_free(ret); + ret = 0; + + /* + * If we are doing an addition into an SADB shared with our peer, errors + * here are to be expected as the peer will already have created the SA, + * and can thus be ignored. + */ + if (err && !(msg.sadb_msg_type == SADB_ADD && + conf_get_str("General", "Shared-SADB"))) { + log_print("pf_key_v2_set_spi: %s: %s", + msg.sadb_msg_type == SADB_ADD ? "ADD" : "UPDATE", + strerror(err)); + goto cleanup; + } + LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: done")); + + return 0; + +cleanup: + if (sid) + free(sid); + if (addr) + free(addr); + if (life) + free(life); + if (key) + free(key); + if (update) + pf_key_v2_msg_free(update); + if (ret) + pf_key_v2_msg_free(ret); + return -1; } static __inline__ int -pf_key_v2_mask_to_bits (u_int32_t mask) +pf_key_v2_mask_to_bits(u_int32_t mask) { - u_int32_t hmask = ntohl (mask); - return (33 - ffs (~hmask + 1)) % 33; + u_int32_t hmask = ntohl(mask); + + return (33 - ffs(~hmask + 1)) % 33; } static int -pf_key_v2_mask6_to_bits (u_int8_t *mask) +pf_key_v2_mask6_to_bits(u_int8_t * mask) { - int n; - bit_ffc (mask, 128, &n); - return n == -1 ? 128 : n; + int n; + + bit_ffc(mask, 128, &n); + return n == -1 ? 128 : n; } /* @@ -1728,740 +1659,718 @@ pf_key_v2_mask6_to_bits (u_int8_t *mask) * Should probably be moved to sysdep.c */ static int -pf_key_v2_flow (struct sockaddr *laddr, struct sockaddr *lmask, - struct sockaddr *raddr, struct sockaddr *rmask, - u_int8_t tproto, u_int16_t sport, u_int16_t dport, - u_int8_t *spi, u_int8_t proto, struct sockaddr *dst, - struct sockaddr *src, int delete, int ingress, - u_int8_t srcid_type, u_int8_t *srcid, int srcid_len, - u_int8_t dstid_type, u_int8_t *dstid, int dstid_len, - struct ipsec_proto *iproto) +pf_key_v2_flow(struct sockaddr *laddr, struct sockaddr *lmask, + struct sockaddr *raddr, struct sockaddr *rmask, + u_int8_t tproto, u_int16_t sport, u_int16_t dport, + u_int8_t *spi, u_int8_t proto, struct sockaddr *dst, + struct sockaddr *src, int delete, int ingress, + u_int8_t srcid_type, u_int8_t *srcid, int srcid_len, + u_int8_t dstid_type, u_int8_t *dstid, int dstid_len, + struct ipsec_proto *iproto) { #ifdef USE_DEBUG - char *laddr_str, *lmask_str, *raddr_str, *rmask_str; + char *laddr_str, *lmask_str, *raddr_str, *rmask_str; #endif #if defined (SADB_X_ADDFLOW) && defined (SADB_X_DELFLOW) - struct sadb_msg msg; + struct sadb_msg msg; #if defined (SADB_X_EXT_FLOW_TYPE) - struct sadb_protocol flowtype; - struct sadb_ident *sid = 0; + struct sadb_protocol flowtype; + struct sadb_ident *sid = 0; #else - struct sadb_sa ssa; + struct sadb_sa ssa; #endif - struct sadb_address *addr = 0; - struct sadb_protocol tprotocol; - struct pf_key_v2_msg *flow = 0, *ret = 0; - size_t len; - int err; + struct sadb_address *addr = 0; + struct sadb_protocol tprotocol; + struct pf_key_v2_msg *flow = 0, *ret = 0; + size_t len; + int err; #if !defined (SADB_X_SAFLAGS_INGRESS_FLOW) && !defined (SADB_X_EXT_FLOW_TYPE) - if (ingress) - return 0; -#endif - - msg.sadb_msg_type = delete ? SADB_X_DELFLOW : SADB_X_ADDFLOW; - switch (proto) - { - case IPSEC_PROTO_IPSEC_ESP: - msg.sadb_msg_satype = SADB_SATYPE_ESP; - break; - case IPSEC_PROTO_IPSEC_AH: - msg.sadb_msg_satype = SADB_SATYPE_AH; - break; - case IPSEC_PROTO_IPCOMP: - msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; - break; - default: - log_print ("pf_key_v2_flow: invalid proto %d", proto); - goto cleanup; - } - msg.sadb_msg_seq = 0; - flow = pf_key_v2_msg_new (&msg, 0); - if (!flow) - goto cleanup; - -#if defined (SADB_X_EXT_FLOW_TYPE) - if (!delete) - { - /* Setup the source ID, if provided. */ - if (srcid) - { - sid = calloc (PF_KEY_V2_ROUND (srcid_len + 1) + sizeof *sid, - sizeof (u_int8_t)); - if (!sid) - goto cleanup; - - sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) - + PF_KEY_V2_ROUND (srcid_len + 1) / PF_KEY_V2_CHUNK; - sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; - sid->sadb_ident_type = srcid_type; - - memcpy (sid + 1, srcid, srcid_len); - - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)sid, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - - sid = 0; + if (ingress) + return 0; +#endif + + msg.sadb_msg_type = delete ? SADB_X_DELFLOW : SADB_X_ADDFLOW; + switch (proto) { + case IPSEC_PROTO_IPSEC_ESP: + msg.sadb_msg_satype = SADB_SATYPE_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + msg.sadb_msg_satype = SADB_SATYPE_AH; + break; + case IPSEC_PROTO_IPCOMP: + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + break; + default: + log_print("pf_key_v2_flow: invalid proto %d", proto); + goto cleanup; } + msg.sadb_msg_seq = 0; + flow = pf_key_v2_msg_new(&msg, 0); + if (!flow) + goto cleanup; - /* Setup the destination ID, if provided. */ - if (dstid) - { - sid = calloc (PF_KEY_V2_ROUND (dstid_len + 1) + sizeof *sid, - sizeof (u_int8_t)); - if (!sid) - goto cleanup; +#if defined (SADB_X_EXT_FLOW_TYPE) + if (!delete) { + /* Setup the source ID, if provided. */ + if (srcid) { + sid = calloc(PF_KEY_V2_ROUND(srcid_len + 1) + sizeof *sid, + sizeof(u_int8_t)); + if (!sid) + goto cleanup; + + sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(srcid_len + 1) / PF_KEY_V2_CHUNK; + sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; + sid->sadb_ident_type = srcid_type; + + memcpy(sid + 1, srcid, srcid_len); + + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) sid, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + + sid = 0; + } + /* Setup the destination ID, if provided. */ + if (dstid) { + sid = calloc(PF_KEY_V2_ROUND(dstid_len + 1) + sizeof *sid, + sizeof(u_int8_t)); + if (!sid) + goto cleanup; - sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) - + PF_KEY_V2_ROUND (dstid_len + 1) / PF_KEY_V2_CHUNK; - sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; - sid->sadb_ident_type = dstid_type; + sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK) + + PF_KEY_V2_ROUND(dstid_len + 1) / PF_KEY_V2_CHUNK; + sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; + sid->sadb_ident_type = dstid_type; - memcpy (sid + 1, dstid, dstid_len); + memcpy(sid + 1, dstid, dstid_len); - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)sid, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) sid, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; - sid = 0; + sid = 0; + } } - } - - /* Setup the flow type extension. */ - bzero (&flowtype, sizeof flowtype); - flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; - flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK; - flowtype.sadb_protocol_direction - = ingress ? IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; - flowtype.sadb_protocol_proto - = ingress ? SADB_X_FLOW_TYPE_USE : SADB_X_FLOW_TYPE_REQUIRE; - - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)&flowtype, 0) == -1) - goto cleanup; -#else /* SADB_X_EXT_FLOW_TYPE */ - /* Setup the SA extension. */ - ssa.sadb_sa_exttype = SADB_EXT_SA; - ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; - memcpy (&ssa.sadb_sa_spi, spi, sizeof ssa.sadb_sa_spi); - ssa.sadb_sa_replay = 0; - ssa.sadb_sa_state = 0; - ssa.sadb_sa_auth = 0; - ssa.sadb_sa_encrypt = 0; - ssa.sadb_sa_flags = 0; + /* Setup the flow type extension. */ + bzero(&flowtype, sizeof flowtype); + flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; + flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK; + flowtype.sadb_protocol_direction + = ingress ? IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; + flowtype.sadb_protocol_proto + = ingress ? SADB_X_FLOW_TYPE_USE : SADB_X_FLOW_TYPE_REQUIRE; + + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) & flowtype, 0) == -1) + goto cleanup; +#else /* SADB_X_EXT_FLOW_TYPE */ + /* Setup the SA extension. */ + ssa.sadb_sa_exttype = SADB_EXT_SA; + ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; + memcpy(&ssa.sadb_sa_spi, spi, sizeof ssa.sadb_sa_spi); + ssa.sadb_sa_replay = 0; + ssa.sadb_sa_state = 0; + ssa.sadb_sa_auth = 0; + ssa.sadb_sa_encrypt = 0; + ssa.sadb_sa_flags = 0; #if defined (SADB_X_SAFLAGS_INGRESS_FLOW) - if (ingress) - ssa.sadb_sa_flags |= SADB_X_SAFLAGS_INGRESS_FLOW; + if (ingress) + ssa.sadb_sa_flags |= SADB_X_SAFLAGS_INGRESS_FLOW; #endif #if defined (SADB_X_SAFLAGS_REPLACEFLOW) - if (!delete && !ingress) - ssa.sadb_sa_flags |= SADB_X_SAFLAGS_REPLACEFLOW; + if (!delete && !ingress) + ssa.sadb_sa_flags |= SADB_X_SAFLAGS_REPLACEFLOW; #endif - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)&ssa, 0) == -1) - goto cleanup; -#endif /* SADB_X_EXT_FLOW_TYPE */ + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) & ssa, 0) == -1) + goto cleanup; +#endif /* SADB_X_EXT_FLOW_TYPE */ - /* - * Setup the ADDRESS extensions. - */ - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (src)); + /* + * Setup the ADDRESS extensions. + */ + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(src)); #if !defined (SADB_X_EXT_FLOW_TYPE) - if (!delete || ingress) + if (!delete || ingress) #else - if (!delete) -#endif /* SADB_X_EXT_FLOW_TYPE */ - { - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; + if (!delete) +#endif /* SADB_X_EXT_FLOW_TYPE */ + { + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; #if defined (SADB_X_EXT_FLOW_TYPE) - pf_key_v2_setup_sockaddr (addr + 1, src, dst, 0, ingress); + pf_key_v2_setup_sockaddr(addr + 1, src, dst, 0, ingress); #else - pf_key_v2_setup_sockaddr (addr + 1, dst, 0, 0, 0); + pf_key_v2_setup_sockaddr(addr + 1, dst, 0, 0, 0); #endif - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - } - - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (laddr)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_X_EXT_SRC_FLOW; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, laddr, 0, sport, 0); - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_X_EXT_SRC_MASK; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, lmask, 0, sport ? 0xffff : 0, 0); - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_X_EXT_DST_FLOW; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, raddr, 0, dport, 0); - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_X_EXT_DST_MASK; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; - addr->sadb_address_reserved = 0; - pf_key_v2_setup_sockaddr (addr + 1, rmask, 0, dport ? 0xffff : 0, 0); - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - /* Setup the protocol extension. */ - bzero (&tprotocol, sizeof tprotocol); - tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; - tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK; - tprotocol.sadb_protocol_proto = tproto; - - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)&tprotocol, 0) == -1) - goto cleanup; + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + } + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(laddr)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_X_EXT_SRC_FLOW; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, laddr, 0, sport, 0); + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_X_EXT_SRC_MASK; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, lmask, 0, sport ? 0xffff : 0, 0); + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_X_EXT_DST_FLOW; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, raddr, 0, dport, 0); + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_X_EXT_DST_MASK; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + pf_key_v2_setup_sockaddr(addr + 1, rmask, 0, dport ? 0xffff : 0, 0); + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + /* Setup the protocol extension. */ + bzero(&tprotocol, sizeof tprotocol); + tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; + tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK; + tprotocol.sadb_protocol_proto = tproto; + + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) & tprotocol, 0) == -1) + goto cleanup; #ifdef USE_DEBUG - if (sockaddr2text (laddr, &laddr_str, 0)) - laddr_str = 0; - if (sockaddr2text (lmask, &lmask_str, 0)) - lmask_str = 0; - if (sockaddr2text (raddr, &raddr_str, 0)) - raddr_str = 0; - if (sockaddr2text (rmask, &rmask_str, 0)) - rmask_str = 0; - - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u", - laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", - raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", - tproto, ntohs (sport), ntohs (dport))); - - if (laddr_str) - free (laddr_str); - if (lmask_str) - free (lmask_str); - if (raddr_str) - free (raddr_str); - if (rmask_str) - free (rmask_str); -#endif /* USE_DEBUG */ - - ret = pf_key_v2_call (flow); - pf_key_v2_msg_free (flow); - flow = 0; - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - if (err == ESRCH) /* These are common and usually harmless. */ - LOG_DBG ((LOG_SYSDEP, 10, "pf_key_v2_flow: %sFLOW: %s", - delete ? "DEL" : "ADD", strerror (err))); - else - log_print ("pf_key_v2_flow: %sFLOW: %s", delete ? "DEL" : "ADD", - strerror (err)); - goto cleanup; - } - pf_key_v2_msg_free (ret); - - LOG_DBG ((LOG_MISC, 50, "pf_key_v2_flow: %sFLOW: done", - delete ? "DEL" : "ADD")); - - return 0; - - cleanup: + if (sockaddr2text(laddr, &laddr_str, 0)) + laddr_str = 0; + if (sockaddr2text(lmask, &lmask_str, 0)) + lmask_str = 0; + if (sockaddr2text(raddr, &raddr_str, 0)) + raddr_str = 0; + if (sockaddr2text(rmask, &rmask_str, 0)) + rmask_str = 0; + + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u", + laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", + raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", + tproto, ntohs(sport), ntohs(dport))); + + if (laddr_str) + free(laddr_str); + if (lmask_str) + free(lmask_str); + if (raddr_str) + free(raddr_str); + if (rmask_str) + free(rmask_str); +#endif /* USE_DEBUG */ + + ret = pf_key_v2_call(flow); + pf_key_v2_msg_free(flow); + flow = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + if (err == ESRCH) /* These are common and usually + * harmless. */ + LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_flow: %sFLOW: %s", + delete ? "DEL" : "ADD", strerror(err))); + else + log_print("pf_key_v2_flow: %sFLOW: %s", delete ? "DEL" : "ADD", + strerror(err)); + goto cleanup; + } + pf_key_v2_msg_free(ret); + + LOG_DBG((LOG_MISC, 50, "pf_key_v2_flow: %sFLOW: done", + delete ? "DEL" : "ADD")); + + return 0; + +cleanup: #if defined (SADB_X_EXT_FLOW_TYPE) - if (sid) - free (sid); -#endif /* SADB_X_EXT_FLOW_TYPE */ - if (addr) - free (addr); - if (flow) - pf_key_v2_msg_free (flow); - if (ret) - pf_key_v2_msg_free (ret); - return -1; + if (sid) + free(sid); +#endif /* SADB_X_EXT_FLOW_TYPE */ + if (addr) + free(addr); + if (flow) + pf_key_v2_msg_free(flow); + if (ret) + pf_key_v2_msg_free(ret); + return -1; #elif defined (SADB_X_SPDADD) && defined (SADB_X_SPDDELETE) - struct sadb_msg msg; - struct sadb_x_policy *policy = 0; - struct sadb_x_ipsecrequest *ipsecrequest; - struct sadb_x_sa2 ssa2; - struct sadb_address *addr = 0; - struct sockaddr *saddr; - struct pf_key_v2_msg *flow = 0, *ret = 0; - u_int8_t *policy_buf; - size_t len; - int err; - struct sockaddr_in *ip4_sa; - struct sockaddr_in6 *ip6_sa; - - msg.sadb_msg_type = delete ? SADB_X_SPDDELETE : SADB_X_SPDADD; - msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; - msg.sadb_msg_seq = 0; - flow = pf_key_v2_msg_new (&msg, 0); - if (!flow) - goto cleanup; - - memset (&ssa2, 0, sizeof ssa2); - ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; - ssa2.sadb_x_sa2_mode = 0; - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)&ssa2, 0) == -1) - goto cleanup; - - /* - * Setup the ADDRESS extensions. - */ - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (src)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + struct sadb_msg msg; + struct sadb_x_policy *policy = 0; + struct sadb_x_ipsecrequest *ipsecrequest; + struct sadb_x_sa2 ssa2; + struct sadb_address *addr = 0; + struct sockaddr *saddr; + struct pf_key_v2_msg *flow = 0, *ret = 0; + u_int8_t *policy_buf; + size_t len; + int err; + struct sockaddr_in *ip4_sa; + struct sockaddr_in6 *ip6_sa; + + msg.sadb_msg_type = delete ? SADB_X_SPDDELETE : SADB_X_SPDADD; + msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; + msg.sadb_msg_seq = 0; + flow = pf_key_v2_msg_new(&msg, 0); + if (!flow) + goto cleanup; + + memset(&ssa2, 0, sizeof ssa2); + ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; + ssa2.sadb_x_sa2_mode = 0; + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) & ssa2, 0) == -1) + goto cleanup; + + /* + * Setup the ADDRESS extensions. + */ + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(src)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifdef LINUX_IPSEC - addr->sadb_address_proto = tproto; + addr->sadb_address_proto = tproto; #else - addr->sadb_address_proto = IPSEC_ULPROTO_ANY; + addr->sadb_address_proto = IPSEC_ULPROTO_ANY; #endif - addr->sadb_address_reserved = 0; + addr->sadb_address_reserved = 0; #ifdef LINUX_IPSEC - pf_key_v2_setup_sockaddr (addr + 1, laddr, 0, sport, 0); + pf_key_v2_setup_sockaddr(addr + 1, laddr, 0, sport, 0); #else - pf_key_v2_setup_sockaddr (addr + 1, laddr, 0, IPSEC_PORT_ANY, 0); + pf_key_v2_setup_sockaddr(addr + 1, laddr, 0, IPSEC_PORT_ANY, 0); #endif - switch (laddr->sa_family) - { - case AF_INET: - ip4_sa = (struct sockaddr_in *)lmask; - addr->sadb_address_prefixlen - = pf_key_v2_mask_to_bits (ip4_sa->sin_addr.s_addr); - break; - case AF_INET6: - ip6_sa = (struct sockaddr_in6 *)lmask; - addr->sadb_address_prefixlen - = pf_key_v2_mask6_to_bits (&ip6_sa->sin6_addr.s6_addr[0]); - break; - } - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (raddr)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + switch (laddr->sa_family) { + case AF_INET: + ip4_sa = (struct sockaddr_in *) lmask; + addr->sadb_address_prefixlen + = pf_key_v2_mask_to_bits(ip4_sa->sin_addr.s_addr); + break; + case AF_INET6: + ip6_sa = (struct sockaddr_in6 *) lmask; + addr->sadb_address_prefixlen + = pf_key_v2_mask6_to_bits(&ip6_sa->sin6_addr.s6_addr[0]); + break; + } + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(raddr)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifdef LINUX_IPSEC - addr->sadb_address_proto = tproto; + addr->sadb_address_proto = tproto; #else - addr->sadb_address_proto = IPSEC_ULPROTO_ANY; + addr->sadb_address_proto = IPSEC_ULPROTO_ANY; #endif - addr->sadb_address_reserved = 0; + addr->sadb_address_reserved = 0; #ifdef LINUX_IPSEC - pf_key_v2_setup_sockaddr (addr + 1, raddr, 0, dport, 0); + pf_key_v2_setup_sockaddr(addr + 1, raddr, 0, dport, 0); #else - pf_key_v2_setup_sockaddr (addr + 1, raddr, 0, IPSEC_PORT_ANY, 0); + pf_key_v2_setup_sockaddr(addr + 1, raddr, 0, IPSEC_PORT_ANY, 0); #endif - switch (raddr->sa_family) - { - case AF_INET: - ip4_sa = (struct sockaddr_in *)rmask; - addr->sadb_address_prefixlen - = pf_key_v2_mask_to_bits (ip4_sa->sin_addr.s_addr); - break; - case AF_INET6: - ip6_sa = (struct sockaddr_in6 *)rmask; - addr->sadb_address_prefixlen - = pf_key_v2_mask6_to_bits (&ip6_sa->sin6_addr.s6_addr[0]); - break; - } - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - /* Setup the POLICY extension. */ - len = sizeof *policy + sizeof *ipsecrequest + - 2 * PF_KEY_V2_ROUND (sysdep_sa_len (src)); - policy_buf = (u_int8_t *)calloc (1, len); - if (!policy_buf) - { - log_error ("pf_key_v2_flow: calloc %lu failed", (unsigned long)len); - goto cleanup; - } - - policy = (struct sadb_x_policy *)policy_buf; - policy->sadb_x_policy_exttype = SADB_X_EXT_POLICY; - policy->sadb_x_policy_len = len / PF_KEY_V2_CHUNK; - policy->sadb_x_policy_type = IPSEC_POLICY_IPSEC; - if (ingress) - policy->sadb_x_policy_dir = IPSEC_DIR_INBOUND; - else - policy->sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; - policy->sadb_x_policy_reserved = 0; - - /* Setup the IPSECREQUEST extension part. */ - ipsecrequest = (struct sadb_x_ipsecrequest *)(policy + 1); - ipsecrequest->sadb_x_ipsecrequest_len = len - sizeof *policy; - switch (proto) - { - case IPSEC_PROTO_IPSEC_ESP: - ipsecrequest->sadb_x_ipsecrequest_proto = IPPROTO_ESP; - break; - case IPSEC_PROTO_IPSEC_AH: - ipsecrequest->sadb_x_ipsecrequest_proto = IPPROTO_AH; - break; - default: - log_print ("pf_key_v2_flow: invalid proto %d", proto); - goto cleanup; - } + switch (raddr->sa_family) { + case AF_INET: + ip4_sa = (struct sockaddr_in *) rmask; + addr->sadb_address_prefixlen + = pf_key_v2_mask_to_bits(ip4_sa->sin_addr.s_addr); + break; + case AF_INET6: + ip6_sa = (struct sockaddr_in6 *) rmask; + addr->sadb_address_prefixlen + = pf_key_v2_mask6_to_bits(&ip6_sa->sin6_addr.s6_addr[0]); + break; + } + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + /* Setup the POLICY extension. */ + len = sizeof *policy + sizeof *ipsecrequest + + 2 * PF_KEY_V2_ROUND(sysdep_sa_len(src)); + policy_buf = (u_int8_t *) calloc(1, len); + if (!policy_buf) { + log_error("pf_key_v2_flow: calloc %lu failed", (unsigned long) len); + goto cleanup; + } + policy = (struct sadb_x_policy *) policy_buf; + policy->sadb_x_policy_exttype = SADB_X_EXT_POLICY; + policy->sadb_x_policy_len = len / PF_KEY_V2_CHUNK; + policy->sadb_x_policy_type = IPSEC_POLICY_IPSEC; + if (ingress) + policy->sadb_x_policy_dir = IPSEC_DIR_INBOUND; + else + policy->sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; + policy->sadb_x_policy_reserved = 0; + + /* Setup the IPSECREQUEST extension part. */ + ipsecrequest = (struct sadb_x_ipsecrequest *) (policy + 1); + ipsecrequest->sadb_x_ipsecrequest_len = len - sizeof *policy; + switch (proto) { + case IPSEC_PROTO_IPSEC_ESP: + ipsecrequest->sadb_x_ipsecrequest_proto = IPPROTO_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + ipsecrequest->sadb_x_ipsecrequest_proto = IPPROTO_AH; + break; + default: + log_print("pf_key_v2_flow: invalid proto %d", proto); + goto cleanup; + } #if defined (LINUX_IPSEC) - if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) - ipsecrequest->sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL; - else - ipsecrequest->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT; + if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) + ipsecrequest->sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL; + else + ipsecrequest->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT; #else - ipsecrequest->sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL; /* XXX */ + ipsecrequest->sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL; /* XXX */ #endif - ipsecrequest->sadb_x_ipsecrequest_level - = ingress ? IPSEC_LEVEL_USE : IPSEC_LEVEL_REQUIRE; - ipsecrequest->sadb_x_ipsecrequest_reqid = 0; /* XXX */ - - /* Add source and destination addresses. */ - saddr = (struct sockaddr *)(ipsecrequest + 1); - pf_key_v2_setup_sockaddr (saddr, src, 0, 0, 0); - switch (src->sa_family) - { - case AF_INET: - saddr = (struct sockaddr *)((struct sockaddr_in *)saddr + 1); - break; - case AF_INET6: - saddr = (struct sockaddr *)((struct sockaddr_in6 *)saddr + 1); - break; - } - pf_key_v2_setup_sockaddr (saddr, dst, 0, 0, 0); - if (pf_key_v2_msg_add (flow, (struct sadb_ext *)policy, 0) == -1) - goto cleanup; + ipsecrequest->sadb_x_ipsecrequest_level + = ingress ? IPSEC_LEVEL_USE : IPSEC_LEVEL_REQUIRE; + ipsecrequest->sadb_x_ipsecrequest_reqid = 0; /* XXX */ + + /* Add source and destination addresses. */ + saddr = (struct sockaddr *) (ipsecrequest + 1); + pf_key_v2_setup_sockaddr(saddr, src, 0, 0, 0); + switch (src->sa_family) { + case AF_INET: + saddr = (struct sockaddr *) ((struct sockaddr_in *) saddr + 1); + break; + case AF_INET6: + saddr = (struct sockaddr *) ((struct sockaddr_in6 *) saddr + 1); + break; + } + pf_key_v2_setup_sockaddr(saddr, dst, 0, 0, 0); + if (pf_key_v2_msg_add(flow, (struct sadb_ext *) policy, 0) == -1) + goto cleanup; #ifdef USE_DEBUG - if (sockaddr2text (laddr, &laddr_str, 0)) - laddr_str = 0; - if (sockaddr2text (lmask, &lmask_str, 0)) - lmask_str = 0; - if (sockaddr2text (raddr, &raddr_str, 0)) - raddr_str = 0; - if (sockaddr2text (rmask, &rmask_str, 0)) - rmask_str = 0; - - LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s", - laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", - raddr_str ? raddr_str : "<??\?>", - rmask_str ? rmask_str : "<??\?>")); - - if (laddr_str) - free (laddr_str); - if (lmask_str) - free (lmask_str); - if (raddr_str) - free (raddr_str); - if (rmask_str) - free (rmask_str); -#endif + if (sockaddr2text(laddr, &laddr_str, 0)) + laddr_str = 0; + if (sockaddr2text(lmask, &lmask_str, 0)) + lmask_str = 0; + if (sockaddr2text(raddr, &raddr_str, 0)) + raddr_str = 0; + if (sockaddr2text(rmask, &rmask_str, 0)) + rmask_str = 0; + + LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s", + laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", + raddr_str ? raddr_str : "<??\?>", + rmask_str ? rmask_str : "<??\?>")); + + if (laddr_str) + free(laddr_str); + if (lmask_str) + free(lmask_str); + if (raddr_str) + free(raddr_str); + if (rmask_str) + free(rmask_str); +#endif + + ret = pf_key_v2_call(flow); + pf_key_v2_msg_free(flow); + flow = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (!delete && err == EEXIST) { + LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_flow: SPDADD returns EEXIST")); + } else if (err) { + log_print("pf_key_v2_flow: SPD%s: %s", delete ? "DELETE" : "ADD", + strerror(err)); + goto cleanup; + } + pf_key_v2_msg_free(ret); + + LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_flow: SPD%s: done", + delete ? "DELETE" : "ADD")); - ret = pf_key_v2_call (flow); - pf_key_v2_msg_free (flow); - flow = 0; - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (!delete && err == EEXIST) - { - LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_flow: SPDADD returns EEXIST")); - } - else if (err) - { - log_print ("pf_key_v2_flow: SPD%s: %s", delete ? "DELETE" : "ADD", - strerror (err)); - goto cleanup; - } - pf_key_v2_msg_free (ret); - - LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_flow: SPD%s: done", - delete ? "DELETE" : "ADD")); - - return 0; - - cleanup: - if (addr) - free (addr); - if (policy) - free (policy); - if (flow) - pf_key_v2_msg_free (flow); - if (ret) - pf_key_v2_msg_free (ret); - return -1; + return 0; + +cleanup: + if (addr) + free(addr); + if (policy) + free(policy); + if (flow) + pf_key_v2_msg_free(flow); + if (ret) + pf_key_v2_msg_free(ret); + return -1; #else - log_print ("pf_key_v2_flow: not supported in pure PF_KEYv2"); - return -1; + log_print("pf_key_v2_flow: not supported in pure PF_KEYv2"); + return -1; #endif } #ifndef KAME static u_int8_t * -pf_key_v2_convert_id (u_int8_t *id, int idlen, size_t *reslen, int *idtype) +pf_key_v2_convert_id(u_int8_t * id, int idlen, size_t * reslen, int *idtype) { - u_int8_t *addr, *res = 0; - char addrbuf[ADDRESS_MAX + 5]; - - switch (id[0]) - { - case IPSEC_ID_FQDN: - res = calloc (idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ, - sizeof (u_int8_t)); - if (!res) - return 0; - - *reslen = idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; - memcpy (res, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, *reslen); - *idtype = SADB_IDENTTYPE_FQDN; - LOG_DBG ((LOG_SYSDEP, 40, "pf_key_v2_convert_id: FQDN %.*s", - (int)*reslen, res)); - return res; - - case IPSEC_ID_USER_FQDN: - res = calloc (idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ, - sizeof (u_int8_t)); - if (!res) - return 0; - - *reslen = idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; - memcpy (res, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, *reslen); - *idtype = SADB_IDENTTYPE_USERFQDN; - LOG_DBG ((LOG_SYSDEP, 40, "pf_key_v2_convert_id: UFQDN %.*s", - (int)*reslen, res)); - return res; - - case IPSEC_ID_IPV4_ADDR: /* XXX CONNECTION ? */ - if (inet_ntop (AF_INET, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - addrbuf, ADDRESS_MAX) == NULL) - return 0; - *reslen = strlen (addrbuf) + 3; - strlcat (addrbuf, "/32", ADDRESS_MAX + 5); - res = (u_int8_t *)strdup (addrbuf); - if (!res) - return 0; - *idtype = SADB_IDENTTYPE_PREFIX; - LOG_DBG ((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv4 address %s", res)); - return res; - - case IPSEC_ID_IPV6_ADDR: /* XXX CONNECTION ? */ - if (inet_ntop (AF_INET6, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - addrbuf, ADDRESS_MAX) == NULL) - return 0; - *reslen = strlen (addrbuf) + 4; - strlcat (addrbuf, "/128", ADDRESS_MAX + 5); - res = (u_int8_t *)strdup (addrbuf); - if (!res) - return 0; - LOG_DBG ((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv6 address %s", res)); - *idtype = SADB_IDENTTYPE_PREFIX; - return res; - - case IPSEC_ID_IPV4_ADDR_SUBNET: /* XXX PREFIX */ - addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; - if (inet_ntop (AF_INET, addr, addrbuf, ADDRESS_MAX) == NULL) - return 0; - snprintf (addrbuf + strlen (addrbuf), ADDRESS_MAX - strlen (addrbuf), - "/%d", pf_key_v2_mask_to_bits ((u_int32_t) - *(addr + - sizeof (struct in_addr)))); - *reslen = strlen (addrbuf); - res = (u_int8_t *)strdup (addrbuf); - if (!res) - return 0; - *idtype = SADB_IDENTTYPE_PREFIX; - LOG_DBG ((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv4 subnet %s", res)); - return res; + u_int8_t *addr, *res = 0; + char addrbuf[ADDRESS_MAX + 5]; + + switch (id[0]) { + case IPSEC_ID_FQDN: + res = calloc(idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ, + sizeof(u_int8_t)); + if (!res) + return 0; + + *reslen = idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; + memcpy(res, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, *reslen); + *idtype = SADB_IDENTTYPE_FQDN; + LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: FQDN %.*s", + (int) *reslen, res)); + return res; + + case IPSEC_ID_USER_FQDN: + res = calloc(idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ, + sizeof(u_int8_t)); + if (!res) + return 0; + + *reslen = idlen - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; + memcpy(res, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, *reslen); + *idtype = SADB_IDENTTYPE_USERFQDN; + LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: UFQDN %.*s", + (int) *reslen, res)); + return res; + + case IPSEC_ID_IPV4_ADDR: /* XXX CONNECTION ? */ + if (inet_ntop(AF_INET, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + addrbuf, ADDRESS_MAX) == NULL) + return 0; + *reslen = strlen(addrbuf) + 3; + strlcat(addrbuf, "/32", ADDRESS_MAX + 5); + res = (u_int8_t *) strdup(addrbuf); + if (!res) + return 0; + *idtype = SADB_IDENTTYPE_PREFIX; + LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv4 address %s", res)); + return res; + + case IPSEC_ID_IPV6_ADDR: /* XXX CONNECTION ? */ + if (inet_ntop(AF_INET6, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + addrbuf, ADDRESS_MAX) == NULL) + return 0; + *reslen = strlen(addrbuf) + 4; + strlcat(addrbuf, "/128", ADDRESS_MAX + 5); + res = (u_int8_t *) strdup(addrbuf); + if (!res) + return 0; + LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv6 address %s", res)); + *idtype = SADB_IDENTTYPE_PREFIX; + return res; + + case IPSEC_ID_IPV4_ADDR_SUBNET: /* XXX PREFIX */ + addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + if (inet_ntop(AF_INET, addr, addrbuf, ADDRESS_MAX) == NULL) + return 0; + snprintf(addrbuf + strlen(addrbuf), ADDRESS_MAX - strlen(addrbuf), + "/%d", pf_key_v2_mask_to_bits((u_int32_t) + * (addr + + sizeof(struct in_addr)))); + *reslen = strlen(addrbuf); + res = (u_int8_t *) strdup(addrbuf); + if (!res) + return 0; + *idtype = SADB_IDENTTYPE_PREFIX; + LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv4 subnet %s", res)); + return res; + + case IPSEC_ID_IPV6_ADDR_SUBNET: /* XXX PREFIX */ + addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + if (inet_ntop(AF_INET6, addr, addrbuf, ADDRESS_MAX) == NULL) + return 0; + snprintf(addrbuf + strlen(addrbuf), ADDRESS_MAX - strlen(addrbuf), + "/%d", pf_key_v2_mask6_to_bits(addr + + sizeof(struct in6_addr))); + *reslen = strlen(addrbuf); + res = (u_int8_t *) strdup(addrbuf); + if (!res) + return 0; + LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv6 subnet %s", res)); + *idtype = SADB_IDENTTYPE_PREFIX; + return res; + + case IPSEC_ID_IPV4_RANGE: + case IPSEC_ID_IPV6_RANGE: + case IPSEC_ID_DER_ASN1_DN: + case IPSEC_ID_DER_ASN1_GN: + case IPSEC_ID_KEY_ID: + /* XXX Not implemented yet. */ + return 0; + } - case IPSEC_ID_IPV6_ADDR_SUBNET: /* XXX PREFIX */ - addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; - if (inet_ntop (AF_INET6, addr, addrbuf, ADDRESS_MAX) == NULL) - return 0; - snprintf (addrbuf + strlen (addrbuf), ADDRESS_MAX - strlen (addrbuf), - "/%d", pf_key_v2_mask6_to_bits (addr + - sizeof (struct in6_addr))); - *reslen = strlen (addrbuf); - res = (u_int8_t *)strdup (addrbuf); - if (!res) return 0; - LOG_DBG ((LOG_SYSDEP, 40, "pf_key_v2_convert_id: IPv6 subnet %s", res)); - *idtype = SADB_IDENTTYPE_PREFIX; - return res; - - case IPSEC_ID_IPV4_RANGE: - case IPSEC_ID_IPV6_RANGE: - case IPSEC_ID_DER_ASN1_DN: - case IPSEC_ID_DER_ASN1_GN: - case IPSEC_ID_KEY_ID: - /* XXX Not implemented yet. */ - return 0; - } - - return 0; } #endif /* Enable a flow given an SA. */ int -pf_key_v2_enable_sa (struct sa *sa, struct sa *isakmp_sa) +pf_key_v2_enable_sa(struct sa * sa, struct sa * isakmp_sa) { - struct ipsec_sa *isa = sa->data; - struct sockaddr *dst, *src; - int error; - struct proto *proto = TAILQ_FIRST (&sa->protos); - int sidtype = 0, didtype = 0; - size_t sidlen = 0, didlen = 0; - u_int8_t *sid = 0, *did = 0; + struct ipsec_sa *isa = sa->data; + struct sockaddr *dst, *src; + int error; + struct proto *proto = TAILQ_FIRST(&sa->protos); + int sidtype = 0, didtype = 0; + size_t sidlen = 0, didlen = 0; + u_int8_t *sid = 0, *did = 0; #if !defined (SADB_X_EXT_FLOW_TYPE) - struct sockaddr_storage hostmask_storage; - struct sockaddr *hostmask = (struct sockaddr *)&hostmask_storage; -#endif /* SADB_X_EXT_FLOW_TYPE */ + struct sockaddr_storage hostmask_storage; + struct sockaddr *hostmask = (struct sockaddr *) & hostmask_storage; +#endif /* SADB_X_EXT_FLOW_TYPE */ - sa->transport->vtbl->get_dst (sa->transport, &dst); - sa->transport->vtbl->get_src (sa->transport, &src); + sa->transport->vtbl->get_dst(sa->transport, &dst); + sa->transport->vtbl->get_src(sa->transport, &src); #if defined (SADB_X_EXT_FLOW_TYPE) - if (isakmp_sa->id_i) - { - if (isakmp_sa->initiator) - sid = pf_key_v2_convert_id (isakmp_sa->id_i, isakmp_sa->id_i_len, - &sidlen, &sidtype); - else - did = pf_key_v2_convert_id (isakmp_sa->id_i, isakmp_sa->id_i_len, - &didlen, &didtype); - } - - if (isakmp_sa->id_r) - { - if (isakmp_sa->initiator) - did = pf_key_v2_convert_id (isakmp_sa->id_r, isakmp_sa->id_r_len, - &didlen, &didtype); - else - sid = pf_key_v2_convert_id (isakmp_sa->id_r, isakmp_sa->id_r_len, - &sidlen, &sidtype); - } -#endif /* SADB_X_EXT_FLOW_TYPE */ - - error = pf_key_v2_flow (isa->src_net, isa->src_mask, isa->dst_net, - isa->dst_mask, isa->tproto, isa->sport, isa->dport, - proto->spi[0], proto->proto, dst, src, 0, 0, - sidtype, sid, sidlen, didtype, did, didlen, - proto->data); - if (error) - goto cleanup; + if (isakmp_sa->id_i) { + if (isakmp_sa->initiator) + sid = pf_key_v2_convert_id(isakmp_sa->id_i, isakmp_sa->id_i_len, + &sidlen, &sidtype); + else + did = pf_key_v2_convert_id(isakmp_sa->id_i, isakmp_sa->id_i_len, + &didlen, &didtype); + } + if (isakmp_sa->id_r) { + if (isakmp_sa->initiator) + did = pf_key_v2_convert_id(isakmp_sa->id_r, isakmp_sa->id_r_len, + &didlen, &didtype); + else + sid = pf_key_v2_convert_id(isakmp_sa->id_r, isakmp_sa->id_r_len, + &sidlen, &sidtype); + } +#endif /* SADB_X_EXT_FLOW_TYPE */ + + error = pf_key_v2_flow(isa->src_net, isa->src_mask, isa->dst_net, + isa->dst_mask, isa->tproto, isa->sport, isa->dport, + proto->spi[0], proto->proto, dst, src, 0, 0, + sidtype, sid, sidlen, didtype, did, didlen, + proto->data); + if (error) + goto cleanup; #if !defined (SADB_X_EXT_FLOW_TYPE) - /* Set hostmask to '-1'. */ - switch (dst->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)hostmask)->sin_family = AF_INET; + /* Set hostmask to '-1'. */ + switch (dst->sa_family) { + case AF_INET: + ((struct sockaddr_in *) hostmask)->sin_family = AF_INET; #ifndef USE_OLD_SOCKADDR - ((struct sockaddr_in *)hostmask)->sin_len = sizeof (struct in_addr); + ((struct sockaddr_in *) hostmask)->sin_len = sizeof(struct in_addr); #endif - memset (&((struct sockaddr_in *)hostmask)->sin_addr.s_addr, 0xff, - sizeof (struct in_addr)); - break; - case AF_INET6: - ((struct sockaddr_in6 *)hostmask)->sin6_family = AF_INET6; + memset(&((struct sockaddr_in *) hostmask)->sin_addr.s_addr, 0xff, + sizeof(struct in_addr)); + break; + case AF_INET6: + ((struct sockaddr_in6 *) hostmask)->sin6_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - ((struct sockaddr_in6 *)hostmask)->sin6_len = sizeof (struct in6_addr); + ((struct sockaddr_in6 *) hostmask)->sin6_len = sizeof(struct in6_addr); #endif - memset (&((struct sockaddr_in6 *)hostmask)->sin6_addr.s6_addr, 0xff, - sizeof (struct in6_addr)); - break; - } - - /* Ingress flows, handling SA bundles. */ - while (TAILQ_NEXT (proto, link)) - { - error = pf_key_v2_flow (dst, hostmask, src, hostmask, 0, 0, 0, - proto->spi[1], proto->proto, src, dst, - 0, 1, 0, 0, 0, 0, 0, 0, proto->data); - if (error) - goto cleanup; - proto = TAILQ_NEXT (proto, link); - } -#endif /* SADB_X_EXT_FLOW_TYPE */ + memset(&((struct sockaddr_in6 *) hostmask)->sin6_addr.s6_addr, 0xff, + sizeof(struct in6_addr)); + break; + } + + /* Ingress flows, handling SA bundles. */ + while (TAILQ_NEXT(proto, link)) { + error = pf_key_v2_flow(dst, hostmask, src, hostmask, 0, 0, 0, + proto->spi[1], proto->proto, src, dst, + 0, 1, 0, 0, 0, 0, 0, 0, proto->data); + if (error) + goto cleanup; + proto = TAILQ_NEXT(proto, link); + } +#endif /* SADB_X_EXT_FLOW_TYPE */ - error = pf_key_v2_flow (isa->dst_net, isa->dst_mask, isa->src_net, - isa->src_mask, isa->tproto, isa->dport, isa->sport, - proto->spi[1], proto->proto, src, dst, 0, 1, - sidtype, sid, sidlen, didtype, did, didlen, - proto->data); + error = pf_key_v2_flow(isa->dst_net, isa->dst_mask, isa->src_net, + isa->src_mask, isa->tproto, isa->dport, isa->sport, + proto->spi[1], proto->proto, src, dst, 0, 1, + sidtype, sid, sidlen, didtype, did, didlen, + proto->data); - cleanup: +cleanup: #if defined (SADB_X_EXT_FLOW_TYPE) - if (sid) - free (sid); - if (did) - free (did); -#endif /* SADB_X_EXT_FLOW_TYPE */ + if (sid) + free(sid); + if (did) + free(did); +#endif /* SADB_X_EXT_FLOW_TYPE */ - return error; + return error; } #if defined (SADB_X_ASKPOLICY) /* Increase reference count of refcounted sections. */ static int -pf_key_v2_conf_refinc (int af, char *section) +pf_key_v2_conf_refinc(int af, char *section) { - char conn[22]; - int num; + char conn[22]; + int num; - if (!section) - return 0; + if (!section) + return 0; - num = conf_get_num (section, "Refcount", 0); - if (num == 0) - return 0; + num = conf_get_num(section, "Refcount", 0); + if (num == 0) + return 0; - snprintf (conn, sizeof conn, "%d", num + 1); - conf_set (af, section, "Refcount", conn, 1, 0); - return 0; + snprintf(conn, sizeof conn, "%d", num + 1); + conf_set(af, section, "Refcount", conn, 1, 0); + return 0; } #endif @@ -2470,159 +2379,147 @@ pf_key_v2_conf_refinc (int af, char *section) * Don't touch non-refcounted (statically defined) sections. */ static int -pf_key_v2_conf_refhandle (int af, char *section) +pf_key_v2_conf_refhandle(int af, char *section) { - char conn[22]; - int num; - - if (!section) - return 0; - - num = conf_get_num (section, "Refcount", 0); - if (num == 1) - { - conf_remove_section (af, section); - num--; - } - else - if (num != 0) - { - snprintf (conn, sizeof conn, "%d", num - 1); - conf_set (af, section, "Refcount", conn, 1, 0); - } - - return num; + char conn[22]; + int num; + + if (!section) + return 0; + + num = conf_get_num(section, "Refcount", 0); + if (num == 1) { + conf_remove_section(af, section); + num--; + } else if (num != 0) { + snprintf(conn, sizeof conn, "%d", num - 1); + conf_set(af, section, "Refcount", conn, 1, 0); + } + return num; } /* Remove all dynamically-established configuration entries. */ static int -pf_key_v2_remove_conf (char *section) +pf_key_v2_remove_conf(char *section) { - char *ikepeer, *localid, *remoteid, *configname; - struct conf_list_node *attr; - struct conf_list *attrs; - int af; - - if (!section) - return 0; - - if (!conf_get_str (section, "Phase")) - return 0; - - /* Only remove dynamically-established entries. */ - attrs = conf_get_list (section, "Flags"); - if (attrs) - { - for (attr = TAILQ_FIRST (&attrs->fields); attr; - attr = TAILQ_NEXT (attr, link)) - if (!strcasecmp (attr->field, "__ondemand")) - goto passed; - - conf_free_list (attrs); - } - - return 0; - - passed: - conf_free_list (attrs); + char *ikepeer, *localid, *remoteid, *configname; + struct conf_list_node *attr; + struct conf_list *attrs; + int af; + + if (!section) + return 0; + + if (!conf_get_str(section, "Phase")) + return 0; + + /* Only remove dynamically-established entries. */ + attrs = conf_get_list(section, "Flags"); + if (attrs) { + for (attr = TAILQ_FIRST(&attrs->fields); attr; + attr = TAILQ_NEXT(attr, link)) + if (!strcasecmp(attr->field, "__ondemand")) + goto passed; + + conf_free_list(attrs); + } + return 0; - af = conf_begin (); +passed: + conf_free_list(attrs); - configname = conf_get_str (section, "Configuration"); - conf_remove_section (af, configname); + af = conf_begin(); - /* These are the Phase 2 Local/Remote IDs. */ - localid = conf_get_str (section, "Local-ID"); - pf_key_v2_conf_refhandle (af, localid); + configname = conf_get_str(section, "Configuration"); + conf_remove_section(af, configname); - remoteid = conf_get_str (section, "Remote-ID"); - pf_key_v2_conf_refhandle (af, remoteid); + /* These are the Phase 2 Local/Remote IDs. */ + localid = conf_get_str(section, "Local-ID"); + pf_key_v2_conf_refhandle(af, localid); - ikepeer = conf_get_str (section, "ISAKMP-peer"); + remoteid = conf_get_str(section, "Remote-ID"); + pf_key_v2_conf_refhandle(af, remoteid); - pf_key_v2_conf_refhandle (af, section); + ikepeer = conf_get_str(section, "ISAKMP-peer"); - if (ikepeer) - { - remoteid = conf_get_str (ikepeer, "Remote-ID"); - localid = conf_get_str (ikepeer, "ID"); - configname = conf_get_str (ikepeer, "Configuration"); + pf_key_v2_conf_refhandle(af, section); - pf_key_v2_conf_refhandle (af, ikepeer); - pf_key_v2_conf_refhandle (af, configname); + if (ikepeer) { + remoteid = conf_get_str(ikepeer, "Remote-ID"); + localid = conf_get_str(ikepeer, "ID"); + configname = conf_get_str(ikepeer, "Configuration"); - /* Phase 1 IDs */ - pf_key_v2_conf_refhandle (af, localid); - pf_key_v2_conf_refhandle (af, remoteid); - } + pf_key_v2_conf_refhandle(af, ikepeer); + pf_key_v2_conf_refhandle(af, configname); - conf_end (af, 1); - return 0; + /* Phase 1 IDs */ + pf_key_v2_conf_refhandle(af, localid); + pf_key_v2_conf_refhandle(af, remoteid); + } + conf_end(af, 1); + return 0; } /* Disable a flow given a SA. */ static int -pf_key_v2_disable_sa (struct sa *sa, int incoming) +pf_key_v2_disable_sa(struct sa * sa, int incoming) { - struct ipsec_sa *isa = sa->data; - struct sockaddr *dst, *src; - struct proto *proto = TAILQ_FIRST (&sa->protos); + struct ipsec_sa *isa = sa->data; + struct sockaddr *dst, *src; + struct proto *proto = TAILQ_FIRST(&sa->protos); #if !defined (SADB_X_EXT_FLOW_TYPE) - struct sockaddr_storage hostmask_storage; - struct sockaddr *hostmask = (struct sockaddr *)&hostmask_storage; - int error; -#endif /* SADB_X_EXT_FLOW_TYPE */ - - sa->transport->vtbl->get_dst (sa->transport, &dst); - sa->transport->vtbl->get_src (sa->transport, &src); - - if (!incoming) - return pf_key_v2_flow (isa->src_net, isa->src_mask, isa->dst_net, - isa->dst_mask, isa->tproto, isa->sport, isa->dport, - proto->spi[0], proto->proto, src, dst, 1, 0, - 0, 0, 0, 0, 0, 0, proto->data); - else - { + struct sockaddr_storage hostmask_storage; + struct sockaddr *hostmask = (struct sockaddr *) & hostmask_storage; + int error; +#endif /* SADB_X_EXT_FLOW_TYPE */ + + sa->transport->vtbl->get_dst(sa->transport, &dst); + sa->transport->vtbl->get_src(sa->transport, &src); + + if (!incoming) + return pf_key_v2_flow(isa->src_net, isa->src_mask, isa->dst_net, + isa->dst_mask, isa->tproto, isa->sport, isa->dport, + proto->spi[0], proto->proto, src, dst, 1, 0, + 0, 0, 0, 0, 0, 0, proto->data); + else { #if !defined (SADB_X_EXT_FLOW_TYPE) - /* Set hostmask to '-1'. */ - switch (dst->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)hostmask)->sin_family = AF_INET; + /* Set hostmask to '-1'. */ + switch (dst->sa_family) { + case AF_INET: + ((struct sockaddr_in *) hostmask)->sin_family = AF_INET; #ifndef USE_OLD_SOCKADDR - ((struct sockaddr_in *)hostmask)->sin_len = sizeof (struct in_addr); + ((struct sockaddr_in *) hostmask)->sin_len = sizeof(struct in_addr); #endif - memset (&((struct sockaddr_in *)hostmask)->sin_addr.s_addr, 0xff, - sizeof (struct in_addr)); - break; - case AF_INET6: - ((struct sockaddr_in6 *)hostmask)->sin6_family = AF_INET6; + memset(&((struct sockaddr_in *) hostmask)->sin_addr.s_addr, 0xff, + sizeof(struct in_addr)); + break; + case AF_INET6: + ((struct sockaddr_in6 *) hostmask)->sin6_family = AF_INET6; #ifndef USE_OLD_SOCKADDR - ((struct sockaddr_in6 *)hostmask)->sin6_len = - sizeof (struct in6_addr); + ((struct sockaddr_in6 *) hostmask)->sin6_len = + sizeof(struct in6_addr); #endif - memset (&((struct sockaddr_in6 *)hostmask)->sin6_addr.s6_addr, 0xff, - sizeof (struct in6_addr)); - break; - } + memset(&((struct sockaddr_in6 *) hostmask)->sin6_addr.s6_addr, 0xff, + sizeof(struct in6_addr)); + break; + } - /* Ingress flow --- SA bundles */ - while (TAILQ_NEXT (proto, link)) - { - error = pf_key_v2_flow (dst, hostmask, src, hostmask, 0, 0, 0, - proto->spi[1], proto->proto, src, dst, - 1, 1, 0, 0, 0, 0, 0, 0, proto->data); - if (error) - return error; - proto = TAILQ_NEXT (proto, link); - } -#endif /* SADB_X_EXT_FLOW_TYPE */ + /* Ingress flow --- SA bundles */ + while (TAILQ_NEXT(proto, link)) { + error = pf_key_v2_flow(dst, hostmask, src, hostmask, 0, 0, 0, + proto->spi[1], proto->proto, src, dst, + 1, 1, 0, 0, 0, 0, 0, 0, proto->data); + if (error) + return error; + proto = TAILQ_NEXT(proto, link); + } +#endif /* SADB_X_EXT_FLOW_TYPE */ - return pf_key_v2_flow (isa->dst_net, isa->dst_mask, isa->src_net, - isa->src_mask, isa->tproto, isa->dport, - isa->sport, proto->spi[1], proto->proto, + return pf_key_v2_flow(isa->dst_net, isa->dst_mask, isa->src_net, + isa->src_mask, isa->tproto, isa->dport, + isa->sport, proto->spi[1], proto->proto, src, dst, 1, 1, 0, 0, 0, 0, 0, 0, proto->data); - } + } } /* @@ -2630,1518 +2527,1351 @@ pf_key_v2_disable_sa (struct sa *sa, int incoming) * of the IKE security association SA. Also delete potential flows tied to it. */ int -pf_key_v2_delete_spi (struct sa *sa, struct proto *proto, int incoming) +pf_key_v2_delete_spi(struct sa * sa, struct proto * proto, int incoming) { - struct sadb_msg msg; - struct sadb_sa ssa; - struct sadb_address *addr = 0; - struct sockaddr *saddr; - int len, err; - struct pf_key_v2_msg *delete = 0, *ret = 0; + struct sadb_msg msg; + struct sadb_sa ssa; + struct sadb_address *addr = 0; + struct sockaddr *saddr; + int len, err; + struct pf_key_v2_msg *delete = 0, *ret = 0; #ifdef KAME - struct sadb_x_sa2 ssa2; -#endif - - /* If it's not an established SA, don't proceed. */ - if (!(sa->flags & SA_FLAG_READY)) - return 0; - - /* - * If the SA was not replaced and was not one acquired through the - * kernel (ACQUIRE message), remove the flow associated with it. - * We ignore any errors from the disabling of the flow. - */ - if (!(sa->flags & SA_FLAG_REPLACED) - && !(sa->flags & SA_FLAG_ONDEMAND)) - pf_key_v2_disable_sa (sa, incoming); - - if (sa->name && !(sa->flags & SA_FLAG_REPLACED)) - { - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_delete_spi: removing configuration %s", - sa->name)); - pf_key_v2_remove_conf (sa->name); - } - - msg.sadb_msg_type = SADB_DELETE; - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_ESP: - msg.sadb_msg_satype = SADB_SATYPE_ESP; - break; - case IPSEC_PROTO_IPSEC_AH: - msg.sadb_msg_satype = SADB_SATYPE_AH; - break; + struct sadb_x_sa2 ssa2; +#endif + + /* If it's not an established SA, don't proceed. */ + if (!(sa->flags & SA_FLAG_READY)) + return 0; + + /* + * If the SA was not replaced and was not one acquired through the + * kernel (ACQUIRE message), remove the flow associated with it. + * We ignore any errors from the disabling of the flow. + */ + if (!(sa->flags & SA_FLAG_REPLACED) + && !(sa->flags & SA_FLAG_ONDEMAND)) + pf_key_v2_disable_sa(sa, incoming); + + if (sa->name && !(sa->flags & SA_FLAG_REPLACED)) { + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_delete_spi: removing configuration %s", + sa->name)); + pf_key_v2_remove_conf(sa->name); + } + msg.sadb_msg_type = SADB_DELETE; + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_ESP: + msg.sadb_msg_satype = SADB_SATYPE_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + msg.sadb_msg_satype = SADB_SATYPE_AH; + break; #if defined (SADB_X_SATYPE_IPCOMP) - case IPSEC_PROTO_IPCOMP: - msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; - break; + case IPSEC_PROTO_IPCOMP: + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + break; #endif - default: - log_print ("pf_key_v2_delete_spi: invalid proto %d", proto->proto); - goto cleanup; - } - msg.sadb_msg_seq = 0; - delete = pf_key_v2_msg_new (&msg, 0); - if (!delete) - goto cleanup; - - /* Setup the SA extension. */ - ssa.sadb_sa_exttype = SADB_EXT_SA; - ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; - memcpy (&ssa.sadb_sa_spi, proto->spi[incoming], sizeof ssa.sadb_sa_spi); - ssa.sadb_sa_replay = 0; - ssa.sadb_sa_state = 0; - ssa.sadb_sa_auth = 0; - ssa.sadb_sa_encrypt = 0; - ssa.sadb_sa_flags = 0; - if (pf_key_v2_msg_add (delete, (struct sadb_ext *)&ssa, 0) == -1) - goto cleanup; + default: + log_print("pf_key_v2_delete_spi: invalid proto %d", proto->proto); + goto cleanup; + } + msg.sadb_msg_seq = 0; + delete = pf_key_v2_msg_new(&msg, 0); + if (!delete) + goto cleanup; + + /* Setup the SA extension. */ + ssa.sadb_sa_exttype = SADB_EXT_SA; + ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK; + memcpy(&ssa.sadb_sa_spi, proto->spi[incoming], sizeof ssa.sadb_sa_spi); + ssa.sadb_sa_replay = 0; + ssa.sadb_sa_state = 0; + ssa.sadb_sa_auth = 0; + ssa.sadb_sa_encrypt = 0; + ssa.sadb_sa_flags = 0; + if (pf_key_v2_msg_add(delete, (struct sadb_ext *) & ssa, 0) == -1) + goto cleanup; #ifdef KAME - memset (&ssa2, 0, sizeof ssa2); - ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; - ssa2.sadb_x_sa2_mode = 0; - if (pf_key_v2_msg_add (delete, (struct sadb_ext *)&ssa2, 0) == -1) - goto cleanup; + memset(&ssa2, 0, sizeof ssa2); + ssa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + ssa2.sadb_x_sa2_len = sizeof ssa2 / PF_KEY_V2_CHUNK; + ssa2.sadb_x_sa2_mode = 0; + if (pf_key_v2_msg_add(delete, (struct sadb_ext *) & ssa2, 0) == -1) + goto cleanup; #endif - /* - * Setup the ADDRESS extensions. - */ - if (incoming) - sa->transport->vtbl->get_dst (sa->transport, &saddr); - else - sa->transport->vtbl->get_src (sa->transport, &saddr); - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (saddr)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + /* + * Setup the ADDRESS extensions. + */ + if (incoming) + sa->transport->vtbl->get_dst(sa->transport, &saddr); + else + sa->transport->vtbl->get_src(sa->transport, &saddr); + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(saddr)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, saddr, sysdep_sa_len (saddr)); - switch (saddr->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; - } - if (pf_key_v2_msg_add (delete, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - if (incoming) - sa->transport->vtbl->get_src (sa->transport, &saddr); - else - sa->transport->vtbl->get_dst (sa->transport, &saddr); - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (saddr)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + memcpy(addr + 1, saddr, sysdep_sa_len(saddr)); + switch (saddr->sa_family) { + case AF_INET: + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; + } + if (pf_key_v2_msg_add(delete, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + if (incoming) + sa->transport->vtbl->get_src(sa->transport, &saddr); + else + sa->transport->vtbl->get_dst(sa->transport, &saddr); + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(saddr)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, saddr, sysdep_sa_len (saddr)); - switch (saddr->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; - break; - } - if (pf_key_v2_msg_add (delete, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - ret = pf_key_v2_call (delete); - pf_key_v2_msg_free (delete); - delete = 0; - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - LOG_DBG ((LOG_SYSDEP, 10, "pf_key_v2_delete_spi: DELETE: %s", - strerror (err))); - goto cleanup; - } - pf_key_v2_msg_free (ret); - - LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_delete_spi: done")); - - return 0; - - cleanup: - if (addr) - free (addr); - if (delete) - pf_key_v2_msg_free (delete); - if (ret) - pf_key_v2_msg_free (ret); - return -1; + addr->sadb_address_reserved = 0; + memcpy(addr + 1, saddr, sysdep_sa_len(saddr)); + switch (saddr->sa_family) { + case AF_INET: + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; + break; + } + if (pf_key_v2_msg_add(delete, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + ret = pf_key_v2_call(delete); + pf_key_v2_msg_free(delete); + delete = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_delete_spi: DELETE: %s", + strerror(err))); + goto cleanup; + } + pf_key_v2_msg_free(ret); + + LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_delete_spi: done")); + + return 0; + +cleanup: + if (addr) + free(addr); + if (delete) + pf_key_v2_msg_free(delete); + if (ret) + pf_key_v2_msg_free(ret); + return -1; } static void -pf_key_v2_stayalive (struct exchange *exchange, void *vconn, int fail) +pf_key_v2_stayalive(struct exchange * exchange, void *vconn, int fail) { - char *conn = vconn; - struct sa *sa; - - /* XXX What if it is phase 1 ? */ - sa = sa_lookup_by_name (conn, 2); - if (sa) - sa->flags |= SA_FLAG_STAYALIVE; - - /* - * Remove failed configuration entry -- call twice because it is - * created with a Refcount of 2. - */ - if (fail && (!exchange || exchange->name)) - { - pf_key_v2_remove_conf (conn); - pf_key_v2_remove_conf (conn); - } + char *conn = vconn; + struct sa *sa; + + /* XXX What if it is phase 1 ? */ + sa = sa_lookup_by_name(conn, 2); + if (sa) + sa->flags |= SA_FLAG_STAYALIVE; + + /* + * Remove failed configuration entry -- call twice because it is + * created with a Refcount of 2. + */ + if (fail && (!exchange || exchange->name)) { + pf_key_v2_remove_conf(conn); + pf_key_v2_remove_conf(conn); + } } /* Check if a connection CONN exists, otherwise establish it. */ void -pf_key_v2_connection_check (char *conn) +pf_key_v2_connection_check(char *conn) { - if (!sa_lookup_by_name (conn, 2)) - { - LOG_DBG ((LOG_SYSDEP, 70, - "pf_key_v2_connection_check: SA for %s missing", conn)); - exchange_establish (conn, pf_key_v2_stayalive, conn); - } - else - LOG_DBG ((LOG_SYSDEP, 70, "pf_key_v2_connection_check: SA for %s exists", - conn)); + if (!sa_lookup_by_name(conn, 2)) { + LOG_DBG((LOG_SYSDEP, 70, + "pf_key_v2_connection_check: SA for %s missing", conn)); + exchange_establish(conn, pf_key_v2_stayalive, conn); + } else + LOG_DBG((LOG_SYSDEP, 70, "pf_key_v2_connection_check: SA for %s exists", + conn)); } /* Handle a PF_KEY lifetime expiration message PMSG. */ static void -pf_key_v2_expire (struct pf_key_v2_msg *pmsg) +pf_key_v2_expire(struct pf_key_v2_msg * pmsg) { - struct sadb_msg *msg; - struct sadb_sa *ssa; - struct sadb_address *dst; - struct sockaddr *dstaddr; - struct sadb_lifetime *life, *lifecurrent; - struct sa *sa; - struct pf_key_v2_node *lifenode, *ext; - char *dst_str; - - msg = (struct sadb_msg *)TAILQ_FIRST (pmsg)->seg; - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_SA); - if (!ext) - { - log_print ("pf_key_v2_expire: no SA extension found"); - return; - } - ssa = ext->seg; - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_ADDRESS_DST); - if (!ext) - { - log_print ("pf_key_v2_expire: no destination address extension found"); - return; - } - dst = ext->seg; - dstaddr = (struct sockaddr *)(dst + 1); - lifenode = pf_key_v2_find_ext (pmsg, SADB_EXT_LIFETIME_HARD); - if (!lifenode) - lifenode = pf_key_v2_find_ext (pmsg, SADB_EXT_LIFETIME_SOFT); - if (!lifenode) - { - log_print ("pf_key_v2_expire: no lifetime extension found"); - return; - } - life = lifenode->seg; - - lifenode = pf_key_v2_find_ext (pmsg, SADB_EXT_LIFETIME_CURRENT); - if (!lifenode) - { - log_print ("pf_key_v2_expire: no current lifetime extension found"); - return; - } - lifecurrent = lifenode->seg; + struct sadb_msg *msg; + struct sadb_sa *ssa; + struct sadb_address *dst; + struct sockaddr *dstaddr; + struct sadb_lifetime *life, *lifecurrent; + struct sa *sa; + struct pf_key_v2_node *lifenode, *ext; + char *dst_str; + + msg = (struct sadb_msg *) TAILQ_FIRST(pmsg)->seg; + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_SA); + if (!ext) { + log_print("pf_key_v2_expire: no SA extension found"); + return; + } + ssa = ext->seg; + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_DST); + if (!ext) { + log_print("pf_key_v2_expire: no destination address extension found"); + return; + } + dst = ext->seg; + dstaddr = (struct sockaddr *) (dst + 1); + lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_HARD); + if (!lifenode) + lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_SOFT); + if (!lifenode) { + log_print("pf_key_v2_expire: no lifetime extension found"); + return; + } + life = lifenode->seg; + + lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_CURRENT); + if (!lifenode) { + log_print("pf_key_v2_expire: no current lifetime extension found"); + return; + } + lifecurrent = lifenode->seg; #ifdef USE_DEBUG - if (sockaddr2text (dstaddr, &dst_str, 0)) - dst_str = 0; - - LOG_DBG ((LOG_SYSDEP, 20, "pf_key_v2_expire: %s dst %s SPI %x sproto %d", - life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT ? "SOFT" - : "HARD", dst_str ? dst_str : "<unknown>", - ntohl (ssa->sadb_sa_spi), msg->sadb_msg_satype)); - - if (dst_str) - free (dst_str); - -#endif /* USE_DEBUG */ - - /* - * Find the IPsec SA. The IPsec stack has two SAs for every IKE SA, - * one outgoing and one incoming, we regard expirations for any of - * them as an expiration of the full IKE SA. Likewise, in - * protection suites consisting of more than one protocol, any - * expired individual IPsec stack SA will be seen as an expiration - * of the full suite. - */ - switch (msg->sadb_msg_satype) - { - case SADB_SATYPE_ESP: - sa = ipsec_sa_lookup (dstaddr, ssa->sadb_sa_spi, IPSEC_PROTO_IPSEC_ESP); - break; - - case SADB_SATYPE_AH: - sa = ipsec_sa_lookup (dstaddr, ssa->sadb_sa_spi, IPSEC_PROTO_IPSEC_AH); - break; + if (sockaddr2text(dstaddr, &dst_str, 0)) + dst_str = 0; + + LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_expire: %s dst %s SPI %x sproto %d", + life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT ? "SOFT" + : "HARD", dst_str ? dst_str : "<unknown>", + ntohl(ssa->sadb_sa_spi), msg->sadb_msg_satype)); + + if (dst_str) + free(dst_str); + +#endif /* USE_DEBUG */ + + /* + * Find the IPsec SA. The IPsec stack has two SAs for every IKE SA, + * one outgoing and one incoming, we regard expirations for any of + * them as an expiration of the full IKE SA. Likewise, in + * protection suites consisting of more than one protocol, any + * expired individual IPsec stack SA will be seen as an expiration + * of the full suite. + */ + switch (msg->sadb_msg_satype) { + case SADB_SATYPE_ESP: + sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, IPSEC_PROTO_IPSEC_ESP); + break; + + case SADB_SATYPE_AH: + sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, IPSEC_PROTO_IPSEC_AH); + break; #ifdef SADB_X_SATYPE_IPCOMP - case SADB_X_SATYPE_IPCOMP: - sa = ipsec_sa_lookup (dstaddr, ssa->sadb_sa_spi, IPSEC_PROTO_IPCOMP); - break; + case SADB_X_SATYPE_IPCOMP: + sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, IPSEC_PROTO_IPCOMP); + break; #endif - default: - /* XXX Log? */ - sa = 0; - break; - } - - /* If the SA is already gone, don't do anything. */ - if (!sa) - return; - - /* - * If we got a notification, try to renegotiate the SA -- unless of - * course it has already been replaced by another. - * Also, ignore SAs that were not dynamically established, or that - * did not see any use. - */ - if (!(sa->flags & SA_FLAG_REPLACED) && (sa->flags & SA_FLAG_ONDEMAND) && - lifecurrent->sadb_lifetime_bytes) - exchange_establish (sa->name, 0, 0); - - if (life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_HARD) - { - /* Remove the old SA, it isn't useful anymore. */ - sa_free (sa); - } + default: + /* XXX Log? */ + sa = 0; + break; + } + + /* If the SA is already gone, don't do anything. */ + if (!sa) + return; + + /* + * If we got a notification, try to renegotiate the SA -- unless of + * course it has already been replaced by another. + * Also, ignore SAs that were not dynamically established, or that + * did not see any use. + */ + if (!(sa->flags & SA_FLAG_REPLACED) && (sa->flags & SA_FLAG_ONDEMAND) && + lifecurrent->sadb_lifetime_bytes) + exchange_establish(sa->name, 0, 0); + + if (life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_HARD) { + /* Remove the old SA, it isn't useful anymore. */ + sa_free(sa); + } } /* Handle a PF_KEY SA ACQUIRE message PMSG. */ static void -pf_key_v2_acquire (struct pf_key_v2_msg *pmsg) +pf_key_v2_acquire(struct pf_key_v2_msg * pmsg) { #if defined (SADB_X_ASKPOLICY) - struct sadb_msg *msg, askpolicy_msg; - struct pf_key_v2_msg *askpolicy = 0, *ret = 0; - struct sadb_x_policy policy; - struct sadb_address *dst = 0, *src = 0; - struct sockaddr *dstaddr, *srcaddr = 0; - struct sadb_comb *scmb = 0; - struct sadb_prop *sprp = 0; - struct sadb_ident *srcident = 0, *dstident = 0; - char dstbuf[ADDRESS_MAX], srcbuf[ADDRESS_MAX], *peer = 0, *conn = 0; - char confname[120]; - char *srcid = 0, *dstid = 0, *prefstring = 0; - int slen, af, afamily, masklen, buflen; - struct sockaddr *smask, *sflow, *dmask, *dflow; - struct sadb_protocol *sproto; - char ssflow[ADDRESS_MAX], sdflow[ADDRESS_MAX]; - char sdmask[ADDRESS_MAX], ssmask[ADDRESS_MAX]; - char *sidtype = 0, *didtype = 0; - char lname[100], dname[100], configname[30]; - int shostflag = 0, dhostflag = 0; - struct pf_key_v2_node *ext; - struct passwd *pwd = 0; - u_int16_t sport = 0, dport = 0; - u_int8_t tproto = 0; - char tmbuf[sizeof sport * 3 + 1], *xform; - int connlen; + struct sadb_msg *msg, askpolicy_msg; + struct pf_key_v2_msg *askpolicy = 0, *ret = 0; + struct sadb_x_policy policy; + struct sadb_address *dst = 0, *src = 0; + struct sockaddr *dstaddr, *srcaddr = 0; + struct sadb_comb *scmb = 0; + struct sadb_prop *sprp = 0; + struct sadb_ident *srcident = 0, *dstident = 0; + char dstbuf[ADDRESS_MAX], srcbuf[ADDRESS_MAX], *peer = 0, + *conn = 0; + char confname[120]; + char *srcid = 0, *dstid = 0, *prefstring = 0; + int slen, af, afamily, masklen, buflen; + struct sockaddr *smask, *sflow, *dmask, *dflow; + struct sadb_protocol *sproto; + char ssflow[ADDRESS_MAX], sdflow[ADDRESS_MAX]; + char sdmask[ADDRESS_MAX], ssmask[ADDRESS_MAX]; + char *sidtype = 0, *didtype = 0; + char lname[100], dname[100], configname[30]; + int shostflag = 0, dhostflag = 0; + struct pf_key_v2_node *ext; + struct passwd *pwd = 0; + u_int16_t sport = 0, dport = 0; + u_int8_t tproto = 0; + char tmbuf[sizeof sport * 3 + 1], *xform; + int connlen; #if defined (SADB_X_CREDTYPE_NONE) - struct sadb_x_cred *cred = 0, *sauth = 0; + struct sadb_x_cred *cred = 0, *sauth = 0; #endif - /* This needs to be dynamically allocated. */ - connlen = 22; - conn = malloc (connlen); - if (!conn) - { - log_error ("pf_key_v2_acquire: malloc (%d) failed", connlen); - return; - } - - msg = (struct sadb_msg *)TAILQ_FIRST (pmsg)->seg; - - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_ADDRESS_DST); - if (!ext) - { - log_print ("pf_key_v2_acquire: no destination address specified"); - return; - } - dst = ext->seg; - - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_ADDRESS_SRC); - if (ext) - src = ext->seg; - - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_PROPOSAL); - if (ext) - { - sprp = ext->seg; - scmb = (struct sadb_comb *)(sprp + 1); - } - - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_IDENTITY_SRC); - if (ext) - srcident = ext->seg; - - ext = pf_key_v2_find_ext (pmsg, SADB_EXT_IDENTITY_DST); - if (ext) - dstident = ext->seg; - - /* Ask the kernel for the matching policy. */ - bzero (&askpolicy_msg, sizeof askpolicy_msg); - askpolicy_msg.sadb_msg_type = SADB_X_ASKPOLICY; - askpolicy = pf_key_v2_msg_new (&askpolicy_msg, 0); - if (!askpolicy) - goto fail; - - policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; - policy.sadb_x_policy_len = sizeof policy / PF_KEY_V2_CHUNK; - policy.sadb_x_policy_seq = msg->sadb_msg_seq; - if (pf_key_v2_msg_add (askpolicy, (struct sadb_ext *)&policy, 0) == -1) - goto fail; - - ret = pf_key_v2_call (askpolicy); - if (!ret) - goto fail; - - /* Now we have all the information needed. */ - - ext = pf_key_v2_find_ext (ret, SADB_X_EXT_SRC_FLOW); - if (!ext) - { - log_print ("pf_key_v2_acquire: no source flow extension found"); - goto fail; - } - sflow = (struct sockaddr *)(((struct sadb_address *)ext->seg) + 1); - - ext = pf_key_v2_find_ext (ret, SADB_X_EXT_DST_FLOW); - if (!ext) - { - log_print ("pf_key_v2_acquire: no destination flow extension found"); - goto fail; - } - dflow = (struct sockaddr *)(((struct sadb_address *)ext->seg) + 1); - ext = pf_key_v2_find_ext (ret, SADB_X_EXT_SRC_MASK); - if (!ext) - { - log_print ("pf_key_v2_acquire: no source mask extension found"); - goto fail; - } - smask = (struct sockaddr *)(((struct sadb_address *)ext->seg) + 1); - - ext = pf_key_v2_find_ext (ret, SADB_X_EXT_DST_MASK); - if (!ext) - { - log_print ("pf_key_v2_acquire: no destination mask extension found"); - goto fail; - } - dmask = (struct sockaddr *)(((struct sadb_address *)ext->seg) + 1); - - ext = pf_key_v2_find_ext (ret, SADB_X_EXT_FLOW_TYPE); - if (!ext) - { - log_print ("pf_key_v2_acquire: no flow type extension found"); - goto fail; - } - sproto = ext->seg; - tproto = sproto->sadb_protocol_proto; + /* This needs to be dynamically allocated. */ + connlen = 22; + conn = malloc(connlen); + if (!conn) { + log_error("pf_key_v2_acquire: malloc (%d) failed", connlen); + return; + } + msg = (struct sadb_msg *) TAILQ_FIRST(pmsg)->seg; -#if defined (SADB_X_EXT_LOCAL_CREDENTIALS) - ext = pf_key_v2_find_ext (pmsg, SADB_X_EXT_LOCAL_CREDENTIALS); - if (ext) - cred = (struct sadb_x_cred *) ext->seg; - else - cred = 0; -#endif + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_DST); + if (!ext) { + log_print("pf_key_v2_acquire: no destination address specified"); + return; + } + dst = ext->seg; -#if defined (SADB_X_EXT_LOCAL_AUTH) - ext = pf_key_v2_find_ext (pmsg, SADB_X_EXT_LOCAL_AUTH); - if (ext) - sauth = (struct sadb_x_cred *) ext->seg; - else - sauth = 0; -#endif + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_SRC); + if (ext) + src = ext->seg; - bzero (ssflow, sizeof ssflow); - bzero (sdflow, sizeof sdflow); - bzero (ssmask, sizeof ssmask); - bzero (sdmask, sizeof sdmask); + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_PROPOSAL); + if (ext) { + sprp = ext->seg; + scmb = (struct sadb_comb *) (sprp + 1); + } + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_IDENTITY_SRC); + if (ext) + srcident = ext->seg; + + ext = pf_key_v2_find_ext(pmsg, SADB_EXT_IDENTITY_DST); + if (ext) + dstident = ext->seg; + + /* Ask the kernel for the matching policy. */ + bzero(&askpolicy_msg, sizeof askpolicy_msg); + askpolicy_msg.sadb_msg_type = SADB_X_ASKPOLICY; + askpolicy = pf_key_v2_msg_new(&askpolicy_msg, 0); + if (!askpolicy) + goto fail; - sidtype = didtype = "IPV4_ADDR_SUBNET"; /* default */ + policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; + policy.sadb_x_policy_len = sizeof policy / PF_KEY_V2_CHUNK; + policy.sadb_x_policy_seq = msg->sadb_msg_seq; + if (pf_key_v2_msg_add(askpolicy, (struct sadb_ext *) & policy, 0) == -1) + goto fail; - switch (sflow->sa_family) - { - case AF_INET: - if (inet_ntop (AF_INET, &((struct sockaddr_in *)sflow)->sin_addr, ssflow, - ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - sport = ((struct sockaddr_in *)sflow)->sin_port; - if (inet_ntop (AF_INET, &((struct sockaddr_in *)dflow)->sin_addr, sdflow, - ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - dport = ((struct sockaddr_in *)dflow)->sin_port; - if (inet_ntop (AF_INET, &((struct sockaddr_in *)smask)->sin_addr, ssmask, - ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - if (inet_ntop (AF_INET, &((struct sockaddr_in *)dmask)->sin_addr, sdmask, - ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - if (((struct sockaddr_in *)smask)->sin_addr.s_addr == INADDR_BROADCAST) - { - shostflag = 1; - sidtype = "IPV4_ADDR"; - } - if (((struct sockaddr_in *)dmask)->sin_addr.s_addr == INADDR_BROADCAST) - { - dhostflag = 1; - didtype = "IPV4_ADDR"; - } - break; + ret = pf_key_v2_call(askpolicy); + if (!ret) + goto fail; - case AF_INET6: - if (inet_ntop (AF_INET6, &((struct sockaddr_in6 *)sflow)->sin6_addr, - ssflow, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - sport = ((struct sockaddr_in6 *)sflow)->sin6_port; - if (inet_ntop (AF_INET6, &((struct sockaddr_in6 *)dflow)->sin6_addr, - sdflow, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - dport = ((struct sockaddr_in6 *)dflow)->sin6_port; - if (inet_ntop (AF_INET6, &((struct sockaddr_in6 *)smask)->sin6_addr, - ssmask, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - if (inet_ntop (AF_INET6, &((struct sockaddr_in6 *)dmask)->sin6_addr, - sdmask, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; + /* Now we have all the information needed. */ + + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_SRC_FLOW); + if (!ext) { + log_print("pf_key_v2_acquire: no source flow extension found"); + goto fail; } - sidtype = didtype = "IPV6_ADDR_SUBNET"; - if (IN6_IS_ADDR_FULL (&((struct sockaddr_in6 *)smask)->sin6_addr)) - { - shostflag = 1; - sidtype = "IPV6_ADDR"; + sflow = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); + + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_DST_FLOW); + if (!ext) { + log_print("pf_key_v2_acquire: no destination flow extension found"); + goto fail; } - if (IN6_IS_ADDR_FULL (&((struct sockaddr_in6 *)dmask)->sin6_addr)) - { - dhostflag = 1; - didtype = "IPV6_ADDR"; + dflow = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_SRC_MASK); + if (!ext) { + log_print("pf_key_v2_acquire: no source mask extension found"); + goto fail; } - break; - } + smask = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); - dstaddr = (struct sockaddr *)(dst + 1); - bzero (dstbuf, sizeof dstbuf); - bzero (srcbuf, sizeof srcbuf); - - if (dstaddr->sa_family == 0) - { - /* Destination was not specified in the flow -- can we derive it? */ - if (dhostflag == 0) - { - log_print("pf_key_v2_acquire: Cannot determine precise destination"); - goto fail; - } - dstaddr = dflow; - } - switch (dstaddr->sa_family) - { - case AF_INET: - if (inet_ntop (AF_INET, &((struct sockaddr_in *)dstaddr)->sin_addr, - dstbuf, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_DST_MASK); + if (!ext) { + log_print("pf_key_v2_acquire: no destination mask extension found"); + goto fail; } - LOG_DBG ((LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d", dstbuf, - msg->sadb_msg_satype)); - break; + dmask = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); - case AF_INET6: - if (inet_ntop (AF_INET6, &((struct sockaddr_in6 *)dstaddr)->sin6_addr, - dstbuf, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_FLOW_TYPE); + if (!ext) { + log_print("pf_key_v2_acquire: no flow type extension found"); + goto fail; } - LOG_DBG ((LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d", dstbuf, - msg->sadb_msg_satype)); - break; - } + sproto = ext->seg; + tproto = sproto->sadb_protocol_proto; - if (src) - { - srcaddr = (struct sockaddr *)(src + 1); +#if defined (SADB_X_EXT_LOCAL_CREDENTIALS) + ext = pf_key_v2_find_ext(pmsg, SADB_X_EXT_LOCAL_CREDENTIALS); + if (ext) + cred = (struct sadb_x_cred *) ext->seg; + else + cred = 0; +#endif - switch (srcaddr->sa_family) - { - case AF_INET: - if (inet_ntop (AF_INET, &((struct sockaddr_in *)srcaddr)->sin_addr, - srcbuf, ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - break; +#if defined (SADB_X_EXT_LOCAL_AUTH) + ext = pf_key_v2_find_ext(pmsg, SADB_X_EXT_LOCAL_AUTH); + if (ext) + sauth = (struct sadb_x_cred *) ext->seg; + else + sauth = 0; +#endif - case AF_INET6: - if (inet_ntop (AF_INET6, - &((struct sockaddr_in6 *)srcaddr)->sin6_addr, srcbuf, - ADDRESS_MAX) == NULL) - { - log_print ("pf_key_v2_acquire: inet_ntop failed"); - goto fail; - } - break; + bzero(ssflow, sizeof ssflow); + bzero(sdflow, sizeof sdflow); + bzero(ssmask, sizeof ssmask); + bzero(sdmask, sizeof sdmask); - default: - /* - * The kernel will pass an all '0' EXT_ADDRESS_SRC if it wasn't - * specified for the flow. In that case, do NOT specify the srcaddr - * in the Peer- name below - */ - srcbuf[0] = 0; - srcaddr = NULL; - break; - } - } - - /* Insert source ID. */ - if (srcident) - { - slen = (srcident->sadb_ident_len * sizeof (u_int64_t)) - - sizeof (struct sadb_ident); - if (((unsigned char *)(srcident + 1))[slen - 1] != '\0') - { - log_print ("pf_key_v2_acquire: source identity not NUL-terminated"); - goto fail; - } - - /* Check for valid type. */ - switch (srcident->sadb_ident_type) - { -#if defined (SADB_X_IDENTTYPE_CONNECTION) - case SADB_X_IDENTTYPE_CONNECTION: - /* XXX */ - break; -#endif + sidtype = didtype = "IPV4_ADDR_SUBNET"; /* default */ - case SADB_IDENTTYPE_PREFIX: - /* Determine what the address family is. */ - srcid = memchr (srcident + 1, ':', slen); - if (srcid) - afamily = AF_INET6; - else - afamily = AF_INET; - - srcid = memchr (srcident + 1, '/', slen); - if (!srcid) - { - log_print ("pf_key_v2_acquire: badly formatted PREFIX identity"); - goto fail; - } - - masklen = atoi (srcid + 1); - - /* XXX We only support host addresses. */ - if ((afamily == AF_INET6 && masklen != 128) - || (afamily == AF_INET && masklen != 32)) - { - log_print ("pf_key_v2_acquire: non-host address specified in " - "source identity (mask length %d), ignoring request", - masklen); - goto fail; - } - - /* NUL-terminate the PREFIX string at the separator, then dup. */ - *srcid = '\0'; - slen = strlen ((char *)(srcident + 1)) + sizeof "ID:Address/"; - srcid = malloc (slen); - if (!srcid) - { - log_error ("pf_key_v2_acquire: malloc (%d) failed", slen); - goto fail; - } - - snprintf (srcid, slen, "ID:Address/%s", (char *)(srcident + 1)); - - /* Set the section if it doesn't already exist. */ - af = conf_begin (); - if (!conf_get_str (srcid, "ID-type")) - { - if (conf_set (af, srcid, "ID-type", - afamily == AF_INET ? "IPV4_ADDR" : "IPV6_ADDR", - 1, 0) - || conf_set (af, srcid, "Refcount", "1", 1, 0) - || conf_set (af, srcid, "Address", (char *)(srcident + 1), - 1, 0)) - { - conf_end (af, 0); - goto fail; + switch (sflow->sa_family) { + case AF_INET: + if (inet_ntop(AF_INET, &((struct sockaddr_in *) sflow)->sin_addr, ssflow, + ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; } - } - else - pf_key_v2_conf_refinc (af, srcid); - conf_end (af, 1); - break; - - case SADB_IDENTTYPE_FQDN: - prefstring = "FQDN"; - /* Fall through */ - case SADB_IDENTTYPE_USERFQDN: - if (!prefstring) - { - prefstring = "USER_FQDN"; - - /* - * Check whether there is a string following the header; - * if no, that there is a user ID (and acquire the login - * name). If there is both a string and a user ID, check - * that they match. - */ - if ((slen == 0) && (srcident->sadb_ident_id == 0)) - { - log_print ("pf_key_v2_acquire: no user FQDN or ID provided"); - goto fail; + sport = ((struct sockaddr_in *) sflow)->sin_port; + if (inet_ntop(AF_INET, &((struct sockaddr_in *) dflow)->sin_addr, sdflow, + ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; } - - if (srcident->sadb_ident_id) - { - pwd = getpwuid (srcident->sadb_ident_id); - if (!pwd) - { - log_error ("pf_key_v2_acquire: could not acquire " - "username from provided ID %llu", - srcident->sadb_ident_id); - goto fail; - } - - if (slen != 0) - if (strcmp (pwd->pw_name, (char *)(srcident + 1)) != 0) - { - log_print ("pf_key_v2_acquire: provided user name and " - "ID do not match (%s != %s)", - (char *)(srcident + 1), pwd->pw_name); - /* String has precedence, per RFC 2367. */ - } + dport = ((struct sockaddr_in *) dflow)->sin_port; + if (inet_ntop(AF_INET, &((struct sockaddr_in *) smask)->sin_addr, ssmask, + ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; } - } - - buflen = (slen ? slen : strlen (pwd->pw_name)) + strlen (prefstring) - + sizeof "ID:/"; - srcid = malloc (buflen); - if (!srcid) - { - log_error ("pf_key_v2_acquire: malloc (%d) failed", buflen); - goto fail; - } - - snprintf (srcid, buflen, "ID:%s/", prefstring); - if (slen != 0) - strlcat (srcid, (char *)(srcident + 1), buflen); - else - strlcat (srcid, pwd->pw_name, buflen); - pwd = 0; - - /* Set the section if it doesn't already exist. */ - af = conf_begin (); - if (!conf_get_str (srcid, "ID-type")) - { - if (conf_set (af, srcid, "ID-type", prefstring, 1, 0) - || conf_set (af, srcid, "Refcount", "1", 1, 0) - || conf_set (af, srcid, "Name", - srcid + sizeof "ID:/" - 1 + strlen (prefstring), - 1, 0)) - { - conf_end (af, 0); - goto fail; + if (inet_ntop(AF_INET, &((struct sockaddr_in *) dmask)->sin_addr, sdmask, + ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; } - } - else - pf_key_v2_conf_refinc (af, srcid); - conf_end (af, 1); - break; + if (((struct sockaddr_in *) smask)->sin_addr.s_addr == INADDR_BROADCAST) { + shostflag = 1; + sidtype = "IPV4_ADDR"; + } + if (((struct sockaddr_in *) dmask)->sin_addr.s_addr == INADDR_BROADCAST) { + dhostflag = 1; + didtype = "IPV4_ADDR"; + } + break; - default: - LOG_DBG ((LOG_SYSDEP, 20, - "pf_key_v2_acquire: invalid source ID type %d", - srcident->sadb_ident_type)); - goto fail; + case AF_INET6: + if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *) sflow)->sin6_addr, + ssflow, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + sport = ((struct sockaddr_in6 *) sflow)->sin6_port; + if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *) dflow)->sin6_addr, + sdflow, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + dport = ((struct sockaddr_in6 *) dflow)->sin6_port; + if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *) smask)->sin6_addr, + ssmask, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *) dmask)->sin6_addr, + sdmask, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + sidtype = didtype = "IPV6_ADDR_SUBNET"; + if (IN6_IS_ADDR_FULL(&((struct sockaddr_in6 *) smask)->sin6_addr)) { + shostflag = 1; + sidtype = "IPV6_ADDR"; + } + if (IN6_IS_ADDR_FULL(&((struct sockaddr_in6 *) dmask)->sin6_addr)) { + dhostflag = 1; + didtype = "IPV6_ADDR"; + } + break; } - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_acquire: constructed source ID \"%s\"", srcid)); - prefstring = 0; - } + dstaddr = (struct sockaddr *) (dst + 1); + bzero(dstbuf, sizeof dstbuf); + bzero(srcbuf, sizeof srcbuf); + + if (dstaddr->sa_family == 0) { + /* + * Destination was not specified in the flow -- can we derive + * it? + */ + if (dhostflag == 0) { + log_print("pf_key_v2_acquire: Cannot determine precise destination"); + goto fail; + } + dstaddr = dflow; + } + switch (dstaddr->sa_family) { + case AF_INET: + if (inet_ntop(AF_INET, &((struct sockaddr_in *) dstaddr)->sin_addr, + dstbuf, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d", dstbuf, + msg->sadb_msg_satype)); + break; - /* Insert destination ID. */ - if (dstident) - { - slen = (dstident->sadb_ident_len * sizeof (u_int64_t)) - - sizeof (struct sadb_ident); + case AF_INET6: + if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *) dstaddr)->sin6_addr, + dstbuf, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d", dstbuf, + msg->sadb_msg_satype)); + break; + } - /* Check for valid type. */ - switch (dstident->sadb_ident_type) - { -#if defined (SADB_X_IDENTTYPE_CONNECTION) - case SADB_X_IDENTTYPE_CONNECTION: - /* XXX */ - break; -#endif + if (src) { + srcaddr = (struct sockaddr *) (src + 1); + + switch (srcaddr->sa_family) { + case AF_INET: + if (inet_ntop(AF_INET, &((struct sockaddr_in *) srcaddr)->sin_addr, + srcbuf, ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + break; + + case AF_INET6: + if (inet_ntop(AF_INET6, + &((struct sockaddr_in6 *) srcaddr)->sin6_addr, srcbuf, + ADDRESS_MAX) == NULL) { + log_print("pf_key_v2_acquire: inet_ntop failed"); + goto fail; + } + break; - case SADB_IDENTTYPE_PREFIX: - /* Determine what the address family is. */ - dstid = memchr (dstident + 1, ':', slen); - if (dstid) - afamily = AF_INET6; - else - afamily = AF_INET; - - dstid = memchr (dstident + 1, '/', slen); - if (!dstid) - { - log_print ("pf_key_v2_acquire: badly formatted PREFIX identity"); - goto fail; - } - - masklen = atoi (dstid + 1); - - /* XXX We only support host addresses. */ - if ((afamily == AF_INET6 && masklen != 128) - || (afamily == AF_INET && masklen != 32)) - { - log_print ("pf_key_v2_acquire: non-host address specified in " - "destination identity (mask length %d), ignoring " - "request", - masklen); - goto fail; - } - - /* NUL-terminate the PREFIX string at the separator, then dup. */ - *dstid = '\0'; - slen = strlen ((char *)(dstident + 1)) + sizeof "ID:Address/"; - dstid = malloc (slen); - if (!dstid) - { - log_error ("pf_key_v2_acquire: malloc (%d) failed", slen); - goto fail; - } - - snprintf (dstid, slen, "ID:Address/%s", (char *)(dstident + 1)); - - /* Set the section if it doesn't already exist. */ - af = conf_begin (); - if (!conf_get_str (dstid, "ID-type")) - { - if (conf_set (af, dstid, "ID-type", - afamily == AF_INET ? "IPV4_ADDR" : "IPV6_ADDR", - 1, 0) - || conf_set (af, dstid, "Refcount", "1", 1, 0) - || conf_set (af, dstid, "Address", (char *)(dstident + 1), - 1, 0)) - { - conf_end (af, 0); - goto fail; + default: + /* + * The kernel will pass an all '0' EXT_ADDRESS_SRC if it wasn't + * specified for the flow. In that case, do NOT specify the srcaddr + * in the Peer- name below + */ + srcbuf[0] = 0; + srcaddr = NULL; + break; } - } - else - pf_key_v2_conf_refinc (af, dstid); - conf_end (af, 1); - break; - - case SADB_IDENTTYPE_FQDN: - prefstring = "FQDN"; - /* Fall through */ - - case SADB_IDENTTYPE_USERFQDN: - if (!prefstring) - { - prefstring = "USER_FQDN"; - - /* - * Check whether there is a string following the header; - * if no, that there is a user ID (and acquire the login - * name). If there is both a string and a user ID, check - * that they match. - */ - if (slen == 0 && dstident->sadb_ident_id == 0) - { - log_print ("pf_key_v2_acquire: no user FQDN or ID provided"); - goto fail; + } + /* Insert source ID. */ + if (srcident) { + slen = (srcident->sadb_ident_len * sizeof(u_int64_t)) + - sizeof(struct sadb_ident); + if (((unsigned char *) (srcident + 1))[slen - 1] != '\0') { + log_print("pf_key_v2_acquire: source identity not NUL-terminated"); + goto fail; } + /* Check for valid type. */ + switch (srcident->sadb_ident_type) { +#if defined (SADB_X_IDENTTYPE_CONNECTION) + case SADB_X_IDENTTYPE_CONNECTION: + /* XXX */ + break; +#endif + + case SADB_IDENTTYPE_PREFIX: + /* Determine what the address family is. */ + srcid = memchr(srcident + 1, ':', slen); + if (srcid) + afamily = AF_INET6; + else + afamily = AF_INET; + + srcid = memchr(srcident + 1, '/', slen); + if (!srcid) { + log_print("pf_key_v2_acquire: badly formatted PREFIX identity"); + goto fail; + } + masklen = atoi(srcid + 1); + + /* XXX We only support host addresses. */ + if ((afamily == AF_INET6 && masklen != 128) + || (afamily == AF_INET && masklen != 32)) { + log_print("pf_key_v2_acquire: non-host address specified in " + "source identity (mask length %d), ignoring request", + masklen); + goto fail; + } + /* + * NUL-terminate the PREFIX string at the separator, + * then dup. + */ + *srcid = '\0'; + slen = strlen((char *) (srcident + 1)) + sizeof "ID:Address/"; + srcid = malloc(slen); + if (!srcid) { + log_error("pf_key_v2_acquire: malloc (%d) failed", slen); + goto fail; + } + snprintf(srcid, slen, "ID:Address/%s", (char *) (srcident + 1)); + + /* Set the section if it doesn't already exist. */ + af = conf_begin(); + if (!conf_get_str(srcid, "ID-type")) { + if (conf_set(af, srcid, "ID-type", + afamily == AF_INET ? "IPV4_ADDR" : "IPV6_ADDR", + 1, 0) + || conf_set(af, srcid, "Refcount", "1", 1, 0) + || conf_set(af, srcid, "Address", (char *) (srcident + 1), + 1, 0)) { + conf_end(af, 0); + goto fail; + } + } else + pf_key_v2_conf_refinc(af, srcid); + conf_end(af, 1); + break; + + case SADB_IDENTTYPE_FQDN: + prefstring = "FQDN"; + /* Fall through */ + case SADB_IDENTTYPE_USERFQDN: + if (!prefstring) { + prefstring = "USER_FQDN"; + + /* + * Check whether there is a string following the header; + * if no, that there is a user ID (and acquire the login + * name). If there is both a string and a user ID, check + * that they match. + */ + if ((slen == 0) && (srcident->sadb_ident_id == 0)) { + log_print("pf_key_v2_acquire: no user FQDN or ID provided"); + goto fail; + } + if (srcident->sadb_ident_id) { + pwd = getpwuid(srcident->sadb_ident_id); + if (!pwd) { + log_error("pf_key_v2_acquire: could not acquire " + "username from provided ID %llu", + srcident->sadb_ident_id); + goto fail; + } + if (slen != 0) + if (strcmp(pwd->pw_name, (char *) (srcident + 1)) != 0) { + log_print("pf_key_v2_acquire: provided user name and " + "ID do not match (%s != %s)", + (char *) (srcident + 1), pwd->pw_name); + /* + * String has + * precedence, per + * RFC 2367. + */ + } + } + } + buflen = (slen ? slen : strlen(pwd->pw_name)) + strlen(prefstring) + + sizeof "ID:/"; + srcid = malloc(buflen); + if (!srcid) { + log_error("pf_key_v2_acquire: malloc (%d) failed", buflen); + goto fail; + } + snprintf(srcid, buflen, "ID:%s/", prefstring); + if (slen != 0) + strlcat(srcid, (char *) (srcident + 1), buflen); + else + strlcat(srcid, pwd->pw_name, buflen); + pwd = 0; + + /* Set the section if it doesn't already exist. */ + af = conf_begin(); + if (!conf_get_str(srcid, "ID-type")) { + if (conf_set(af, srcid, "ID-type", prefstring, 1, 0) + || conf_set(af, srcid, "Refcount", "1", 1, 0) + || conf_set(af, srcid, "Name", + srcid + sizeof "ID:/" - 1 + strlen(prefstring), + 1, 0)) { + conf_end(af, 0); + goto fail; + } + } else + pf_key_v2_conf_refinc(af, srcid); + conf_end(af, 1); + break; - if (dstident->sadb_ident_id) - { - pwd = getpwuid (dstident->sadb_ident_id); - if (!pwd) - { - log_error ("pf_key_v2_acquire: could not acquire " - "username from provided ID %llu", - dstident->sadb_ident_id); - goto fail; - } - - if (slen != 0) - if (strcmp (pwd->pw_name, (char *)(dstident + 1)) != 0) - { - log_print ("pf_key_v2_acquire: provided user name and " - "ID do not match (%s != %s)", - (char *)(dstident + 1), pwd->pw_name); - /* String has precedence, per RF 2367. */ - } - } - } - - buflen = (slen ? slen : strlen (pwd->pw_name)) + strlen (prefstring) - + sizeof "ID:/"; - dstid = malloc (buflen); - if (!dstid) - { - log_error ("pf_key_v2_acquire: malloc (%d) failed", buflen); - goto fail; - } - - snprintf (dstid, buflen, "ID:%s/", prefstring); - if (slen != 0) - strlcat (dstid, (char *)(dstident + 1), buflen); - else - strlcat (dstid, pwd->pw_name, buflen); - pwd = 0; - - /* Set the section if it doesn't already exist. */ - af = conf_begin (); - if (!conf_get_str (dstid, "ID-type")) - { - if (conf_set (af, dstid, "ID-type", prefstring, 1, 0) - || conf_set (af, dstid, "Refcount", "1", 1, 0) - || conf_set (af, dstid, "Name", - dstid + sizeof "ID:/" - 1 + strlen (prefstring), - 1, 0)) - { - conf_end (af, 0); - goto fail; + default: + LOG_DBG((LOG_SYSDEP, 20, + "pf_key_v2_acquire: invalid source ID type %d", + srcident->sadb_ident_type)); + goto fail; } - } - else - pf_key_v2_conf_refinc (af, dstid); - conf_end (af, 1); - break; - default: - LOG_DBG ((LOG_SYSDEP, 20, - "pf_key_v2_acquire: invalid destination ID type %d", - dstident->sadb_ident_type)); - goto fail; + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_acquire: constructed source ID \"%s\"", srcid)); + prefstring = 0; } + /* Insert destination ID. */ + if (dstident) { + slen = (dstident->sadb_ident_len * sizeof(u_int64_t)) + - sizeof(struct sadb_ident); - LOG_DBG ((LOG_SYSDEP, 50, - "pf_key_v2_acquire: constructed destination ID \"%s\"", - dstid)); - } - - /* Now we've placed the necessary IDs in the configuration space. */ - - /* Get a new connection sequence number. */ - for (;; connection_seq++) - { - snprintf (conn, connlen, "Connection-%u", connection_seq); - snprintf (configname, sizeof configname, "Config-Phase2-%u", - connection_seq); - - /* Does it exist ? */ - if (!conf_get_str (conn, "Phase") - && !conf_get_str (configname, "Suites")) - break; - } - - /* - * Set the IPsec connection entry. In particular, the following fields: - * - Phase - * - ISAKMP-peer - * - Local-ID/Remote-ID (if provided) - * - Acquire-ID (sequence number of kernel message, e.g., PF_KEYv2) - * - Configuration - * - * Also set the following section: - * [Peer-dstaddr(/srcaddr)(-srcid)(/dstid)] - * with these fields: - * - Phase - * - ID (if provided) - * - Remote-ID (if provided) - * - Local-address (if provided) - * - Address - * - Configuration (if an entry "ISAKMP-configuration-dstaddr(/srcaddr)" - * exists -- otherwise use the defaults) - */ - - slen = strlen (dstbuf) + strlen (srcbuf) + (srcid ? strlen (srcid) : 0) - + (dstid ? strlen (dstid) : 0) + sizeof "Peer-/-/"; - peer = malloc (slen); - if (!peer) - goto fail; - - /* - * The various cases: - * - Peer-dstaddr - * - Peer-dstaddr/srcaddr - * - Peer-dstaddr/srcaddr-srcid - * - Peer-dstaddr/srcaddr-srcid/dstid - * - Peer-dstaddr/srcaddr-/dstid - * - Peer-dstaddr-srcid/dstid - * - Peer-dstaddr-/dstid - * - Peer-dstaddr-srcid - */ - snprintf (peer, slen, "Peer-%s%s%s%s%s%s%s", dstbuf, srcaddr ? "/" : "", - srcaddr ? srcbuf : "", srcid ? "-" : "", srcid ? srcid : "", - dstid ? (srcid ? "/" : "-/") : "", dstid ? dstid : ""); - - /* - * Set the IPsec connection section. Refcount is set to 2, because - * it will be linked both to the incoming and the outgoing SA. - */ - af = conf_begin (); - if (conf_set (af, conn, "Phase", "2", 0, 0) - || conf_set (af, conn, "Flags", "__ondemand", 0 , 0) - || conf_set (af, conn, "Refcount", "2", 0 , 0) - || conf_set (af, conn, "ISAKMP-peer", peer, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - /* Set the sequence number. */ - snprintf (lname, sizeof lname, "%u", msg->sadb_msg_seq); - if (conf_set (af, conn, "Acquire-ID", lname, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - /* Set Phase 2 IDs -- this is the Local-ID section. */ - snprintf (lname, sizeof lname, "Phase2-ID:%s/%s/%u/%u", ssflow, ssmask, - tproto, sport); - if (conf_set (af, conn, "Local-ID", lname, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (!conf_get_str (lname, "ID-type")) - { - if (conf_set (af, lname, "Refcount", "1", 0, 0)) - { - conf_end (af, 0); - goto fail; - } + /* Check for valid type. */ + switch (dstident->sadb_ident_type) { +#if defined (SADB_X_IDENTTYPE_CONNECTION) + case SADB_X_IDENTTYPE_CONNECTION: + /* XXX */ + break; +#endif + + case SADB_IDENTTYPE_PREFIX: + /* Determine what the address family is. */ + dstid = memchr(dstident + 1, ':', slen); + if (dstid) + afamily = AF_INET6; + else + afamily = AF_INET; + + dstid = memchr(dstident + 1, '/', slen); + if (!dstid) { + log_print("pf_key_v2_acquire: badly formatted PREFIX identity"); + goto fail; + } + masklen = atoi(dstid + 1); + + /* XXX We only support host addresses. */ + if ((afamily == AF_INET6 && masklen != 128) + || (afamily == AF_INET && masklen != 32)) { + log_print("pf_key_v2_acquire: non-host address specified in " + "destination identity (mask length %d), ignoring " + "request", + masklen); + goto fail; + } + /* + * NUL-terminate the PREFIX string at the separator, + * then dup. + */ + *dstid = '\0'; + slen = strlen((char *) (dstident + 1)) + sizeof "ID:Address/"; + dstid = malloc(slen); + if (!dstid) { + log_error("pf_key_v2_acquire: malloc (%d) failed", slen); + goto fail; + } + snprintf(dstid, slen, "ID:Address/%s", (char *) (dstident + 1)); + + /* Set the section if it doesn't already exist. */ + af = conf_begin(); + if (!conf_get_str(dstid, "ID-type")) { + if (conf_set(af, dstid, "ID-type", + afamily == AF_INET ? "IPV4_ADDR" : "IPV6_ADDR", + 1, 0) + || conf_set(af, dstid, "Refcount", "1", 1, 0) + || conf_set(af, dstid, "Address", (char *) (dstident + 1), + 1, 0)) { + conf_end(af, 0); + goto fail; + } + } else + pf_key_v2_conf_refinc(af, dstid); + conf_end(af, 1); + break; + + case SADB_IDENTTYPE_FQDN: + prefstring = "FQDN"; + /* Fall through */ + + case SADB_IDENTTYPE_USERFQDN: + if (!prefstring) { + prefstring = "USER_FQDN"; + + /* + * Check whether there is a string following the header; + * if no, that there is a user ID (and acquire the login + * name). If there is both a string and a user ID, check + * that they match. + */ + if (slen == 0 && dstident->sadb_ident_id == 0) { + log_print("pf_key_v2_acquire: no user FQDN or ID provided"); + goto fail; + } + if (dstident->sadb_ident_id) { + pwd = getpwuid(dstident->sadb_ident_id); + if (!pwd) { + log_error("pf_key_v2_acquire: could not acquire " + "username from provided ID %llu", + dstident->sadb_ident_id); + goto fail; + } + if (slen != 0) + if (strcmp(pwd->pw_name, (char *) (dstident + 1)) != 0) { + log_print("pf_key_v2_acquire: provided user name and " + "ID do not match (%s != %s)", + (char *) (dstident + 1), pwd->pw_name); + /* + * String has + * precedence, per RF + * 2367. + */ + } + } + } + buflen = (slen ? slen : strlen(pwd->pw_name)) + strlen(prefstring) + + sizeof "ID:/"; + dstid = malloc(buflen); + if (!dstid) { + log_error("pf_key_v2_acquire: malloc (%d) failed", buflen); + goto fail; + } + snprintf(dstid, buflen, "ID:%s/", prefstring); + if (slen != 0) + strlcat(dstid, (char *) (dstident + 1), buflen); + else + strlcat(dstid, pwd->pw_name, buflen); + pwd = 0; + + /* Set the section if it doesn't already exist. */ + af = conf_begin(); + if (!conf_get_str(dstid, "ID-type")) { + if (conf_set(af, dstid, "ID-type", prefstring, 1, 0) + || conf_set(af, dstid, "Refcount", "1", 1, 0) + || conf_set(af, dstid, "Name", + dstid + sizeof "ID:/" - 1 + strlen(prefstring), + 1, 0)) { + conf_end(af, 0); + goto fail; + } + } else + pf_key_v2_conf_refinc(af, dstid); + conf_end(af, 1); + break; - if (shostflag) - { - if (conf_set (af, lname, "ID-type", sidtype, 0, 0) - || conf_set (af, lname, "Address", ssflow, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - } - else - { - if (conf_set (af, lname, "ID-type", sidtype, 0, 0) - || conf_set (af, lname, "Network", ssflow, 0, 0) - || conf_set (af, lname, "Netmask", ssmask, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - } - if (tproto) - { - snprintf (tmbuf, sizeof sport * 3 + 1, "%u", tproto); - if (conf_set (af, lname, "Protocol", tmbuf, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (sport) - { - snprintf (tmbuf, sizeof sport * 3 + 1, "%u", ntohs (sport)); - if (conf_set (af, lname, "Port", tmbuf, 0, 0)) - { - conf_end (af, 0); - goto fail; + default: + LOG_DBG((LOG_SYSDEP, 20, + "pf_key_v2_acquire: invalid destination ID type %d", + dstident->sadb_ident_type)); + goto fail; } - } - } - } - else - pf_key_v2_conf_refinc (af, lname); - - /* Set Remote-ID section. */ - snprintf (dname, sizeof dname, "Phase2-ID:%s/%s/%u/%u", sdflow, sdmask, - tproto, dport); - if (conf_set (af, conn, "Remote-ID", dname, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (!conf_get_str (dname, "ID-type")) - { - if (conf_set (af, dname, "Refcount", "1", 0, 0)) - { - conf_end (af, 0); - goto fail; - } - if (dhostflag) - { - if (conf_set (af, dname, "ID-type", didtype, 0, 0) - || conf_set (af, dname, "Address", sdflow, 0, 0)) - { - conf_end (af, 0); - goto fail; - } + LOG_DBG((LOG_SYSDEP, 50, + "pf_key_v2_acquire: constructed destination ID \"%s\"", + dstid)); } - else - { - if (conf_set (af, dname, "ID-type", didtype, 0, 0) - || conf_set (af, dname, "Network", sdflow, 0, 0) - || conf_set (af, dname, "Netmask", sdmask, 0, 0)) - { - conf_end (af, 0); - goto fail; - } + /* Now we've placed the necessary IDs in the configuration space. */ + + /* Get a new connection sequence number. */ + for (;; connection_seq++) { + snprintf(conn, connlen, "Connection-%u", connection_seq); + snprintf(configname, sizeof configname, "Config-Phase2-%u", + connection_seq); + + /* Does it exist ? */ + if (!conf_get_str(conn, "Phase") + && !conf_get_str(configname, "Suites")) + break; } - if (tproto) - { - snprintf (tmbuf, sizeof dport * 3 + 1, "%u", tproto); - if (conf_set (af, dname, "Protocol", tmbuf, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (dport) - { - snprintf (tmbuf, sizeof dport * 3 + 1, "%u", ntohs (dport)); - if (conf_set (af, dname, "Port", tmbuf, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - } + /* + * Set the IPsec connection entry. In particular, the following fields: + * - Phase + * - ISAKMP-peer + * - Local-ID/Remote-ID (if provided) + * - Acquire-ID (sequence number of kernel message, e.g., PF_KEYv2) + * - Configuration + * + * Also set the following section: + * [Peer-dstaddr(/srcaddr)(-srcid)(/dstid)] + * with these fields: + * - Phase + * - ID (if provided) + * - Remote-ID (if provided) + * - Local-address (if provided) + * - Address + * - Configuration (if an entry "ISAKMP-configuration-dstaddr(/srcaddr)" + * exists -- otherwise use the defaults) + */ + + slen = strlen(dstbuf) + strlen(srcbuf) + (srcid ? strlen(srcid) : 0) + + (dstid ? strlen(dstid) : 0) + sizeof "Peer-/-/"; + peer = malloc(slen); + if (!peer) + goto fail; + + /* + * The various cases: + * - Peer-dstaddr + * - Peer-dstaddr/srcaddr + * - Peer-dstaddr/srcaddr-srcid + * - Peer-dstaddr/srcaddr-srcid/dstid + * - Peer-dstaddr/srcaddr-/dstid + * - Peer-dstaddr-srcid/dstid + * - Peer-dstaddr-/dstid + * - Peer-dstaddr-srcid + */ + snprintf(peer, slen, "Peer-%s%s%s%s%s%s%s", dstbuf, srcaddr ? "/" : "", + srcaddr ? srcbuf : "", srcid ? "-" : "", srcid ? srcid : "", + dstid ? (srcid ? "/" : "-/") : "", dstid ? dstid : ""); + + /* + * Set the IPsec connection section. Refcount is set to 2, because + * it will be linked both to the incoming and the outgoing SA. + */ + af = conf_begin(); + if (conf_set(af, conn, "Phase", "2", 0, 0) + || conf_set(af, conn, "Flags", "__ondemand", 0, 0) + || conf_set(af, conn, "Refcount", "2", 0, 0) + || conf_set(af, conn, "ISAKMP-peer", peer, 0, 0)) { + conf_end(af, 0); + goto fail; } - } - else - pf_key_v2_conf_refinc (af, dname); - - /* - * XXX - * We should be using information from the proposal to set this up. - * At least, we should make this selectable. - */ - - /* Phase 2 configuration. */ - if (conf_set (af, conn, "Configuration", configname, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (conf_set (af, configname, "Exchange_type", "Quick_mode", 0, 0) - || conf_set (af, configname, "DOI", "IPSEC", 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (conf_get_str ("General", "Default-phase-2-suites")) - { - if (conf_set (af, configname, "Suites", - conf_get_str ("General", "Default-phase-2-suites"), 0, 0)) - { - conf_end (af, 0); - goto fail; + /* Set the sequence number. */ + snprintf(lname, sizeof lname, "%u", msg->sadb_msg_seq); + if (conf_set(af, conn, "Acquire-ID", lname, 0, 0)) { + conf_end(af, 0); + goto fail; } - } - else - { - if (conf_set (af, configname, "Suites", - "QM-ESP-3DES-SHA-PFS-SUITE", 0, 0)) - { - conf_end (af, 0); - goto fail; + /* Set Phase 2 IDs -- this is the Local-ID section. */ + snprintf(lname, sizeof lname, "Phase2-ID:%s/%s/%u/%u", ssflow, ssmask, + tproto, sport); + if (conf_set(af, conn, "Local-ID", lname, 0, 0)) { + conf_end(af, 0); + goto fail; } - } - - /* Set the ISAKMP-peer section. */ - if (!conf_get_str (peer, "Phase")) - { - if (conf_set (af, peer, "Phase", "1", 0, 0) - || conf_set (af, peer, "Refcount", "1", 0, 0) - || conf_set (af, peer, "Address", dstbuf, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (srcaddr && conf_set (af, peer, "Local-address", srcbuf, 0, 0)) - { - conf_end (af, 0); - goto fail; + if (!conf_get_str(lname, "ID-type")) { + if (conf_set(af, lname, "Refcount", "1", 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (shostflag) { + if (conf_set(af, lname, "ID-type", sidtype, 0, 0) + || conf_set(af, lname, "Address", ssflow, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } else { + if (conf_set(af, lname, "ID-type", sidtype, 0, 0) + || conf_set(af, lname, "Network", ssflow, 0, 0) + || conf_set(af, lname, "Netmask", ssmask, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } + if (tproto) { + snprintf(tmbuf, sizeof sport * 3 + 1, "%u", tproto); + if (conf_set(af, lname, "Protocol", tmbuf, 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (sport) { + snprintf(tmbuf, sizeof sport * 3 + 1, "%u", ntohs(sport)); + if (conf_set(af, lname, "Port", tmbuf, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } + } + } else + pf_key_v2_conf_refinc(af, lname); + + /* Set Remote-ID section. */ + snprintf(dname, sizeof dname, "Phase2-ID:%s/%s/%u/%u", sdflow, sdmask, + tproto, dport); + if (conf_set(af, conn, "Remote-ID", dname, 0, 0)) { + conf_end(af, 0); + goto fail; } + if (!conf_get_str(dname, "ID-type")) { + if (conf_set(af, dname, "Refcount", "1", 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (dhostflag) { + if (conf_set(af, dname, "ID-type", didtype, 0, 0) + || conf_set(af, dname, "Address", sdflow, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } else { + if (conf_set(af, dname, "ID-type", didtype, 0, 0) + || conf_set(af, dname, "Network", sdflow, 0, 0) + || conf_set(af, dname, "Netmask", sdmask, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } - snprintf (confname, sizeof confname, "ISAKMP-Configuration-%s", peer); - if (conf_set (af, peer, "Configuration", confname, 0, 0)) - { - conf_end (af, 0); - goto fail; + if (tproto) { + snprintf(tmbuf, sizeof dport * 3 + 1, "%u", tproto); + if (conf_set(af, dname, "Protocol", tmbuf, 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (dport) { + snprintf(tmbuf, sizeof dport * 3 + 1, "%u", ntohs(dport)); + if (conf_set(af, dname, "Port", tmbuf, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } + } + } else + pf_key_v2_conf_refinc(af, dname); + + /* + * XXX + * We should be using information from the proposal to set this up. + * At least, we should make this selectable. + */ + + /* Phase 2 configuration. */ + if (conf_set(af, conn, "Configuration", configname, 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (conf_set(af, configname, "Exchange_type", "Quick_mode", 0, 0) + || conf_set(af, configname, "DOI", "IPSEC", 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (conf_get_str("General", "Default-phase-2-suites")) { + if (conf_set(af, configname, "Suites", + conf_get_str("General", "Default-phase-2-suites"), 0, 0)) { + conf_end(af, 0); + goto fail; + } + } else { + if (conf_set(af, configname, "Suites", + "QM-ESP-3DES-SHA-PFS-SUITE", 0, 0)) { + conf_end(af, 0); + goto fail; + } } + /* Set the ISAKMP-peer section. */ + if (!conf_get_str(peer, "Phase")) { + if (conf_set(af, peer, "Phase", "1", 0, 0) + || conf_set(af, peer, "Refcount", "1", 0, 0) + || conf_set(af, peer, "Address", dstbuf, 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (srcaddr && conf_set(af, peer, "Local-address", srcbuf, 0, 0)) { + conf_end(af, 0); + goto fail; + } + snprintf(confname, sizeof confname, "ISAKMP-Configuration-%s", peer); + if (conf_set(af, peer, "Configuration", confname, 0, 0)) { + conf_end(af, 0); + goto fail; + } #if defined (SADB_X_CREDTYPE_NONE) - /* Store any credentials passed to us. */ - if (cred) - { - struct cert_handler *handler = 0; - void *cert; - char num[12], *certprint; - - /* Convert to bytes in-place. */ - cred->sadb_x_cred_len *= PF_KEY_V2_CHUNK; - - if (cred->sadb_x_cred_len <= sizeof *cred) - { - log_print ("pf_key_v2_acquire: zero-length credentials, " - "aborting SA acquisition"); - conf_end (af, 0); - goto fail; - } - - switch (cred->sadb_x_cred_type) - { - case SADB_X_CREDTYPE_X509: - snprintf (num, sizeof num, "%d", ISAKMP_CERTENC_X509_SIG); - handler = cert_get (ISAKMP_CERTENC_X509_SIG); - break; - case SADB_X_CREDTYPE_KEYNOTE: - snprintf (num, sizeof num, "%d", ISAKMP_CERTENC_KEYNOTE); - handler = cert_get (ISAKMP_CERTENC_KEYNOTE); - break; - default: - log_print ("pf_key_v2_acquire: unknown credential type %d", - cred->sadb_x_cred_type); - conf_end (af, 0); - goto fail; - } - - if (!handler) - { - log_print ("pf_key_v2_acquire: cert_get (%s) failed", num); - conf_end (af, 0); - goto fail; - } - - /* Set the credential type as a number. */ - if (conf_set (af, peer, "Credential_type", num, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - /* Get the certificate. */ - cert = handler->cert_get ((u_int8_t *)(cred + 1), - cred->sadb_x_cred_len - sizeof *cred); - - /* Now convert to printable format. */ - certprint = handler->cert_printable (cert); - handler->cert_free (cert); - if (!certprint - || conf_set (af, peer, "Credentials", certprint, 0, 0)) - { - if (certprint) - free (certprint); - conf_end (af, 0); - goto fail; - } - free (certprint); - } -#endif /* SADB_X_CREDTYPE_NONE */ + /* Store any credentials passed to us. */ + if (cred) { + struct cert_handler *handler = 0; + void *cert; + char num[12], *certprint; + + /* Convert to bytes in-place. */ + cred->sadb_x_cred_len *= PF_KEY_V2_CHUNK; + + if (cred->sadb_x_cred_len <= sizeof *cred) { + log_print("pf_key_v2_acquire: zero-length credentials, " + "aborting SA acquisition"); + conf_end(af, 0); + goto fail; + } + switch (cred->sadb_x_cred_type) { + case SADB_X_CREDTYPE_X509: + snprintf(num, sizeof num, "%d", ISAKMP_CERTENC_X509_SIG); + handler = cert_get(ISAKMP_CERTENC_X509_SIG); + break; + case SADB_X_CREDTYPE_KEYNOTE: + snprintf(num, sizeof num, "%d", ISAKMP_CERTENC_KEYNOTE); + handler = cert_get(ISAKMP_CERTENC_KEYNOTE); + break; + default: + log_print("pf_key_v2_acquire: unknown credential type %d", + cred->sadb_x_cred_type); + conf_end(af, 0); + goto fail; + } + + if (!handler) { + log_print("pf_key_v2_acquire: cert_get (%s) failed", num); + conf_end(af, 0); + goto fail; + } + /* Set the credential type as a number. */ + if (conf_set(af, peer, "Credential_type", num, 0, 0)) { + conf_end(af, 0); + goto fail; + } + /* Get the certificate. */ + cert = handler->cert_get((u_int8_t *) (cred + 1), + cred->sadb_x_cred_len - sizeof *cred); + + /* Now convert to printable format. */ + certprint = handler->cert_printable(cert); + handler->cert_free(cert); + if (!certprint + || conf_set(af, peer, "Credentials", certprint, 0, 0)) { + if (certprint) + free(certprint); + conf_end(af, 0); + goto fail; + } + free(certprint); + } +#endif /* SADB_X_CREDTYPE_NONE */ - /* Phase 1 configuration. */ - if (!conf_get_str (confname, "exchange_type")) - { + /* Phase 1 configuration. */ + if (!conf_get_str(confname, "exchange_type")) { #if defined (SADB_X_EXT_LOCAL_AUTH) - /* We may have been provided with authentication material. */ - if (sauth) - { - char *authm; - - /* Convert to bytes in-place. */ - sauth->sadb_x_cred_len *= PF_KEY_V2_CHUNK; - - switch (sauth->sadb_x_cred_type) - { - case SADB_X_AUTHTYPE_PASSPHRASE: - if (conf_set (af, confname, "Transforms", "3DES-SHA", 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (sauth->sadb_x_cred_len <= sizeof *sauth) - { - log_print ("pf_key_v2_acquire: zero-length passphrase, " - "aborting SA acquisition"); - conf_end (af, 0); - goto fail; - } - - authm = malloc (sauth->sadb_x_cred_len - sizeof *sauth + 1); - if (!authm) - { - log_error ("pf_key_v2_acquire: malloc (%lu) failed", - sauth->sadb_x_cred_len - - (unsigned long)sizeof *sauth + 1); - conf_end (af, 0); - goto fail; - } - memcpy (authm, sauth + 1, - sauth->sadb_x_cred_len - sizeof *sauth + 1); - - /* Set the passphrase in the peer. */ - if (conf_set (af, peer, "Authentication", authm, 0, 0)) - { - free (authm); - conf_end (af, 0); - goto fail; - } - free (authm); - break; - - case SADB_X_AUTHTYPE_RSA: - if (conf_set (af, confname, "Transforms", "3DES-SHA-RSA_SIG", - 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - if (sauth->sadb_x_cred_len <= sizeof *sauth) - { - log_print ("pf_key_v2_acquire: zero-length RSA key, " - "aborting SA acquisition"); - conf_end (af, 0); - goto fail; - } - - authm = key_printable (ISAKMP_KEY_RSA, - ISAKMP_KEYTYPE_PRIVATE, - (u_int8_t *) sauth + 1, - sauth->sadb_x_cred_len - - sizeof *sauth); - if (!authm) - { - log_print ("pf_key_v2_acquire: failed to convert " - "private key to printable format (size %lu)", - sauth->sadb_x_cred_len - - (unsigned long)sizeof *sauth); - conf_end (af, 0); - goto fail; - } - - /* - * Set the key in the peer. We don't use "Authentication" - * to avoid potential conflicts with file-based - * configurations that use public key authentication - * but still specify an "Authentication" tag (typically - * as a remnant of passphrase-based testing). - */ - if (conf_set (af, peer, "PKAuthentication", authm, 0, 0)) - { - free (authm); - conf_end (af, 0); - goto fail; - } - free (authm); - break; - - default: - log_print ("pf_key_v2_acquire: unknown authentication " - "material type %d received from kernel", - sauth->sadb_x_cred_type); - conf_end (af, 0); - goto fail; + /* + * We may have been provided with authentication + * material. + */ + if (sauth) { + char *authm; + + /* Convert to bytes in-place. */ + sauth->sadb_x_cred_len *= PF_KEY_V2_CHUNK; + + switch (sauth->sadb_x_cred_type) { + case SADB_X_AUTHTYPE_PASSPHRASE: + if (conf_set(af, confname, "Transforms", "3DES-SHA", 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (sauth->sadb_x_cred_len <= sizeof *sauth) { + log_print("pf_key_v2_acquire: zero-length passphrase, " + "aborting SA acquisition"); + conf_end(af, 0); + goto fail; + } + authm = malloc(sauth->sadb_x_cred_len - sizeof *sauth + 1); + if (!authm) { + log_error("pf_key_v2_acquire: malloc (%lu) failed", + sauth->sadb_x_cred_len - + (unsigned long) sizeof *sauth + 1); + conf_end(af, 0); + goto fail; + } + memcpy(authm, sauth + 1, + sauth->sadb_x_cred_len - sizeof *sauth + 1); + + /* Set the passphrase in the peer. */ + if (conf_set(af, peer, "Authentication", authm, 0, 0)) { + free(authm); + conf_end(af, 0); + goto fail; + } + free(authm); + break; + + case SADB_X_AUTHTYPE_RSA: + if (conf_set(af, confname, "Transforms", "3DES-SHA-RSA_SIG", + 0, 0)) { + conf_end(af, 0); + goto fail; + } + if (sauth->sadb_x_cred_len <= sizeof *sauth) { + log_print("pf_key_v2_acquire: zero-length RSA key, " + "aborting SA acquisition"); + conf_end(af, 0); + goto fail; + } + authm = key_printable(ISAKMP_KEY_RSA, + ISAKMP_KEYTYPE_PRIVATE, + (u_int8_t *) sauth + 1, + sauth->sadb_x_cred_len + - sizeof *sauth); + if (!authm) { + log_print("pf_key_v2_acquire: failed to convert " + "private key to printable format (size %lu)", + sauth->sadb_x_cred_len - + (unsigned long) sizeof *sauth); + conf_end(af, 0); + goto fail; + } + /* + * Set the key in the peer. We don't use "Authentication" + * to avoid potential conflicts with file-based + * configurations that use public key authentication + * but still specify an "Authentication" tag (typically + * as a remnant of passphrase-based testing). + */ + if (conf_set(af, peer, "PKAuthentication", authm, 0, 0)) { + free(authm); + conf_end(af, 0); + goto fail; + } + free(authm); + break; + + default: + log_print("pf_key_v2_acquire: unknown authentication " + "material type %d received from kernel", + sauth->sadb_x_cred_type); + conf_end(af, 0); + goto fail; + } + } else /* Fall through */ +#endif /* SADB_X_EXT_LOCAL_AUTH */ + { + xform = conf_get_str("Default-phase-1-configuration", + "Transforms"); + if (conf_set(af, confname, "Transforms", + xform ? xform : "3DES-SHA-RSA_SIG", 0, 0)) { + conf_end(af, 0); + goto fail; + } + } + + if (conf_set(af, confname, "Exchange_Type", "ID_PROT", 0, 0) + || conf_set(af, confname, "DOI", "IPSEC", 0, 0) + || conf_set(af, confname, "Refcount", "1", 0, 0)) { + conf_end(af, 0); + goto fail; + } + } else + pf_key_v2_conf_refinc(af, confname); + + /* The ID we should use in Phase 1. */ + if (srcid && conf_set(af, peer, "ID", srcid, 0, 0)) { + conf_end(af, 0); + goto fail; } - } - else /* Fall through */ -#endif /* SADB_X_EXT_LOCAL_AUTH */ - { - xform = conf_get_str ("Default-phase-1-configuration", - "Transforms"); - if (conf_set (af, confname, "Transforms", - xform ? xform : "3DES-SHA-RSA_SIG", 0, 0)) - { - conf_end (af, 0); - goto fail; - } - } - - if (conf_set (af, confname, "Exchange_Type", "ID_PROT", 0, 0) - || conf_set (af, confname, "DOI", "IPSEC", 0, 0) - || conf_set (af, confname, "Refcount", "1", 0, 0)) - { - conf_end (af, 0); - goto fail; - } - } - else - pf_key_v2_conf_refinc (af, confname); - - /* The ID we should use in Phase 1. */ - if (srcid && conf_set (af, peer, "ID", srcid, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - - /* The ID the other side should use in Phase 1. */ - if (dstid && conf_set (af, peer, "Remote-ID", dstid, 0, 0)) - { - conf_end (af, 0); - goto fail; - } - } - else - pf_key_v2_conf_refinc (af, peer); - - /* All done. */ - conf_end (af, 1); - - /* Let's rock 'n roll. */ - pf_key_v2_connection_check (conn); - conn = 0; - - /* Fall-through to cleanup. */ - fail: - if (ret) - pf_key_v2_msg_free (ret); - if (askpolicy) - pf_key_v2_msg_free (askpolicy); - if (srcid) - free (srcid); - if (dstid) - free (dstid); - if (peer) - free (peer); - if (conn) - free (conn); - return; + /* The ID the other side should use in Phase 1. */ + if (dstid && conf_set(af, peer, "Remote-ID", dstid, 0, 0)) { + conf_end(af, 0); + goto fail; + } + } else + pf_key_v2_conf_refinc(af, peer); + + /* All done. */ + conf_end(af, 1); + + /* Let's rock 'n roll. */ + pf_key_v2_connection_check(conn); + conn = 0; + + /* Fall-through to cleanup. */ +fail: + if (ret) + pf_key_v2_msg_free(ret); + if (askpolicy) + pf_key_v2_msg_free(askpolicy); + if (srcid) + free(srcid); + if (dstid) + free(dstid); + if (peer) + free(peer); + if (conn) + free(conn); + return; #else - /* acquire not supported */ - return; -#endif /* SADB_X_ASKPOLICY */ + /* acquire not supported */ + return; +#endif /* SADB_X_ASKPOLICY */ } static void -pf_key_v2_notify (struct pf_key_v2_msg *msg) +pf_key_v2_notify(struct pf_key_v2_msg * msg) { - switch (((struct sadb_msg *)TAILQ_FIRST (msg)->seg)->sadb_msg_type) - { - case SADB_EXPIRE: - pf_key_v2_expire (msg); - break; - - case SADB_ACQUIRE: - pf_key_v2_acquire (msg); - break; - - default: - log_print ("pf_key_v2_notify: unexpected message type (%d)", - ((struct sadb_msg *)TAILQ_FIRST (msg)->seg)->sadb_msg_type); - } - pf_key_v2_msg_free (msg); + switch (((struct sadb_msg *) TAILQ_FIRST(msg)->seg)->sadb_msg_type) { + case SADB_EXPIRE: + pf_key_v2_expire(msg); + break; + + case SADB_ACQUIRE: + pf_key_v2_acquire(msg); + break; + + default: + log_print("pf_key_v2_notify: unexpected message type (%d)", + ((struct sadb_msg *) TAILQ_FIRST(msg)->seg)->sadb_msg_type); + } + pf_key_v2_msg_free(msg); } void -pf_key_v2_handler (int fd) +pf_key_v2_handler(int fd) { - struct pf_key_v2_msg *msg; + struct pf_key_v2_msg *msg; #if !defined (LINUX_IPSEC) - int n; - - /* - * As synchronous read/writes to the socket can have taken place between - * the select(2) call of the main loop and this handler, we need to recheck - * the readability. - */ - if (ioctl (pf_key_v2_socket, FIONREAD, &n) == -1) - { - log_error ("pf_key_v2_handler: ioctl (%d, FIONREAD, &n) failed", - pf_key_v2_socket); - return; - } - if (!n) - return; -#endif /* LINUX_IPSEC */ - - msg = pf_key_v2_read (0); - if (msg) - pf_key_v2_notify (msg); + int n; + + /* + * As synchronous read/writes to the socket can have taken place between + * the select(2) call of the main loop and this handler, we need to recheck + * the readability. + */ + if (ioctl(pf_key_v2_socket, FIONREAD, &n) == -1) { + log_error("pf_key_v2_handler: ioctl (%d, FIONREAD, &n) failed", + pf_key_v2_socket); + return; + } + if (!n) + return; +#endif /* LINUX_IPSEC */ + + msg = pf_key_v2_read(0); + if (msg) + pf_key_v2_notify(msg); } /* @@ -4150,171 +3880,168 @@ pf_key_v2_handler (int fd) * XXX Assumes OpenBSD GRPSPIS extension. Should probably be moved to sysdep.c */ int -pf_key_v2_group_spis (struct sa *sa, struct proto *proto1, - struct proto *proto2, int incoming) +pf_key_v2_group_spis(struct sa * sa, struct proto * proto1, + struct proto * proto2, int incoming) { #if defined (SADB_X_GRPSPIS) - struct sadb_msg msg; - struct sadb_sa sa1, sa2; - struct sadb_address *addr = 0; - struct sadb_protocol protocol; - struct pf_key_v2_msg *grpspis = 0, *ret = 0; - struct sockaddr *saddr; - int err; - size_t len; + struct sadb_msg msg; + struct sadb_sa sa1, sa2; + struct sadb_address *addr = 0; + struct sadb_protocol protocol; + struct pf_key_v2_msg *grpspis = 0, *ret = 0; + struct sockaddr *saddr; + int err; + size_t len; #ifdef KAME - struct sadb_x_sa2 kamesa2; + struct sadb_x_sa2 kamesa2; #endif - msg.sadb_msg_type = SADB_X_GRPSPIS; - switch (proto1->proto) - { - case IPSEC_PROTO_IPSEC_ESP: - msg.sadb_msg_satype = SADB_SATYPE_ESP; - break; - case IPSEC_PROTO_IPSEC_AH: - msg.sadb_msg_satype = SADB_SATYPE_AH; - break; + msg.sadb_msg_type = SADB_X_GRPSPIS; + switch (proto1->proto) { + case IPSEC_PROTO_IPSEC_ESP: + msg.sadb_msg_satype = SADB_SATYPE_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + msg.sadb_msg_satype = SADB_SATYPE_AH; + break; #if defined (SADB_X_SATYPE_IPCOMP) - case IPSEC_PROTO_IPCOMP: - msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; - break; + case IPSEC_PROTO_IPCOMP: + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + break; #endif - default: - log_print ("pf_key_v2_group_spis: invalid proto %d", proto1->proto); - goto cleanup; - } - msg.sadb_msg_seq = 0; - grpspis = pf_key_v2_msg_new (&msg, 0); - if (!grpspis) - goto cleanup; - - /* Setup the SA extensions. */ - sa1.sadb_sa_exttype = SADB_EXT_SA; - sa1.sadb_sa_len = sizeof sa1 / PF_KEY_V2_CHUNK; - memcpy (&sa1.sadb_sa_spi, proto1->spi[incoming], sizeof sa1.sadb_sa_spi); - sa1.sadb_sa_replay = 0; - sa1.sadb_sa_state = 0; - sa1.sadb_sa_auth = 0; - sa1.sadb_sa_encrypt = 0; - sa1.sadb_sa_flags = 0; - if (pf_key_v2_msg_add (grpspis, (struct sadb_ext *)&sa1, 0) == -1) - goto cleanup; + default: + log_print("pf_key_v2_group_spis: invalid proto %d", proto1->proto); + goto cleanup; + } + msg.sadb_msg_seq = 0; + grpspis = pf_key_v2_msg_new(&msg, 0); + if (!grpspis) + goto cleanup; + + /* Setup the SA extensions. */ + sa1.sadb_sa_exttype = SADB_EXT_SA; + sa1.sadb_sa_len = sizeof sa1 / PF_KEY_V2_CHUNK; + memcpy(&sa1.sadb_sa_spi, proto1->spi[incoming], sizeof sa1.sadb_sa_spi); + sa1.sadb_sa_replay = 0; + sa1.sadb_sa_state = 0; + sa1.sadb_sa_auth = 0; + sa1.sadb_sa_encrypt = 0; + sa1.sadb_sa_flags = 0; + if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) & sa1, 0) == -1) + goto cleanup; #ifndef KAME - sa2.sadb_sa_exttype = SADB_X_EXT_SA2; - sa2.sadb_sa_len = sizeof sa2 / PF_KEY_V2_CHUNK; - memcpy (&sa2.sadb_sa_spi, proto2->spi[incoming], sizeof sa2.sadb_sa_spi); - sa2.sadb_sa_replay = 0; - sa2.sadb_sa_state = 0; - sa2.sadb_sa_auth = 0; - sa2.sadb_sa_encrypt = 0; - sa2.sadb_sa_flags = 0; - if (pf_key_v2_msg_add (grpspis, (struct sadb_ext *)&sa2, 0) == -1) - goto cleanup; + sa2.sadb_sa_exttype = SADB_X_EXT_SA2; + sa2.sadb_sa_len = sizeof sa2 / PF_KEY_V2_CHUNK; + memcpy(&sa2.sadb_sa_spi, proto2->spi[incoming], sizeof sa2.sadb_sa_spi); + sa2.sadb_sa_replay = 0; + sa2.sadb_sa_state = 0; + sa2.sadb_sa_auth = 0; + sa2.sadb_sa_encrypt = 0; + sa2.sadb_sa_flags = 0; + if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) & sa2, 0) == -1) + goto cleanup; #else - memset (&kamesa2, 0, sizeof kamesa2); - kamesa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - kamesa2.sadb_x_sa2_len = sizeof kamesa2 / PF_KEY_V2_CHUNK; - kamesa2.sadb_x_sa2_mode = 0; - if (pf_key_v2_msg_add (grpspis, (struct sadb_ext *)&kamesa2, 0) == -1) - goto cleanup; + memset(&kamesa2, 0, sizeof kamesa2); + kamesa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + kamesa2.sadb_x_sa2_len = sizeof kamesa2 / PF_KEY_V2_CHUNK; + kamesa2.sadb_x_sa2_mode = 0; + if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) & kamesa2, 0) == -1) + goto cleanup; #endif - /* - * Setup the ADDRESS extensions. - */ - if (incoming) - sa->transport->vtbl->get_src (sa->transport, &saddr); - else - sa->transport->vtbl->get_dst (sa->transport, &saddr); - len = sizeof *addr + PF_KEY_V2_ROUND (sysdep_sa_len (saddr)); - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + /* + * Setup the ADDRESS extensions. + */ + if (incoming) + sa->transport->vtbl->get_src(sa->transport, &saddr); + else + sa->transport->vtbl->get_dst(sa->transport, &saddr); + len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(saddr)); + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, saddr, sysdep_sa_len (saddr)); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - if (pf_key_v2_msg_add (grpspis, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - addr = calloc (1, len); - if (!addr) - goto cleanup; - addr->sadb_address_exttype = SADB_X_EXT_DST2; - addr->sadb_address_len = len / PF_KEY_V2_CHUNK; + addr->sadb_address_reserved = 0; + memcpy(addr + 1, saddr, sysdep_sa_len(saddr)); + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + addr = calloc(1, len); + if (!addr) + goto cleanup; + addr->sadb_address_exttype = SADB_X_EXT_DST2; + addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ - addr->sadb_address_proto = 0; - addr->sadb_address_prefixlen = 0; + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; #endif - addr->sadb_address_reserved = 0; - memcpy (addr + 1, saddr, sysdep_sa_len (saddr)); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; - if (pf_key_v2_msg_add (grpspis, (struct sadb_ext *)addr, - PF_KEY_V2_NODE_MALLOCED) == -1) - goto cleanup; - addr = 0; - - /* Setup the PROTOCOL extension. */ - protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; - protocol.sadb_protocol_len = sizeof protocol / PF_KEY_V2_CHUNK; - switch (proto2->proto) - { - case IPSEC_PROTO_IPSEC_ESP: - protocol.sadb_protocol_proto = SADB_SATYPE_ESP; - break; - case IPSEC_PROTO_IPSEC_AH: - protocol.sadb_protocol_proto = SADB_SATYPE_AH; - break; + addr->sadb_address_reserved = 0; + memcpy(addr + 1, saddr, sysdep_sa_len(saddr)); + ((struct sockaddr_in *) (addr + 1))->sin_port = 0; + if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + /* Setup the PROTOCOL extension. */ + protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; + protocol.sadb_protocol_len = sizeof protocol / PF_KEY_V2_CHUNK; + switch (proto2->proto) { + case IPSEC_PROTO_IPSEC_ESP: + protocol.sadb_protocol_proto = SADB_SATYPE_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + protocol.sadb_protocol_proto = SADB_SATYPE_AH; + break; #if defined (SADB_X_SATYPE_IPCOMP) - case IPSEC_PROTO_IPCOMP: - protocol.sadb_protocol_proto = SADB_X_SATYPE_IPCOMP; - break; + case IPSEC_PROTO_IPCOMP: + protocol.sadb_protocol_proto = SADB_X_SATYPE_IPCOMP; + break; #endif - default: - log_print ("pf_key_v2_group_spis: invalid proto %d", proto2->proto); - goto cleanup; - } - protocol.sadb_protocol_reserved2 = 0; - if (pf_key_v2_msg_add (grpspis, (struct sadb_ext *)&protocol, 0) == -1) - goto cleanup; - - ret = pf_key_v2_call (grpspis); - pf_key_v2_msg_free (grpspis); - grpspis = 0; - if (!ret) - goto cleanup; - err = ((struct sadb_msg *)TAILQ_FIRST (ret)->seg)->sadb_msg_errno; - if (err) - { - log_print ("pf_key_v2_group_spis: GRPSPIS: %s", strerror (err)); - goto cleanup; - } - pf_key_v2_msg_free (ret); - - LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_group_spis: done")); - - return 0; - - cleanup: - if (addr) - free (addr); - if (grpspis) - pf_key_v2_msg_free (grpspis); - if (ret) - pf_key_v2_msg_free (ret); - return -1; - -#else /* SADB_X_GRPSPIS */ - log_print ("pf_key_v2_group_spis: not supported in pure PF_KEYv2"); - return -1; + default: + log_print("pf_key_v2_group_spis: invalid proto %d", proto2->proto); + goto cleanup; + } + protocol.sadb_protocol_reserved2 = 0; + if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) & protocol, 0) == -1) + goto cleanup; + + ret = pf_key_v2_call(grpspis); + pf_key_v2_msg_free(grpspis); + grpspis = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *) TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + log_print("pf_key_v2_group_spis: GRPSPIS: %s", strerror(err)); + goto cleanup; + } + pf_key_v2_msg_free(ret); + + LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_group_spis: done")); + + return 0; + +cleanup: + if (addr) + free(addr); + if (grpspis) + pf_key_v2_msg_free(grpspis); + if (ret) + pf_key_v2_msg_free(ret); + return -1; + +#else /* SADB_X_GRPSPIS */ + log_print("pf_key_v2_group_spis: not supported in pure PF_KEYv2"); + return -1; #endif } diff --git a/sbin/isakmpd/pf_key_v2.h b/sbin/isakmpd/pf_key_v2.h index 4236420159f..f3abff45963 100644 --- a/sbin/isakmpd/pf_key_v2.h +++ b/sbin/isakmpd/pf_key_v2.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pf_key_v2.h,v 1.8 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: pf_key_v2.h,v 1.4 2000/12/04 04:46:35 angelos Exp $ */ +/* $OpenBSD: pf_key_v2.h,v 1.9 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: pf_key_v2.h,v 1.4 2000/12/04 04:46:35 angelos Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -39,17 +39,20 @@ struct proto; struct sa; struct sockaddr; -extern void pf_key_v2_connection_check (char *); -extern int pf_key_v2_delete_spi (struct sa *, struct proto *, int); -extern int pf_key_v2_enable_sa (struct sa *, struct sa *); -extern int pf_key_v2_enable_spi (in_addr_t, in_addr_t, in_addr_t, in_addr_t, - u_int8_t *, u_int8_t, in_addr_t); -extern u_int8_t *pf_key_v2_get_spi (size_t *, u_int8_t, struct sockaddr *, - struct sockaddr *, u_int32_t); -extern int pf_key_v2_group_spis (struct sa *, struct proto *, struct proto *, - int); -extern void pf_key_v2_handler (int); -extern int pf_key_v2_open (void); -extern int pf_key_v2_set_spi (struct sa *, struct proto *, int, struct sa *); +extern void pf_key_v2_connection_check(char *); +extern int pf_key_v2_delete_spi(struct sa *, struct proto *, int); +extern int pf_key_v2_enable_sa(struct sa *, struct sa *); +extern int +pf_key_v2_enable_spi(in_addr_t, in_addr_t, in_addr_t, in_addr_t, + u_int8_t *, u_int8_t, in_addr_t); +extern u_int8_t * +pf_key_v2_get_spi(size_t *, u_int8_t, struct sockaddr *, + struct sockaddr *, u_int32_t); +extern int +pf_key_v2_group_spis(struct sa *, struct proto *, struct proto *, + int); +extern void pf_key_v2_handler(int); +extern int pf_key_v2_open(void); +extern int pf_key_v2_set_spi(struct sa *, struct proto *, int, struct sa *); -#endif /* _PF_KEY_V2_H_ */ +#endif /* _PF_KEY_V2_H_ */ diff --git a/sbin/isakmpd/policy.c b/sbin/isakmpd/policy.c index 2b7ab8e7042..d6ea76eefff 100644 --- a/sbin/isakmpd/policy.c +++ b/sbin/isakmpd/policy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: policy.c,v 1.69 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */ +/* $OpenBSD: policy.c,v 1.70 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved. @@ -66,1861 +66,1773 @@ #include "policy.h" #include "x509.h" -char **keynote_policy_asserts = NULL; -int keynote_policy_asserts_num = 0; +char **keynote_policy_asserts = NULL; +int keynote_policy_asserts_num = 0; struct exchange *policy_exchange = 0; -struct sa *policy_sa = 0; -struct sa *policy_isakmp_sa = 0; +struct sa *policy_sa = 0; +struct sa *policy_isakmp_sa = 0; static const char hextab[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /* * Adaptation of Vixie's inet_ntop4 () */ static const char * -my_inet_ntop4 (const in_addr_t *src, char *dst, size_t size, int normalize) +my_inet_ntop4(const in_addr_t * src, char *dst, size_t size, int normalize) { - static const char fmt[] = "%03u.%03u.%03u.%03u"; - char tmp[sizeof "255.255.255.255"]; - in_addr_t src2; - - if (normalize) - src2 = ntohl (*src); - else - src2 = *src; - - if (snprintf (tmp, sizeof tmp, fmt, ((u_int8_t *) &src2)[0], - ((u_int8_t *) &src2)[1], ((u_int8_t *) &src2)[2], - ((u_int8_t *) &src2)[3]) > (int)size) - { - errno = ENOSPC; - return 0; - } - strlcpy (dst, tmp, size); - return dst; + static const char fmt[] = "%03u.%03u.%03u.%03u"; + char tmp[sizeof "255.255.255.255"]; + in_addr_t src2; + + if (normalize) + src2 = ntohl(*src); + else + src2 = *src; + + if (snprintf(tmp, sizeof tmp, fmt, ((u_int8_t *) & src2)[0], + ((u_int8_t *) & src2)[1], ((u_int8_t *) & src2)[2], + ((u_int8_t *) & src2)[3]) > (int) size) { + errno = ENOSPC; + return 0; + } + strlcpy(dst, tmp, size); + return dst; } static const char * -my_inet_ntop6 (const unsigned char *src, char *dst, size_t size) +my_inet_ntop6(const unsigned char *src, char *dst, size_t size) { - static const char fmt[] = "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"; - char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; - - if (snprintf (tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3], src[4], - src[5], src[6], src[7], src[8], src[9], src[10], src[11], - src[12], src[13], src[14], src[15]) > (int)size) - { - errno = ENOSPC; - return 0; - } - strlcpy (dst, tmp, size); - return dst; + static const char fmt[] = + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; + + if (snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3], src[4], + src[5], src[6], src[7], src[8], src[9], src[10], src[11], + src[12], src[13], src[14], src[15]) > (int) size) { + errno = ENOSPC; + return 0; + } + strlcpy(dst, tmp, size); + return dst; } char * -policy_callback (char *name) +policy_callback(char *name) { - struct proto *proto; - - u_int8_t *attr, *value, *id, *idlocal, *idremote; - size_t id_sz, idlocalsz, idremotesz; - struct sockaddr *sin; - struct ipsec_exch *ie; - struct ipsec_sa *is; - size_t i; - int fmt, lifetype = 0; - in_addr_t net, subnet; - u_int16_t len, type; - time_t tt; - char *addr; - static char mytimeofday[15]; - - /* We use all these as a cache. */ + struct proto *proto; + + u_int8_t *attr, *value, *id, *idlocal, *idremote; + size_t id_sz, idlocalsz, idremotesz; + struct sockaddr *sin; + struct ipsec_exch *ie; + struct ipsec_sa *is; + size_t i; + int fmt, lifetype = 0; + in_addr_t net, subnet; + u_int16_t len, type; + time_t tt; + char *addr; + static char mytimeofday[15]; + + /* We use all these as a cache. */ #define PMAX 32 - static char *esp_present, *ah_present, *comp_present; - static char *ah_hash_alg, *ah_auth_alg, *esp_auth_alg, *esp_enc_alg; - static char *comp_alg, ah_life_kbytes[PMAX], ah_life_seconds[PMAX]; - static char esp_life_kbytes[PMAX], esp_life_seconds[PMAX]; - static char comp_life_kbytes[PMAX]; - static char *ah_ecn, *esp_ecn, *comp_ecn; - static char comp_life_seconds[PMAX], *ah_encapsulation, *esp_encapsulation; - static char *comp_encapsulation, ah_key_length[PMAX], esp_key_length[PMAX]; - static char ah_key_rounds[PMAX], esp_key_rounds[PMAX], comp_dict_size[PMAX]; - static char comp_private_alg[PMAX], *remote_filter_type, *local_filter_type; - static char remote_filter_addr_upper[NI_MAXHOST]; - static char remote_filter_addr_lower[NI_MAXHOST]; - static char local_filter_addr_upper[NI_MAXHOST]; - static char local_filter_addr_lower[NI_MAXHOST]; - static char ah_group_desc[PMAX], esp_group_desc[PMAX], comp_group_desc[PMAX]; - static char remote_ike_address[NI_MAXHOST]; - static char local_ike_address[NI_MAXHOST]; - static char *remote_id_type, remote_id_addr_upper[NI_MAXHOST], *phase_1; - static char remote_id_addr_lower[NI_MAXHOST]; - static char *remote_id_proto, remote_id_port[PMAX]; - static char remote_filter_port[PMAX], local_filter_port[PMAX]; - static char *remote_filter_proto, *local_filter_proto, *pfs, *initiator; - static char remote_filter_proto_num[3], local_filter_proto_num[3]; - static char remote_id_proto_num[3]; - static char phase1_group[PMAX]; - - /* Allocated. */ - static char *remote_filter = 0, *local_filter = 0, *remote_id = 0; - - static int dirty = 1; - - /* We only need to set dirty at initialization time really. */ - if (strcmp (name, KEYNOTE_CALLBACK_CLEANUP) == 0 - || strcmp (name, KEYNOTE_CALLBACK_INITIALIZE) == 0) - { - esp_present = ah_present = comp_present = pfs = "no"; - ah_hash_alg = ah_auth_alg = phase_1 = ""; - esp_auth_alg = esp_enc_alg = comp_alg = ah_encapsulation = ""; - ah_ecn = esp_ecn = comp_ecn = "no"; - esp_encapsulation = comp_encapsulation = remote_filter_type = ""; - local_filter_type = remote_id_type = initiator = ""; - remote_filter_proto = local_filter_proto = remote_id_proto = ""; - - if (remote_filter != 0) - { - free (remote_filter); - remote_filter = 0; - } - - if (local_filter != 0) - { - free (local_filter); - local_filter = 0; - } - - if (remote_id != 0) - { - free (remote_id); - remote_id = 0; + static char *esp_present, *ah_present, *comp_present; + static char *ah_hash_alg, *ah_auth_alg, *esp_auth_alg, *esp_enc_alg; + static char *comp_alg, ah_life_kbytes[PMAX], ah_life_seconds[PMAX]; + static char esp_life_kbytes[PMAX], esp_life_seconds[PMAX]; + static char comp_life_kbytes[PMAX]; + static char *ah_ecn, *esp_ecn, *comp_ecn; + static char comp_life_seconds[PMAX], *ah_encapsulation, *esp_encapsulation; + static char *comp_encapsulation, ah_key_length[PMAX], esp_key_length[PMAX]; + static char ah_key_rounds[PMAX], esp_key_rounds[PMAX], comp_dict_size[PMAX]; + static char comp_private_alg[PMAX], *remote_filter_type, *local_filter_type; + static char remote_filter_addr_upper[NI_MAXHOST]; + static char remote_filter_addr_lower[NI_MAXHOST]; + static char local_filter_addr_upper[NI_MAXHOST]; + static char local_filter_addr_lower[NI_MAXHOST]; + static char ah_group_desc[PMAX], esp_group_desc[PMAX], comp_group_desc[PMAX]; + static char remote_ike_address[NI_MAXHOST]; + static char local_ike_address[NI_MAXHOST]; + static char *remote_id_type, remote_id_addr_upper[NI_MAXHOST], + *phase_1; + static char remote_id_addr_lower[NI_MAXHOST]; + static char *remote_id_proto, remote_id_port[PMAX]; + static char remote_filter_port[PMAX], local_filter_port[PMAX]; + static char *remote_filter_proto, *local_filter_proto, *pfs, + *initiator; + static char remote_filter_proto_num[3], local_filter_proto_num[3]; + static char remote_id_proto_num[3]; + static char phase1_group[PMAX]; + + /* Allocated. */ + static char *remote_filter = 0, *local_filter = 0, *remote_id = 0; + + static int dirty = 1; + + /* We only need to set dirty at initialization time really. */ + if (strcmp(name, KEYNOTE_CALLBACK_CLEANUP) == 0 + || strcmp(name, KEYNOTE_CALLBACK_INITIALIZE) == 0) { + esp_present = ah_present = comp_present = pfs = "no"; + ah_hash_alg = ah_auth_alg = phase_1 = ""; + esp_auth_alg = esp_enc_alg = comp_alg = ah_encapsulation = ""; + ah_ecn = esp_ecn = comp_ecn = "no"; + esp_encapsulation = comp_encapsulation = remote_filter_type = ""; + local_filter_type = remote_id_type = initiator = ""; + remote_filter_proto = local_filter_proto = remote_id_proto = ""; + + if (remote_filter != 0) { + free(remote_filter); + remote_filter = 0; + } + if (local_filter != 0) { + free(local_filter); + local_filter = 0; + } + if (remote_id != 0) { + free(remote_id); + remote_id = 0; + } + memset(remote_ike_address, 0, sizeof remote_ike_address); + memset(local_ike_address, 0, sizeof local_ike_address); + memset(ah_life_kbytes, 0, sizeof ah_life_kbytes); + memset(ah_life_seconds, 0, sizeof ah_life_seconds); + memset(esp_life_kbytes, 0, sizeof esp_life_kbytes); + memset(esp_life_seconds, 0, sizeof esp_life_seconds); + memset(comp_life_kbytes, 0, sizeof comp_life_kbytes); + memset(comp_life_seconds, 0, sizeof comp_life_seconds); + memset(ah_key_length, 0, sizeof ah_key_length); + memset(ah_key_rounds, 0, sizeof ah_key_rounds); + memset(esp_key_length, 0, sizeof esp_key_length); + memset(esp_key_rounds, 0, sizeof esp_key_rounds); + memset(comp_dict_size, 0, sizeof comp_dict_size); + memset(comp_private_alg, 0, sizeof comp_private_alg); + memset(remote_filter_addr_upper, 0, sizeof remote_filter_addr_upper); + memset(remote_filter_addr_lower, 0, sizeof remote_filter_addr_lower); + memset(local_filter_addr_upper, 0, sizeof local_filter_addr_upper); + memset(local_filter_addr_lower, 0, sizeof local_filter_addr_lower); + memset(remote_id_addr_upper, 0, sizeof remote_id_addr_upper); + memset(remote_id_addr_lower, 0, sizeof remote_id_addr_lower); + memset(ah_group_desc, 0, sizeof ah_group_desc); + memset(esp_group_desc, 0, sizeof esp_group_desc); + memset(remote_id_port, 0, sizeof remote_id_port); + memset(remote_filter_port, 0, sizeof remote_filter_port); + memset(local_filter_port, 0, sizeof local_filter_port); + memset(phase1_group, 0, sizeof phase1_group); + + dirty = 1; + return ""; } + /* + * If dirty is set, this is the first request for an attribute, so + * populate our value cache. + */ + if (dirty) { + ie = policy_exchange->data; + + if (ie->pfs) + pfs = "yes"; + + is = policy_isakmp_sa->data; + snprintf(phase1_group, sizeof phase1_group, "%u", is->group_desc); + + for (proto = TAILQ_FIRST(&policy_sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_present = "yes"; + switch (proto->id) { + case IPSEC_AH_MD5: + ah_hash_alg = "md5"; + break; + + case IPSEC_AH_SHA: + ah_hash_alg = "sha"; + break; + + case IPSEC_AH_RIPEMD: + ah_hash_alg = "ripemd"; + break; + + case IPSEC_AH_SHA2_256: + ah_auth_alg = "sha2-256"; + break; + + case IPSEC_AH_SHA2_384: + ah_auth_alg = "sha2-384"; + break; + + case IPSEC_AH_SHA2_512: + ah_auth_alg = "sha2-512"; + break; + + case IPSEC_AH_DES: + ah_hash_alg = "des"; + break; + } + + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_present = "yes"; + switch (proto->id) { + case IPSEC_ESP_DES_IV64: + esp_enc_alg = "des-iv64"; + break; + + case IPSEC_ESP_DES: + esp_enc_alg = "des"; + break; + + case IPSEC_ESP_3DES: + esp_enc_alg = "3des"; + break; + + case IPSEC_ESP_AES: + case IPSEC_ESP_AES_128_CTR: + esp_enc_alg = "aes"; + break; + + case IPSEC_ESP_RC5: + esp_enc_alg = "rc5"; + break; + + case IPSEC_ESP_IDEA: + esp_enc_alg = "idea"; + break; + + case IPSEC_ESP_CAST: + esp_enc_alg = "cast"; + break; + + case IPSEC_ESP_BLOWFISH: + esp_enc_alg = "blowfish"; + break; + + case IPSEC_ESP_3IDEA: + esp_enc_alg = "3idea"; + break; + + case IPSEC_ESP_DES_IV32: + esp_enc_alg = "des-iv32"; + break; + + case IPSEC_ESP_RC4: + esp_enc_alg = "rc4"; + break; + + case IPSEC_ESP_NULL: + esp_enc_alg = "null"; + break; + } + + break; + + case IPSEC_PROTO_IPCOMP: + comp_present = "yes"; + switch (proto->id) { + case IPSEC_IPCOMP_OUI: + comp_alg = "oui"; + break; + + case IPSEC_IPCOMP_DEFLATE: + comp_alg = "deflate"; + break; + + case IPSEC_IPCOMP_LZS: + comp_alg = "lzs"; + break; + + case IPSEC_IPCOMP_V42BIS: + comp_alg = "v42bis"; + break; + } + + break; + } - memset (remote_ike_address, 0, sizeof remote_ike_address); - memset (local_ike_address, 0, sizeof local_ike_address); - memset (ah_life_kbytes, 0, sizeof ah_life_kbytes); - memset (ah_life_seconds, 0, sizeof ah_life_seconds); - memset (esp_life_kbytes, 0, sizeof esp_life_kbytes); - memset (esp_life_seconds, 0, sizeof esp_life_seconds); - memset (comp_life_kbytes, 0, sizeof comp_life_kbytes); - memset (comp_life_seconds, 0, sizeof comp_life_seconds); - memset (ah_key_length, 0, sizeof ah_key_length); - memset (ah_key_rounds, 0, sizeof ah_key_rounds); - memset (esp_key_length, 0, sizeof esp_key_length); - memset (esp_key_rounds, 0, sizeof esp_key_rounds); - memset (comp_dict_size, 0, sizeof comp_dict_size); - memset (comp_private_alg, 0, sizeof comp_private_alg); - memset (remote_filter_addr_upper, 0, sizeof remote_filter_addr_upper); - memset (remote_filter_addr_lower, 0, sizeof remote_filter_addr_lower); - memset (local_filter_addr_upper, 0, sizeof local_filter_addr_upper); - memset (local_filter_addr_lower, 0, sizeof local_filter_addr_lower); - memset (remote_id_addr_upper, 0, sizeof remote_id_addr_upper); - memset (remote_id_addr_lower, 0, sizeof remote_id_addr_lower); - memset (ah_group_desc, 0, sizeof ah_group_desc); - memset (esp_group_desc, 0, sizeof esp_group_desc); - memset (remote_id_port, 0, sizeof remote_id_port); - memset (remote_filter_port, 0, sizeof remote_filter_port); - memset (local_filter_port, 0, sizeof local_filter_port); - memset (phase1_group, 0, sizeof phase1_group); - - dirty = 1; - return ""; - } - - /* - * If dirty is set, this is the first request for an attribute, so - * populate our value cache. - */ - if (dirty) - { - ie = policy_exchange->data; - - if (ie->pfs) - pfs = "yes"; - - is = policy_isakmp_sa->data; - snprintf (phase1_group, sizeof phase1_group, "%u", is->group_desc); - - for (proto = TAILQ_FIRST (&policy_sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - ah_present = "yes"; - switch (proto->id) - { - case IPSEC_AH_MD5: - ah_hash_alg = "md5"; - break; - - case IPSEC_AH_SHA: - ah_hash_alg = "sha"; - break; - - case IPSEC_AH_RIPEMD: - ah_hash_alg = "ripemd"; - break; - - case IPSEC_AH_SHA2_256: - ah_auth_alg = "sha2-256"; - break; - - case IPSEC_AH_SHA2_384: - ah_auth_alg = "sha2-384"; - break; + for (attr = proto->chosen->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF; + attr < proto->chosen->p + + GET_ISAKMP_GEN_LENGTH(proto->chosen->p); + attr = value + len) { + if (attr + ISAKMP_ATTR_VALUE_OFF > + (proto->chosen->p + + GET_ISAKMP_GEN_LENGTH(proto->chosen->p))) + return ""; + + type = GET_ISAKMP_ATTR_TYPE(attr); + fmt = ISAKMP_ATTR_FORMAT(type); + type = ISAKMP_ATTR_TYPE(type); + value = attr + (fmt ? ISAKMP_ATTR_LENGTH_VALUE_OFF : + ISAKMP_ATTR_VALUE_OFF); + len = (fmt ? ISAKMP_ATTR_LENGTH_VALUE_LEN : + GET_ISAKMP_ATTR_LENGTH_VALUE(attr)); + + if (value + len > proto->chosen->p + + GET_ISAKMP_GEN_LENGTH(proto->chosen->p)) + return ""; + + switch (type) { + case IPSEC_ATTR_SA_LIFE_TYPE: + lifetype = decode_16(value); + break; + + case IPSEC_ATTR_SA_LIFE_DURATION: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + if (lifetype == IPSEC_DURATION_SECONDS) { + if (len == 2) + snprintf(ah_life_seconds, sizeof ah_life_seconds, + "%u", decode_16(value)); + else + snprintf(ah_life_seconds, sizeof ah_life_seconds, + "%u", decode_32(value)); + } else { + if (len == 2) + snprintf(ah_life_kbytes, sizeof ah_life_kbytes, + "%u", decode_16(value)); + else + snprintf(ah_life_kbytes, sizeof ah_life_kbytes, + "%u", decode_32(value)); + } + + break; + + case IPSEC_PROTO_IPSEC_ESP: + if (lifetype == IPSEC_DURATION_SECONDS) { + if (len == 2) + snprintf(esp_life_seconds, + sizeof esp_life_seconds, "%u", + decode_16(value)); + else + snprintf(esp_life_seconds, + sizeof esp_life_seconds, "%u", + decode_32(value)); + } else { + if (len == 2) + snprintf(esp_life_kbytes, + sizeof esp_life_kbytes, "%u", + decode_16(value)); + else + snprintf(esp_life_kbytes, + sizeof esp_life_kbytes, "%u", + decode_32(value)); + } + + break; + + case IPSEC_PROTO_IPCOMP: + if (lifetype == IPSEC_DURATION_SECONDS) { + if (len == 2) + snprintf(comp_life_seconds, + sizeof comp_life_seconds, "%u", + decode_16(value)); + else + snprintf(comp_life_seconds, + sizeof comp_life_seconds, "%u", + decode_32(value)); + } else { + if (len == 2) + snprintf(comp_life_kbytes, + sizeof comp_life_kbytes, "%u", + decode_16(value)); + else + snprintf(comp_life_kbytes, + sizeof comp_life_kbytes, "%u", + decode_32(value)); + } + break; + } + break; + + case IPSEC_ATTR_GROUP_DESCRIPTION: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + snprintf(ah_group_desc, + sizeof ah_group_desc, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPSEC_ESP: + snprintf(esp_group_desc, + sizeof esp_group_desc, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPCOMP: + snprintf(comp_group_desc, + sizeof comp_group_desc, "%u", + decode_16(value)); + break; + } + break; + + case IPSEC_ATTR_ECN_TUNNEL: + if (decode_16(value)) + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_ecn = "yes"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_ecn = "yes"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_ecn = "yes"; + break; + } + + case IPSEC_ATTR_ENCAPSULATION_MODE: + if (decode_16(value) == IPSEC_ENCAP_TUNNEL) + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_encapsulation = "tunnel"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_encapsulation = "tunnel"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_encapsulation = "tunnel"; + break; + } + else + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_encapsulation = "transport"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_encapsulation = "transport"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_encapsulation = "transport"; + break; + } + break; + + case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + switch (decode_16(value)) { + case IPSEC_AUTH_HMAC_MD5: + ah_auth_alg = "hmac-md5"; + break; + + case IPSEC_AUTH_HMAC_SHA: + ah_auth_alg = "hmac-sha"; + break; + + case IPSEC_AUTH_HMAC_RIPEMD: + ah_auth_alg = "hmac-ripemd"; + break; + + case IPSEC_AUTH_HMAC_SHA2_256: + ah_auth_alg = "hmac-sha2-256"; + break; + + case IPSEC_AUTH_HMAC_SHA2_384: + ah_auth_alg = "hmac-sha2-384"; + break; + + case IPSEC_AUTH_HMAC_SHA2_512: + ah_auth_alg = "hmac-sha2-512"; + break; + + case IPSEC_AUTH_DES_MAC: + ah_auth_alg = "des-mac"; + break; + + case IPSEC_AUTH_KPDK: + ah_auth_alg = "kpdk"; + break; + } + break; + + case IPSEC_PROTO_IPSEC_ESP: + switch (decode_16(value)) { + case IPSEC_AUTH_HMAC_MD5: + esp_auth_alg = "hmac-md5"; + break; + + case IPSEC_AUTH_HMAC_SHA: + esp_auth_alg = "hmac-sha"; + break; + + case IPSEC_AUTH_HMAC_RIPEMD: + esp_auth_alg = "hmac-ripemd"; + break; + + case IPSEC_AUTH_HMAC_SHA2_256: + esp_auth_alg = "hmac-sha2-256"; + break; + + case IPSEC_AUTH_HMAC_SHA2_384: + esp_auth_alg = "hmac-sha2-384"; + break; + + case IPSEC_AUTH_HMAC_SHA2_512: + esp_auth_alg = "hmac-sha2-512"; + break; + + case IPSEC_AUTH_DES_MAC: + esp_auth_alg = "des-mac"; + break; + + case IPSEC_AUTH_KPDK: + esp_auth_alg = "kpdk"; + break; + } + break; + } + break; + + case IPSEC_ATTR_KEY_LENGTH: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + snprintf(ah_key_length, + sizeof ah_key_length, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPSEC_ESP: + snprintf(esp_key_length, + sizeof esp_key_length, "%u", + decode_16(value)); + break; + } + break; + + case IPSEC_ATTR_KEY_ROUNDS: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + snprintf(ah_key_rounds, + sizeof ah_key_rounds, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPSEC_ESP: + snprintf(esp_key_rounds, + sizeof esp_key_rounds, "%u", + decode_16(value)); + break; + } + break; + + case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: + snprintf(comp_dict_size, + sizeof comp_dict_size, "%u", + decode_16(value)); + break; + + case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: + snprintf(comp_private_alg, + sizeof comp_private_alg, "%u", + decode_16(value)); + break; + } + } + } - case IPSEC_AH_SHA2_512: - ah_auth_alg = "sha2-512"; - break; + policy_sa->transport->vtbl->get_src(policy_sa->transport, &sin); + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: sockaddr2text failed"); + goto bad; + } + strlcpy(local_ike_address, addr, sizeof local_ike_address); + free(addr); - case IPSEC_AH_DES: - ah_hash_alg = "des"; - break; + policy_sa->transport->vtbl->get_dst(policy_sa->transport, &sin); + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: sockaddr2text failed"); + goto bad; } + strlcpy(remote_ike_address, addr, sizeof remote_ike_address); + free(addr); - break; + switch (policy_isakmp_sa->exch_type) { + case ISAKMP_EXCH_AGGRESSIVE: + phase_1 = "aggressive"; + break; - case IPSEC_PROTO_IPSEC_ESP: - esp_present = "yes"; - switch (proto->id) - { - case IPSEC_ESP_DES_IV64: - esp_enc_alg = "des-iv64"; - break; - - case IPSEC_ESP_DES: - esp_enc_alg = "des"; - break; - - case IPSEC_ESP_3DES: - esp_enc_alg = "3des"; - break; - - case IPSEC_ESP_AES: - case IPSEC_ESP_AES_128_CTR: - esp_enc_alg = "aes"; - break; - - case IPSEC_ESP_RC5: - esp_enc_alg = "rc5"; - break; - - case IPSEC_ESP_IDEA: - esp_enc_alg = "idea"; - break; - - case IPSEC_ESP_CAST: - esp_enc_alg = "cast"; - break; - - case IPSEC_ESP_BLOWFISH: - esp_enc_alg = "blowfish"; - break; - - case IPSEC_ESP_3IDEA: - esp_enc_alg = "3idea"; - break; - - case IPSEC_ESP_DES_IV32: - esp_enc_alg = "des-iv32"; - break; - - case IPSEC_ESP_RC4: - esp_enc_alg = "rc4"; - break; - - case IPSEC_ESP_NULL: - esp_enc_alg = "null"; - break; + case ISAKMP_EXCH_ID_PROT: + phase_1 = "main"; + break; } - break; + if (policy_isakmp_sa->initiator) { + id = policy_isakmp_sa->id_r; + id_sz = policy_isakmp_sa->id_r_len; + } else { + id = policy_isakmp_sa->id_i; + id_sz = policy_isakmp_sa->id_i_len; + } - case IPSEC_PROTO_IPCOMP: - comp_present = "yes"; - switch (proto->id) - { - case IPSEC_IPCOMP_OUI: - comp_alg = "oui"; - break; + switch (id[0]) { + case IPSEC_ID_IPV4_ADDR: + remote_id_type = "IPv4 address"; + + net = decode_32(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + my_inet_ntop4(&net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1, 1); + my_inet_ntop4(&net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1, 1); + remote_id = strdup(remote_id_addr_upper); + if (!remote_id) { + log_error("policy_callback: strdup (\"%s\") failed", + remote_id_addr_upper); + goto bad; + } + break; - case IPSEC_IPCOMP_DEFLATE: - comp_alg = "deflate"; - break; + case IPSEC_ID_IPV4_RANGE: + remote_id_type = "IPv4 range"; + + net = decode_32(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + my_inet_ntop4(&net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1, 1); + net = decode_32(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 4); + my_inet_ntop4(&net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1, 1); + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%d, %lu) failed", + len, (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; - case IPSEC_IPCOMP_LZS: - comp_alg = "lzs"; - break; + case IPSEC_ID_IPV4_ADDR_SUBNET: + remote_id_type = "IPv4 subnet"; + + net = decode_32(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + subnet = decode_32(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 4); + net &= subnet; + my_inet_ntop4(&net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1, 1); + net |= ~subnet; + my_inet_ntop4(&net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1, 1); + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%d, %lu) failed", + len, (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; - case IPSEC_IPCOMP_V42BIS: - comp_alg = "v42bis"; - break; - } + case IPSEC_ID_IPV6_ADDR: + remote_id_type = "IPv6 address"; + my_inet_ntop6(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + remote_id_addr_upper, sizeof remote_id_addr_upper); + strlcpy(remote_id_addr_lower, remote_id_addr_upper, + sizeof remote_id_addr_lower); + remote_id = strdup(remote_id_addr_upper); + if (!remote_id) { + log_error("policy_callback: strdup (\"%s\") failed", + remote_id_addr_upper); + goto bad; + } + break; - break; - } - - for (attr = proto->chosen->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF; - attr - < proto->chosen->p + GET_ISAKMP_GEN_LENGTH (proto->chosen->p); - attr = value + len) - { - if (attr + ISAKMP_ATTR_VALUE_OFF - > (proto->chosen->p - + GET_ISAKMP_GEN_LENGTH (proto->chosen->p))) - return ""; + case IPSEC_ID_IPV6_RANGE: + remote_id_type = "IPv6 range"; - type = GET_ISAKMP_ATTR_TYPE (attr); - fmt = ISAKMP_ATTR_FORMAT (type); - type = ISAKMP_ATTR_TYPE (type); - value = attr + (fmt ? ISAKMP_ATTR_LENGTH_VALUE_OFF : - ISAKMP_ATTR_VALUE_OFF); - len = (fmt ? ISAKMP_ATTR_LENGTH_VALUE_LEN : - GET_ISAKMP_ATTR_LENGTH_VALUE (attr)); + my_inet_ntop6(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + remote_id_addr_lower, + sizeof remote_id_addr_lower - 1); - if (value + len > proto->chosen->p + - GET_ISAKMP_GEN_LENGTH (proto->chosen->p)) - return ""; + my_inet_ntop6(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 16, + remote_id_addr_upper, + sizeof remote_id_addr_upper - 1); - switch (type) - { - case IPSEC_ATTR_SA_LIFE_TYPE: - lifetype = decode_16 (value); - break; + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%d, %lu) failed", + len, (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; - case IPSEC_ATTR_SA_LIFE_DURATION: - switch (proto->proto) + case IPSEC_ID_IPV6_ADDR_SUBNET: { - case IPSEC_PROTO_IPSEC_AH: - if (lifetype == IPSEC_DURATION_SECONDS) - { - if (len == 2) - snprintf (ah_life_seconds, sizeof ah_life_seconds, - "%u", decode_16 (value)); - else - snprintf (ah_life_seconds, sizeof ah_life_seconds, - "%u", decode_32 (value)); - } - else - { - if (len == 2) - snprintf (ah_life_kbytes, sizeof ah_life_kbytes, - "%u", decode_16 (value)); - else - snprintf (ah_life_kbytes, sizeof ah_life_kbytes, - "%u", decode_32 (value)); - } + struct in6_addr net, mask; - break; - - case IPSEC_PROTO_IPSEC_ESP: - if (lifetype == IPSEC_DURATION_SECONDS) - { - if (len == 2) - snprintf (esp_life_seconds, - sizeof esp_life_seconds, "%u", - decode_16 (value)); - else - snprintf (esp_life_seconds, - sizeof esp_life_seconds, "%u", - decode_32 (value)); - } - else - { - if (len == 2) - snprintf (esp_life_kbytes, - sizeof esp_life_kbytes, "%u", - decode_16 (value)); - else - snprintf (esp_life_kbytes, - sizeof esp_life_kbytes, "%u", - decode_32 (value)); - } + remote_id_type = "IPv6 subnet"; - break; - - case IPSEC_PROTO_IPCOMP: - if (lifetype == IPSEC_DURATION_SECONDS) - { - if (len == 2) - snprintf (comp_life_seconds, - sizeof comp_life_seconds, "%u", - decode_16 (value)); - else - snprintf (comp_life_seconds, - sizeof comp_life_seconds, "%u", - decode_32 (value)); - } - else - { - if (len == 2) - snprintf (comp_life_kbytes, - sizeof comp_life_kbytes, "%u", - decode_16 (value)); - else - snprintf (comp_life_kbytes, - sizeof comp_life_kbytes, "%u", - decode_32 (value)); - } + bcopy(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, &net, + sizeof(net)); + bcopy(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 16, &mask, + sizeof(mask)); - break; - } - break; + for (i = 0; i < 16; i++) + net.s6_addr[i] &= mask.s6_addr[i]; - case IPSEC_ATTR_GROUP_DESCRIPTION: - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - snprintf (ah_group_desc, sizeof ah_group_desc, "%u", - decode_16 (value)); - break; - - case IPSEC_PROTO_IPSEC_ESP: - snprintf (esp_group_desc, sizeof esp_group_desc, "%u", - decode_16 (value)); - break; - - case IPSEC_PROTO_IPCOMP: - snprintf (comp_group_desc, sizeof comp_group_desc, "%u", - decode_16 (value)); - break; - } - break; - - case IPSEC_ATTR_ECN_TUNNEL: - if (decode_16 (value)) - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - ah_ecn = "yes"; - break; + my_inet_ntop6((unsigned char *) &net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1); - case IPSEC_PROTO_IPSEC_ESP: - esp_ecn = "yes"; - break; + for (i = 0; i < 16; i++) + net.s6_addr[i] |= ~mask.s6_addr[i]; - case IPSEC_PROTO_IPCOMP: - comp_ecn = "yes"; - break; - } - - case IPSEC_ATTR_ENCAPSULATION_MODE: - if (decode_16 (value) == IPSEC_ENCAP_TUNNEL) - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - ah_encapsulation = "tunnel"; - break; + my_inet_ntop6((unsigned char *) &net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1); - case IPSEC_PROTO_IPSEC_ESP: - esp_encapsulation = "tunnel"; + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%d, %lu) failed", + len, (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); break; + } - case IPSEC_PROTO_IPCOMP: - comp_encapsulation = "tunnel"; + case IPSEC_ID_FQDN: + remote_id_type = "FQDN"; + remote_id = calloc(id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%lu, %lu) failed", + (unsigned long) id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, + (unsigned long) sizeof(char)); + goto bad; + } + memcpy(remote_id, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); break; - } - else - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - ah_encapsulation = "transport"; + + case IPSEC_ID_USER_FQDN: + remote_id_type = "User FQDN"; + remote_id = calloc(id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%lu, %lu) failed", + (unsigned long) id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, + (unsigned long) sizeof(char)); + goto bad; + } + memcpy(remote_id, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); break; - case IPSEC_PROTO_IPSEC_ESP: - esp_encapsulation = "transport"; + case IPSEC_ID_DER_ASN1_DN: + remote_id_type = "ASN1 DN"; + + remote_id = x509_DN_string(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + if (!remote_id) { + LOG_DBG((LOG_POLICY, 50, + "policy_callback: failed to decode name")); + goto bad; + } break; - case IPSEC_PROTO_IPCOMP: - comp_encapsulation = "transport"; + case IPSEC_ID_DER_ASN1_GN: /* XXX */ + remote_id_type = "ASN1 GN"; break; - } - break; - case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - switch (decode_16 (value)) - { - case IPSEC_AUTH_HMAC_MD5: - ah_auth_alg = "hmac-md5"; - break; - - case IPSEC_AUTH_HMAC_SHA: - ah_auth_alg = "hmac-sha"; - break; - - case IPSEC_AUTH_HMAC_RIPEMD: - ah_auth_alg = "hmac-ripemd"; - break; - - case IPSEC_AUTH_HMAC_SHA2_256: - ah_auth_alg = "hmac-sha2-256"; - break; - - case IPSEC_AUTH_HMAC_SHA2_384: - ah_auth_alg = "hmac-sha2-384"; - break; - - case IPSEC_AUTH_HMAC_SHA2_512: - ah_auth_alg = "hmac-sha2-512"; - break; - - case IPSEC_AUTH_DES_MAC: - ah_auth_alg = "des-mac"; - break; - - case IPSEC_AUTH_KPDK: - ah_auth_alg = "kpdk"; - break; + case IPSEC_ID_KEY_ID: + remote_id_type = "Key ID"; + remote_id = calloc(2 * (id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ) + 1, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: calloc (%lu, %lu) failed", + 2 * ((unsigned long) id_sz - + ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) + 1, + (unsigned long) sizeof(char)); + goto bad; } - break; - - case IPSEC_PROTO_IPSEC_ESP: - switch (decode_16 (value)) - { - case IPSEC_AUTH_HMAC_MD5: - esp_auth_alg = "hmac-md5"; - break; - - case IPSEC_AUTH_HMAC_SHA: - esp_auth_alg = "hmac-sha"; - break; - - case IPSEC_AUTH_HMAC_RIPEMD: - esp_auth_alg = "hmac-ripemd"; - break; - - case IPSEC_AUTH_HMAC_SHA2_256: - esp_auth_alg = "hmac-sha2-256"; - break; - - case IPSEC_AUTH_HMAC_SHA2_384: - esp_auth_alg = "hmac-sha2-384"; - break; - - case IPSEC_AUTH_HMAC_SHA2_512: - esp_auth_alg = "hmac-sha2-512"; - break; - - case IPSEC_AUTH_DES_MAC: - esp_auth_alg = "des-mac"; - break; - - case IPSEC_AUTH_KPDK: - esp_auth_alg = "kpdk"; - break; + /* Does it contain any non-printable characters ? */ + for (i = 0; i < id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; i++) + if (!isprint(*(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + i))) + break; + if (i >= id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) { + memcpy(remote_id, id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; } - break; - } - break; - - case IPSEC_ATTR_KEY_LENGTH: - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - snprintf (ah_key_length, sizeof ah_key_length, "%u", - decode_16 (value)); - break; - - case IPSEC_PROTO_IPSEC_ESP: - snprintf (esp_key_length, sizeof esp_key_length, "%u", - decode_16 (value)); - break; - } - break; - - case IPSEC_ATTR_KEY_ROUNDS: - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_AH: - snprintf (ah_key_rounds, sizeof ah_key_rounds, "%u", - decode_16 (value)); - break; - - case IPSEC_PROTO_IPSEC_ESP: - snprintf (esp_key_rounds, sizeof esp_key_rounds, "%u", - decode_16 (value)); - break; - } - break; - - case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: - snprintf (comp_dict_size, sizeof comp_dict_size, "%u", - decode_16 (value)); - break; + /* Non-printable characters, convert to hex */ + for (i = 0; + i < id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; i++) { + remote_id[2 * i] = hextab[*(id + + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ) >> 4]; + remote_id[2 * i + 1] = hextab[*(id + + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ) & 0xF]; + } + break; - case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: - snprintf (comp_private_alg, sizeof comp_private_alg, "%u", - decode_16 (value)); - break; + default: + log_print("policy_callback: unknown remote ID type %u", id[0]); + goto bad; } - } - } - - policy_sa->transport->vtbl->get_src (policy_sa->transport, &sin); - if (sockaddr2text (sin, &addr, 1)) - { - log_error ("policy_callback: sockaddr2text failed"); - goto bad; - } - strlcpy (local_ike_address, addr, sizeof local_ike_address); - free (addr); - - policy_sa->transport->vtbl->get_dst (policy_sa->transport, &sin); - if (sockaddr2text (sin, &addr, 1)) - { - log_error ("policy_callback: sockaddr2text failed"); - goto bad; - } - strlcpy (remote_ike_address, addr, sizeof remote_ike_address); - free (addr); - - switch (policy_isakmp_sa->exch_type) - { - case ISAKMP_EXCH_AGGRESSIVE: - phase_1 = "aggressive"; - break; - - case ISAKMP_EXCH_ID_PROT: - phase_1 = "main"; - break; - } - - if (policy_isakmp_sa->initiator) - { - id = policy_isakmp_sa->id_r; - id_sz = policy_isakmp_sa->id_r_len; - } - else - { - id = policy_isakmp_sa->id_i; - id_sz = policy_isakmp_sa->id_i_len; - } - - switch (id[0]) - { - case IPSEC_ID_IPV4_ADDR: - remote_id_type = "IPv4 address"; - - net = decode_32 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); - my_inet_ntop4 (&net, remote_id_addr_upper, - sizeof remote_id_addr_upper - 1, 1); - my_inet_ntop4 (&net, remote_id_addr_lower, - sizeof remote_id_addr_lower - 1, 1); - remote_id = strdup (remote_id_addr_upper); - if (!remote_id) - { - log_error ("policy_callback: strdup (\"%s\") failed", - remote_id_addr_upper); - goto bad; - } - break; - - case IPSEC_ID_IPV4_RANGE: - remote_id_type = "IPv4 range"; - - net = decode_32 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); - my_inet_ntop4 (&net, remote_id_addr_lower, - sizeof remote_id_addr_lower - 1, 1); - net = decode_32 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 4); - my_inet_ntop4 (&net, remote_id_addr_upper, - sizeof remote_id_addr_upper - 1, 1); - len = strlen (remote_id_addr_upper) + strlen (remote_id_addr_lower) - + 2; - remote_id = calloc (len, sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - - strlcpy (remote_id, remote_id_addr_lower, len); - strlcat (remote_id, "-", len); - strlcat (remote_id, remote_id_addr_upper, len); - break; - - case IPSEC_ID_IPV4_ADDR_SUBNET: - remote_id_type = "IPv4 subnet"; - - net = decode_32 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); - subnet = decode_32 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 4); - net &= subnet; - my_inet_ntop4 (&net, remote_id_addr_lower, - sizeof remote_id_addr_lower - 1, 1); - net |= ~subnet; - my_inet_ntop4 (&net, remote_id_addr_upper, - sizeof remote_id_addr_upper - 1, 1); - len = strlen (remote_id_addr_upper) + strlen (remote_id_addr_lower) - + 2; - remote_id = calloc (len, sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - - strlcpy (remote_id, remote_id_addr_lower, len); - strlcat (remote_id, "-", len); - strlcat (remote_id, remote_id_addr_upper, len); - break; - case IPSEC_ID_IPV6_ADDR: - remote_id_type = "IPv6 address"; - my_inet_ntop6 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - remote_id_addr_upper, sizeof remote_id_addr_upper); - strlcpy (remote_id_addr_lower, remote_id_addr_upper, - sizeof remote_id_addr_lower); - remote_id = strdup (remote_id_addr_upper); - if (!remote_id) - { - log_error ("policy_callback: strdup (\"%s\") failed", - remote_id_addr_upper); - goto bad; - } - break; - - case IPSEC_ID_IPV6_RANGE: - remote_id_type = "IPv6 range"; - - my_inet_ntop6 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - remote_id_addr_lower, - sizeof remote_id_addr_lower - 1); - - my_inet_ntop6 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 16, - remote_id_addr_upper, - sizeof remote_id_addr_upper - 1); - - len = strlen (remote_id_addr_upper) + strlen (remote_id_addr_lower) - + 2; - remote_id = calloc (len, sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - - strlcpy (remote_id, remote_id_addr_lower, len); - strlcat (remote_id, "-", len); - strlcat (remote_id, remote_id_addr_upper, len); - break; - - case IPSEC_ID_IPV6_ADDR_SUBNET: - { - struct in6_addr net, mask; - - remote_id_type = "IPv6 subnet"; - - bcopy (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, &net, sizeof (net)); - bcopy (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 16, &mask, - sizeof (mask)); - - for (i = 0; i < 16; i++) - net.s6_addr[i] &= mask.s6_addr[i]; - - my_inet_ntop6 ((unsigned char *) &net, remote_id_addr_lower, - sizeof remote_id_addr_lower - 1); - - for (i = 0; i < 16; i++) - net.s6_addr[i] |= ~mask.s6_addr[i]; - - my_inet_ntop6 ((unsigned char *) &net, remote_id_addr_upper, - sizeof remote_id_addr_upper - 1); - - len = strlen (remote_id_addr_upper) + strlen (remote_id_addr_lower) - + 2; - remote_id = calloc (len, sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - - strlcpy (remote_id, remote_id_addr_lower, len); - strlcat (remote_id, "-", len); - strlcat (remote_id, remote_id_addr_upper, len); - break; - } - - case IPSEC_ID_FQDN: - remote_id_type = "FQDN"; - remote_id = calloc (id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, - sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%lu, %lu) failed", - (unsigned long)id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, - (unsigned long)sizeof (char)); - goto bad; - } - memcpy (remote_id, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); - break; - - case IPSEC_ID_USER_FQDN: - remote_id_type = "User FQDN"; - remote_id = calloc (id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, - sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%lu, %lu) failed", - (unsigned long)id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, - (unsigned long)sizeof (char)); - goto bad; - } - memcpy (remote_id, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); - break; - - case IPSEC_ID_DER_ASN1_DN: - remote_id_type = "ASN1 DN"; - - remote_id = x509_DN_string (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - id_sz - ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ); - if (!remote_id) - { - LOG_DBG ((LOG_POLICY, 50, - "policy_callback: failed to decode name")); - goto bad; - } - break; - - case IPSEC_ID_DER_ASN1_GN: /* XXX */ - remote_id_type = "ASN1 GN"; - break; - - case IPSEC_ID_KEY_ID: - remote_id_type = "Key ID"; - remote_id - = calloc (2 * (id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) + 1, - sizeof (char)); - if (!remote_id) - { - log_error ("policy_callback: calloc (%lu, %lu) failed", - 2 * ((unsigned long)id_sz - ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ) + 1, - (unsigned long)sizeof (char)); - goto bad; - } - /* Does it contain any non-printable characters ? */ - for (i = 0; i < id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; i++) - if (!isprint (*(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + i))) - break; - if (i >= id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) - { - memcpy (remote_id, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); - break; - } - /* Non-printable characters, convert to hex */ - for (i = 0; i < id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; i++) - { - remote_id[2 * i] - = hextab[*(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ) >> 4]; - remote_id[2 * i + 1] - = hextab[*(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ) & 0xF]; - } - break; - - default: - log_print ("policy_callback: unknown remote ID type %u", id[0]); - goto bad; - } - - switch (id[1]) - { - case IPPROTO_TCP: - remote_id_proto = "tcp"; - break; + switch (id[1]) { + case IPPROTO_TCP: + remote_id_proto = "tcp"; + break; - case IPPROTO_UDP: - remote_id_proto = "udp"; - break; + case IPPROTO_UDP: + remote_id_proto = "udp"; + break; #ifdef IPPROTO_ETHERIP - case IPPROTO_ETHERIP: - remote_id_proto = "etherip"; - break; + case IPPROTO_ETHERIP: + remote_id_proto = "etherip"; + break; #endif - default: - snprintf (remote_id_proto_num, sizeof remote_id_proto_num, "%d", - id[1]); - remote_id_proto = remote_id_proto_num; - break; - } - - snprintf (remote_id_port, sizeof remote_id_port, "%u", - decode_16 (id + 2)); - - if (policy_exchange->initiator) - { - initiator = "yes"; - idlocal = ie->id_ci; - idremote = ie->id_cr; - idlocalsz = ie->id_ci_sz; - idremotesz = ie->id_cr_sz; - } - else - { - initiator = "no"; - idlocal = ie->id_cr; - idremote = ie->id_ci; - idlocalsz = ie->id_cr_sz; - idremotesz = ie->id_ci_sz; - } - - /* Initialize the ID variables. */ - if (idremote) - { - switch (GET_ISAKMP_ID_TYPE (idremote)) - { - case IPSEC_ID_IPV4_ADDR: - remote_filter_type = "IPv4 address"; - - net = decode_32 (idremote + ISAKMP_ID_DATA_OFF); - my_inet_ntop4 (&net, remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1, 1); - my_inet_ntop4 (&net, remote_filter_addr_lower, - sizeof remote_filter_addr_lower - 1, 1); - remote_filter = strdup (remote_filter_addr_upper); - if (!remote_filter) - { - log_error ("policy_callback: strdup (\"%s\") failed", - remote_filter_addr_upper); - goto bad; - } - break; - - case IPSEC_ID_IPV4_RANGE: - remote_filter_type = "IPv4 range"; - - net = decode_32 (idremote + ISAKMP_ID_DATA_OFF); - my_inet_ntop4 (&net, remote_filter_addr_lower, - sizeof remote_filter_addr_lower - 1, 1); - net = decode_32 (idremote + ISAKMP_ID_DATA_OFF + 4); - my_inet_ntop4 (&net, remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1, 1); - len = strlen (remote_filter_addr_upper) - + strlen (remote_filter_addr_lower) + 2; - remote_filter = calloc (len, sizeof (char)); - if (!remote_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; + default: + snprintf(remote_id_proto_num, sizeof remote_id_proto_num, "%d", + id[1]); + remote_id_proto = remote_id_proto_num; + break; } - strlcpy (remote_filter, remote_filter_addr_lower, len); - strlcat (remote_filter, "-", len); - strlcat (remote_filter, remote_filter_addr_upper, len); - break; - - case IPSEC_ID_IPV4_ADDR_SUBNET: - remote_filter_type = "IPv4 subnet"; - - net = decode_32 (idremote + ISAKMP_ID_DATA_OFF); - subnet = decode_32 (idremote + ISAKMP_ID_DATA_OFF + 4); - net &= subnet; - my_inet_ntop4 (&net, remote_filter_addr_lower, - sizeof remote_filter_addr_lower - 1, 1); - net |= ~subnet; - my_inet_ntop4 (&net, remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1, 1); - len = strlen (remote_filter_addr_upper) - + strlen (remote_filter_addr_lower) + 2; - remote_filter = calloc (len, sizeof (char)); - if (!remote_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - strlcpy (remote_filter, remote_filter_addr_lower, len); - strlcat (remote_filter, "-", len); - strlcat (remote_filter, remote_filter_addr_upper, len); - break; - - case IPSEC_ID_IPV6_ADDR: - remote_filter_type = "IPv6 address"; - my_inet_ntop6 (idremote + ISAKMP_ID_DATA_OFF, - remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1); - strlcpy (remote_filter_addr_lower, remote_filter_addr_upper, - sizeof remote_filter_addr_lower); - remote_filter = strdup (remote_filter_addr_upper); - if (!remote_filter) - { - log_error ("policy_callback: strdup (\"%s\") failed", - remote_filter_addr_upper); - goto bad; + snprintf(remote_id_port, sizeof remote_id_port, "%u", + decode_16(id + 2)); + + if (policy_exchange->initiator) { + initiator = "yes"; + idlocal = ie->id_ci; + idremote = ie->id_cr; + idlocalsz = ie->id_ci_sz; + idremotesz = ie->id_cr_sz; + } else { + initiator = "no"; + idlocal = ie->id_cr; + idremote = ie->id_ci; + idlocalsz = ie->id_cr_sz; + idremotesz = ie->id_ci_sz; } - break; - - case IPSEC_ID_IPV6_RANGE: - remote_filter_type = "IPv6 range"; - my_inet_ntop6 (idremote + ISAKMP_ID_DATA_OFF, - remote_filter_addr_lower, - sizeof remote_filter_addr_lower - 1); + /* Initialize the ID variables. */ + if (idremote) { + switch (GET_ISAKMP_ID_TYPE(idremote)) { + case IPSEC_ID_IPV4_ADDR: + remote_filter_type = "IPv4 address"; + + net = decode_32(idremote + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1, 1); + my_inet_ntop4(&net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1, 1); + remote_filter = strdup(remote_filter_addr_upper); + if (!remote_filter) { + log_error("policy_callback: strdup " + "(\"%s\") failed", + remote_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV4_RANGE: + remote_filter_type = "IPv4 range"; + + net = decode_32(idremote + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1, 1); + net = decode_32(idremote + ISAKMP_ID_DATA_OFF + 4); + my_inet_ntop4(&net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1, 1); + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc " + "(%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_filter, remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, remote_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + remote_filter_type = "IPv4 subnet"; + + net = decode_32(idremote + ISAKMP_ID_DATA_OFF); + subnet = decode_32(idremote + ISAKMP_ID_DATA_OFF + 4); + net &= subnet; + my_inet_ntop4(&net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1, 1); + net |= ~subnet; + my_inet_ntop4(&net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1, 1); + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc " + "(%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_filter, remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, remote_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR: + remote_filter_type = "IPv6 address"; + my_inet_ntop6(idremote + ISAKMP_ID_DATA_OFF, + remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1); + strlcpy(remote_filter_addr_lower, + remote_filter_addr_upper, + sizeof remote_filter_addr_lower); + remote_filter = strdup(remote_filter_addr_upper); + if (!remote_filter) { + log_error("policy_callback: strdup " + "(\"%s\") failed", + remote_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV6_RANGE: + remote_filter_type = "IPv6 range"; + + my_inet_ntop6(idremote + ISAKMP_ID_DATA_OFF, + remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1); + + my_inet_ntop6(idremote + ISAKMP_ID_DATA_OFF + 16, + remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1); + + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc " + "(%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_filter, remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, remote_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + { + struct in6_addr net, mask; + + remote_filter_type = "IPv6 subnet"; + + bcopy(idremote + ISAKMP_ID_DATA_OFF, &net, sizeof(net)); + bcopy(idremote + ISAKMP_ID_DATA_OFF + 16, &mask, sizeof(mask)); + + for (i = 0; i < 16; i++) + net.s6_addr[i] &= mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *) &net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1); + + for (i = 0; i < 16; i++) + net.s6_addr[i] |= ~mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *) &net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1); + + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(remote_filter, remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, remote_filter_addr_upper, len); + break; + } + + case IPSEC_ID_FQDN: + remote_filter_type = "FQDN"; + remote_filter = malloc(idremotesz - ISAKMP_ID_DATA_OFF + 1); + if (!remote_filter) { + log_error("policy_callback: malloc (%lu) failed", + (unsigned long) idremotesz - ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(remote_filter, idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + remote_filter[idremotesz - ISAKMP_ID_DATA_OFF] = '\0'; + break; + + case IPSEC_ID_USER_FQDN: + remote_filter_type = "User FQDN"; + remote_filter = malloc(idremotesz - ISAKMP_ID_DATA_OFF + 1); + if (!remote_filter) { + log_error("policy_callback: malloc (%lu) failed", + (unsigned long) idremotesz - ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(remote_filter, idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + remote_filter[idremotesz - ISAKMP_ID_DATA_OFF] = '\0'; + break; + + case IPSEC_ID_DER_ASN1_DN: + remote_filter_type = "ASN1 DN"; + + remote_filter = x509_DN_string(idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + if (!remote_filter) { + LOG_DBG((LOG_POLICY, 50, + "policy_callback: failed to decode name")); + goto bad; + } + break; + + case IPSEC_ID_DER_ASN1_GN: /* XXX -- not sure + * what's in this. */ + remote_filter_type = "ASN1 GN"; + break; + + case IPSEC_ID_KEY_ID: + remote_filter_type = "Key ID"; + remote_filter + = calloc(2 * (idremotesz - ISAKMP_ID_DATA_OFF) + 1, + sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc (%lu, %lu) failed", + 2 * ((unsigned long) idremotesz - ISAKMP_ID_DATA_OFF) + 1, + (unsigned long) sizeof(char)); + goto bad; + } + /* + * Does it contain any non-printable + * characters ? + */ + for (i = 0; i < idremotesz - ISAKMP_ID_DATA_OFF; i++) + if (!isprint(*(idremote + ISAKMP_ID_DATA_OFF + i))) + break; + if (i >= idremotesz - ISAKMP_ID_DATA_OFF) { + memcpy(remote_filter, idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + break; + } + /* Non-printable characters, convert to hex */ + for (i = 0; i < idremotesz - ISAKMP_ID_DATA_OFF; i++) { + remote_filter[2 * i] + = hextab[*(idremote + ISAKMP_ID_DATA_OFF) >> 4]; + remote_filter[2 * i + 1] + = hextab[*(idremote + ISAKMP_ID_DATA_OFF) & 0xF]; + } + break; + + default: + log_print("policy_callback: unknown Remote ID type %u", + GET_ISAKMP_ID_TYPE(idremote)); + goto bad; + } - my_inet_ntop6 (idremote + ISAKMP_ID_DATA_OFF + 16, - remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1); + switch (idremote[ISAKMP_GEN_SZ + 1]) { + case IPPROTO_TCP: + remote_filter_proto = "tcp"; + break; - len = strlen (remote_filter_addr_upper) - + strlen (remote_filter_addr_lower) + 2; - remote_filter = calloc (len, sizeof (char)); - if (!remote_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } + case IPPROTO_UDP: + remote_filter_proto = "udp"; + break; - strlcpy (remote_filter, remote_filter_addr_lower, len); - strlcat (remote_filter, "-", len); - strlcat (remote_filter, remote_filter_addr_upper, len); - break; +#ifdef IPPROTO_ETHERIP + case IPPROTO_ETHERIP: + remote_filter_proto = "etherip"; + break; +#endif - case IPSEC_ID_IPV6_ADDR_SUBNET: - { - struct in6_addr net, mask; + default: + snprintf(remote_filter_proto_num, + sizeof remote_filter_proto_num, "%d", + idremote[ISAKMP_GEN_SZ + 1]); + remote_filter_proto = remote_filter_proto_num; + break; + } - remote_filter_type = "IPv6 subnet"; + snprintf(remote_filter_port, sizeof remote_filter_port, "%u", + decode_16(idremote + ISAKMP_GEN_SZ + 2)); + } else { + policy_sa->transport->vtbl->get_dst(policy_sa->transport, &sin); + switch (sin->sa_family) { + case AF_INET: + remote_filter_type = "IPv4 address"; + break; + case AF_INET6: + remote_filter_type = "IPv6 address"; + break; + default: + log_print("policy_callback: unsupported protocol family %d", + sin->sa_family); + goto bad; + } + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: sockaddr2text failed"); + goto bad; + } + memcpy(remote_filter_addr_upper, addr, + sizeof remote_filter_addr_upper); + memcpy(remote_filter_addr_lower, addr, + sizeof remote_filter_addr_lower); + free(addr); + remote_filter = strdup(remote_filter_addr_upper); + if (!remote_filter) { + log_error("policy_callback: strdup (\"%s\") failed", + remote_filter_addr_upper); + goto bad; + } + } - bcopy (idremote + ISAKMP_ID_DATA_OFF, &net, sizeof (net)); - bcopy (idremote + ISAKMP_ID_DATA_OFF + 16, &mask, sizeof (mask)); + if (idlocal) { + switch (GET_ISAKMP_ID_TYPE(idlocal)) { + case IPSEC_ID_IPV4_ADDR: + local_filter_type = "IPv4 address"; + + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1, 1); + my_inet_ntop4(&net, local_filter_addr_lower, + sizeof local_filter_addr_upper - 1, 1); + local_filter = strdup(local_filter_addr_upper); + if (!local_filter) { + log_error("policy_callback: strdup (\"%s\") failed", + local_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV4_RANGE: + local_filter_type = "IPv4 range"; + + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, local_filter_addr_lower, + sizeof local_filter_addr_lower - 1, 1); + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF + 4); + my_inet_ntop4(&net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1, 1); + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + local_filter_type = "IPv4 subnet"; + + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF); + subnet = decode_32(idlocal + ISAKMP_ID_DATA_OFF + 4); + net &= subnet; + my_inet_ntop4(&net, local_filter_addr_lower, + sizeof local_filter_addr_lower - 1, 1); + net |= ~subnet; + my_inet_ntop4(&net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1, 1); + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR: + local_filter_type = "IPv6 address"; + my_inet_ntop6(idlocal + ISAKMP_ID_DATA_OFF, + local_filter_addr_upper, + sizeof local_filter_addr_upper - 1); + strlcpy(local_filter_addr_lower, local_filter_addr_upper, + sizeof local_filter_addr_lower); + local_filter = strdup(local_filter_addr_upper); + if (!local_filter) { + log_error("policy_callback: strdup (\"%s\") failed", + local_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV6_RANGE: + local_filter_type = "IPv6 range"; + + my_inet_ntop6(idlocal + ISAKMP_ID_DATA_OFF, + local_filter_addr_lower, + sizeof local_filter_addr_lower - 1); + + my_inet_ntop6(idlocal + ISAKMP_ID_DATA_OFF + 16, + local_filter_addr_upper, + sizeof local_filter_addr_upper - 1); + + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + { + struct in6_addr net, mask; + + local_filter_type = "IPv6 subnet"; + + bcopy(idlocal + ISAKMP_ID_DATA_OFF, &net, sizeof(net)); + bcopy(idlocal + ISAKMP_ID_DATA_OFF + 16, &mask, sizeof(mask)); + + for (i = 0; i < 16; i++) + net.s6_addr[i] &= mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *) &net, local_filter_addr_lower, + sizeof local_filter_addr_lower - 1); + + for (i = 0; i < 16; i++) + net.s6_addr[i] |= ~mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *) &net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1); + + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: calloc (%d, %lu) failed", len, + (unsigned long) sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, len); + break; + } + + case IPSEC_ID_FQDN: + local_filter_type = "FQDN"; + local_filter = malloc(idlocalsz - ISAKMP_ID_DATA_OFF + 1); + if (!local_filter) { + log_error("policy_callback: malloc (%lu) failed", + (unsigned long) idlocalsz - ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(local_filter, idlocal + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + local_filter[idlocalsz - ISAKMP_ID_DATA_OFF] = '\0'; + break; + + case IPSEC_ID_USER_FQDN: + local_filter_type = "User FQDN"; + local_filter = malloc(idlocalsz - ISAKMP_ID_DATA_OFF + 1); + if (!local_filter) { + log_error("policy_callback: malloc (%lu) failed", + (unsigned long) idlocalsz - ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(local_filter, idlocal + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + local_filter[idlocalsz - ISAKMP_ID_DATA_OFF] = '\0'; + break; + + case IPSEC_ID_DER_ASN1_DN: + local_filter_type = "ASN1 DN"; + + local_filter = x509_DN_string(idlocal + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + if (!local_filter) { + LOG_DBG((LOG_POLICY, 50, + "policy_callback: failed to decode name")); + goto bad; + } + break; + + case IPSEC_ID_DER_ASN1_GN: + /* XXX -- not sure what's in this. */ + local_filter_type = "ASN1 GN"; + break; + + case IPSEC_ID_KEY_ID: + local_filter_type = "Key ID"; + local_filter = calloc(2 * (idlocalsz - ISAKMP_ID_DATA_OFF) + 1, + sizeof(char)); + if (!local_filter) { + log_error("policy_callback: calloc (%lu, %lu) failed", + 2 * ((unsigned long) idlocalsz - ISAKMP_ID_DATA_OFF) + 1, + (unsigned long) sizeof(char)); + goto bad; + } + /* + * Does it contain any non-printable + * characters ? + */ + for (i = 0; i < idlocalsz - ISAKMP_ID_DATA_OFF; i++) + if (!isprint(*(idlocal + ISAKMP_ID_DATA_OFF + i))) + break; + if (i >= idlocalsz - ISAKMP_ID_DATA_OFF) { + memcpy(local_filter, idlocal + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + break; + } + /* Non-printable characters, convert to hex */ + for (i = 0; i < idlocalsz - ISAKMP_ID_DATA_OFF; i++) { + local_filter[2 * i] + = hextab[*(idlocal + ISAKMP_ID_DATA_OFF) >> 4]; + local_filter[2 * i + 1] + = hextab[*(idlocal + ISAKMP_ID_DATA_OFF) & 0xF]; + } + break; + + default: + log_print("policy_callback: unknown Local ID type %u", + GET_ISAKMP_ID_TYPE(idlocal)); + goto bad; + } - for (i = 0; i < 16; i++) - net.s6_addr[i] &= mask.s6_addr[i]; + switch (idlocal[ISAKMP_GEN_SZ + 1]) { + case IPPROTO_TCP: + local_filter_proto = "tcp"; + break; - my_inet_ntop6 ((unsigned char *) &net, remote_filter_addr_lower, - sizeof remote_filter_addr_lower - 1); + case IPPROTO_UDP: + local_filter_proto = "udp"; + break; - for (i = 0; i < 16; i++) - net.s6_addr[i] |= ~mask.s6_addr[i]; +#ifdef IPPROTO_ETHERIP + case IPPROTO_ETHERIP: + local_filter_proto = "etherip"; + break; +#endif - my_inet_ntop6 ((unsigned char *) &net, remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1); + default: + snprintf(local_filter_proto_num, sizeof local_filter_proto_num, + "%d", idlocal[ISAKMP_GEN_SZ + 1]); + local_filter_proto = local_filter_proto_num; + break; + } - len = strlen (remote_filter_addr_upper) - + strlen (remote_filter_addr_lower) + 2; - remote_filter = calloc (len, sizeof (char)); - if (!remote_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } + snprintf(local_filter_port, sizeof local_filter_port, "%u", + decode_16(idlocal + ISAKMP_GEN_SZ + 2)); + } else { + policy_sa->transport->vtbl->get_src(policy_sa->transport, + (struct sockaddr **) & sin); + switch (sin->sa_family) { + case AF_INET: + local_filter_type = "IPv4 address"; + break; + case AF_INET6: + local_filter_type = "IPv6 address"; + break; + default: + log_print("policy_callback: unsupported protocol family %d", + sin->sa_family); + goto bad; + } - strlcpy (remote_filter, remote_filter_addr_lower, len); - strlcat (remote_filter, "-", len); - strlcat (remote_filter, remote_filter_addr_upper, len); - break; - } - - case IPSEC_ID_FQDN: - remote_filter_type = "FQDN"; - remote_filter = malloc (idremotesz - ISAKMP_ID_DATA_OFF + 1); - if (!remote_filter) - { - log_error ("policy_callback: malloc (%lu) failed", - (unsigned long)idremotesz - ISAKMP_ID_DATA_OFF + 1); - goto bad; - } - memcpy (remote_filter, idremote + ISAKMP_ID_DATA_OFF, - idremotesz - ISAKMP_ID_DATA_OFF); - remote_filter[idremotesz - ISAKMP_ID_DATA_OFF] = '\0'; - break; - - case IPSEC_ID_USER_FQDN: - remote_filter_type = "User FQDN"; - remote_filter = malloc (idremotesz - ISAKMP_ID_DATA_OFF + 1); - if (!remote_filter) - { - log_error ("policy_callback: malloc (%lu) failed", - (unsigned long)idremotesz - ISAKMP_ID_DATA_OFF + 1); - goto bad; - } - memcpy (remote_filter, idremote + ISAKMP_ID_DATA_OFF, - idremotesz - ISAKMP_ID_DATA_OFF); - remote_filter[idremotesz - ISAKMP_ID_DATA_OFF] = '\0'; - break; - - case IPSEC_ID_DER_ASN1_DN: - remote_filter_type = "ASN1 DN"; - - remote_filter = x509_DN_string (idremote + ISAKMP_ID_DATA_OFF, - idremotesz - ISAKMP_ID_DATA_OFF); - if (!remote_filter) - { - LOG_DBG ((LOG_POLICY, 50, - "policy_callback: failed to decode name")); - goto bad; - } - break; - - case IPSEC_ID_DER_ASN1_GN: /* XXX -- not sure what's in this. */ - remote_filter_type = "ASN1 GN"; - break; - - case IPSEC_ID_KEY_ID: - remote_filter_type = "Key ID"; - remote_filter - = calloc (2 * (idremotesz - ISAKMP_ID_DATA_OFF) + 1, - sizeof (char)); - if (!remote_filter) - { - log_error ("policy_callback: calloc (%lu, %lu) failed", - 2 * ((unsigned long)idremotesz - ISAKMP_ID_DATA_OFF) + 1, - (unsigned long)sizeof (char)); - goto bad; - } - /* Does it contain any non-printable characters ? */ - for (i = 0; i < idremotesz - ISAKMP_ID_DATA_OFF; i++) - if (!isprint (*(idremote + ISAKMP_ID_DATA_OFF + i))) - break; - if (i >= idremotesz - ISAKMP_ID_DATA_OFF) - { - memcpy (remote_filter, idremote + ISAKMP_ID_DATA_OFF, - idremotesz - ISAKMP_ID_DATA_OFF); - break; + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: sockaddr2text failed"); + goto bad; + } + memcpy(local_filter_addr_upper, addr, + sizeof local_filter_addr_upper); + memcpy(local_filter_addr_lower, addr, + sizeof local_filter_addr_lower); + free(addr); + local_filter = strdup(local_filter_addr_upper); + if (!local_filter) { + log_error("policy_callback: strdup (\"%s\") failed", + local_filter_addr_upper); + goto bad; + } } - /* Non-printable characters, convert to hex */ - for (i = 0; i < idremotesz - ISAKMP_ID_DATA_OFF; i++) - { - remote_filter[2 * i] - = hextab[*(idremote + ISAKMP_ID_DATA_OFF) >> 4]; - remote_filter[2 * i + 1] - = hextab[*(idremote + ISAKMP_ID_DATA_OFF) & 0xF]; - } - break; - - default: - log_print ("policy_callback: unknown Remote ID type %u", - GET_ISAKMP_ID_TYPE (idremote)); - goto bad; - } - - switch (idremote[ISAKMP_GEN_SZ + 1]) - { - case IPPROTO_TCP: - remote_filter_proto = "tcp"; - break; - - case IPPROTO_UDP: - remote_filter_proto = "udp"; - break; - -#ifdef IPPROTO_ETHERIP - case IPPROTO_ETHERIP: - remote_filter_proto = "etherip"; - break; -#endif - default: - snprintf (remote_filter_proto_num, - sizeof remote_filter_proto_num, "%d", - idremote[ISAKMP_GEN_SZ + 1]); - remote_filter_proto = remote_filter_proto_num; - break; - } + LOG_DBG((LOG_POLICY, 80, "Policy context (action attributes):")); + LOG_DBG((LOG_POLICY, 80, "esp_present == %s", esp_present)); + LOG_DBG((LOG_POLICY, 80, "ah_present == %s", ah_present)); + LOG_DBG((LOG_POLICY, 80, "comp_present == %s", comp_present)); + LOG_DBG((LOG_POLICY, 80, "ah_hash_alg == %s", ah_hash_alg)); + LOG_DBG((LOG_POLICY, 80, "esp_enc_alg == %s", esp_enc_alg)); + LOG_DBG((LOG_POLICY, 80, "comp_alg == %s", comp_alg)); + LOG_DBG((LOG_POLICY, 80, "ah_auth_alg == %s", ah_auth_alg)); + LOG_DBG((LOG_POLICY, 80, "esp_auth_alg == %s", esp_auth_alg)); + LOG_DBG((LOG_POLICY, 80, "ah_life_seconds == %s", ah_life_seconds)); + LOG_DBG((LOG_POLICY, 80, "ah_life_kbytes == %s", ah_life_kbytes)); + LOG_DBG((LOG_POLICY, 80, "esp_life_seconds == %s", esp_life_seconds)); + LOG_DBG((LOG_POLICY, 80, "esp_life_kbytes == %s", esp_life_kbytes)); + LOG_DBG((LOG_POLICY, 80, "comp_life_seconds == %s", comp_life_seconds)); + LOG_DBG((LOG_POLICY, 80, "comp_life_kbytes == %s", comp_life_kbytes)); + LOG_DBG((LOG_POLICY, 80, "ah_encapsulation == %s", ah_encapsulation)); + LOG_DBG((LOG_POLICY, 80, "esp_encapsulation == %s", esp_encapsulation)); + LOG_DBG((LOG_POLICY, 80, "comp_encapsulation == %s", + comp_encapsulation)); + LOG_DBG((LOG_POLICY, 80, "comp_dict_size == %s", comp_dict_size)); + LOG_DBG((LOG_POLICY, 80, "comp_private_alg == %s", comp_private_alg)); + LOG_DBG((LOG_POLICY, 80, "ah_key_length == %s", ah_key_length)); + LOG_DBG((LOG_POLICY, 80, "ah_key_rounds == %s", ah_key_rounds)); + LOG_DBG((LOG_POLICY, 80, "esp_key_length == %s", esp_key_length)); + LOG_DBG((LOG_POLICY, 80, "esp_key_rounds == %s", esp_key_rounds)); + LOG_DBG((LOG_POLICY, 80, "ah_group_desc == %s", ah_group_desc)); + LOG_DBG((LOG_POLICY, 80, "esp_group_desc == %s", esp_group_desc)); + LOG_DBG((LOG_POLICY, 80, "comp_group_desc == %s", comp_group_desc)); + LOG_DBG((LOG_POLICY, 80, "ah_ecn == %s", ah_ecn)); + LOG_DBG((LOG_POLICY, 80, "esp_ecn == %s", esp_ecn)); + LOG_DBG((LOG_POLICY, 80, "comp_ecn == %s", comp_ecn)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_type == %s", + remote_filter_type)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_addr_upper == %s", + remote_filter_addr_upper)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_addr_lower == %s", + remote_filter_addr_lower)); + LOG_DBG((LOG_POLICY, 80, "remote_filter == %s", + (remote_filter ? remote_filter : ""))); + LOG_DBG((LOG_POLICY, 80, "remote_filter_port == %s", + remote_filter_port)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_proto == %s", + remote_filter_proto)); + LOG_DBG((LOG_POLICY, 80, "local_filter_type == %s", local_filter_type)); + LOG_DBG((LOG_POLICY, 80, "local_filter_addr_upper == %s", + local_filter_addr_upper)); + LOG_DBG((LOG_POLICY, 80, "local_filter_addr_lower == %s", + local_filter_addr_lower)); + LOG_DBG((LOG_POLICY, 80, "local_filter == %s", + (local_filter ? local_filter : ""))); + LOG_DBG((LOG_POLICY, 80, "local_filter_port == %s", local_filter_port)); + LOG_DBG((LOG_POLICY, 80, "local_filter_proto == %s", + local_filter_proto)); + LOG_DBG((LOG_POLICY, 80, "remote_id_type == %s", remote_id_type)); + LOG_DBG((LOG_POLICY, 80, "remote_id_addr_upper == %s", + remote_id_addr_upper)); + LOG_DBG((LOG_POLICY, 80, "remote_id_addr_lower == %s", + remote_id_addr_lower)); + LOG_DBG((LOG_POLICY, 80, "remote_id == %s", + (remote_id ? remote_id : ""))); + LOG_DBG((LOG_POLICY, 80, "remote_id_port == %s", remote_id_port)); + LOG_DBG((LOG_POLICY, 80, "remote_id_proto == %s", remote_id_proto)); + LOG_DBG((LOG_POLICY, 80, "remote_negotiation_address == %s", + remote_ike_address)); + LOG_DBG((LOG_POLICY, 80, "local_negotiation_address == %s", + local_ike_address)); + LOG_DBG((LOG_POLICY, 80, "pfs == %s", pfs)); + LOG_DBG((LOG_POLICY, 80, "initiator == %s", initiator)); + LOG_DBG((LOG_POLICY, 80, "phase1_group_desc == %s", phase1_group)); + + /* Unset dirty now. */ + dirty = 0; + } + if (strcmp(name, "phase_1") == 0) + return phase_1; - snprintf (remote_filter_port, sizeof remote_filter_port, "%u", - decode_16 (idremote + ISAKMP_GEN_SZ + 2)); + if (strcmp(name, "GMTTimeOfDay") == 0) { + tt = time((time_t) NULL); + strftime(mytimeofday, 14, "%Y%m%d%H%M%S", gmtime(&tt)); + return mytimeofday; } - else - { - policy_sa->transport->vtbl->get_dst (policy_sa->transport, &sin); - switch (sin->sa_family) - { - case AF_INET: - remote_filter_type = "IPv4 address"; - break; - case AF_INET6: - remote_filter_type = "IPv6 address"; - break; - default: - log_print ("policy_callback: unsupported protocol family %d", - sin->sa_family); - goto bad; - } - if (sockaddr2text (sin, &addr, 1)) - { - log_error ("policy_callback: sockaddr2text failed"); - goto bad; - } - memcpy (remote_filter_addr_upper, addr, - sizeof remote_filter_addr_upper); - memcpy (remote_filter_addr_lower, addr, - sizeof remote_filter_addr_lower); - free (addr); - remote_filter = strdup (remote_filter_addr_upper); - if (!remote_filter) - { - log_error ("policy_callback: strdup (\"%s\") failed", - remote_filter_addr_upper); - goto bad; - } + if (strcmp(name, "LocalTimeOfDay") == 0) { + tt = time((time_t) NULL); + strftime(mytimeofday, 14, "%Y%m%d%H%M%S", localtime(&tt)); + return mytimeofday; } + if (strcmp(name, "initiator") == 0) + return initiator; - if (idlocal) - { - switch (GET_ISAKMP_ID_TYPE (idlocal)) - { - case IPSEC_ID_IPV4_ADDR: - local_filter_type = "IPv4 address"; - - net = decode_32 (idlocal + ISAKMP_ID_DATA_OFF); - my_inet_ntop4 (&net, local_filter_addr_upper, - sizeof local_filter_addr_upper - 1, 1); - my_inet_ntop4 (&net, local_filter_addr_lower, - sizeof local_filter_addr_upper - 1, 1); - local_filter = strdup (local_filter_addr_upper); - if (!local_filter) - { - log_error ("policy_callback: strdup (\"%s\") failed", - local_filter_addr_upper); - goto bad; - } - break; - - case IPSEC_ID_IPV4_RANGE: - local_filter_type = "IPv4 range"; - - net = decode_32 (idlocal + ISAKMP_ID_DATA_OFF); - my_inet_ntop4 (&net, local_filter_addr_lower, - sizeof local_filter_addr_lower - 1, 1); - net = decode_32 (idlocal + ISAKMP_ID_DATA_OFF + 4); - my_inet_ntop4 (&net, local_filter_addr_upper, - sizeof local_filter_addr_upper - 1, 1); - len = strlen (local_filter_addr_upper) - + strlen (local_filter_addr_lower) + 2; - local_filter = calloc (len, sizeof (char)); - if (!local_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - strlcpy (local_filter, local_filter_addr_lower, len); - strlcat (local_filter, "-", len); - strlcat (local_filter, local_filter_addr_upper, len); - break; - - case IPSEC_ID_IPV4_ADDR_SUBNET: - local_filter_type = "IPv4 subnet"; - - net = decode_32 (idlocal + ISAKMP_ID_DATA_OFF); - subnet = decode_32 (idlocal + ISAKMP_ID_DATA_OFF + 4); - net &= subnet; - my_inet_ntop4 (&net, local_filter_addr_lower, - sizeof local_filter_addr_lower - 1, 1); - net |= ~subnet; - my_inet_ntop4 (&net, local_filter_addr_upper, - sizeof local_filter_addr_upper - 1, 1); - len = strlen (local_filter_addr_upper) - + strlen (local_filter_addr_lower) + 2; - local_filter = calloc (len, sizeof (char)); - if (!local_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } - strlcpy (local_filter, local_filter_addr_lower, len); - strlcat (local_filter, "-", len); - strlcat (local_filter, local_filter_addr_upper, len); - break; - - case IPSEC_ID_IPV6_ADDR: - local_filter_type = "IPv6 address"; - my_inet_ntop6 (idlocal + ISAKMP_ID_DATA_OFF, - local_filter_addr_upper, - sizeof local_filter_addr_upper - 1); - strlcpy (local_filter_addr_lower, local_filter_addr_upper, - sizeof local_filter_addr_lower); - local_filter = strdup (local_filter_addr_upper); - if (!local_filter) - { - log_error ("policy_callback: strdup (\"%s\") failed", - local_filter_addr_upper); - goto bad; - } - break; + if (strcmp(name, "pfs") == 0) + return pfs; - case IPSEC_ID_IPV6_RANGE: - local_filter_type = "IPv6 range"; + if (strcmp(name, "app_domain") == 0) + return "IPsec policy"; - my_inet_ntop6 (idlocal + ISAKMP_ID_DATA_OFF, - local_filter_addr_lower, - sizeof local_filter_addr_lower - 1); + if (strcmp(name, "doi") == 0) + return "ipsec"; - my_inet_ntop6 (idlocal + ISAKMP_ID_DATA_OFF + 16, - local_filter_addr_upper, - sizeof local_filter_addr_upper - 1); + if (strcmp(name, "esp_present") == 0) + return esp_present; - len = strlen (local_filter_addr_upper) - + strlen (local_filter_addr_lower) + 2; - local_filter = calloc (len, sizeof (char)); - if (!local_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } + if (strcmp(name, "ah_present") == 0) + return ah_present; - strlcpy (local_filter, local_filter_addr_lower, len); - strlcat (local_filter, "-", len); - strlcat (local_filter, local_filter_addr_upper, len); - break; + if (strcmp(name, "comp_present") == 0) + return comp_present; - case IPSEC_ID_IPV6_ADDR_SUBNET: - { - struct in6_addr net, mask; + if (strcmp(name, "ah_hash_alg") == 0) + return ah_hash_alg; - local_filter_type = "IPv6 subnet"; + if (strcmp(name, "ah_auth_alg") == 0) + return ah_auth_alg; - bcopy (idlocal + ISAKMP_ID_DATA_OFF, &net, sizeof (net)); - bcopy (idlocal + ISAKMP_ID_DATA_OFF + 16, &mask, sizeof (mask)); + if (strcmp(name, "esp_auth_alg") == 0) + return esp_auth_alg; - for (i = 0; i < 16; i++) - net.s6_addr[i] &= mask.s6_addr[i]; + if (strcmp(name, "esp_enc_alg") == 0) + return esp_enc_alg; - my_inet_ntop6 ((unsigned char *) &net, local_filter_addr_lower, - sizeof local_filter_addr_lower - 1); + if (strcmp(name, "comp_alg") == 0) + return comp_alg; - for (i = 0; i < 16; i++) - net.s6_addr[i] |= ~mask.s6_addr[i]; + if (strcmp(name, "ah_life_kbytes") == 0) + return ah_life_kbytes; - my_inet_ntop6 ((unsigned char *) &net, local_filter_addr_upper, - sizeof local_filter_addr_upper - 1); + if (strcmp(name, "ah_life_seconds") == 0) + return ah_life_seconds; - len = strlen (local_filter_addr_upper) - + strlen (local_filter_addr_lower) + 2; - local_filter = calloc (len, sizeof (char)); - if (!local_filter) - { - log_error ("policy_callback: calloc (%d, %lu) failed", len, - (unsigned long)sizeof (char)); - goto bad; - } + if (strcmp(name, "esp_life_kbytes") == 0) + return esp_life_kbytes; - strlcpy (local_filter, local_filter_addr_lower, len); - strlcat (local_filter, "-", len); - strlcat (local_filter, local_filter_addr_upper, len); - break; - } - - case IPSEC_ID_FQDN: - local_filter_type = "FQDN"; - local_filter = malloc (idlocalsz - ISAKMP_ID_DATA_OFF + 1); - if (!local_filter) - { - log_error ("policy_callback: malloc (%lu) failed", - (unsigned long)idlocalsz - ISAKMP_ID_DATA_OFF + 1); - goto bad; - } - memcpy (local_filter, idlocal + ISAKMP_ID_DATA_OFF, - idlocalsz - ISAKMP_ID_DATA_OFF); - local_filter[idlocalsz - ISAKMP_ID_DATA_OFF] = '\0'; - break; - - case IPSEC_ID_USER_FQDN: - local_filter_type = "User FQDN"; - local_filter = malloc (idlocalsz - ISAKMP_ID_DATA_OFF + 1); - if (!local_filter) - { - log_error ("policy_callback: malloc (%lu) failed", - (unsigned long)idlocalsz - ISAKMP_ID_DATA_OFF + 1); - goto bad; - } - memcpy (local_filter, idlocal + ISAKMP_ID_DATA_OFF, - idlocalsz - ISAKMP_ID_DATA_OFF); - local_filter[idlocalsz - ISAKMP_ID_DATA_OFF] = '\0'; - break; - - case IPSEC_ID_DER_ASN1_DN: - local_filter_type = "ASN1 DN"; - - local_filter = x509_DN_string (idlocal + ISAKMP_ID_DATA_OFF, - idlocalsz - ISAKMP_ID_DATA_OFF); - if (!local_filter) - { - LOG_DBG ((LOG_POLICY, 50, - "policy_callback: failed to decode name")); - goto bad; - } - break; - - case IPSEC_ID_DER_ASN1_GN: - /* XXX -- not sure what's in this. */ - local_filter_type = "ASN1 GN"; - break; - - case IPSEC_ID_KEY_ID: - local_filter_type = "Key ID"; - local_filter = calloc (2 * (idlocalsz - ISAKMP_ID_DATA_OFF) + 1, - sizeof (char)); - if (!local_filter) - { - log_error ("policy_callback: calloc (%lu, %lu) failed", - 2 * ((unsigned long)idlocalsz - ISAKMP_ID_DATA_OFF) + 1, - (unsigned long)sizeof (char)); - goto bad; - } - /* Does it contain any non-printable characters ? */ - for (i = 0; i < idlocalsz - ISAKMP_ID_DATA_OFF; i++) - if (!isprint (*(idlocal + ISAKMP_ID_DATA_OFF + i))) - break; - if (i >= idlocalsz - ISAKMP_ID_DATA_OFF) - { - memcpy (local_filter, idlocal + ISAKMP_ID_DATA_OFF, - idlocalsz - ISAKMP_ID_DATA_OFF); - break; - } - /* Non-printable characters, convert to hex */ - for (i = 0; i < idlocalsz - ISAKMP_ID_DATA_OFF; i++) - { - local_filter[2 * i] - = hextab[*(idlocal + ISAKMP_ID_DATA_OFF) >> 4]; - local_filter[2 * i + 1] - = hextab[*(idlocal + ISAKMP_ID_DATA_OFF) & 0xF]; - } - break; - - default: - log_print ("policy_callback: unknown Local ID type %u", - GET_ISAKMP_ID_TYPE (idlocal)); - goto bad; - } - - switch (idlocal[ISAKMP_GEN_SZ + 1]) - { - case IPPROTO_TCP: - local_filter_proto = "tcp"; - break; - - case IPPROTO_UDP: - local_filter_proto = "udp"; - break; - -#ifdef IPPROTO_ETHERIP - case IPPROTO_ETHERIP: - local_filter_proto = "etherip"; - break; -#endif + if (strcmp(name, "esp_life_seconds") == 0) + return esp_life_seconds; - default: - snprintf (local_filter_proto_num, sizeof local_filter_proto_num, - "%d", idlocal[ISAKMP_GEN_SZ + 1]); - local_filter_proto = local_filter_proto_num; - break; - } + if (strcmp(name, "comp_life_kbytes") == 0) + return comp_life_kbytes; - snprintf (local_filter_port, sizeof local_filter_port, "%u", - decode_16 (idlocal + ISAKMP_GEN_SZ + 2)); - } - else - { - policy_sa->transport->vtbl->get_src (policy_sa->transport, - (struct sockaddr **)&sin); - switch (sin->sa_family) - { - case AF_INET: - local_filter_type = "IPv4 address"; - break; - case AF_INET6: - local_filter_type = "IPv6 address"; - break; - default: - log_print ("policy_callback: unsupported protocol family %d", - sin->sa_family); - goto bad; - } - - if (sockaddr2text (sin, &addr, 1)) - { - log_error ("policy_callback: sockaddr2text failed"); - goto bad; - } - memcpy (local_filter_addr_upper, addr, - sizeof local_filter_addr_upper); - memcpy (local_filter_addr_lower, addr, - sizeof local_filter_addr_lower); - free (addr); - local_filter = strdup (local_filter_addr_upper); - if (!local_filter) - { - log_error ("policy_callback: strdup (\"%s\") failed", - local_filter_addr_upper); - goto bad; - } - } - - LOG_DBG ((LOG_POLICY, 80, "Policy context (action attributes):")); - LOG_DBG ((LOG_POLICY, 80, "esp_present == %s", esp_present)); - LOG_DBG ((LOG_POLICY, 80, "ah_present == %s", ah_present)); - LOG_DBG ((LOG_POLICY, 80, "comp_present == %s", comp_present)); - LOG_DBG ((LOG_POLICY, 80, "ah_hash_alg == %s", ah_hash_alg)); - LOG_DBG ((LOG_POLICY, 80, "esp_enc_alg == %s", esp_enc_alg)); - LOG_DBG ((LOG_POLICY, 80, "comp_alg == %s", comp_alg)); - LOG_DBG ((LOG_POLICY, 80, "ah_auth_alg == %s", ah_auth_alg)); - LOG_DBG ((LOG_POLICY, 80, "esp_auth_alg == %s", esp_auth_alg)); - LOG_DBG ((LOG_POLICY, 80, "ah_life_seconds == %s", ah_life_seconds)); - LOG_DBG ((LOG_POLICY, 80, "ah_life_kbytes == %s", ah_life_kbytes)); - LOG_DBG ((LOG_POLICY, 80, "esp_life_seconds == %s", esp_life_seconds)); - LOG_DBG ((LOG_POLICY, 80, "esp_life_kbytes == %s", esp_life_kbytes)); - LOG_DBG ((LOG_POLICY, 80, "comp_life_seconds == %s", comp_life_seconds)); - LOG_DBG ((LOG_POLICY, 80, "comp_life_kbytes == %s", comp_life_kbytes)); - LOG_DBG ((LOG_POLICY, 80, "ah_encapsulation == %s", ah_encapsulation)); - LOG_DBG ((LOG_POLICY, 80, "esp_encapsulation == %s", esp_encapsulation)); - LOG_DBG ((LOG_POLICY, 80, "comp_encapsulation == %s", - comp_encapsulation)); - LOG_DBG ((LOG_POLICY, 80, "comp_dict_size == %s", comp_dict_size)); - LOG_DBG ((LOG_POLICY, 80, "comp_private_alg == %s", comp_private_alg)); - LOG_DBG ((LOG_POLICY, 80, "ah_key_length == %s", ah_key_length)); - LOG_DBG ((LOG_POLICY, 80, "ah_key_rounds == %s", ah_key_rounds)); - LOG_DBG ((LOG_POLICY, 80, "esp_key_length == %s", esp_key_length)); - LOG_DBG ((LOG_POLICY, 80, "esp_key_rounds == %s", esp_key_rounds)); - LOG_DBG ((LOG_POLICY, 80, "ah_group_desc == %s", ah_group_desc)); - LOG_DBG ((LOG_POLICY, 80, "esp_group_desc == %s", esp_group_desc)); - LOG_DBG ((LOG_POLICY, 80, "comp_group_desc == %s", comp_group_desc)); - LOG_DBG ((LOG_POLICY, 80, "ah_ecn == %s", ah_ecn)); - LOG_DBG ((LOG_POLICY, 80, "esp_ecn == %s", esp_ecn)); - LOG_DBG ((LOG_POLICY, 80, "comp_ecn == %s", comp_ecn)); - LOG_DBG ((LOG_POLICY, 80, "remote_filter_type == %s", - remote_filter_type)); - LOG_DBG ((LOG_POLICY, 80, "remote_filter_addr_upper == %s", - remote_filter_addr_upper)); - LOG_DBG ((LOG_POLICY, 80, "remote_filter_addr_lower == %s", - remote_filter_addr_lower)); - LOG_DBG ((LOG_POLICY, 80, "remote_filter == %s", - (remote_filter ? remote_filter : ""))); - LOG_DBG ((LOG_POLICY, 80, "remote_filter_port == %s", - remote_filter_port)); - LOG_DBG ((LOG_POLICY, 80, "remote_filter_proto == %s", - remote_filter_proto)); - LOG_DBG ((LOG_POLICY, 80, "local_filter_type == %s", local_filter_type)); - LOG_DBG ((LOG_POLICY, 80, "local_filter_addr_upper == %s", - local_filter_addr_upper)); - LOG_DBG ((LOG_POLICY, 80, "local_filter_addr_lower == %s", - local_filter_addr_lower)); - LOG_DBG ((LOG_POLICY, 80, "local_filter == %s", - (local_filter ? local_filter : ""))); - LOG_DBG ((LOG_POLICY, 80, "local_filter_port == %s", local_filter_port)); - LOG_DBG ((LOG_POLICY, 80, "local_filter_proto == %s", - local_filter_proto)); - LOG_DBG ((LOG_POLICY, 80, "remote_id_type == %s", remote_id_type)); - LOG_DBG ((LOG_POLICY, 80, "remote_id_addr_upper == %s", - remote_id_addr_upper)); - LOG_DBG ((LOG_POLICY, 80, "remote_id_addr_lower == %s", - remote_id_addr_lower)); - LOG_DBG ((LOG_POLICY, 80, "remote_id == %s", - (remote_id ? remote_id : ""))); - LOG_DBG ((LOG_POLICY, 80, "remote_id_port == %s", remote_id_port)); - LOG_DBG ((LOG_POLICY, 80, "remote_id_proto == %s", remote_id_proto)); - LOG_DBG ((LOG_POLICY, 80, "remote_negotiation_address == %s", - remote_ike_address)); - LOG_DBG ((LOG_POLICY, 80, "local_negotiation_address == %s", - local_ike_address)); - LOG_DBG ((LOG_POLICY, 80, "pfs == %s", pfs)); - LOG_DBG ((LOG_POLICY, 80, "initiator == %s", initiator)); - LOG_DBG ((LOG_POLICY, 80, "phase1_group_desc == %s", phase1_group)); - - /* Unset dirty now. */ - dirty = 0; - } - - if (strcmp (name, "phase_1") == 0) - return phase_1; - - if (strcmp (name, "GMTTimeOfDay") == 0) - { - tt = time ((time_t) NULL); - strftime (mytimeofday, 14, "%Y%m%d%H%M%S", gmtime (&tt)); - return mytimeofday; - } - - if (strcmp (name, "LocalTimeOfDay") == 0) - { - tt = time ((time_t) NULL); - strftime (mytimeofday, 14, "%Y%m%d%H%M%S", localtime (&tt)); - return mytimeofday; - } - - if (strcmp (name, "initiator") == 0) - return initiator; - - if (strcmp (name, "pfs") == 0) - return pfs; - - if (strcmp (name, "app_domain") == 0) - return "IPsec policy"; - - if (strcmp (name, "doi") == 0) - return "ipsec"; - - if (strcmp (name, "esp_present") == 0) - return esp_present; - - if (strcmp (name, "ah_present") == 0) - return ah_present; - - if (strcmp (name, "comp_present") == 0) - return comp_present; - - if (strcmp (name, "ah_hash_alg") == 0) - return ah_hash_alg; - - if (strcmp (name, "ah_auth_alg") == 0) - return ah_auth_alg; - - if (strcmp (name, "esp_auth_alg") == 0) - return esp_auth_alg; - - if (strcmp (name, "esp_enc_alg") == 0) - return esp_enc_alg; - - if (strcmp (name, "comp_alg") == 0) - return comp_alg; + if (strcmp(name, "comp_life_seconds") == 0) + return comp_life_seconds; - if (strcmp (name, "ah_life_kbytes") == 0) - return ah_life_kbytes; + if (strcmp(name, "ah_encapsulation") == 0) + return ah_encapsulation; - if (strcmp (name, "ah_life_seconds") == 0) - return ah_life_seconds; + if (strcmp(name, "esp_encapsulation") == 0) + return esp_encapsulation; - if (strcmp (name, "esp_life_kbytes") == 0) - return esp_life_kbytes; + if (strcmp(name, "comp_encapsulation") == 0) + return comp_encapsulation; - if (strcmp (name, "esp_life_seconds") == 0) - return esp_life_seconds; + if (strcmp(name, "ah_key_length") == 0) + return ah_key_length; - if (strcmp (name, "comp_life_kbytes") == 0) - return comp_life_kbytes; + if (strcmp(name, "ah_key_rounds") == 0) + return ah_key_rounds; - if (strcmp (name, "comp_life_seconds") == 0) - return comp_life_seconds; + if (strcmp(name, "esp_key_length") == 0) + return esp_key_length; - if (strcmp (name, "ah_encapsulation") == 0) - return ah_encapsulation; + if (strcmp(name, "esp_key_rounds") == 0) + return esp_key_rounds; - if (strcmp (name, "esp_encapsulation") == 0) - return esp_encapsulation; + if (strcmp(name, "comp_dict_size") == 0) + return comp_dict_size; - if (strcmp (name, "comp_encapsulation") == 0) - return comp_encapsulation; + if (strcmp(name, "comp_private_alg") == 0) + return comp_private_alg; - if (strcmp (name, "ah_key_length") == 0) - return ah_key_length; + if (strcmp(name, "remote_filter_type") == 0) + return remote_filter_type; - if (strcmp (name, "ah_key_rounds") == 0) - return ah_key_rounds; + if (strcmp(name, "remote_filter") == 0) + return (remote_filter ? remote_filter : ""); - if (strcmp (name, "esp_key_length") == 0) - return esp_key_length; + if (strcmp(name, "remote_filter_addr_upper") == 0) + return remote_filter_addr_upper; - if (strcmp (name, "esp_key_rounds") == 0) - return esp_key_rounds; + if (strcmp(name, "remote_filter_addr_lower") == 0) + return remote_filter_addr_lower; - if (strcmp (name, "comp_dict_size") == 0) - return comp_dict_size; + if (strcmp(name, "remote_filter_port") == 0) + return remote_filter_port; - if (strcmp (name, "comp_private_alg") == 0) - return comp_private_alg; + if (strcmp(name, "remote_filter_proto") == 0) + return remote_filter_proto; - if (strcmp (name, "remote_filter_type") == 0) - return remote_filter_type; + if (strcmp(name, "local_filter_type") == 0) + return local_filter_type; - if (strcmp (name, "remote_filter") == 0) - return (remote_filter ? remote_filter : ""); + if (strcmp(name, "local_filter") == 0) + return (local_filter ? local_filter : ""); - if (strcmp (name, "remote_filter_addr_upper") == 0) - return remote_filter_addr_upper; + if (strcmp(name, "local_filter_addr_upper") == 0) + return local_filter_addr_upper; - if (strcmp (name, "remote_filter_addr_lower") == 0) - return remote_filter_addr_lower; + if (strcmp(name, "local_filter_addr_lower") == 0) + return local_filter_addr_lower; - if (strcmp (name, "remote_filter_port") == 0) - return remote_filter_port; + if (strcmp(name, "local_filter_port") == 0) + return local_filter_port; - if (strcmp (name, "remote_filter_proto") == 0) - return remote_filter_proto; + if (strcmp(name, "local_filter_proto") == 0) + return local_filter_proto; - if (strcmp (name, "local_filter_type") == 0) - return local_filter_type; + if (strcmp(name, "remote_ike_address") == 0) + return remote_ike_address; - if (strcmp (name, "local_filter") == 0) - return (local_filter ? local_filter : ""); + if (strcmp(name, "remote_negotiation_address") == 0) + return remote_ike_address; - if (strcmp (name, "local_filter_addr_upper") == 0) - return local_filter_addr_upper; + if (strcmp(name, "local_ike_address") == 0) + return local_ike_address; - if (strcmp (name, "local_filter_addr_lower") == 0) - return local_filter_addr_lower; + if (strcmp(name, "local_negotiation_address") == 0) + return local_ike_address; - if (strcmp (name, "local_filter_port") == 0) - return local_filter_port; + if (strcmp(name, "remote_id_type") == 0) + return remote_id_type; - if (strcmp (name, "local_filter_proto") == 0) - return local_filter_proto; + if (strcmp(name, "remote_id") == 0) + return (remote_id ? remote_id : ""); - if (strcmp (name, "remote_ike_address") == 0) - return remote_ike_address; + if (strcmp(name, "remote_id_addr_upper") == 0) + return remote_id_addr_upper; - if (strcmp (name, "remote_negotiation_address") == 0) - return remote_ike_address; + if (strcmp(name, "remote_id_addr_lower") == 0) + return remote_id_addr_lower; - if (strcmp (name, "local_ike_address") == 0) - return local_ike_address; + if (strcmp(name, "remote_id_port") == 0) + return remote_id_port; - if (strcmp (name, "local_negotiation_address") == 0) - return local_ike_address; + if (strcmp(name, "remote_id_proto") == 0) + return remote_id_proto; - if (strcmp (name, "remote_id_type") == 0) - return remote_id_type; + if (strcmp(name, "phase1_group_desc") == 0) + return phase1_group; - if (strcmp (name, "remote_id") == 0) - return (remote_id ? remote_id : ""); + if (strcmp(name, "esp_group_desc") == 0) + return esp_group_desc; - if (strcmp (name, "remote_id_addr_upper") == 0) - return remote_id_addr_upper; + if (strcmp(name, "ah_group_desc") == 0) + return ah_group_desc; - if (strcmp (name, "remote_id_addr_lower") == 0) - return remote_id_addr_lower; + if (strcmp(name, "comp_group_desc") == 0) + return comp_group_desc; - if (strcmp (name, "remote_id_port") == 0) - return remote_id_port; + if (strcmp(name, "comp_ecn") == 0) + return comp_ecn; - if (strcmp (name, "remote_id_proto") == 0) - return remote_id_proto; + if (strcmp(name, "ah_ecn") == 0) + return ah_ecn; - if (strcmp (name, "phase1_group_desc") == 0) - return phase1_group; + if (strcmp(name, "esp_ecn") == 0) + return esp_ecn; - if (strcmp (name, "esp_group_desc") == 0) - return esp_group_desc; + return ""; - if (strcmp (name, "ah_group_desc") == 0) - return ah_group_desc; +bad: + policy_callback(KEYNOTE_CALLBACK_INITIALIZE); + return ""; +} - if (strcmp (name, "comp_group_desc") == 0) - return comp_group_desc; +void +policy_init(void) +{ + char *ptr, *policy_file; + char **asserts; + size_t sz, len; + int fd, i; + + LOG_DBG((LOG_POLICY, 30, "policy_init: initializing")); + + /* Get policy file from configuration. */ + policy_file = conf_get_str("General", "Policy-file"); + if (!policy_file) + policy_file = CONF_DFLT_POLICY_FILE; + + /* Check file modes and collect file size */ + if (check_file_secrecy(policy_file, &sz)) + log_fatal("policy_init: cannot read %s", policy_file); + + /* Open policy file. */ + fd = monitor_open(policy_file, O_RDONLY, 0); + if (fd == -1) + log_fatal("policy_init: open (\"%s\", O_RDONLY) failed", policy_file); + + /* Allocate memory to keep policies. */ + ptr = calloc(sz + 1, sizeof(char)); + if (!ptr) + log_fatal("policy_init: calloc (%lu, %lu) failed", (unsigned long) sz + 1, + (unsigned long) sizeof(char)); + + /* Just in case there are short reads... */ + for (len = 0; len < sz; len += i) { + i = read(fd, ptr + len, sz - len); + if (i == -1) + log_fatal("policy_init: read (%d, %p, %lu) failed", fd, ptr + len, + (unsigned long) (sz - len)); + } - if (strcmp (name, "comp_ecn") == 0) - return comp_ecn; + /* We're done with this. */ + close(fd); - if (strcmp (name, "ah_ecn") == 0) - return ah_ecn; + /* Parse buffer, break up into individual policies. */ + asserts = kn_read_asserts(ptr, sz, &i); - if (strcmp (name, "esp_ecn") == 0) - return esp_ecn; + /* Begone! */ + free(ptr); - return ""; + if (asserts == (char **) NULL) + log_print("policy_init: all policies flushed"); - bad: - policy_callback (KEYNOTE_CALLBACK_INITIALIZE); - return ""; -} + /* Cleanup */ + if (keynote_policy_asserts) { + for (fd = 0; fd < keynote_policy_asserts_num; fd++) + if (keynote_policy_asserts && keynote_policy_asserts[fd]) + free(keynote_policy_asserts[fd]); -void -policy_init (void) -{ - char *ptr, *policy_file; - char **asserts; - size_t sz, len; - int fd, i; - - LOG_DBG ((LOG_POLICY, 30, "policy_init: initializing")); - - /* Get policy file from configuration. */ - policy_file = conf_get_str ("General", "Policy-file"); - if (!policy_file) - policy_file = CONF_DFLT_POLICY_FILE; - - /* Check file modes and collect file size */ - if (check_file_secrecy (policy_file, &sz)) - log_fatal ("policy_init: cannot read %s", policy_file); - - /* Open policy file. */ - fd = monitor_open (policy_file, O_RDONLY, 0); - if (fd == -1) - log_fatal ("policy_init: open (\"%s\", O_RDONLY) failed", policy_file); - - /* Allocate memory to keep policies. */ - ptr = calloc (sz + 1, sizeof (char)); - if (!ptr) - log_fatal ("policy_init: calloc (%lu, %lu) failed", (unsigned long)sz + 1, - (unsigned long)sizeof (char)); - - /* Just in case there are short reads... */ - for (len = 0; len < sz; len += i) - { - i = read (fd, ptr + len, sz - len); - if (i == -1) - log_fatal ("policy_init: read (%d, %p, %lu) failed", fd, ptr + len, - (unsigned long)(sz - len)); - } - - /* We're done with this. */ - close (fd); - - /* Parse buffer, break up into individual policies. */ - asserts = kn_read_asserts (ptr, sz, &i); - - /* Begone! */ - free (ptr); - - if (asserts == (char **) NULL) - log_print ("policy_init: all policies flushed"); - - /* Cleanup */ - if (keynote_policy_asserts) - { - for (fd = 0; fd < keynote_policy_asserts_num; fd++) - if (keynote_policy_asserts && keynote_policy_asserts[fd]) - free (keynote_policy_asserts[fd]); - - free (keynote_policy_asserts); - } - - keynote_policy_asserts = asserts; - keynote_policy_asserts_num = i; + free(keynote_policy_asserts); + } + keynote_policy_asserts = asserts; + keynote_policy_asserts_num = i; } /* Nothing needed for initialization */ int -keynote_cert_init (void) +keynote_cert_init(void) { - return 1; + return 1; } /* Just copy and return. */ -void * -keynote_cert_get (u_int8_t *data, u_int32_t len) +void * +keynote_cert_get(u_int8_t * data, u_int32_t len) { - char *foo = malloc (len + 1); + char *foo = malloc(len + 1); - if (foo == NULL) - return NULL; + if (foo == NULL) + return NULL; - memcpy (foo, data, len); - foo[len] = '\0'; - return foo; + memcpy(foo, data, len); + foo[len] = '\0'; + return foo; } /* @@ -1928,312 +1840,283 @@ keynote_cert_get (u_int8_t *data, u_int32_t len) * On signature failure, just drop the whole payload. */ int -keynote_cert_validate (void *scert) +keynote_cert_validate(void *scert) { - char **foo; - int num, i; - - if (scert == NULL) - return 0; - - foo = kn_read_asserts ((char *) scert, strlen ((char *) scert), &num); - if (foo == NULL) - return 0; - - for (i = 0; i < num; i++) - { - if (kn_verify_assertion (scert, strlen ((char *) scert)) - != SIGRESULT_TRUE) - { - for (; i < num; i++) - free (foo[i]); - free (foo); - return 0; + char **foo; + int num, i; + + if (scert == NULL) + return 0; + + foo = kn_read_asserts((char *) scert, strlen((char *) scert), &num); + if (foo == NULL) + return 0; + + for (i = 0; i < num; i++) { + if (kn_verify_assertion(scert, strlen((char *) scert)) + != SIGRESULT_TRUE) { + for (; i < num; i++) + free(foo[i]); + free(foo); + return 0; + } + free(foo[i]); } - free (foo[i]); - } - - free (foo); - return 1; + free(foo); + return 1; } /* Add received credentials. */ int -keynote_cert_insert (int sid, void *scert) +keynote_cert_insert(int sid, void *scert) { - char **foo; - int num; + char **foo; + int num; - if (scert == NULL) - return 0; + if (scert == NULL) + return 0; - foo = kn_read_asserts ((char *) scert, strlen ((char *) scert), &num); - if (foo == NULL) - return 0; + foo = kn_read_asserts((char *) scert, strlen((char *) scert), &num); + if (foo == NULL) + return 0; - while (num--) - kn_add_assertion (sid, foo[num], strlen (foo[num]), 0); + while (num--) + kn_add_assertion(sid, foo[num], strlen(foo[num]), 0); - return 1; + return 1; } /* Just regular memory free. */ void -keynote_cert_free (void *cert) +keynote_cert_free(void *cert) { - free (cert); + free(cert); } /* Verify that the key given to us is valid. */ int -keynote_certreq_validate (u_int8_t *data, u_int32_t len) +keynote_certreq_validate(u_int8_t * data, u_int32_t len) { - struct keynote_deckey dc; - int err = 1; - char *dat; - - dat = calloc (len + 1, sizeof (char)); - if (!dat) - { - log_error ("keynote_certreq_validate: calloc (%d, %lu) failed", len + 1, - (unsigned long)sizeof (char)); - return 0; - } - - memcpy (dat, data, len); + struct keynote_deckey dc; + int err = 1; + char *dat; + + dat = calloc(len + 1, sizeof(char)); + if (!dat) { + log_error("keynote_certreq_validate: calloc (%d, %lu) failed", len + 1, + (unsigned long) sizeof(char)); + return 0; + } + memcpy(dat, data, len); - if (kn_decode_key (&dc, dat, KEYNOTE_PUBLIC_KEY) != 0) - err = 0; - else - kn_free_key (&dc); + if (kn_decode_key(&dc, dat, KEYNOTE_PUBLIC_KEY) != 0) + err = 0; + else + kn_free_key(&dc); - free (dat); + free(dat); - return err; + return err; } /* Beats me what we should be doing with this. */ -void * -keynote_certreq_decode (u_int8_t *data, u_int32_t len) +void * +keynote_certreq_decode(u_int8_t * data, u_int32_t len) { - /* XXX */ - return NULL; + /* XXX */ + return NULL; } void -keynote_free_aca (void *blob) +keynote_free_aca(void *blob) { - /* XXX */ + /* XXX */ } int -keynote_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, - u_int32_t *certlen) +keynote_cert_obtain(u_int8_t * id, size_t id_len, void *data, u_int8_t ** cert, + u_int32_t * certlen) { - char *dirname, *file, *addr_str; - struct stat sb; - size_t size; - int idtype, fd, len; - - if (!id) - { - log_print ("keynote_cert_obtain: ID is missing"); - return 0; - } - - /* Get type of ID. */ - idtype = id[0]; - id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; - id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; - - dirname = conf_get_str ("KeyNote", "Credential-directory"); - if (!dirname) - { - LOG_DBG ((LOG_POLICY, 30, - "keynote_cert_obtain: no Credential-directory")); - return 0; - } - - len = strlen (dirname) + strlen (CREDENTIAL_FILE) + 3; - - switch (idtype) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - util_ntoa (&addr_str, idtype == IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6, - id); - if (addr_str == 0) - return 0; + char *dirname, *file, *addr_str; + struct stat sb; + size_t size; + int idtype, fd, len; + + if (!id) { + log_print("keynote_cert_obtain: ID is missing"); + return 0; + } + /* Get type of ID. */ + idtype = id[0]; + id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + + dirname = conf_get_str("KeyNote", "Credential-directory"); + if (!dirname) { + LOG_DBG((LOG_POLICY, 30, + "keynote_cert_obtain: no Credential-directory")); + return 0; + } + len = strlen(dirname) + strlen(CREDENTIAL_FILE) + 3; - file = calloc (len + strlen (addr_str), sizeof (char)); - if (file == NULL) - { - log_error ("keynote_cert_obtain: failed to allocate %lu bytes", - (unsigned long)len + strlen (addr_str)); - free (addr_str); - return 0; + switch (idtype) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + util_ntoa(&addr_str, idtype == IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6, + id); + if (addr_str == 0) + return 0; + + file = calloc(len + strlen(addr_str), sizeof(char)); + if (file == NULL) { + log_error("keynote_cert_obtain: failed to allocate %lu bytes", + (unsigned long) len + strlen(addr_str)); + free(addr_str); + return 0; + } + snprintf(file, len + strlen(addr_str), "%s/%s/%s", dirname, addr_str, + CREDENTIAL_FILE); + free(addr_str); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + { + file = calloc(len + id_len, sizeof(char)); + if (file == NULL) { + log_error("keynote_cert_obtain: failed to allocate %lu bytes", + (unsigned long) len + id_len); + return 0; + } + snprintf(file, len + id_len, "%s/", dirname); + memcpy(file + strlen(dirname) + 1, id, id_len); + snprintf(file + strlen(dirname) + 1 + id_len, + len - strlen(dirname) - 1, "/%s", CREDENTIAL_FILE); + break; + } + + default: + return 0; } - snprintf (file, len + strlen (addr_str), "%s/%s/%s", dirname, addr_str, - CREDENTIAL_FILE); - free (addr_str); - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - { - file = calloc (len + id_len, sizeof (char)); - if (file == NULL) - { - log_error ("keynote_cert_obtain: failed to allocate %lu bytes", - (unsigned long)len + id_len); - return 0; - } - - snprintf (file, len + id_len, "%s/", dirname); - memcpy (file + strlen (dirname) + 1, id, id_len); - snprintf (file + strlen (dirname) + 1 + id_len, - len - strlen (dirname) - 1, "/%s", CREDENTIAL_FILE); - break; - } - - default: - return 0; - } - - if (monitor_stat (file, &sb) < 0) - { - LOG_DBG ((LOG_POLICY, 30, "keynote_cert_obtain: failed to stat \"%s\"", - file)); - free (file); - return 0; - } - size = (size_t)sb.st_size; - - *cert = calloc (size + 1, sizeof (char)); - if (*cert == NULL) - { - log_error ("keynote_cert_obtain: failed to allocate %lu bytes", - (unsigned long)size); - free (file); - return 0; - } - - fd = monitor_open (file, O_RDONLY, 0); - if (fd < 0) - { - LOG_DBG ((LOG_POLICY, 30, "keynote_cert_obtain: failed to open \"%s\"", - file)); - free (file); - return 0; - } - - if (read (fd, *cert, size) != (int)size) - { - LOG_DBG ((LOG_POLICY, 30, "keynote_cert_obtain: failed to read %lu " - "bytes from \"%s\"", (unsigned long)size, file)); - free (file); - close (fd); - return 0; - } - - close (fd); - free (file); - *certlen = size; - return 1; + if (monitor_stat(file, &sb) < 0) { + LOG_DBG((LOG_POLICY, 30, "keynote_cert_obtain: failed to stat \"%s\"", + file)); + free(file); + return 0; + } + size = (size_t) sb.st_size; + + *cert = calloc(size + 1, sizeof(char)); + if (*cert == NULL) { + log_error("keynote_cert_obtain: failed to allocate %lu bytes", + (unsigned long) size); + free(file); + return 0; + } + fd = monitor_open(file, O_RDONLY, 0); + if (fd < 0) { + LOG_DBG((LOG_POLICY, 30, "keynote_cert_obtain: failed to open \"%s\"", + file)); + free(file); + return 0; + } + if (read(fd, *cert, size) != (int) size) { + LOG_DBG((LOG_POLICY, 30, "keynote_cert_obtain: failed to read %lu " + "bytes from \"%s\"", (unsigned long) size, file)); + free(file); + close(fd); + return 0; + } + close(fd); + free(file); + *certlen = size; + return 1; } /* This should never be called. */ int -keynote_cert_get_subjects (void *scert, int *n, u_int8_t ***id, - u_int32_t **id_len) +keynote_cert_get_subjects(void *scert, int *n, u_int8_t ***id, + u_int32_t **id_len) { - return 0; + return 0; } /* Get the authorizer key. */ int -keynote_cert_get_key (void *scert, void *keyp) +keynote_cert_get_key(void *scert, void *keyp) { - struct keynote_keylist *kl; - int sid, kid, num; - char **foo; - - foo = kn_read_asserts ((char *)scert, strlen ((char *)scert), &num); - if (foo == NULL || num == 0) - { - log_print ("keynote_cert_get_key: failed to decompose credentials"); - return 0; - } - - kid = kn_init (); - if (kid == -1) - { - log_print ("keynote_cert_get_key: failed to initialize new policy " - "session"); - while (num--) - free (foo[num]); - free (foo); - return 0; - } - - sid = kn_add_assertion (kid, foo[num - 1], strlen (foo[num - 1]), 0); - while (num--) - free (foo[num]); - free (foo); - - if (sid == -1) - { - log_print ("keynote_cert_get_key: failed to add assertion"); - kn_close (kid); - return 0; - } - - *(RSA **)keyp = NULL; - - kl = kn_get_licensees (kid, sid); - while (kl) - { - if (kl->key_alg == KEYNOTE_ALGORITHM_RSA) - { - *(RSA **)keyp = RSAPublicKey_dup (kl->key_key); - break; + struct keynote_keylist *kl; + int sid, kid, num; + char **foo; + + foo = kn_read_asserts((char *) scert, strlen((char *) scert), &num); + if (foo == NULL || num == 0) { + log_print("keynote_cert_get_key: failed to decompose credentials"); + return 0; } + kid = kn_init(); + if (kid == -1) { + log_print("keynote_cert_get_key: failed to initialize new policy " + "session"); + while (num--) + free(foo[num]); + free(foo); + return 0; + } + sid = kn_add_assertion(kid, foo[num - 1], strlen(foo[num - 1]), 0); + while (num--) + free(foo[num]); + free(foo); + + if (sid == -1) { + log_print("keynote_cert_get_key: failed to add assertion"); + kn_close(kid); + return 0; + } + *(RSA **) keyp = NULL; - kl = kl->key_next; - } + kl = kn_get_licensees(kid, sid); + while (kl) { + if (kl->key_alg == KEYNOTE_ALGORITHM_RSA) { + *(RSA **) keyp = RSAPublicKey_dup(kl->key_key); + break; + } + kl = kl->key_next; + } - kn_remove_assertion (kid, sid); - kn_close (kid); - return *(RSA **)keyp == NULL ? 0 : 1; + kn_remove_assertion(kid, sid); + kn_close(kid); + return *(RSA **) keyp == NULL ? 0 : 1; } void * -keynote_cert_dup (void *cert) +keynote_cert_dup(void *cert) { - return strdup ((char *)cert); + return strdup((char *) cert); } void -keynote_serialize (void *cert, u_int8_t **data, u_int32_t *datalen) +keynote_serialize(void *cert, u_int8_t **data, u_int32_t *datalen) { - *datalen = strlen ((char *)cert) + 1; - *data = (u_int8_t *)strdup (cert); /* i.e an extra character at the end... */ - if (*data == NULL) - log_error ("keynote_serialize: malloc (%d) failed", *datalen); + *datalen = strlen((char *) cert) + 1; + *data = (u_int8_t *) strdup(cert); /* i.e an extra character at + * the end... */ + if (*data == NULL) + log_error("keynote_serialize: malloc (%d) failed", *datalen); } /* From cert to printable */ char * -keynote_printable (void *cert) +keynote_printable(void *cert) { - return strdup ((char *)cert); + return strdup((char *) cert); } /* From printable to cert */ void * -keynote_from_printable (char *cert) +keynote_from_printable(char *cert) { - return strdup (cert); + return strdup(cert); } diff --git a/sbin/isakmpd/policy.h b/sbin/isakmpd/policy.h index 8d9abbe3c46..4434f53c5bc 100644 --- a/sbin/isakmpd/policy.h +++ b/sbin/isakmpd/policy.h @@ -1,5 +1,5 @@ -/* $OpenBSD: policy.h,v 1.12 2003/06/04 07:31:17 ho Exp $ */ -/* $EOM: policy.h,v 1.12 2000/09/28 12:53:27 niklas Exp $ */ +/* $OpenBSD: policy.h,v 1.13 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: policy.h,v 1.12 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1999, 2000 Angelos D. Keromytis. All rights reserved. @@ -38,33 +38,35 @@ #define PRIVATE_KEY_FILE "private_key" #endif -extern int keynote_sessid; -extern int keynote_policy_asserts_num; -extern int x509_policy_asserts_num; -extern int x509_policy_asserts_num_alloc; -extern char **keynote_policy_asserts; -extern char **x509_policy_asserts; +extern int keynote_sessid; +extern int keynote_policy_asserts_num; +extern int x509_policy_asserts_num; +extern int x509_policy_asserts_num_alloc; +extern char **keynote_policy_asserts; +extern char **x509_policy_asserts; extern struct exchange *policy_exchange; extern struct sa *policy_sa; extern struct sa *policy_isakmp_sa; -extern void policy_init (void); -extern char *policy_callback (char *); -extern int keynote_cert_init (void); -extern void *keynote_cert_get (u_int8_t *, u_int32_t); -extern int keynote_cert_validate (void *); -extern int keynote_cert_insert (int, void *); -extern void keynote_cert_free (void *); -extern int keynote_certreq_validate (u_int8_t *, u_int32_t); -extern void *keynote_certreq_decode (u_int8_t *, u_int32_t); -extern void keynote_free_aca (void *); -extern int keynote_cert_obtain (u_int8_t *, size_t, void *, - u_int8_t **, u_int32_t *); -extern int keynote_cert_get_subjects (void *, int *, u_int8_t ***, - u_int32_t **); -extern int keynote_cert_get_key (void *, void *); -extern void *keynote_cert_dup (void *); -extern void keynote_serialize (void *, u_int8_t **, u_int32_t *); -extern char *keynote_printable (void *); -extern void *keynote_from_printable (char *); -#endif /* _POLICY_H_ */ +extern void policy_init(void); +extern char *policy_callback(char *); +extern int keynote_cert_init(void); +extern void *keynote_cert_get(u_int8_t *, u_int32_t); +extern int keynote_cert_validate(void *); +extern int keynote_cert_insert(int, void *); +extern void keynote_cert_free(void *); +extern int keynote_certreq_validate(u_int8_t *, u_int32_t); +extern void *keynote_certreq_decode(u_int8_t *, u_int32_t); +extern void keynote_free_aca(void *); +extern int +keynote_cert_obtain(u_int8_t *, size_t, void *, + u_int8_t **, u_int32_t *); +extern int +keynote_cert_get_subjects(void *, int *, u_int8_t ***, + u_int32_t **); +extern int keynote_cert_get_key(void *, void *); +extern void *keynote_cert_dup(void *); +extern void keynote_serialize(void *, u_int8_t **, u_int32_t *); +extern char *keynote_printable(void *); +extern void *keynote_from_printable(char *); +#endif /* _POLICY_H_ */ diff --git a/sbin/isakmpd/prf.c b/sbin/isakmpd/prf.c index 0c4a4c90781..c5d538a11b5 100644 --- a/sbin/isakmpd/prf.c +++ b/sbin/isakmpd/prf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: prf.c,v 1.12 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: prf.c,v 1.7 1999/05/02 12:50:29 niklas Exp $ */ +/* $OpenBSD: prf.c,v 1.13 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: prf.c,v 1.7 1999/05/02 12:50:29 niklas Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -40,30 +40,30 @@ #include "log.h" #include "prf.h" -void prf_hash_init (struct prf_hash_ctx *); -void prf_hash_update (struct prf_hash_ctx *, unsigned char *, unsigned int); -void prf_hash_final (unsigned char *, struct prf_hash_ctx *); +void prf_hash_init(struct prf_hash_ctx *); +void prf_hash_update(struct prf_hash_ctx *, unsigned char *, unsigned int); +void prf_hash_final(unsigned char *, struct prf_hash_ctx *); /* PRF behaves likes a hash */ void -prf_hash_init (struct prf_hash_ctx *ctx) +prf_hash_init(struct prf_hash_ctx *ctx) { - memcpy (ctx->hash->ctx, ctx->ctx, ctx->hash->ctxsize); - memcpy (ctx->hash->ctx2, ctx->ctx2, ctx->hash->ctxsize); + memcpy(ctx->hash->ctx, ctx->ctx, ctx->hash->ctxsize); + memcpy(ctx->hash->ctx2, ctx->ctx2, ctx->hash->ctxsize); } void -prf_hash_update (struct prf_hash_ctx *ctx, unsigned char *data, - unsigned int len) +prf_hash_update(struct prf_hash_ctx *ctx, unsigned char *data, + unsigned int len) { - ctx->hash->Update (ctx->hash->ctx, data, len); + ctx->hash->Update(ctx->hash->ctx, data, len); } void -prf_hash_final (unsigned char *digest, struct prf_hash_ctx *ctx) +prf_hash_final(unsigned char *digest, struct prf_hash_ctx *ctx) { - ctx->hash->HMACFinal (digest, ctx->hash); + ctx->hash->HMACFinal(digest, ctx->hash); } /* @@ -71,99 +71,89 @@ prf_hash_final (unsigned char *digest, struct prf_hash_ctx *ctx) * the HMAC version of a hash. See RFC-2104 for reference. */ struct prf * -prf_alloc (enum prfs type, int subtype, unsigned char *shared, - unsigned int sharedsize) +prf_alloc(enum prfs type, int subtype, unsigned char *shared, + unsigned int sharedsize) { - struct hash *hash; - struct prf *prf; - struct prf_hash_ctx *prfctx; - - switch (type) - { - case PRF_HMAC: - hash = hash_get (subtype); - if (!hash) - { - log_print ("prf_alloc: unknown hash type %d", subtype); - return 0; + struct hash *hash; + struct prf *prf; + struct prf_hash_ctx *prfctx; + + switch (type) { + case PRF_HMAC: + hash = hash_get(subtype); + if (!hash) { + log_print("prf_alloc: unknown hash type %d", subtype); + return 0; + } + break; + default: + log_print("prf_alloc: unknown PRF type %d", type); + return 0; } - break; - default: - log_print ("prf_alloc: unknown PRF type %d", type); - return 0; - } - - prf = malloc (sizeof *prf); - if (!prf) - { - log_error ("prf_alloc: malloc (%lu) failed", (unsigned long)sizeof *prf); - return 0; - } - - if (type == PRF_HMAC) - { - /* Obtain needed memory. */ - prfctx = malloc (sizeof *prfctx); - if (!prfctx) - { - log_error ("prf_alloc: malloc (%lu) failed", - (unsigned long)sizeof *prfctx); - goto cleanprf; - } - prf->prfctx = prfctx; - prfctx->ctx = malloc (hash->ctxsize); - if (!prfctx->ctx) - { - log_error ("prf_alloc: malloc (%d) failed", hash->ctxsize); - goto cleanprfctx; + prf = malloc(sizeof *prf); + if (!prf) { + log_error("prf_alloc: malloc (%lu) failed", + (unsigned long) sizeof *prf); + return 0; } - - prfctx->ctx2 = malloc (hash->ctxsize); - if (!prfctx->ctx2) - { - log_error ("prf_alloc: malloc (%d) failed", hash->ctxsize); - free (prfctx->ctx); - goto cleanprfctx; + if (type == PRF_HMAC) { + /* Obtain needed memory. */ + prfctx = malloc(sizeof *prfctx); + if (!prfctx) { + log_error("prf_alloc: malloc (%lu) failed", + (unsigned long) sizeof *prfctx); + goto cleanprf; + } + prf->prfctx = prfctx; + + prfctx->ctx = malloc(hash->ctxsize); + if (!prfctx->ctx) { + log_error("prf_alloc: malloc (%d) failed", hash->ctxsize); + goto cleanprfctx; + } + prfctx->ctx2 = malloc(hash->ctxsize); + if (!prfctx->ctx2) { + log_error("prf_alloc: malloc (%d) failed", hash->ctxsize); + free(prfctx->ctx); + goto cleanprfctx; + } + prf->type = PRF_HMAC; + prf->blocksize = hash->hashsize; + prfctx->hash = hash; + + /* Use the correct function pointers. */ + prf->Init = (void (*) (void *)) prf_hash_init; + prf->Update = (void (*) (void *, unsigned char *, + unsigned int)) prf_hash_update; + prf->Final = (void (*) (unsigned char *, void *)) prf_hash_final; + + /* Init HMAC contexts. */ + hash->HMACInit(hash, shared, sharedsize); + + /* Save contexts. */ + memcpy(prfctx->ctx, hash->ctx, hash->ctxsize); + memcpy(prfctx->ctx2, hash->ctx2, hash->ctxsize); } - prf->type = PRF_HMAC; - prf->blocksize = hash->hashsize; - prfctx->hash = hash; - - /* Use the correct function pointers. */ - prf->Init = (void (*) (void *))prf_hash_init; - prf->Update - = (void (*) (void *, unsigned char *, unsigned int))prf_hash_update; - prf->Final = (void (*) (unsigned char *, void *))prf_hash_final; - - /* Init HMAC contexts. */ - hash->HMACInit (hash, shared, sharedsize); - - /* Save contexts. */ - memcpy (prfctx->ctx, hash->ctx, hash->ctxsize); - memcpy (prfctx->ctx2, hash->ctx2, hash->ctxsize); - } - - return prf; - - cleanprfctx: - free (prf->prfctx); - cleanprf: - free (prf); - return 0; + return prf; + +cleanprfctx: + free(prf->prfctx); +cleanprf: + free(prf); + return 0; } /* Deallocate the PRF pointed to by PRF. */ void -prf_free (struct prf *prf) +prf_free(struct prf *prf) { - struct prf_hash_ctx *prfctx = prf->prfctx; - - if (prf->type == PRF_HMAC) - { - free (prfctx->ctx2); - free (prfctx->ctx); - } - free (prf->prfctx); - free (prf); + struct prf_hash_ctx *prfctx = prf->prfctx; + + if (prf->type == PRF_HMAC) { + free(prfctx->ctx2); + free(prfctx->ctx); + } + free(prf->prfctx); + free(prf); } diff --git a/sbin/isakmpd/prf.h b/sbin/isakmpd/prf.h index e2838f866f4..08a6fb3589c 100644 --- a/sbin/isakmpd/prf.h +++ b/sbin/isakmpd/prf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: prf.h,v 1.9 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: prf.h,v 1.1 1998/07/11 20:06:22 provos Exp $ */ +/* $OpenBSD: prf.h,v 1.10 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: prf.h,v 1.1 1998/07/11 20:06:22 provos Exp $ */ /* * Copyright (c) 1998 Niels Provos. All rights reserved. @@ -35,24 +35,24 @@ /* Enumeration of possible PRF - Pseudo-Random Functions. */ enum prfs { - PRF_HMAC = 0 /* No PRFs in drafts, this is the default */ + PRF_HMAC = 0 /* No PRFs in drafts, this is the default */ }; struct prf { - enum prfs type; /* Type of PRF */ - void *prfctx; /* Context for PRF */ - u_int8_t blocksize; /* The blocksize of PRF */ - void (*Init) (void *); - void (*Update) (void *, unsigned char *, unsigned int); - void (*Final) (unsigned char *, void *); + enum prfs type; /* Type of PRF */ + void *prfctx; /* Context for PRF */ + u_int8_t blocksize; /* The blocksize of PRF */ + void (*Init) (void *); + void (*Update) (void *, unsigned char *, unsigned int); + void (*Final) (unsigned char *, void *); }; struct prf_hash_ctx { - struct hash *hash; /* Hash type to use */ - void *ctx, *ctx2; /* Contexts we need for later */ + struct hash *hash; /* Hash type to use */ + void *ctx, *ctx2; /* Contexts we need for later */ }; -struct prf *prf_alloc (enum prfs, int, unsigned char *, unsigned int); -void prf_free (struct prf *); +struct prf *prf_alloc(enum prfs, int, unsigned char *, unsigned int); +void prf_free(struct prf *); -#endif /* _PRF_H_ */ +#endif /* _PRF_H_ */ diff --git a/sbin/isakmpd/sa.c b/sbin/isakmpd/sa.c index 35a11c6cbd7..fa00096d5ed 100644 --- a/sbin/isakmpd/sa.c +++ b/sbin/isakmpd/sa.c @@ -1,5 +1,5 @@ -/* $OpenBSD: sa.c,v 1.79 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $ */ +/* $OpenBSD: sa.c,v 1.80 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. @@ -38,7 +38,7 @@ #if defined (USE_KEYNOTE) || defined (USE_POLICY) #include <regex.h> #include <keynote.h> -#endif /* USE_KEYNOTE || USE_POLICY */ +#endif /* USE_KEYNOTE || USE_POLICY */ #include "sysdep.h" @@ -73,121 +73,116 @@ #define MAX_BUCKET_BITS 16 #if 0 -static void sa_resize (void); +static void sa_resize(void); #endif -static void sa_soft_expire (void *); -static void sa_hard_expire (void *); +static void sa_soft_expire(void *); +static void sa_hard_expire(void *); -static LIST_HEAD (sa_list, sa) *sa_tab; +static LIST_HEAD(sa_list, sa) *sa_tab; /* Works both as a maximum index and a mask. */ -static int bucket_mask; +static int bucket_mask; void -sa_init (void) +sa_init(void) { - int i; - - bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1; - sa_tab = malloc ((bucket_mask + 1) * sizeof (struct sa_list)); - if (!sa_tab) - log_fatal ("sa_init: malloc (%lu) failed", - (bucket_mask + 1) * (unsigned long)sizeof (struct sa_list)); - for (i = 0; i <= bucket_mask; i++) - { - LIST_INIT (&sa_tab[i]); - } + int i; + + bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1; + sa_tab = malloc((bucket_mask + 1) * sizeof(struct sa_list)); + if (!sa_tab) + log_fatal("sa_init: malloc (%lu) failed", + (bucket_mask + 1) * (unsigned long) sizeof(struct sa_list)); + for (i = 0; i <= bucket_mask; i++) { + LIST_INIT(&sa_tab[i]); + } } #if 0 /* XXX We don't yet resize. */ static void -sa_resize (void) +sa_resize(void) { - int new_mask = (bucket_mask + 1) * 2 - 1; - int i; - struct sa_list *new_tab; - - new_tab = realloc (sa_tab, (new_mask + 1) * sizeof (struct sa_list)); - if (!new_tab) - return; - sa_tab = new_tab; - for (i = bucket_mask + 1; i <= new_mask; i++) - { - LIST_INIT (&sa_tab[i]); - } - bucket_mask = new_mask; - - /* XXX Rehash existing entries. */ + int new_mask = (bucket_mask + 1) * 2 - 1; + int i; + struct sa_list *new_tab; + + new_tab = realloc(sa_tab, (new_mask + 1) * sizeof(struct sa_list)); + if (!new_tab) + return; + sa_tab = new_tab; + for (i = bucket_mask + 1; i <= new_mask; i++) { + LIST_INIT(&sa_tab[i]); + } + bucket_mask = new_mask; + + /* XXX Rehash existing entries. */ } #endif /* Lookup an SA with the help from a user-supplied checking function. */ struct sa * -sa_find (int (*check) (struct sa *, void *), void *arg) +sa_find(int (*check) (struct sa*, void *), void *arg) { - int i; - struct sa *sa; - - for (i = 0; i <= bucket_mask; i++) - for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = LIST_NEXT (sa, link)) - if (check (sa, arg)) - { - LOG_DBG ((LOG_SA, 90, "sa_find: return SA %p", sa)); - return sa; - } - LOG_DBG ((LOG_SA, 90, "sa_find: no SA matched query")); - return 0; + int i; + struct sa *sa; + + for (i = 0; i <= bucket_mask; i++) + for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = LIST_NEXT(sa, link)) + if (check(sa, arg)) { + LOG_DBG((LOG_SA, 90, "sa_find: return SA %p", sa)); + return sa; + } + LOG_DBG((LOG_SA, 90, "sa_find: no SA matched query")); + return 0; } /* Check if SA is an ISAKMP SA with an initiator cookie equal to ICOOKIE. */ static int -sa_check_icookie (struct sa *sa, void *icookie) +sa_check_icookie(struct sa *sa, void *icookie) { - return sa->phase == 1 - && memcmp (sa->cookies, icookie, ISAKMP_HDR_ICOOKIE_LEN) == 0; + return sa->phase == 1 + && memcmp(sa->cookies, icookie, ISAKMP_HDR_ICOOKIE_LEN) == 0; } /* Lookup an ISAKMP SA out of just the initiator cookie. */ -struct sa * -sa_lookup_from_icookie (u_int8_t *cookie) +struct sa * +sa_lookup_from_icookie(u_int8_t *cookie) { - return sa_find (sa_check_icookie, cookie); + return sa_find(sa_check_icookie, cookie); } struct name_phase_arg { - char *name; - u_int8_t phase; + char *name; + u_int8_t phase; }; /* Check if SA has the name and phase given by V_ARG. */ static int -sa_check_name_phase (struct sa *sa, void *v_arg) +sa_check_name_phase(struct sa *sa, void *v_arg) { - struct name_phase_arg *arg = v_arg; + struct name_phase_arg *arg = v_arg; - return sa->name && strcasecmp (sa->name, arg->name) == 0 && - sa->phase == arg->phase && !(sa->flags & SA_FLAG_REPLACED); + return sa->name && strcasecmp(sa->name, arg->name) == 0 && + sa->phase == arg->phase && !(sa->flags & SA_FLAG_REPLACED); } /* Lookup an SA by name, case-independent, and phase. */ struct sa * -sa_lookup_by_name (char *name, int phase) +sa_lookup_by_name(char *name, int phase) { - struct name_phase_arg arg; + struct name_phase_arg arg; - arg.name = name; - arg.phase = phase; - - return sa_find (sa_check_name_phase, &arg); + arg.name = name; + arg.phase = phase; + return sa_find(sa_check_name_phase, &arg); } -struct addr_arg -{ - struct sockaddr *addr; - socklen_t len; - int phase; - int flags; +struct addr_arg { + struct sockaddr *addr; + socklen_t len; + int phase; + int flags; }; /* @@ -196,23 +191,23 @@ struct addr_arg * that too. */ static int -sa_check_peer (struct sa *sa, void *v_addr) +sa_check_peer(struct sa *sa, void *v_addr) { - struct addr_arg *addr = v_addr; - struct sockaddr *dst; + struct addr_arg *addr = v_addr; + struct sockaddr *dst; - if (!sa->transport || (sa->flags & SA_FLAG_READY) == 0 - || (addr->phase && addr->phase != sa->phase)) - return 0; + if (!sa->transport || (sa->flags & SA_FLAG_READY) == 0 || + (addr->phase && addr->phase != sa->phase)) + return 0; - sa->transport->vtbl->get_dst (sa->transport, &dst); - return sysdep_sa_len (dst) == addr->len - && memcmp (dst, addr->addr, sysdep_sa_len (dst)) == 0; + sa->transport->vtbl->get_dst(sa->transport, &dst); + return sysdep_sa_len(dst) == addr->len && + memcmp(dst, addr->addr, sysdep_sa_len(dst)) == 0; } struct dst_isakmpspi_arg { - struct sockaddr *dst; - u_int8_t *spi; /* must be ISAKMP_SPI_SIZE octets */ + struct sockaddr *dst; + u_int8_t *spi; /* must be ISAKMP_SPI_SIZE octets */ }; /* @@ -220,105 +215,103 @@ struct dst_isakmpspi_arg { * be a finished phaes 1 (ISAKMP) SA. */ static int -isakmp_sa_check (struct sa *sa, void *v_arg) +isakmp_sa_check(struct sa * sa, void *v_arg) { - struct dst_isakmpspi_arg *arg = v_arg; - struct sockaddr *dst, *src; + struct dst_isakmpspi_arg *arg = v_arg; + struct sockaddr *dst, *src; - if (sa->phase != 1 || !(sa->flags & SA_FLAG_READY)) - return 0; + if (sa->phase != 1 || !(sa->flags & SA_FLAG_READY)) + return 0; - /* verify address is either src or dst for this sa */ - sa->transport->vtbl->get_dst (sa->transport, &dst); - sa->transport->vtbl->get_src (sa->transport, &src); - if (memcmp (src, arg->dst, sysdep_sa_len (src)) && - memcmp (dst, arg->dst, sysdep_sa_len (dst))) - return 0; + /* verify address is either src or dst for this sa */ + sa->transport->vtbl->get_dst(sa->transport, &dst); + sa->transport->vtbl->get_src(sa->transport, &src); + if (memcmp(src, arg->dst, sysdep_sa_len(src)) && + memcmp(dst, arg->dst, sysdep_sa_len(dst))) + return 0; - /* match icookie+rcookie against spi */ - if (memcmp (sa->cookies, arg->spi, ISAKMP_HDR_COOKIES_LEN) == 0) - return 1; + /* match icookie+rcookie against spi */ + if (memcmp(sa->cookies, arg->spi, ISAKMP_HDR_COOKIES_LEN) == 0) + return 1; - return 0; + return 0; } /* * Find an ISAKMP SA with a "name" of DST & SPI. */ struct sa * -sa_lookup_isakmp_sa (struct sockaddr *dst, u_int8_t *spi) +sa_lookup_isakmp_sa(struct sockaddr * dst, u_int8_t * spi) { - struct dst_isakmpspi_arg arg; + struct dst_isakmpspi_arg arg; - arg.dst = dst; - arg.spi = spi; + arg.dst = dst; + arg.spi = spi; - return sa_find (isakmp_sa_check, &arg); + return sa_find(isakmp_sa_check, &arg); } /* Lookup a ready SA by the peer's address. */ struct sa * -sa_lookup_by_peer (struct sockaddr *dst, socklen_t dstlen) +sa_lookup_by_peer(struct sockaddr * dst, socklen_t dstlen) { - struct addr_arg arg; + struct addr_arg arg; - arg.addr = dst; - arg.len = dstlen; - arg.phase = 0; + arg.addr = dst; + arg.len = dstlen; + arg.phase = 0; - return sa_find (sa_check_peer, &arg); + return sa_find(sa_check_peer, &arg); } /* Lookup a ready ISAKMP SA given its peer address. */ struct sa * -sa_isakmp_lookup_by_peer (struct sockaddr *dst, socklen_t dstlen) +sa_isakmp_lookup_by_peer(struct sockaddr * dst, socklen_t dstlen) { - struct addr_arg arg; + struct addr_arg arg; - arg.addr = dst; - arg.len = dstlen; - arg.phase = 1; + arg.addr = dst; + arg.len = dstlen; + arg.phase = 1; - return sa_find (sa_check_peer, &arg); + return sa_find(sa_check_peer, &arg); } int -sa_enter (struct sa *sa) +sa_enter(struct sa *sa) { - u_int16_t bucket = 0; - int i; - u_int8_t *cp; - - /* XXX We might resize if we are crossing a certain threshold */ - - for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2) - { - cp = sa->cookies + i; - /* Doing it this way avoids alignment problems. */ - bucket ^= cp[0] | cp[1] << 8; - } - for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2) - { - cp = sa->message_id + i; - /* Doing it this way avoids alignment problems. */ - bucket ^= cp[0] | cp[1] << 8; - } - bucket &= bucket_mask; - LIST_INSERT_HEAD (&sa_tab[bucket], sa, link); - sa_reference (sa); - LOG_DBG ((LOG_SA, 70, "sa_enter: SA %p added to SA list", sa)); - return 1; + u_int16_t bucket = 0; + int i; + u_int8_t *cp; + + /* XXX We might resize if we are crossing a certain threshold */ + + for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2) { + cp = sa->cookies + i; + /* Doing it this way avoids alignment problems. */ + bucket ^= cp[0] | cp[1] << 8; + } + for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2) { + cp = sa->message_id + i; + /* Doing it this way avoids alignment problems. */ + bucket ^= cp[0] | cp[1] << 8; + } + bucket &= bucket_mask; + LIST_INSERT_HEAD(&sa_tab[bucket], sa, link); + sa_reference(sa); + LOG_DBG((LOG_SA, 70, "sa_enter: SA %p added to SA list", sa)); + return 1; } /* * Lookup the SA given by the header fields MSG. PHASE2 is false when * looking for phase 1 SAa and true otherwise. */ -struct sa * -sa_lookup_by_header (u_int8_t *msg, int phase2) +struct sa * +sa_lookup_by_header(u_int8_t * msg, int phase2) { - return sa_lookup (msg + ISAKMP_HDR_COOKIES_OFF, - phase2 ? msg + ISAKMP_HDR_MESSAGE_ID_OFF : 0); + return sa_lookup(msg + ISAKMP_HDR_COOKIES_OFF, + phase2 ? msg + ISAKMP_HDR_MESSAGE_ID_OFF : 0); } /* @@ -326,97 +319,92 @@ sa_lookup_by_header (u_int8_t *msg, int phase2) * a null pointer, meaning we are looking for phase 1 SAs. */ struct sa * -sa_lookup (u_int8_t *cookies, u_int8_t *message_id) +sa_lookup(u_int8_t *cookies, u_int8_t *message_id) { - u_int16_t bucket = 0; - int i; - struct sa *sa; - u_int8_t *cp; - - /* - * We use the cookies to get bits to use as an index into sa_tab, as at - * least one (our cookie) is a good hash, xoring all the bits, 16 at a - * time, and then masking, should do. Doing it this way means we can - * validate cookies very fast thus delimiting the effects of "Denial of - * service"-attacks using packet flooding. - */ - for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2) - { - cp = cookies + i; - /* Doing it this way avoids alignment problems. */ - bucket ^= cp[0] | cp[1] << 8; - } - if (message_id) - for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2) - { - cp = message_id + i; - /* Doing it this way avoids alignment problems. */ - bucket ^= cp[0] | cp[1] << 8; - } - bucket &= bucket_mask; - for (sa = LIST_FIRST (&sa_tab[bucket]); - sa && (memcmp (cookies, sa->cookies, ISAKMP_HDR_COOKIES_LEN) != 0 - || (message_id && memcmp (message_id, sa->message_id, - ISAKMP_HDR_MESSAGE_ID_LEN) - != 0) - || (!message_id && !zero_test (sa->message_id, - ISAKMP_HDR_MESSAGE_ID_LEN))); - sa = LIST_NEXT (sa, link)) - ; - - return sa; + u_int16_t bucket = 0; + int i; + struct sa *sa; + u_int8_t *cp; + + /* + * We use the cookies to get bits to use as an index into sa_tab, as at + * least one (our cookie) is a good hash, xoring all the bits, 16 at a + * time, and then masking, should do. Doing it this way means we can + * validate cookies very fast thus delimiting the effects of "Denial of + * service"-attacks using packet flooding. + */ + for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2) { + cp = cookies + i; + /* Doing it this way avoids alignment problems. */ + bucket ^= cp[0] | cp[1] << 8; + } + if (message_id) + for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2) { + cp = message_id + i; + /* Doing it this way avoids alignment problems. */ + bucket ^= cp[0] | cp[1] << 8; + } + bucket &= bucket_mask; + for (sa = LIST_FIRST(&sa_tab[bucket]); + sa && (memcmp(cookies, sa->cookies, ISAKMP_HDR_COOKIES_LEN) != 0 || + (message_id && memcmp(message_id, sa->message_id, + ISAKMP_HDR_MESSAGE_ID_LEN) != 0) || + (!message_id && !zero_test(sa->message_id, ISAKMP_HDR_MESSAGE_ID_LEN))); + sa = LIST_NEXT(sa, link)) + ; + + return sa; } /* Create an SA. */ int -sa_create (struct exchange *exchange, struct transport *t) +sa_create(struct exchange * exchange, struct transport * t) { - struct sa *sa; - - /* - * We want the SA zeroed for sa_free to be able to find out what fields - * have been filled-in. - */ - sa = calloc (1, sizeof *sa); - if (!sa) - { - log_error ("sa_create: calloc (1, %lu) failed", - (unsigned long)sizeof *sa); - return -1; - } - sa->transport = t; - if (t) - transport_reference (t); - sa->phase = exchange->phase; - memcpy (sa->cookies, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); - memcpy (sa->message_id, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); - sa->doi = exchange->doi; - sa->policy_id = -1; - - if (sa->doi->sa_size) - { - /* Allocate the DOI-specific structure and initialize it to zeroes. */ - sa->data = calloc (1, sa->doi->sa_size); - if (!sa->data) - { - log_error ("sa_create: calloc (1, %lu) failed", - (unsigned long)sa->doi->sa_size); - free (sa); - return -1; + struct sa *sa; + + /* + * We want the SA zeroed for sa_free to be able to find out what fields + * have been filled-in. + */ + sa = calloc(1, sizeof *sa); + if (!sa) { + log_error("sa_create: calloc (1, %lu) failed", + (unsigned long) sizeof *sa); + return -1; } - } - - TAILQ_INIT (&sa->protos); + sa->transport = t; + if (t) + transport_reference(t); + sa->phase = exchange->phase; + memcpy(sa->cookies, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); + memcpy(sa->message_id, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + sa->doi = exchange->doi; + sa->policy_id = -1; + + if (sa->doi->sa_size) { + /* + * Allocate the DOI-specific structure and initialize it to + * zeroes. + */ + sa->data = calloc(1, sa->doi->sa_size); + if (!sa->data) { + log_error("sa_create: calloc (1, %lu) failed", + (unsigned long) sa->doi->sa_size); + free(sa); + return -1; + } + } + TAILQ_INIT(&sa->protos); - sa_enter (sa); - TAILQ_INSERT_TAIL (&exchange->sa_list, sa, next); - sa_reference (sa); + sa_enter(sa); + TAILQ_INSERT_TAIL(&exchange->sa_list, sa, next); + sa_reference(sa); - LOG_DBG ((LOG_SA, 60, + LOG_DBG((LOG_SA, 60, "sa_create: sa %p phase %d added to exchange %p (%s)", sa, sa->phase, exchange, exchange->name ? exchange->name : "<unnamed>")); - return 0; + return 0; } /* @@ -424,80 +412,74 @@ sa_create (struct exchange *exchange, struct transport *t) * prepended to each line. */ void -sa_dump (int cls, int level, char *header, struct sa *sa) +sa_dump(int cls, int level, char *header, struct sa * sa) { - struct proto *proto; - char spi_header[80]; - int i; + struct proto *proto; + char spi_header[80]; + int i; - LOG_DBG ((cls, level, "%s: %p %s phase %d doi %d flags 0x%x", header, sa, + LOG_DBG((cls, level, "%s: %p %s phase %d doi %d flags 0x%x", header, sa, sa->name ? sa->name : "<unnamed>", sa->phase, sa->doi->id, sa->flags)); - LOG_DBG ((cls, level, "%s: icookie %08x%08x rcookie %08x%08x", header, - decode_32 (sa->cookies), decode_32 (sa->cookies + 4), - decode_32 (sa->cookies + 8), decode_32 (sa->cookies + 12))); - LOG_DBG ((cls, level, "%s: msgid %08x refcnt %d", header, - decode_32 (sa->message_id), sa->refcnt)); - LOG_DBG ((cls, level, "%s: life secs %llu kb %llu", header, sa->seconds, + LOG_DBG((cls, level, "%s: icookie %08x%08x rcookie %08x%08x", header, + decode_32(sa->cookies), decode_32(sa->cookies + 4), + decode_32(sa->cookies + 8), decode_32(sa->cookies + 12))); + LOG_DBG((cls, level, "%s: msgid %08x refcnt %d", header, + decode_32(sa->message_id), sa->refcnt)); + LOG_DBG((cls, level, "%s: life secs %llu kb %llu", header, sa->seconds, sa->kilobytes)); - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - LOG_DBG ((cls, level, "%s: suite %d proto %d", header, proto->no, - proto->proto)); - LOG_DBG ((cls, level, - "%s: spi_sz[0] %d spi[0] %p spi_sz[1] %d spi[1] %p", header, - proto->spi_sz[0], proto->spi[0], proto->spi_sz[1], - proto->spi[1])); - LOG_DBG ((cls, level, "%s: %s, %s", header, - !sa->doi ? "<nodoi>" - : sa->doi->decode_ids ("initiator id: %s, responder id: %s", - sa->id_i, sa->id_i_len, - sa->id_r, sa->id_r_len, 0), - !sa->transport ? "<no transport>" : - sa->transport->vtbl->decode_ids (sa->transport))); - for (i = 0; i < 2; i++) - if (proto->spi[i]) - { - snprintf (spi_header, sizeof spi_header, "%s: spi[%d]", header, i); - LOG_DBG_BUF ((cls, level, spi_header, proto->spi[i], - proto->spi_sz[i])); - } - } + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + LOG_DBG((cls, level, "%s: suite %d proto %d", header, proto->no, + proto->proto)); + LOG_DBG((cls, level, + "%s: spi_sz[0] %d spi[0] %p spi_sz[1] %d spi[1] %p", header, + proto->spi_sz[0], proto->spi[0], proto->spi_sz[1], + proto->spi[1])); + LOG_DBG((cls, level, "%s: %s, %s", header, + !sa->doi ? "<nodoi>" : + sa->doi->decode_ids("initiator id: %s, responder id: %s", + sa->id_i, sa->id_i_len, + sa->id_r, sa->id_r_len, 0), + !sa->transport ? "<no transport>" : + sa->transport->vtbl->decode_ids(sa->transport))); + for (i = 0; i < 2; i++) + if (proto->spi[i]) { + snprintf(spi_header, sizeof spi_header, + "%s: spi[%d]", header, i); + LOG_DBG_BUF((cls, level, spi_header, proto->spi[i], + proto->spi_sz[i])); + } + } } /* * Display the SA's two SPI values. */ static void -report_spi (FILE *fd, const u_int8_t *buf, size_t sz, int spi) +report_spi(FILE *fd, const u_int8_t *buf, size_t sz, int spi) { #define SBUFSZ (2 * 32 + 9) - char s[SBUFSZ]; - size_t i, j; - - for (i = j = 0; i < sz;) - { - snprintf (s + j, sizeof s - j, "%02x", buf[i++]); - j += 2; - if (i % 4 == 0) - { - if (i % 32 == 0) - { - s[j] = '\0'; - fprintf (fd, "%s", s); - j = 0; - } - else - s[j++] = ' '; + char s[SBUFSZ]; + size_t i, j; + + for (i = j = 0; i < sz;) { + snprintf(s + j, sizeof s - j, "%02x", buf[i++]); + j += 2; + if (i % 4 == 0) { + if (i % 32 == 0) { + s[j] = '\0'; + fprintf(fd, "%s", s); + j = 0; + } else + s[j++] = ' '; + } } - } - if (j) - { - s[j] = '\0'; - fprintf (fd, "SPI %d: %s\n", spi, s); - } + if (j) { + s[j] = '\0'; + fprintf(fd, "SPI %d: %s\n", spi, s); + } } @@ -507,144 +489,140 @@ report_spi (FILE *fd, const u_int8_t *buf, size_t sz, int spi) * Transform names are taken from /usr/src/sys/crypto/xform.c. */ static void -report_proto (FILE *fd, struct proto *proto) +report_proto(FILE * fd, struct proto * proto) { - int keylen, hashlen; - struct ipsec_proto *iproto = proto->data; - - switch (proto->proto) - { - case IPSEC_PROTO_IPSEC_ESP: - keylen = ipsec_esp_enckeylength (proto); - hashlen = ipsec_esp_authkeylength (proto); - fprintf (fd, "Transform: IPsec ESP\n"); - fprintf (fd, "Encryption key length: %d\n", keylen); - fprintf (fd, "Authentication key length: %d\n", hashlen); - - fprintf (fd, "Encryption algorithm: "); - switch (proto->id) - { - case IPSEC_ESP_DES: - case IPSEC_ESP_DES_IV32: - case IPSEC_ESP_DES_IV64: - fprintf (fd, "DES\n"); - break; - - case IPSEC_ESP_3DES: - fprintf (fd, "3DES\n"); - break; - - case IPSEC_ESP_AES: - fprintf (fd, "AES-128 (CBC)\n"); - break; - - case IPSEC_ESP_AES_128_CTR: - fprintf (fd, "AES-128 (CTR)\n"); - break; - - case IPSEC_ESP_CAST: - fprintf (fd, "Cast-128\n"); - break; - - case IPSEC_ESP_BLOWFISH: - fprintf (fd, "Blowfish\n"); - break; - - default: - fprintf (fd, "unknown (%d)\n", proto->id); - } - - fprintf (fd, "Authentication algorithm: "); - switch (iproto->auth) - { - case IPSEC_AUTH_HMAC_MD5: - fprintf (fd, "HMAC-MD5\n"); - break; - - case IPSEC_AUTH_HMAC_SHA: - fprintf (fd, "HMAC-SHA1\n"); - break; - - case IPSEC_AUTH_HMAC_RIPEMD: - fprintf (fd, "HMAC-RIPEMD-160\n"); - break; - - case IPSEC_AUTH_HMAC_SHA2_256: - fprintf (fd, "HMAC-SHA2-256\n"); - break; - - case IPSEC_AUTH_HMAC_SHA2_384: - fprintf (fd, "HMAC-SHA2-384\n"); - break; - - case IPSEC_AUTH_HMAC_SHA2_512: - fprintf (fd, "HMAC-SHA2-512\n"); - break; - - case IPSEC_AUTH_DES_MAC: - case IPSEC_AUTH_KPDK: - /* XXX We should be supporting KPDK */ - fprintf (fd, "unknown (%d)", iproto->auth); - break; + int keylen, hashlen; + struct ipsec_proto *iproto = proto->data; + + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_ESP: + keylen = ipsec_esp_enckeylength(proto); + hashlen = ipsec_esp_authkeylength(proto); + fprintf(fd, "Transform: IPsec ESP\n"); + fprintf(fd, "Encryption key length: %d\n", keylen); + fprintf(fd, "Authentication key length: %d\n", hashlen); + + fprintf(fd, "Encryption algorithm: "); + switch (proto->id) { + case IPSEC_ESP_DES: + case IPSEC_ESP_DES_IV32: + case IPSEC_ESP_DES_IV64: + fprintf(fd, "DES\n"); + break; + + case IPSEC_ESP_3DES: + fprintf(fd, "3DES\n"); + break; + + case IPSEC_ESP_AES: + fprintf(fd, "AES-128 (CBC)\n"); + break; + + case IPSEC_ESP_AES_128_CTR: + fprintf(fd, "AES-128 (CTR)\n"); + break; + + case IPSEC_ESP_CAST: + fprintf(fd, "Cast-128\n"); + break; + + case IPSEC_ESP_BLOWFISH: + fprintf(fd, "Blowfish\n"); + break; + + default: + fprintf(fd, "unknown (%d)\n", proto->id); + } + + fprintf(fd, "Authentication algorithm: "); + switch (iproto->auth) { + case IPSEC_AUTH_HMAC_MD5: + fprintf(fd, "HMAC-MD5\n"); + break; + + case IPSEC_AUTH_HMAC_SHA: + fprintf(fd, "HMAC-SHA1\n"); + break; + + case IPSEC_AUTH_HMAC_RIPEMD: + fprintf(fd, "HMAC-RIPEMD-160\n"); + break; + + case IPSEC_AUTH_HMAC_SHA2_256: + fprintf(fd, "HMAC-SHA2-256\n"); + break; + + case IPSEC_AUTH_HMAC_SHA2_384: + fprintf(fd, "HMAC-SHA2-384\n"); + break; + + case IPSEC_AUTH_HMAC_SHA2_512: + fprintf(fd, "HMAC-SHA2-512\n"); + break; + + case IPSEC_AUTH_DES_MAC: + case IPSEC_AUTH_KPDK: + /* XXX We should be supporting KPDK */ + fprintf(fd, "unknown (%d)", iproto->auth); + break; + + default: + fprintf(fd, "none\n"); + } + break; + + case IPSEC_PROTO_IPSEC_AH: + hashlen = ipsec_ah_keylength(proto); + fprintf(fd, "Transform: IPsec AH\n"); + fprintf(fd, "Encryption not used.\n"); + fprintf(fd, "Authentication key length: %d\n", hashlen); + + fprintf(fd, "Authentication algorithm: "); + switch (proto->id) { + case IPSEC_AH_MD5: + fprintf(fd, "HMAC-MD5\n"); + break; + + case IPSEC_AH_SHA: + fprintf(fd, "HMAC-SHA1\n"); + break; + + case IPSEC_AH_RIPEMD: + fprintf(fd, "HMAC-RIPEMD-160\n"); + break; + + case IPSEC_AH_SHA2_256: + fprintf(fd, "HMAC-SHA2-256\n"); + break; + + case IPSEC_AH_SHA2_384: + fprintf(fd, "HMAC-SHA2-384\n"); + break; + + case IPSEC_AH_SHA2_512: + fprintf(fd, "HMAC-SHA2-512\n"); + break; + + default: + fprintf(fd, "unknown (%d)", proto->id); + } + break; default: - fprintf (fd, "none\n"); + fprintf(fd, "report_proto: invalid proto %d\n", proto->proto); } - break; - - case IPSEC_PROTO_IPSEC_AH: - hashlen = ipsec_ah_keylength (proto); - fprintf (fd, "Transform: IPsec AH\n"); - fprintf (fd, "Encryption not used.\n"); - fprintf (fd, "Authentication key length: %d\n", hashlen); - - fprintf (fd, "Authentication algorithm: "); - switch (proto->id) - { - case IPSEC_AH_MD5: - fprintf (fd, "HMAC-MD5\n"); - break; - - case IPSEC_AH_SHA: - fprintf (fd, "HMAC-SHA1\n"); - break; - - case IPSEC_AH_RIPEMD: - fprintf (fd, "HMAC-RIPEMD-160\n"); - break; - - case IPSEC_AH_SHA2_256: - fprintf (fd, "HMAC-SHA2-256\n"); - break; - - case IPSEC_AH_SHA2_384: - fprintf (fd, "HMAC-SHA2-384\n"); - break; - - case IPSEC_AH_SHA2_512: - fprintf (fd, "HMAC-SHA2-512\n"); - break; - - default: - fprintf (fd, "unknown (%d)", proto->id); - } - break; - - default: - fprintf (fd, "report_proto: invalid proto %d\n", proto->proto); - } } /* Report all the SAs to the report channel. */ void -sa_report (void) +sa_report(void) { - int i; - struct sa *sa; + int i; + struct sa *sa; - for (i = 0; i <= bucket_mask; i++) - for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = LIST_NEXT (sa, link)) - sa_dump (LOG_REPORT, 0, "sa_report", sa); + for (i = 0; i <= bucket_mask; i++) + for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = LIST_NEXT(sa, link)) + sa_dump(LOG_REPORT, 0, "sa_report", sa); } @@ -652,188 +630,179 @@ sa_report (void) * Print an SA's connection details to file SA_FILE. */ static void -sa_dump_all (FILE *fd, struct sa *sa) +sa_dump_all(FILE * fd, struct sa * sa) { - struct proto *proto; - int i; - - /* SA name and phase. */ - fprintf (fd, "SA name: %s", sa->name ? sa->name : "<unnamed>"); - fprintf (fd, " (Phase %d)\n", sa->phase); - - /* Source and destination IPs. */ - fprintf (fd, sa->transport == NULL ? "<no transport>" : - sa->transport->vtbl->decode_ids (sa->transport)); - fprintf (fd, "\n"); - - /* Transform information. */ - for (proto = TAILQ_FIRST (&sa->protos); proto; - proto = TAILQ_NEXT (proto, link)) - { - /* SPI values. */ - for (i = 0; i < 2; i++) - if (proto->spi[i]) - report_spi (fd, proto->spi[i], proto->spi_sz[i], i); - else - fprintf (fd, "SPI %d not defined.", i); - - /* Proto values. */ - report_proto (fd, proto); - - /* SA separator. */ - fprintf (fd, "\n"); - } + struct proto *proto; + int i; + + /* SA name and phase. */ + fprintf(fd, "SA name: %s", sa->name ? sa->name : "<unnamed>"); + fprintf(fd, " (Phase %d)\n", sa->phase); + + /* Source and destination IPs. */ + fprintf(fd, sa->transport == NULL ? "<no transport>" : + sa->transport->vtbl->decode_ids(sa->transport)); + fprintf(fd, "\n"); + + /* Transform information. */ + for (proto = TAILQ_FIRST(&sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + /* SPI values. */ + for (i = 0; i < 2; i++) + if (proto->spi[i]) + report_spi(fd, proto->spi[i], proto->spi_sz[i], i); + else + fprintf(fd, "SPI %d not defined.", i); + + /* Proto values. */ + report_proto(fd, proto); + + /* SA separator. */ + fprintf(fd, "\n"); + } } /* Report info of all SAs to file SA_FILE. */ void -sa_report_all (void) +sa_report_all(void) { - int i; - FILE *fd; - struct sa *sa; - - /* Open SA_FILE. */ - fd = monitor_fopen (SA_FILE, "w"); - - /* Start sa_config_report. */ - for (i = 0; i <= bucket_mask; i++) - for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = LIST_NEXT (sa, link)) - if (sa->phase == 1) - fprintf (fd, "SA name: none (phase 1)\n\n"); - else - sa_dump_all (fd, sa); - - /* End sa_config_report. */ - fclose (fd); + int i; + FILE *fd; + struct sa *sa; + + /* Open SA_FILE. */ + fd = monitor_fopen(SA_FILE, "w"); + + /* Start sa_config_report. */ + for (i = 0; i <= bucket_mask; i++) + for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = LIST_NEXT(sa, link)) + if (sa->phase == 1) + fprintf(fd, "SA name: none (phase 1)\n\n"); + else + sa_dump_all(fd, sa); + + /* End sa_config_report. */ + fclose(fd); } /* Free the protocol structure pointed to by PROTO. */ void -proto_free (struct proto *proto) +proto_free(struct proto * proto) { - int i; - struct sa *sa = proto->sa; - struct proto_attr *pa; - - for (i = 0; i < 2; i++) - if (proto->spi[i]) - { - if (sa->doi->delete_spi) - sa->doi->delete_spi (sa, proto, i); - free (proto->spi[i]); - } - TAILQ_REMOVE (&sa->protos, proto, link); - if (proto->data) - { - if (sa->doi && sa->doi->free_proto_data) - sa->doi->free_proto_data (proto->data); - free (proto->data); - } - if (proto->xf_cnt) - while ((pa = TAILQ_FIRST (&proto->xfs)) != NULL) - { - if (pa->attrs) - free (pa->attrs); - TAILQ_REMOVE (&proto->xfs, pa, next); - free (pa); - } - - LOG_DBG ((LOG_SA, 90, "proto_free: freeing %p", proto)); - free (proto); + int i; + struct sa *sa = proto->sa; + struct proto_attr *pa; + + for (i = 0; i < 2; i++) + if (proto->spi[i]) { + if (sa->doi->delete_spi) + sa->doi->delete_spi(sa, proto, i); + free(proto->spi[i]); + } + TAILQ_REMOVE(&sa->protos, proto, link); + if (proto->data) { + if (sa->doi && sa->doi->free_proto_data) + sa->doi->free_proto_data(proto->data); + free(proto->data); + } + if (proto->xf_cnt) + while ((pa = TAILQ_FIRST(&proto->xfs)) != NULL) { + if (pa->attrs) + free(pa->attrs); + TAILQ_REMOVE(&proto->xfs, pa, next); + free(pa); + } + + LOG_DBG((LOG_SA, 90, "proto_free: freeing %p", proto)); + free(proto); } /* Release all resources this SA is using. */ void -sa_free (struct sa *sa) +sa_free(struct sa *sa) { - if (sa->death) - { - timer_remove_event (sa->death); - sa->death = 0; - sa->refcnt--; - } - if (sa->soft_death) - { - timer_remove_event (sa->soft_death); - sa->soft_death = 0; - sa->refcnt--; - } - sa_remove (sa); + if (sa->death) { + timer_remove_event(sa->death); + sa->death = 0; + sa->refcnt--; + } + if (sa->soft_death) { + timer_remove_event(sa->soft_death); + sa->soft_death = 0; + sa->refcnt--; + } + sa_remove(sa); } /* Remove the SA from the hash table of live SAs. */ void -sa_remove (struct sa *sa) +sa_remove(struct sa *sa) { - LIST_REMOVE (sa, link); - LOG_DBG ((LOG_SA, 70, "sa_remove: SA %p removed from SA list", sa)); - sa_release (sa); + LIST_REMOVE(sa, link); + LOG_DBG((LOG_SA, 70, "sa_remove: SA %p removed from SA list", sa)); + sa_release(sa); } /* Raise the reference count of SA. */ void -sa_reference (struct sa *sa) +sa_reference(struct sa * sa) { - sa->refcnt++; - LOG_DBG ((LOG_SA, 80, "sa_reference: SA %p now has %d references", + sa->refcnt++; + LOG_DBG((LOG_SA, 80, "sa_reference: SA %p now has %d references", sa, sa->refcnt)); } /* Release a reference to SA. */ void -sa_release (struct sa *sa) +sa_release(struct sa * sa) { - struct proto *proto; - struct cert_handler *handler; + struct proto *proto; + struct cert_handler *handler; - LOG_DBG ((LOG_SA, 80, "sa_release: SA %p had %d references", + LOG_DBG((LOG_SA, 80, "sa_release: SA %p had %d references", sa, sa->refcnt)); - if (--sa->refcnt) - return; - - LOG_DBG ((LOG_SA, 60, "sa_release: freeing SA %p", sa)); - - while ((proto = TAILQ_FIRST (&sa->protos)) != 0) - proto_free (proto); - if (sa->data) - { - if (sa->doi && sa->doi->free_sa_data) - sa->doi->free_sa_data (sa->data); - free (sa->data); - } - if (sa->id_i) - free (sa->id_i); - if (sa->id_r) - free (sa->id_r); - if (sa->recv_cert) - { - handler = cert_get (sa->recv_certtype); - if (handler) - handler->cert_free (sa->recv_cert); - } - if (sa->sent_cert) - { - handler = cert_get (sa->sent_certtype); - if (handler) - handler->cert_free (sa->sent_cert); - } - if (sa->recv_key) - key_free (sa->recv_keytype, ISAKMP_KEYTYPE_PUBLIC, sa->recv_key); - if (sa->keynote_key) - free (sa->keynote_key); /* This is just a string */ + if (--sa->refcnt) + return; + + LOG_DBG((LOG_SA, 60, "sa_release: freeing SA %p", sa)); + + while ((proto = TAILQ_FIRST(&sa->protos)) != 0) + proto_free(proto); + if (sa->data) { + if (sa->doi && sa->doi->free_sa_data) + sa->doi->free_sa_data(sa->data); + free(sa->data); + } + if (sa->id_i) + free(sa->id_i); + if (sa->id_r) + free(sa->id_r); + if (sa->recv_cert) { + handler = cert_get(sa->recv_certtype); + if (handler) + handler->cert_free(sa->recv_cert); + } + if (sa->sent_cert) { + handler = cert_get(sa->sent_certtype); + if (handler) + handler->cert_free(sa->sent_cert); + } + if (sa->recv_key) + key_free(sa->recv_keytype, ISAKMP_KEYTYPE_PUBLIC, sa->recv_key); + if (sa->keynote_key) + free(sa->keynote_key); /* This is just a string */ #if defined (USE_POLICY) || defined (USE_KEYNOTE) - if (sa->policy_id != -1) - kn_close (sa->policy_id); + if (sa->policy_id != -1) + kn_close(sa->policy_id); #endif - if (sa->name) - free (sa->name); - if (sa->keystate) - free (sa->keystate); - if (sa->transport) - transport_release (sa->transport); - free (sa); + if (sa->name) + free(sa->name); + if (sa->keystate) + free(sa->keystate); + if (sa->transport) + transport_release(sa->transport); + free(sa); } /* @@ -841,143 +810,134 @@ sa_release (struct sa *sa) * filled in. */ void -sa_isakmp_upgrade (struct message *msg) +sa_isakmp_upgrade(struct message * msg) { - struct sa *sa = TAILQ_FIRST (&msg->exchange->sa_list); - - sa_remove (sa); - GET_ISAKMP_HDR_RCOOKIE (msg->iov[0].iov_base, - sa->cookies + ISAKMP_HDR_ICOOKIE_LEN); - - /* - * We don't install a transport in the initiator case as we don't know - * what local address will be chosen. Do it now instead. - */ - sa->transport = msg->transport; - transport_reference (sa->transport); - sa_enter (sa); + struct sa *sa = TAILQ_FIRST(&msg->exchange->sa_list); + + sa_remove(sa); + GET_ISAKMP_HDR_RCOOKIE(msg->iov[0].iov_base, + sa->cookies + ISAKMP_HDR_ICOOKIE_LEN); + + /* + * We don't install a transport in the initiator case as we don't know + * what local address will be chosen. Do it now instead. + */ + sa->transport = msg->transport; + transport_reference(sa->transport); + sa_enter(sa); } -#define ATTRS_SIZE (IKE_ATTR_BLOCK_SIZE + 1) /* XXX Should be dynamic. */ +#define ATTRS_SIZE (IKE_ATTR_BLOCK_SIZE + 1) /* XXX Should be dynamic. */ struct attr_validation_state { - u_int8_t *attrp[ATTRS_SIZE]; - u_int8_t checked[ATTRS_SIZE]; - int phase; /* IKE (1) or IPSEC (2) attrs? */ - int mode; /* 0 = 'load', 1 = check */ + u_int8_t *attrp[ATTRS_SIZE]; + u_int8_t checked[ATTRS_SIZE]; + int phase; /* IKE (1) or IPSEC (2) attrs? */ + int mode; /* 0 = 'load', 1 = check */ }; /* Validate an attribute. Return 0 on match. */ static int -sa_validate_xf_attrs (u_int16_t type, u_int8_t *value, u_int16_t len, - void *arg) +sa_validate_xf_attrs(u_int16_t type, u_int8_t * value, u_int16_t len, + void *arg) { - struct attr_validation_state *avs = (struct attr_validation_state *)arg; + struct attr_validation_state *avs = (struct attr_validation_state *) arg; - LOG_DBG ((LOG_SA, 95, "sa_validate_xf_attrs: phase %d mode %d type %d " + LOG_DBG((LOG_SA, 95, "sa_validate_xf_attrs: phase %d mode %d type %d " "len %d", avs->phase, avs->mode, type, len)); - /* Make sure the phase and type are valid. */ - if (avs->phase == 1) - { - if (type < IKE_ATTR_ENCRYPTION_ALGORITHM || type > IKE_ATTR_BLOCK_SIZE) - return 1; - } - else if (avs->phase == 2) - { - if (type < IPSEC_ATTR_SA_LIFE_TYPE || type > IPSEC_ATTR_ECN_TUNNEL) - return 1; - } - else - return 1; - - if (avs->mode == 0) /* Load attrs. */ - { - avs->attrp[type] = value; - return 0; - } - - /* Checking for a missing attribute is an immediate failure. */ - if (!avs->attrp[type]) - return 1; - - /* Match the loaded attribute against this one, mark it as checked. */ - avs->checked[type]++; - return memcmp (avs->attrp[type], value, len); + /* Make sure the phase and type are valid. */ + if (avs->phase == 1) { + if (type < IKE_ATTR_ENCRYPTION_ALGORITHM || type > IKE_ATTR_BLOCK_SIZE) + return 1; + } else if (avs->phase == 2) { + if (type < IPSEC_ATTR_SA_LIFE_TYPE || type > IPSEC_ATTR_ECN_TUNNEL) + return 1; + } else + return 1; + + if (avs->mode == 0) { /* Load attrs. */ + avs->attrp[type] = value; + return 0; + } + /* Checking for a missing attribute is an immediate failure. */ + if (!avs->attrp[type]) + return 1; + + /* Match the loaded attribute against this one, mark it as checked. */ + avs->checked[type]++; + return memcmp(avs->attrp[type], value, len); } /* * This function is used to validate the returned proposal (protection suite) * we get from the responder against a proposal we sent. Only run as initiator. - * We return 0 if a match is found (in any transform of this proposal), 1 + * We return 0 if a match is found (in any transform of this proposal), 1 * otherwise. Also see note in sa_add_transform() below. */ static int -sa_validate_proto_xf (struct proto *match, struct payload *xf, int phase) +sa_validate_proto_xf(struct proto * match, struct payload * xf, int phase) { - struct proto_attr *pa; - struct attr_validation_state *avs; - int found = 0; - size_t i; - u_int8_t xf_id; - - if (!match->xf_cnt) - return 0; - - if (match->proto != GET_ISAKMP_PROP_PROTO (xf->context->p)) - { - LOG_DBG ((LOG_SA, 70, "sa_validate_proto_xf: proto %p (#%d) " - "protocol mismatch", match, match->no)); - return 1; - } - - avs = (struct attr_validation_state *)calloc (1, sizeof *avs); - if (!avs) - { - log_error ("sa_validate_proto_xf: calloc (1, %lu)", - (unsigned long)sizeof *avs); - return 1; - } - avs->phase = phase; - - /* Load the "proposal candidate" attribute set. */ - (void)attribute_map (xf->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - GET_ISAKMP_GEN_LENGTH (xf->p) - - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - sa_validate_xf_attrs, avs); - xf_id = GET_ISAKMP_TRANSFORM_ID (xf->p); - - /* Check against the transforms we suggested. */ - avs->mode++; - for (pa = TAILQ_FIRST (&match->xfs); pa && !found; - pa = TAILQ_NEXT (pa, next)) - { - if (xf_id != GET_ISAKMP_TRANSFORM_ID (pa->attrs)) - continue; - - memset (avs->checked, 0, sizeof avs->checked); - if (attribute_map (pa->attrs + ISAKMP_TRANSFORM_SA_ATTRS_OFF, - pa->len - ISAKMP_TRANSFORM_SA_ATTRS_OFF, - sa_validate_xf_attrs, avs) == 0) - found++; - - LOG_DBG ((LOG_SA, 80, "sa_validate_proto_xf: attr_map " - "xf %p proto %p pa %p found %d", xf, match, pa, found)); - - if (!found) - continue; - - /* Require all attributes present and checked. XXX perhaps not? */ - for (i = 0; i < sizeof avs->checked; i++) - if (avs->attrp[i] && !avs->checked[i]) - found = 0; - - LOG_DBG ((LOG_SA, 80, "sa_validate_proto_xf: req_attr " - "xf %p proto %p pa %p found %d", xf, match, pa, found)); - } - free (avs); - - return found ? 0 : 1; + struct proto_attr *pa; + struct attr_validation_state *avs; + int found = 0; + size_t i; + u_int8_t xf_id; + + if (!match->xf_cnt) + return 0; + + if (match->proto != GET_ISAKMP_PROP_PROTO(xf->context->p)) { + LOG_DBG((LOG_SA, 70, "sa_validate_proto_xf: proto %p (#%d) " + "protocol mismatch", match, match->no)); + return 1; + } + avs = (struct attr_validation_state *) calloc(1, sizeof *avs); + if (!avs) { + log_error("sa_validate_proto_xf: calloc (1, %lu)", + (unsigned long) sizeof *avs); + return 1; + } + avs->phase = phase; + + /* Load the "proposal candidate" attribute set. */ + (void) attribute_map(xf->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH(xf->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + sa_validate_xf_attrs, avs); + xf_id = GET_ISAKMP_TRANSFORM_ID(xf->p); + + /* Check against the transforms we suggested. */ + avs->mode++; + for (pa = TAILQ_FIRST(&match->xfs); pa && !found; + pa = TAILQ_NEXT(pa, next)) { + if (xf_id != GET_ISAKMP_TRANSFORM_ID(pa->attrs)) + continue; + + memset(avs->checked, 0, sizeof avs->checked); + if (attribute_map(pa->attrs + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + pa->len - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + sa_validate_xf_attrs, avs) == 0) + found++; + + LOG_DBG((LOG_SA, 80, "sa_validate_proto_xf: attr_map " + "xf %p proto %p pa %p found %d", xf, match, pa, found)); + + if (!found) + continue; + + /* + * Require all attributes present and checked. XXX perhaps + * not? + */ + for (i = 0; i < sizeof avs->checked; i++) + if (avs->attrp[i] && !avs->checked[i]) + found = 0; + + LOG_DBG((LOG_SA, 80, "sa_validate_proto_xf: req_attr " + "xf %p proto %p pa %p found %d", xf, match, pa, found)); + } + free(avs); + return found ? 0 : 1; } /* @@ -986,227 +946,229 @@ sa_validate_proto_xf (struct proto *match, struct payload *xf, int phase) * are the initiator. */ int -sa_add_transform (struct sa *sa, struct payload *xf, int initiator, - struct proto **protop) +sa_add_transform(struct sa * sa, struct payload * xf, int initiator, + struct proto ** protop) { - struct proto *proto; - struct payload *prop = xf->context; - - *protop = 0; - if (!initiator) - { - proto = calloc (1, sizeof *proto); - if (!proto) - log_error ("sa_add_transform: calloc (1, %lu) failed", - (unsigned long)sizeof *proto); - } - else - { - /* - * RFC 2408, section 4.2 states the responder SHOULD use the proposal - * number from the initiator (i.e us), in it's selected proposal to make - * this lookup easier. Most vendors follow this. One noted exception is - * the CiscoPIX (and perhaps other Cisco products). - * - * We start by matching on the proposal number, as before. - */ - for (proto = TAILQ_FIRST (&sa->protos); - proto && proto->no != GET_ISAKMP_PROP_NO (prop->p); - proto = TAILQ_NEXT (proto, link)) - ; - /* - * If we did not find a match, search through all proposals and xforms. - */ - if (!proto || sa_validate_proto_xf (proto, xf, sa->phase) != 0) - for (proto = TAILQ_FIRST (&sa->protos); - proto && sa_validate_proto_xf (proto, xf, sa->phase) != 0; - proto = TAILQ_NEXT (proto, link)) - ; - } - if (!proto) - return -1; - *protop = proto; - - /* Allocate DOI-specific part. */ - if (!initiator) - { - proto->data = calloc (1, sa->doi->proto_size); - if (!proto->data) - { - log_error ("sa_add_transform: calloc (1, %lu) failed", - (unsigned long)sa->doi->proto_size); - goto cleanup; + struct proto *proto; + struct payload *prop = xf->context; + + *protop = 0; + if (!initiator) { + proto = calloc(1, sizeof *proto); + if (!proto) + log_error("sa_add_transform: calloc (1, %lu) failed", + (unsigned long) sizeof *proto); + } else { + /* + * RFC 2408, section 4.2 states the responder SHOULD use the proposal + * number from the initiator (i.e us), in it's selected proposal to make + * this lookup easier. Most vendors follow this. One noted exception is + * the CiscoPIX (and perhaps other Cisco products). + * + * We start by matching on the proposal number, as before. + */ + for (proto = TAILQ_FIRST(&sa->protos); + proto && proto->no != GET_ISAKMP_PROP_NO(prop->p); + proto = TAILQ_NEXT(proto, link)) + ; + /* + * If we did not find a match, search through all proposals and xforms. + */ + if (!proto || sa_validate_proto_xf(proto, xf, sa->phase) != 0) + for (proto = TAILQ_FIRST(&sa->protos); + proto && sa_validate_proto_xf(proto, xf, sa->phase) != 0; + proto = TAILQ_NEXT(proto, link)) + ; + } + if (!proto) + return -1; + *protop = proto; + + /* Allocate DOI-specific part. */ + if (!initiator) { + proto->data = calloc(1, sa->doi->proto_size); + if (!proto->data) { + log_error("sa_add_transform: calloc (1, %lu) failed", + (unsigned long) sa->doi->proto_size); + goto cleanup; + } } - } - - proto->no = GET_ISAKMP_PROP_NO (prop->p); - proto->proto = GET_ISAKMP_PROP_PROTO (prop->p); - proto->spi_sz[0] = GET_ISAKMP_PROP_SPI_SZ (prop->p); - if (proto->spi_sz[0]) - { - proto->spi[0] = malloc (proto->spi_sz[0]); - if (!proto->spi[0]) - goto cleanup; - memcpy (proto->spi[0], prop->p + ISAKMP_PROP_SPI_OFF, proto->spi_sz[0]); - } - proto->chosen = xf; - proto->sa = sa; - proto->id = GET_ISAKMP_TRANSFORM_ID (xf->p); - if (!initiator) - TAILQ_INSERT_TAIL (&sa->protos, proto, link); - - /* Let the DOI get at proto for initializing its own data. */ - if (sa->doi->proto_init) - sa->doi->proto_init (proto, 0); - - LOG_DBG ((LOG_SA, 80, + proto->no = GET_ISAKMP_PROP_NO(prop->p); + proto->proto = GET_ISAKMP_PROP_PROTO(prop->p); + proto->spi_sz[0] = GET_ISAKMP_PROP_SPI_SZ(prop->p); + if (proto->spi_sz[0]) { + proto->spi[0] = malloc(proto->spi_sz[0]); + if (!proto->spi[0]) + goto cleanup; + memcpy(proto->spi[0], prop->p + ISAKMP_PROP_SPI_OFF, proto->spi_sz[0]); + } + proto->chosen = xf; + proto->sa = sa; + proto->id = GET_ISAKMP_TRANSFORM_ID(xf->p); + if (!initiator) + TAILQ_INSERT_TAIL(&sa->protos, proto, link); + + /* Let the DOI get at proto for initializing its own data. */ + if (sa->doi->proto_init) + sa->doi->proto_init(proto, 0); + + LOG_DBG((LOG_SA, 80, "sa_add_transform: " "proto %p no %d proto %d chosen %p sa %p id %d", proto, proto->no, proto->proto, proto->chosen, proto->sa, proto->id)); - return 0; - - cleanup: - if (!initiator) - { - if (proto->data) - free (proto->data); - free (proto); - } - *protop = 0; - return -1; + return 0; + +cleanup: + if (!initiator) { + if (proto->data) + free(proto->data); + free(proto); + } + *protop = 0; + return -1; } /* Delete an SA. Tell the peer if NOTIFY is set. */ void -sa_delete (struct sa *sa, int notify) +sa_delete(struct sa * sa, int notify) { - /* Don't bother notifying of Phase 1 SA deletes. */ - if (sa->phase != 1 && notify) - message_send_delete (sa); - sa_free (sa); + /* Don't bother notifying of Phase 1 SA deletes. */ + if (sa->phase != 1 && notify) + message_send_delete(sa); + sa_free(sa); } /* Teardown all SAs. */ void -sa_teardown_all (void) +sa_teardown_all(void) { - int i; - struct sa *sa, *next = 0; - - LOG_DBG ((LOG_SA, 70, "sa_teardown_all:")); - /* Get Phase 2 SAs. */ - for (i = 0; i <= bucket_mask; i++) - for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = next) - { - next = LIST_NEXT (sa, link); - if (sa->phase == 2) - { - /* Teardown the phase 2 SAs by name, similar to ui_teardown. */ - LOG_DBG ((LOG_SA, 70, "sa_teardown_all: tearing down SA %s", - sa->name)); - connection_teardown (sa->name); - sa_delete (sa, 1); - } - } + int i; + struct sa *sa, *next = 0; + + LOG_DBG((LOG_SA, 70, "sa_teardown_all:")); + /* Get Phase 2 SAs. */ + for (i = 0; i <= bucket_mask; i++) + for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = next) { + next = LIST_NEXT(sa, link); + if (sa->phase == 2) { + /* + * Teardown the phase 2 SAs by name, similar + * to ui_teardown. + */ + LOG_DBG((LOG_SA, 70, + "sa_teardown_all: tearing down SA %s", + sa->name)); + connection_teardown(sa->name); + sa_delete(sa, 1); + } + } } /* * This function will get called when we are closing in on the death time of SA */ static void -sa_soft_expire (void *v_sa) +sa_soft_expire(void *v_sa) { - struct sa *sa = v_sa; - - sa->soft_death = 0; - sa_release (sa); - - if ((sa->flags & (SA_FLAG_STAYALIVE | SA_FLAG_REPLACED)) - == SA_FLAG_STAYALIVE) - exchange_establish (sa->name, 0, 0); - else - /* - * Start to watch the use of this SA, so a renegotiation can - * happen as soon as it is shown to be alive. - */ - sa->flags |= SA_FLAG_FADING; + struct sa *sa = v_sa; + + sa->soft_death = 0; + sa_release(sa); + + if ((sa->flags & (SA_FLAG_STAYALIVE | SA_FLAG_REPLACED)) == + SA_FLAG_STAYALIVE) + exchange_establish(sa->name, 0, 0); + else + /* + * Start to watch the use of this SA, so a renegotiation can + * happen as soon as it is shown to be alive. + */ + sa->flags |= SA_FLAG_FADING; } /* SA has passed its best before date. */ static void -sa_hard_expire (void *v_sa) +sa_hard_expire(void *v_sa) { - struct sa *sa = v_sa; + struct sa *sa = v_sa; - sa->death = 0; - sa_release (sa); + sa->death = 0; + sa_release(sa); - if ((sa->flags & (SA_FLAG_STAYALIVE | SA_FLAG_REPLACED)) - == SA_FLAG_STAYALIVE) - exchange_establish (sa->name, 0, 0); + if ((sa->flags & (SA_FLAG_STAYALIVE | SA_FLAG_REPLACED)) == + SA_FLAG_STAYALIVE) + exchange_establish(sa->name, 0, 0); - sa_delete (sa, 1); + sa_delete(sa, 1); } void -sa_reinit (void) +sa_reinit(void) { - struct sa *sa; - char *tag; - int i; - - /* For now; only do this if we have the proper tag configured. */ - tag = conf_get_str ("General", "Renegotiate-on-HUP"); - if (!tag) - return; - - LOG_DBG ((LOG_SA, 30, "sa_reinit: renegotiating active connections")); - - /* Get phase 2 SAs. Soft expire those without active exchanges. */ - for (i = 0; i <= bucket_mask; i++) - for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = LIST_NEXT (sa, link)) - if (sa->phase == 2) - if (exchange_lookup_by_name (sa->name, sa->phase) == 0) - { - timer_remove_event (sa->soft_death); - sa_soft_expire (sa); - } + struct sa *sa; + char *tag; + int i; + + /* For now; only do this if we have the proper tag configured. */ + tag = conf_get_str("General", "Renegotiate-on-HUP"); + if (!tag) + return; + + LOG_DBG((LOG_SA, 30, "sa_reinit: renegotiating active connections")); + + /* Get phase 2 SAs. Soft expire those without active exchanges. */ + for (i = 0; i <= bucket_mask; i++) + for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = LIST_NEXT(sa, link)) + if (sa->phase == 2) + if (exchange_lookup_by_name(sa->name, sa->phase) == 0) { + timer_remove_event(sa->soft_death); + sa_soft_expire(sa); + } } /* * Get an SA attribute's flag value out of textual description. */ int -sa_flag (char *attr) +sa_flag(char *attr) { - static struct sa_flag_map { - char *name; - int flag; - } sa_flag_map[] = { - { "active-only", SA_FLAG_ACTIVE_ONLY }, - /* Below this point are flags that are internal to the implementation. */ - { "__ondemand", SA_FLAG_ONDEMAND }, - { "ikecfg", SA_FLAG_IKECFG }, - }; - size_t i; - - for (i = 0; i < sizeof sa_flag_map / sizeof sa_flag_map[0]; i++) - if (strcasecmp (attr, sa_flag_map[i].name) == 0) - return sa_flag_map[i].flag; - log_print ("sa_flag: attribute \"%s\" unknown", attr); - return 0; + static struct sa_flag_map { + char *name; + int flag; + } sa_flag_map[] = { + { + "active-only", SA_FLAG_ACTIVE_ONLY + }, + + /* + * Below this point are flags that are internal to the + * implementation. + */ + { + "__ondemand", SA_FLAG_ONDEMAND + }, { + "ikecfg", SA_FLAG_IKECFG + }, + }; + size_t i; + + for (i = 0; i < sizeof sa_flag_map / sizeof sa_flag_map[0]; i++) + if (strcasecmp(attr, sa_flag_map[i].name) == 0) + return sa_flag_map[i].flag; + log_print("sa_flag: attribute \"%s\" unknown", attr); + return 0; } /* Mark SA as replaced. */ void -sa_mark_replaced (struct sa *sa) +sa_mark_replaced(struct sa * sa) { - LOG_DBG ((LOG_SA, 60, "sa_mark_replaced: SA %p (%s) marked as replaced", + LOG_DBG((LOG_SA, 60, "sa_mark_replaced: SA %p (%s) marked as replaced", sa, sa->name ? sa->name : "unnamed")); - sa->flags |= SA_FLAG_REPLACED; + sa->flags |= SA_FLAG_REPLACED; } /* @@ -1216,57 +1178,55 @@ sa_mark_replaced (struct sa *sa) * stack. */ int -sa_setup_expirations (struct sa *sa) +sa_setup_expirations(struct sa * sa) { - u_int64_t seconds = sa->seconds; - struct timeval expiration; - - /* - * Set the soft timeout to a random percentage between 85 & 95 of - * the negotiated lifetime to break strictly synchronized - * renegotiations. This works better when the randomization is on the - * order of processing plus network-roundtrip times, or larger. - * I.e. it depends on configuration and negotiated lifetimes. - * It is not good to do the decrease on the hard timeout, because then - * we may drop our SA before our peer. - * XXX Better scheme to come? - */ - if (!sa->soft_death) - { - gettimeofday (&expiration, 0); - /* XXX This should probably be configuration controlled somehow. */ - seconds = sa->seconds * (850 + sysdep_random () % 100) / 1000; - LOG_DBG ((LOG_TIMER, 95, - "sa_setup_expirations: SA %p soft timeout in %llu seconds", - sa, seconds)); - expiration.tv_sec += seconds; - sa->soft_death - = timer_add_event ("sa_soft_expire", sa_soft_expire, sa, &expiration); - if (!sa->soft_death) - { - /* If we don't give up we might start leaking... */ - sa_delete (sa, 1); - return -1; + u_int64_t seconds = sa->seconds; + struct timeval expiration; + + /* + * Set the soft timeout to a random percentage between 85 & 95 of + * the negotiated lifetime to break strictly synchronized + * renegotiations. This works better when the randomization is on the + * order of processing plus network-roundtrip times, or larger. + * I.e. it depends on configuration and negotiated lifetimes. + * It is not good to do the decrease on the hard timeout, because then + * we may drop our SA before our peer. + * XXX Better scheme to come? + */ + if (!sa->soft_death) { + gettimeofday(&expiration, 0); + /* + * XXX This should probably be configuration controlled + * somehow. + */ + seconds = sa->seconds * (850 + sysdep_random() % 100) / 1000; + LOG_DBG((LOG_TIMER, 95, + "sa_setup_expirations: SA %p soft timeout in %llu seconds", + sa, seconds)); + expiration.tv_sec += seconds; + sa->soft_death = timer_add_event("sa_soft_expire", + sa_soft_expire, sa, &expiration); + if (!sa->soft_death) { + /* If we don't give up we might start leaking... */ + sa_delete(sa, 1); + return -1; + } + sa_reference(sa); } - sa_reference (sa); - } - - if (!sa->death) - { - gettimeofday (&expiration, 0); - LOG_DBG ((LOG_TIMER, 95, - "sa_setup_expirations: SA %p hard timeout in %llu seconds", - sa, sa->seconds)); - expiration.tv_sec += sa->seconds; - sa->death - = timer_add_event ("sa_hard_expire", sa_hard_expire, sa, &expiration); - if (!sa->death) - { - /* If we don't give up we might start leaking... */ - sa_delete (sa, 1); - return -1; + if (!sa->death) { + gettimeofday(&expiration, 0); + LOG_DBG((LOG_TIMER, 95, + "sa_setup_expirations: SA %p hard timeout in %llu seconds", + sa, sa->seconds)); + expiration.tv_sec += sa->seconds; + sa->death = timer_add_event("sa_hard_expire", + sa_hard_expire, sa, &expiration); + if (!sa->death) { + /* If we don't give up we might start leaking... */ + sa_delete(sa, 1); + return -1; + } + sa_reference(sa); } - sa_reference (sa); - } - return 0; + return 0; } diff --git a/sbin/isakmpd/sa.h b/sbin/isakmpd/sa.h index f2c28e55abe..f7071755185 100644 --- a/sbin/isakmpd/sa.h +++ b/sbin/isakmpd/sa.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sa.h,v 1.34 2004/02/27 10:16:26 ho Exp $ */ -/* $EOM: sa.h,v 1.58 2000/10/10 12:39:01 provos Exp $ */ +/* $OpenBSD: sa.h,v 1.35 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: sa.h,v 1.58 2000/10/10 12:39:01 provos Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -57,142 +57,151 @@ struct transport; /* A protection suite consists of a set of protocol descriptions like this. */ struct proto { - /* Link to the next protocol in the suite. */ - TAILQ_ENTRY (proto) link; + /* Link to the next protocol in the suite. */ + TAILQ_ENTRY(proto) link; - /* The SA we belong to. */ - struct sa *sa; + /* The SA we belong to. */ + struct sa *sa; - /* The protocol number as found in the proposal payload. */ - u_int8_t no; + /* The protocol number as found in the proposal payload. */ + u_int8_t no; - /* The protocol this SA is for. */ - u_int8_t proto; + /* The protocol this SA is for. */ + u_int8_t proto; - /* Security parameter index info. Element 0 - outgoing, 1 - incoming. */ - u_int8_t spi_sz[2]; - u_int8_t *spi[2]; + /* + * Security parameter index info. Element 0 - outgoing, 1 - + * incoming. + */ + u_int8_t spi_sz[2]; + u_int8_t *spi[2]; - /* - * The chosen transform, only valid while the incoming SA payload that held - * it is available for duplicate testing. - */ - struct payload *chosen; + /* + * The chosen transform, only valid while the incoming SA payload that held + * it is available for duplicate testing. + */ + struct payload *chosen; - /* The chosen transform's ID. */ - u_int8_t id; + /* The chosen transform's ID. */ + u_int8_t id; - /* DOI-specific data. */ - void *data; + /* DOI-specific data. */ + void *data; - /* Proposal transforms data, for validating the responders selection. */ - TAILQ_HEAD (proto_attr_head, proto_attr) xfs; - size_t xf_cnt; + /* Proposal transforms data, for validating the responders selection. */ + TAILQ_HEAD(proto_attr_head, proto_attr) xfs; + size_t xf_cnt; }; struct proto_attr { - /* Link to next transform. */ - TAILQ_ENTRY (proto_attr) next; + /* Link to next transform. */ + TAILQ_ENTRY(proto_attr) next; - /* Transform attribute data and size, suitable for attribute_map(). */ - u_int8_t *attrs; - size_t len; + /* Transform attribute data and size, suitable for attribute_map(). */ + u_int8_t *attrs; + size_t len; }; struct sa { - /* Link to SAs with the same hash value. */ - LIST_ENTRY (sa) link; - - /* - * When several SA's are being negotiated in one message we connect them - * through this link. - */ - TAILQ_ENTRY (sa) next; - - /* A name of the major policy deciding offers and acceptable proposals. */ - char *name; - - /* The transport this SA got negotiated over. */ - struct transport *transport; - - /* Both initiator and responder cookies. */ - u_int8_t cookies[ISAKMP_HDR_COOKIES_LEN]; - - /* The message ID signifying non-ISAKMP SAs. */ - u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; - - /* The protection suite chosen. */ - TAILQ_HEAD (proto_head, proto) protos; - - /* The exchange type we should use when rekeying. */ - u_int8_t exch_type; - - /* Phase is 1 for ISAKMP SAs, and 2 for application ones. */ - u_int8_t phase; - - /* A reference counter for this structure. */ - u_int16_t refcnt; - - /* Various flags, look below for descriptions. */ - u_int32_t flags; - - /* The DOI that is to handle DOI-specific issues for this SA. */ - struct doi *doi; - - /* Crypto info needed to encrypt/decrypt packets protected by this SA. */ - struct crypto_xf *crypto; - int key_length; - struct keystate *keystate; - - /* IDs from Phase 1 */ - u_int8_t *id_i; - size_t id_i_len; - u_int8_t *id_r; - size_t id_r_len; - - /* Set if we were the initiator of the SA/exchange in Phase 1 */ - int initiator; - - /* Policy session ID, where applicable, copied over from the exchange */ - int policy_id; - - /* - * The key used to authenticate phase 1, in printable format, used only by - * KeyNote. - */ - char *keynote_key; - - /* - * Certificates or other information from Phase 1; these are copied from the - * exchange, so look at exchange.h for an explanation of their use. - */ - int recv_certtype, recv_keytype; - /* Certificate received from peer, native format. */ - void *recv_cert; - /* Key peer used to authenticate, native format. */ - void *recv_key; - - /* - * Certificates or other information we used to authenticate to the peer, - * Phase 1. - */ - int sent_certtype; - /* Certificate (to be) sent to peer, native format. */ - void *sent_cert; - - /* DOI-specific opaque data. */ - void *data; - - /* Lifetime data. */ - u_int64_t seconds; - u_int64_t kilobytes; - - /* ACQUIRE sequence number */ - u_int32_t seq; - - /* The events that will occur when an SA has timed out. */ - struct event *soft_death; - struct event *death; + /* Link to SAs with the same hash value. */ + LIST_ENTRY(sa) link; + + /* + * When several SA's are being negotiated in one message we connect them + * through this link. + */ + TAILQ_ENTRY(sa) next; + + /* + * A name of the major policy deciding offers and acceptable + * proposals. + */ + char *name; + + /* The transport this SA got negotiated over. */ + struct transport *transport; + + /* Both initiator and responder cookies. */ + u_int8_t cookies[ISAKMP_HDR_COOKIES_LEN]; + + /* The message ID signifying non-ISAKMP SAs. */ + u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; + + /* The protection suite chosen. */ + TAILQ_HEAD(proto_head, proto) protos; + + /* The exchange type we should use when rekeying. */ + u_int8_t exch_type; + + /* Phase is 1 for ISAKMP SAs, and 2 for application ones. */ + u_int8_t phase; + + /* A reference counter for this structure. */ + u_int16_t refcnt; + + /* Various flags, look below for descriptions. */ + u_int32_t flags; + + /* The DOI that is to handle DOI-specific issues for this SA. */ + struct doi *doi; + + /* + * Crypto info needed to encrypt/decrypt packets protected by this + * SA. + */ + struct crypto_xf *crypto; + int key_length; + struct keystate *keystate; + + /* IDs from Phase 1 */ + u_int8_t *id_i; + size_t id_i_len; + u_int8_t *id_r; + size_t id_r_len; + + /* Set if we were the initiator of the SA/exchange in Phase 1 */ + int initiator; + + /* Policy session ID, where applicable, copied over from the exchange */ + int policy_id; + + /* + * The key used to authenticate phase 1, in printable format, used only by + * KeyNote. + */ + char *keynote_key; + + /* + * Certificates or other information from Phase 1; these are copied from the + * exchange, so look at exchange.h for an explanation of their use. + */ + int recv_certtype, recv_keytype; + /* Certificate received from peer, native format. */ + void *recv_cert; + /* Key peer used to authenticate, native format. */ + void *recv_key; + + /* + * Certificates or other information we used to authenticate to the peer, + * Phase 1. + */ + int sent_certtype; + /* Certificate (to be) sent to peer, native format. */ + void *sent_cert; + + /* DOI-specific opaque data. */ + void *data; + + /* Lifetime data. */ + u_int64_t seconds; + u_int64_t kilobytes; + + /* ACQUIRE sequence number */ + u_int32_t seq; + + /* The events that will occur when an SA has timed out. */ + struct event *soft_death; + struct event *death; }; /* This SA is alive. */ @@ -219,32 +228,33 @@ struct sa { /* Outfile for detailed SA information. */ #define SA_FILE "/var/run/isakmpd_sa" -extern void proto_free (struct proto *proto); -extern int sa_add_transform (struct sa *, struct payload *, int, - struct proto **); -extern int sa_create (struct exchange *, struct transport *); -extern int sa_enter (struct sa *); -extern void sa_delete (struct sa *, int); -extern void sa_teardown_all (void); -extern struct sa *sa_find (int (*) (struct sa *, void *), void *); -extern int sa_flag (char *); -extern void sa_free (struct sa *); -extern void sa_init (void); -extern void sa_reinit (void); -extern struct sa *sa_isakmp_lookup_by_peer (struct sockaddr *, socklen_t); -extern void sa_isakmp_upgrade (struct message *); -extern struct sa *sa_lookup (u_int8_t *, u_int8_t *); -extern struct sa *sa_lookup_by_peer (struct sockaddr *, socklen_t); -extern struct sa *sa_lookup_by_header (u_int8_t *, int); -extern struct sa *sa_lookup_by_name (char *, int); -extern struct sa *sa_lookup_from_icookie (u_int8_t *); -extern struct sa *sa_lookup_isakmp_sa (struct sockaddr *, u_int8_t *); -extern void sa_mark_replaced (struct sa *); -extern void sa_reference (struct sa *); -extern void sa_release (struct sa *); -extern void sa_remove (struct sa *); -extern void sa_report (void); -extern void sa_dump (int, int, char *, struct sa *); -extern void sa_report_all (void); -extern int sa_setup_expirations (struct sa *); -#endif /* _SA_H_ */ +extern void proto_free(struct proto * proto); +extern int +sa_add_transform(struct sa *, struct payload *, int, + struct proto **); +extern int sa_create(struct exchange *, struct transport *); +extern int sa_enter(struct sa *); +extern void sa_delete(struct sa *, int); +extern void sa_teardown_all(void); +extern struct sa *sa_find(int (*) (struct sa *, void *), void *); +extern int sa_flag(char *); +extern void sa_free(struct sa *); +extern void sa_init(void); +extern void sa_reinit(void); +extern struct sa *sa_isakmp_lookup_by_peer(struct sockaddr *, socklen_t); +extern void sa_isakmp_upgrade(struct message *); +extern struct sa *sa_lookup(u_int8_t *, u_int8_t *); +extern struct sa *sa_lookup_by_peer(struct sockaddr *, socklen_t); +extern struct sa *sa_lookup_by_header(u_int8_t *, int); +extern struct sa *sa_lookup_by_name(char *, int); +extern struct sa *sa_lookup_from_icookie(u_int8_t *); +extern struct sa *sa_lookup_isakmp_sa(struct sockaddr *, u_int8_t *); +extern void sa_mark_replaced(struct sa *); +extern void sa_reference(struct sa *); +extern void sa_release(struct sa *); +extern void sa_remove(struct sa *); +extern void sa_report(void); +extern void sa_dump(int, int, char *, struct sa *); +extern void sa_report_all(void); +extern int sa_setup_expirations(struct sa *); +#endif /* _SA_H_ */ diff --git a/sbin/isakmpd/sysdep.h b/sbin/isakmpd/sysdep.h index 3d3b6f79d4c..45e116f88ed 100644 --- a/sbin/isakmpd/sysdep.h +++ b/sbin/isakmpd/sysdep.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sysdep.h,v 1.14 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: sysdep.h,v 1.17 2000/12/04 04:46:35 angelos Exp $ */ +/* $OpenBSD: sysdep.h,v 1.15 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: sysdep.h,v 1.17 2000/12/04 04:46:35 angelos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -40,20 +40,23 @@ struct proto; struct sa; struct sockaddr; -extern void sysdep_app_handler (int); -extern int sysdep_app_open (void); -extern int sysdep_cleartext (int, int); -extern void sysdep_connection_check (char *); -extern int sysdep_ipsec_delete_spi (struct sa *, struct proto *, int); -extern int sysdep_ipsec_enable_sa (struct sa *, struct sa *); -extern u_int8_t *sysdep_ipsec_get_spi (size_t *, u_int8_t, struct sockaddr *, - struct sockaddr *, u_int32_t); -extern int sysdep_ipsec_group_spis (struct sa *, struct proto *, - struct proto *, int); -extern int sysdep_ipsec_set_spi (struct sa *, struct proto *, int, - struct sa *); -extern char *sysdep_progname (void); -extern u_int32_t sysdep_random (void); -extern u_int8_t sysdep_sa_len (struct sockaddr *); - -#endif /* _SYSDEP_H_ */ +extern void sysdep_app_handler(int); +extern int sysdep_app_open(void); +extern int sysdep_cleartext(int, int); +extern void sysdep_connection_check(char *); +extern int sysdep_ipsec_delete_spi(struct sa *, struct proto *, int); +extern int sysdep_ipsec_enable_sa(struct sa *, struct sa *); +extern u_int8_t * +sysdep_ipsec_get_spi(size_t *, u_int8_t, struct sockaddr *, + struct sockaddr *, u_int32_t); +extern int +sysdep_ipsec_group_spis(struct sa *, struct proto *, + struct proto *, int); +extern int +sysdep_ipsec_set_spi(struct sa *, struct proto *, int, + struct sa *); +extern char *sysdep_progname(void); +extern u_int32_t sysdep_random(void); +extern u_int8_t sysdep_sa_len(struct sockaddr *); + +#endif /* _SYSDEP_H_ */ diff --git a/sbin/isakmpd/sysdep/openbsd/keynote_compat.c b/sbin/isakmpd/sysdep/openbsd/keynote_compat.c index ce3f1003fea..a4643750fed 100644 --- a/sbin/isakmpd/sysdep/openbsd/keynote_compat.c +++ b/sbin/isakmpd/sysdep/openbsd/keynote_compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: keynote_compat.c,v 1.5 2003/06/03 14:53:11 ho Exp $ */ +/* $OpenBSD: keynote_compat.c,v 1.6 2004/04/15 18:39:30 deraadt Exp $ */ /* $EOM: keynote_compat.c,v 1.1 2000/10/15 19:18:26 niklas Exp $ */ /* @@ -42,7 +42,7 @@ * in April-May 1998 * * Copyright (C) 1998, 1999 by Angelos D. Keromytis. - * + * * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or @@ -60,23 +60,23 @@ #include <keynote.h> extern void keynote_free_key(void *, int); -extern char *keynote_get_private_key (char *); +extern char *keynote_get_private_key(char *); /* * Exportable front-end to keynote_get_private_key(). */ char * -_kn_get_string (char *buf) +_kn_get_string(char *buf) { - return keynote_get_private_key (buf); + return keynote_get_private_key(buf); } /* * Free a key. */ void -_kn_free_key (struct keynote_deckey *dc) +_kn_free_key(struct keynote_deckey *dc) { - if (dc) - keynote_free_key (dc->dec_key, dc->dec_algorithm); + if (dc) + keynote_free_key(dc->dec_key, dc->dec_algorithm); } diff --git a/sbin/isakmpd/sysdep/openbsd/sysdep.c b/sbin/isakmpd/sysdep/openbsd/sysdep.c index 6d3b03e791e..f51393a2e34 100644 --- a/sbin/isakmpd/sysdep/openbsd/sysdep.c +++ b/sbin/isakmpd/sysdep/openbsd/sysdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: sysdep.c,v 1.25 2003/06/03 14:53:11 ho Exp $ */ -/* $EOM: sysdep.c,v 1.9 2000/12/04 04:46:35 angelos Exp $ */ +/* $OpenBSD: sysdep.c,v 1.26 2004/04/15 18:39:30 deraadt Exp $ */ +/* $EOM: sysdep.c,v 1.9 2000/12/04 04:46:35 angelos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -55,33 +55,33 @@ #endif /* NEED_SYSDEP_APP */ #include "log.h" -extern char *__progname; +extern char *__progname; /* * An as strong as possible random number generator, reverting to a * deterministic pseudo-random one if regrand is set. */ u_int32_t -sysdep_random () +sysdep_random() { - if (!regrand) - return arc4random (); - else - return random(); + if (!regrand) + return arc4random(); + else + return random(); } /* Return the basename of the command used to invoke us. */ char * -sysdep_progname () +sysdep_progname() { - return __progname; + return __progname; } /* Return the length of the sockaddr struct. */ u_int8_t -sysdep_sa_len (struct sockaddr *sa) +sysdep_sa_len(struct sockaddr *sa) { - return sa->sa_len; + return sa->sa_len; } /* As regress/ use this file I protect the sysdep_app_* stuff like this. */ @@ -91,9 +91,9 @@ sysdep_sa_len (struct sockaddr *sa) * for communication. We return a file descriptor useable to select(2) on. */ int -sysdep_app_open () +sysdep_app_open() { - return KEY_API(open) (); + return KEY_API(open)(); } /* @@ -101,16 +101,16 @@ sysdep_app_open () * gets called. FD is the file descriptor causing the alarm. */ void -sysdep_app_handler (int fd) +sysdep_app_handler(int fd) { - KEY_API (handler) (fd); + KEY_API(handler)(fd); } /* Check that the connection named NAME is active, or else make it active. */ void -sysdep_connection_check (char *name) +sysdep_connection_check(char *name) { - KEY_API (connection_check) (name); + KEY_API(connection_check)(name); } /* @@ -118,144 +118,136 @@ sysdep_connection_check (char *name) * SRC, SRCLEN, DST & DSTLEN. Stash the SPI size in SZ. */ u_int8_t * -sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, - struct sockaddr *dst, u_int32_t seq) +sysdep_ipsec_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src, + struct sockaddr *dst, u_int32_t seq) { - if (app_none) - { - *sz = IPSEC_SPI_SIZE; - /* XXX should be random instead I think. */ - return (u_int8_t *)strdup ("\x12\x34\x56\x78"); - } - return KEY_API (get_spi) (sz, proto, src, dst, seq); + if (app_none) { + *sz = IPSEC_SPI_SIZE; + /* XXX should be random instead I think. */ + return (u_int8_t *)strdup("\x12\x34\x56\x78"); + } + return KEY_API(get_spi)(sz, proto, src, dst, seq); } /* Force communication on socket FD to go in the clear. */ int -sysdep_cleartext (int fd, int af) +sysdep_cleartext(int fd, int af) { - int level, sw; - struct { - int ip_proto; /* IP protocol */ - int auth_level; - int esp_trans_level; - int esp_network_level; - int ipcomp_level; - } optsw[] = - { - { - IPPROTO_IP, - IP_AUTH_LEVEL, - IP_ESP_TRANS_LEVEL, - IP_ESP_NETWORK_LEVEL, + int level, sw; + struct { + int ip_proto; /* IP protocol */ + int auth_level; + int esp_trans_level; + int esp_network_level; + int ipcomp_level; + } optsw[] = { + { + IPPROTO_IP, + IP_AUTH_LEVEL, + IP_ESP_TRANS_LEVEL, + IP_ESP_NETWORK_LEVEL, #ifdef IP_IPCOMP_LEVEL - IP_IPCOMP_LEVEL + IP_IPCOMP_LEVEL #else - 0 + 0 #endif - }, - { - IPPROTO_IPV6, - IPV6_AUTH_LEVEL, - IPV6_ESP_TRANS_LEVEL, - IPV6_ESP_NETWORK_LEVEL, + }, { + IPPROTO_IPV6, + IPV6_AUTH_LEVEL, + IPV6_ESP_TRANS_LEVEL, + IPV6_ESP_NETWORK_LEVEL, #ifdef IPV6_IPCOMP_LEVEL - IPV6_IPCOMP_LEVEL + IPV6_IPCOMP_LEVEL #else - 0 + 0 #endif - }, - }; - - if (app_none) - return 0; - - switch (af) - { - case AF_INET: - sw = 0; - break; - case AF_INET6: - sw = 1; - break; - default: - log_print ("sysdep_cleartext: unsupported protocol family %d", af); - return -1; - } - - /* - * Need to bypass system security policy, so I can send and - * receive key management datagrams in the clear. - */ - level = IPSEC_LEVEL_BYPASS; - if (monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].auth_level, - (char *)&level, sizeof level) == -1) - { - log_error ("sysdep_cleartext: " - "setsockopt (%d, %d, IP_AUTH_LEVEL, ...) failed", fd, - optsw[sw].ip_proto); - return -1; - } - if (monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].esp_trans_level, - (char *)&level, sizeof level) == -1) - { - log_error ("sysdep_cleartext: " - "setsockopt (%d, %d, IP_ESP_TRANS_LEVEL, ...) failed", fd, - optsw[sw].ip_proto); - return -1; - } - if (monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].esp_network_level, - (char *)&level, sizeof level) == -1) - { - log_error("sysdep_cleartext: " - "setsockopt (%d, %d, IP_ESP_NETWORK_LEVEL, ...) failed", fd, - optsw[sw].ip_proto); - return -1; - } - if (optsw[sw].ipcomp_level - && monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].ipcomp_level, - (char *)&level, sizeof level) == -1 - && errno != ENOPROTOOPT) - { - log_error("sysdep_cleartext: " - "setsockopt (%d, %d, IP_IPCOMP_LEVEL, ...) failed,", fd, - optsw[sw].ip_proto); - return -1; - } - return 0; + }, + }; + + if (app_none) + return 0; + + switch (af) { + case AF_INET: + sw = 0; + break; + case AF_INET6: + sw = 1; + break; + default: + log_print("sysdep_cleartext: unsupported protocol family %d", af); + return -1; + } + + /* + * Need to bypass system security policy, so I can send and + * receive key management datagrams in the clear. + */ + level = IPSEC_LEVEL_BYPASS; + if (monitor_setsockopt(fd, optsw[sw].ip_proto, optsw[sw].auth_level, + (char *) &level, sizeof level) == -1) { + log_error("sysdep_cleartext: " + "setsockopt (%d, %d, IP_AUTH_LEVEL, ...) failed", fd, + optsw[sw].ip_proto); + return -1; + } + if (monitor_setsockopt(fd, optsw[sw].ip_proto, optsw[sw].esp_trans_level, + (char *) &level, sizeof level) == -1) { + log_error("sysdep_cleartext: " + "setsockopt (%d, %d, IP_ESP_TRANS_LEVEL, ...) failed", fd, + optsw[sw].ip_proto); + return -1; + } + if (monitor_setsockopt(fd, optsw[sw].ip_proto, optsw[sw].esp_network_level, + (char *) &level, sizeof level) == -1) { + log_error("sysdep_cleartext: " + "setsockopt (%d, %d, IP_ESP_NETWORK_LEVEL, ...) failed", fd, + optsw[sw].ip_proto); + return -1; + } + if (optsw[sw].ipcomp_level && + monitor_setsockopt(fd, optsw[sw].ip_proto, optsw[sw].ipcomp_level, + (char *) &level, sizeof level) == -1 && + errno != ENOPROTOOPT) { + log_error("sysdep_cleartext: " + "setsockopt (%d, %d, IP_IPCOMP_LEVEL, ...) failed,", fd, + optsw[sw].ip_proto); + return -1; + } + return 0; } int -sysdep_ipsec_delete_spi (struct sa *sa, struct proto *proto, int incoming) +sysdep_ipsec_delete_spi(struct sa *sa, struct proto *proto, int incoming) { - if (app_none) - return 0; - return KEY_API (delete_spi) (sa, proto, incoming); + if (app_none) + return 0; + return KEY_API(delete_spi)(sa, proto, incoming); } int -sysdep_ipsec_enable_sa (struct sa *sa, struct sa *isakmp_sa) +sysdep_ipsec_enable_sa(struct sa *sa, struct sa *isakmp_sa) { - if (app_none) - return 0; - return KEY_API (enable_sa) (sa, isakmp_sa); + if (app_none) + return 0; + return KEY_API(enable_sa)(sa, isakmp_sa); } int -sysdep_ipsec_group_spis (struct sa *sa, struct proto *proto1, - struct proto *proto2, int incoming) +sysdep_ipsec_group_spis(struct sa *sa, struct proto *proto1, + struct proto *proto2, int incoming) { - if (app_none) - return 0; - return KEY_API (group_spis) (sa, proto1, proto2, incoming); + if (app_none) + return 0; + return KEY_API(group_spis)(sa, proto1, proto2, incoming); } int -sysdep_ipsec_set_spi (struct sa *sa, struct proto *proto, int incoming, - struct sa *isakmp_sa) +sysdep_ipsec_set_spi(struct sa *sa, struct proto *proto, int incoming, + struct sa *isakmp_sa) { - if (app_none) - return 0; - return KEY_API (set_spi) (sa, proto, incoming, isakmp_sa); + if (app_none) + return 0; + return KEY_API(set_spi) (sa,proto, incoming, isakmp_sa); } #endif diff --git a/sbin/isakmpd/timer.c b/sbin/isakmpd/timer.c index aefc84577b4..180ccc823a0 100644 --- a/sbin/isakmpd/timer.c +++ b/sbin/isakmpd/timer.c @@ -1,5 +1,5 @@ -/* $OpenBSD: timer.c,v 1.11 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: timer.c,v 1.13 2000/02/20 19:58:42 niklas Exp $ */ +/* $OpenBSD: timer.c,v 1.12 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: timer.c,v 1.13 2000/02/20 19:58:42 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -38,106 +38,100 @@ #include "log.h" #include "timer.h" -static TAILQ_HEAD (event_list, event) events; +static TAILQ_HEAD(event_list, event) events; void -timer_init (void) +timer_init(void) { - TAILQ_INIT (&events); + TAILQ_INIT(&events); } void -timer_next_event (struct timeval **timeout) +timer_next_event(struct timeval **timeout) { - struct timeval now; - - if (TAILQ_FIRST (&events)) - { - gettimeofday (&now, 0); - if (timercmp (&now, &TAILQ_FIRST (&events)->expiration, >=)) - timerclear (*timeout); - else - timersub (&TAILQ_FIRST (&events)->expiration, &now, *timeout); - } - else - *timeout = 0; + struct timeval now; + + if (TAILQ_FIRST(&events)) { + gettimeofday(&now, 0); + if (timercmp(&now, &TAILQ_FIRST(&events)->expiration, >=)) + timerclear(*timeout); + else + timersub(&TAILQ_FIRST(&events)->expiration, &now, *timeout); + } else + *timeout = 0; } void -timer_handle_expirations (void) +timer_handle_expirations(void) { - struct timeval now; - struct event *n; - - gettimeofday (&now, 0); - for (n = TAILQ_FIRST (&events); n && timercmp (&now, &n->expiration, >=); - n = TAILQ_FIRST (&events)) - { - LOG_DBG ((LOG_TIMER, 10, - "timer_handle_expirations: event %s(%p)", n->name, n->arg)); - TAILQ_REMOVE (&events, n, link); - (*n->func) (n->arg); - free (n); - } + struct timeval now; + struct event *n; + + gettimeofday(&now, 0); + for (n = TAILQ_FIRST(&events); n && timercmp(&now, &n->expiration, >=); + n = TAILQ_FIRST(&events)) { + LOG_DBG((LOG_TIMER, 10, + "timer_handle_expirations: event %s(%p)", n->name, n->arg)); + TAILQ_REMOVE(&events, n, link); + (*n->func)(n->arg); + free(n); + } } struct event * -timer_add_event (char *name, void (*func) (void *), void *arg, - struct timeval *expiration) +timer_add_event(char *name, void (*func)(void *), void *arg, + struct timeval *expiration) { - struct event *ev = (struct event *)malloc (sizeof *ev); - struct event *n; - struct timeval now; - - if (!ev) - return 0; - ev->name = name; - ev->func = func; - ev->arg = arg; - gettimeofday (&now, 0); - memcpy (&ev->expiration, expiration, sizeof *expiration); - for (n = TAILQ_FIRST (&events); - n && timercmp (expiration, &n->expiration, >=); - n = TAILQ_NEXT (n, link)) - ; - if (n) - { - LOG_DBG ((LOG_TIMER, 10, - "timer_add_event: event %s(%p) added before %s(%p), " - "expiration in %lds", name, - arg, n->name, n->arg, expiration->tv_sec - now.tv_sec)); - TAILQ_INSERT_BEFORE (n, ev, link); - } - else - { - LOG_DBG ((LOG_TIMER, 10, "timer_add_event: event %s(%p) added last, " - "expiration in %lds", name, arg, - expiration->tv_sec - now.tv_sec)); - TAILQ_INSERT_TAIL (&events, ev, link); - } - return ev; + struct event *ev = (struct event *) malloc(sizeof *ev); + struct event *n; + struct timeval now; + + if (!ev) + return 0; + ev->name = name; + ev->func = func; + ev->arg = arg; + gettimeofday(&now, 0); + memcpy(&ev->expiration, expiration, sizeof *expiration); + for (n = TAILQ_FIRST(&events); + n && timercmp(expiration, &n->expiration, >=); + n = TAILQ_NEXT(n, link)) + ; + if (n) { + LOG_DBG((LOG_TIMER, 10, + "timer_add_event: event %s(%p) added before %s(%p), " + "expiration in %lds", name, + arg, n->name, n->arg, expiration->tv_sec - now.tv_sec)); + TAILQ_INSERT_BEFORE(n, ev, link); + } else { + LOG_DBG((LOG_TIMER, 10, "timer_add_event: event %s(%p) added last, " + "expiration in %lds", name, arg, + expiration->tv_sec - now.tv_sec)); + TAILQ_INSERT_TAIL(&events, ev, link); + } + return ev; } void -timer_remove_event (struct event *ev) +timer_remove_event(struct event *ev) { - LOG_DBG ((LOG_TIMER, 10, "timer_remove_event: removing event %s(%p)", + LOG_DBG((LOG_TIMER, 10, "timer_remove_event: removing event %s(%p)", ev->name, ev->arg)); - TAILQ_REMOVE (&events, ev, link); - free (ev); + TAILQ_REMOVE(&events, ev, link); + free(ev); } void -timer_report (void) +timer_report(void) { - struct event *ev; - struct timeval now; + struct event *ev; + struct timeval now; - gettimeofday (&now, 0); + gettimeofday(&now, 0); - for (ev = TAILQ_FIRST (&events); ev; ev = TAILQ_NEXT (ev, link)) - LOG_DBG ((LOG_REPORT, 0, - "timer_report: event %s(%p) scheduled in %d seconds", - (ev->name ? ev->name : "<unknown>"), ev, - (int)(ev->expiration.tv_sec - now.tv_sec))); + for (ev = TAILQ_FIRST(&events); ev; ev = TAILQ_NEXT(ev, link)) + LOG_DBG((LOG_REPORT, 0, + "timer_report: event %s(%p) scheduled in %d seconds", + (ev->name ? ev->name : "<unknown>"), ev, + (int) (ev->expiration.tv_sec - now.tv_sec))); } diff --git a/sbin/isakmpd/timer.h b/sbin/isakmpd/timer.h index 253f0b63539..a107107e69e 100644 --- a/sbin/isakmpd/timer.h +++ b/sbin/isakmpd/timer.h @@ -1,5 +1,5 @@ -/* $OpenBSD: timer.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: timer.h,v 1.6 1999/04/11 22:35:55 ho Exp $ */ +/* $OpenBSD: timer.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: timer.h,v 1.6 1999/04/11 22:35:55 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -37,19 +37,19 @@ #include <sys/time.h> struct event { - TAILQ_ENTRY (event) link; - char *name; - void (*func) (void *); - void *arg; - struct timeval expiration; + TAILQ_ENTRY(event) link; + char *name; + void (*func) (void *); + void *arg; + struct timeval expiration; }; -extern void timer_init (void); -extern void timer_next_event (struct timeval **); -extern void timer_handle_expirations (void); -extern struct event *timer_add_event (char *, void (*) (void *), void *, - struct timeval *); -extern void timer_remove_event (struct event *); -extern void timer_report (void); +extern void timer_init(void); +extern void timer_next_event(struct timeval **); +extern void timer_handle_expirations(void); +extern struct event *timer_add_event(char *, void (*) (void *), void *, + struct timeval *); +extern void timer_remove_event(struct event *); +extern void timer_report(void); -#endif /* _TIMER_H_ */ +#endif /* _TIMER_H_ */ diff --git a/sbin/isakmpd/transport.c b/sbin/isakmpd/transport.c index da1cc43d917..ca92f5cda48 100644 --- a/sbin/isakmpd/transport.c +++ b/sbin/isakmpd/transport.c @@ -1,5 +1,5 @@ -/* $OpenBSD: transport.c,v 1.23 2003/12/18 02:03:28 ho Exp $ */ -/* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */ +/* $OpenBSD: transport.c,v 1.24 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -47,117 +47,119 @@ /* If no retransmit limit is given, use this as a default. */ #define RETRANSMIT_DEFAULT 10 -LIST_HEAD (transport_list, transport) transport_list; -LIST_HEAD (transport_method_list, transport_vtbl) transport_method_list; +LIST_HEAD(transport_list, transport) transport_list; +LIST_HEAD(transport_method_list, transport_vtbl) transport_method_list; /* Call the reinit function of the various transports. */ -void -transport_reinit (void) + void + transport_reinit(void) { - struct transport_vtbl *method; + struct transport_vtbl *method; - for (method = LIST_FIRST (&transport_method_list); method; - method = LIST_NEXT (method, link)) - method->reinit (); + for (method = LIST_FIRST(&transport_method_list); method; + method = LIST_NEXT(method, link)) + method->reinit(); } /* Initialize the transport maintenance module. */ void -transport_init (void) +transport_init(void) { - LIST_INIT (&transport_list); - LIST_INIT (&transport_method_list); + LIST_INIT(&transport_list); + LIST_INIT(&transport_method_list); } /* Register another transport T. */ void -transport_add (struct transport *t) +transport_add(struct transport * t) { - LOG_DBG ((LOG_TRANSPORT, 70, "transport_add: adding %p", t)); - TAILQ_INIT (&t->sendq); - TAILQ_INIT (&t->prio_sendq); - LIST_INSERT_HEAD (&transport_list, t, link); - t->flags = 0; - t->refcnt = 0; + LOG_DBG((LOG_TRANSPORT, 70, "transport_add: adding %p", t)); + TAILQ_INIT(&t->sendq); + TAILQ_INIT(&t->prio_sendq); + LIST_INSERT_HEAD(&transport_list, t, link); + t->flags = 0; + t->refcnt = 0; } /* Add a referer to transport T. */ void -transport_reference (struct transport *t) +transport_reference(struct transport * t) { - t->refcnt++; - LOG_DBG ((LOG_TRANSPORT, 95, - "transport_reference: transport %p now has %d references", t, - t->refcnt)); + t->refcnt++; + LOG_DBG((LOG_TRANSPORT, 95, + "transport_reference: transport %p now has %d references", t, + t->refcnt)); } /* * Remove a referer from transport T, removing all of T when no referers left. */ void -transport_release (struct transport *t) +transport_release(struct transport * t) { - LOG_DBG ((LOG_TRANSPORT, 95, - "transport_release: transport %p had %d references", t, - t->refcnt)); - if (--t->refcnt) - return; - - LOG_DBG ((LOG_TRANSPORT, 70, "transport_release: freeing %p", t)); - LIST_REMOVE (t, link); - t->vtbl->remove (t); + LOG_DBG((LOG_TRANSPORT, 95, + "transport_release: transport %p had %d references", t, + t->refcnt)); + if (--t->refcnt) + return; + + LOG_DBG((LOG_TRANSPORT, 70, "transport_release: freeing %p", t)); + LIST_REMOVE(t, link); + t->vtbl->remove(t); } void -transport_report (void) +transport_report(void) { - struct transport *t; - struct message *msg; - - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - { - LOG_DBG ((LOG_REPORT, 0, - "transport_report: transport %p flags %x refcnt %d", t, - t->flags, t->refcnt)); - - t->vtbl->report (t); - - /* This is the reason message_dump_raw lives outside message.c. */ - for (msg = TAILQ_FIRST (&t->prio_sendq); msg; - msg = TAILQ_NEXT (msg, link)) - message_dump_raw ("udp_report", msg, LOG_REPORT); - - for (msg = TAILQ_FIRST (&t->sendq); msg; msg = TAILQ_NEXT (msg, link)) - message_dump_raw ("udp_report", msg, LOG_REPORT); - } + struct transport *t; + struct message *msg; + + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { + LOG_DBG((LOG_REPORT, 0, + "transport_report: transport %p flags %x refcnt %d", t, + t->flags, t->refcnt)); + + t->vtbl->report(t); + + /* + * This is the reason message_dump_raw lives outside + * message.c. + */ + for (msg = TAILQ_FIRST(&t->prio_sendq); msg; + msg = TAILQ_NEXT(msg, link)) + message_dump_raw("udp_report", msg, LOG_REPORT); + + for (msg = TAILQ_FIRST(&t->sendq); msg; msg = TAILQ_NEXT(msg, link)) + message_dump_raw("udp_report", msg, LOG_REPORT); + } } int -transport_prio_sendqs_empty (void) +transport_prio_sendqs_empty(void) { - struct transport *t; + struct transport *t; - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - if (TAILQ_FIRST (&t->prio_sendq)) - return 0; - return 1; + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) + if (TAILQ_FIRST(&t->prio_sendq)) + return 0; + return 1; } /* Register another transport method T. */ void -transport_method_add (struct transport_vtbl *t) +transport_method_add(struct transport_vtbl * t) { - LIST_INSERT_HEAD (&transport_method_list, t, link); + LIST_INSERT_HEAD(&transport_method_list, t, link); } /* Apply a function FUNC on all registered transports. */ void -transport_map (void (*func) (struct transport *)) +transport_map(void (*func) (struct transport *)) { - struct transport *t; + struct transport *t; - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - (*func) (t); + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) + (*func) (t); } /* @@ -166,20 +168,19 @@ transport_map (void (*func) (struct transport *)) * check in order to cover the ones we setup in here. */ int -transport_fd_set (fd_set *fds) +transport_fd_set(fd_set * fds) { - int n; - int max = -1; - struct transport *t; - - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - if (t->flags & TRANSPORT_LISTEN) - { - n = t->vtbl->fd_set (t, fds, 1); - if (n > max) - max = n; - } - return max + 1; + int n; + int max = -1; + struct transport *t; + + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) + if (t->flags & TRANSPORT_LISTEN) { + n = t->vtbl->fd_set(t, fds, 1); + if (n > max) + max = n; + } + return max + 1; } /* @@ -189,22 +190,20 @@ transport_fd_set (fd_set *fds) * we setup in here. */ int -transport_pending_wfd_set (fd_set *fds) +transport_pending_wfd_set(fd_set * fds) { - int n; - int max = -1; - struct transport *t; - - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - { - if (TAILQ_FIRST (&t->sendq) || TAILQ_FIRST (&t->prio_sendq)) - { - n = t->vtbl->fd_set (t, fds, 1); - if (n > max) - max = n; + int n; + int max = -1; + struct transport *t; + + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { + if (TAILQ_FIRST(&t->sendq) || TAILQ_FIRST(&t->prio_sendq)) { + n = t->vtbl->fd_set(t, fds, 1); + if (n > max) + max = n; + } } - } - return max + 1; + return max + 1; } /* @@ -212,13 +211,13 @@ transport_pending_wfd_set (fd_set *fds) * incoming message and start processing it. */ void -transport_handle_messages (fd_set *fds) +transport_handle_messages(fd_set * fds) { - struct transport *t; + struct transport *t; - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - if ((t->flags & TRANSPORT_LISTEN) && (*t->vtbl->fd_isset) (t, fds)) - (*t->vtbl->handle_message) (t); + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) + if ((t->flags & TRANSPORT_LISTEN) && (*t->vtbl->fd_isset) (t, fds)) + (*t->vtbl->handle_message) (t); } /* @@ -231,140 +230,134 @@ transport_handle_messages (fd_set *fds) * be favoured to later ones sharing the file descriptor. */ void -transport_send_messages (fd_set *fds) +transport_send_messages(fd_set * fds) { - struct transport *t, *next; - struct message *msg; - struct exchange *exchange; - struct timeval expiration; - int expiry, ok_to_drop_message; - - /* Reference all transports first so noone will disappear while in use. */ - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - transport_reference (t); - - for (t = LIST_FIRST (&transport_list); t; t = LIST_NEXT (t, link)) - { - if ((TAILQ_FIRST (&t->sendq) || TAILQ_FIRST (&t->prio_sendq)) - && t->vtbl->fd_isset (t, fds)) - { - t->vtbl->fd_set (t, fds, 0); - - /* Prefer a message from the prioritized sendq. */ - if (TAILQ_FIRST (&t->prio_sendq)) - { - msg = TAILQ_FIRST (&t->prio_sendq); - TAILQ_REMOVE (&t->prio_sendq, msg, link); - } - else - { - msg = TAILQ_FIRST (&t->sendq); - TAILQ_REMOVE (&t->sendq, msg, link); - } - - msg->flags &= ~MSG_IN_TRANSIT; - exchange = msg->exchange; - exchange->in_transit = 0; - - /* - * We disregard the potential error message here, hoping that the - * retransmit will go better. - * XXX Consider a retry/fatal error discriminator. - */ - t->vtbl->send_message (msg); - msg->xmits++; - - /* - * This piece of code has been proven to be quite delicate. - * Think twice for before altering. Here's an outline: - * - * If this message is not the one which finishes an exchange, - * check if we have reached the number of retransmit before - * queuing it up for another. - * - * If it is a finishing message we still may have to keep it - * around for an on-demand retransmit when seeing a duplicate - * of our peer's previous message. - * - * If we have no previous message from our peer, we need not - * to keep the message around. - */ - if ((msg->flags & MSG_LAST) == 0) - { - if (msg->xmits > conf_get_num ("General", "retransmits", - RETRANSMIT_DEFAULT)) - { - log_print ("transport_send_messages: giving up on " - "message %p, exchange %s", msg, - exchange->name ? exchange->name : "<unnamed>"); - /* Be more verbose here. */ - if (exchange->phase == 1) - { - log_print ("transport_send_messages: either this " - "message did not reach the other peer"); - if (exchange->initiator) - log_print ("transport_send_messages: or the response" - "message did not reach us back"); - else - log_print ("transport_send_messages: or this is " - "an attempted IKE scan"); - } - exchange->last_sent = 0; + struct transport *t, *next; + struct message *msg; + struct exchange *exchange; + struct timeval expiration; + int expiry, ok_to_drop_message; + + /* + * Reference all transports first so noone will disappear while in + * use. + */ + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) + transport_reference(t); + + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { + if ((TAILQ_FIRST(&t->sendq) || TAILQ_FIRST(&t->prio_sendq)) + && t->vtbl->fd_isset(t, fds)) { + t->vtbl->fd_set(t, fds, 0); + + /* Prefer a message from the prioritized sendq. */ + if (TAILQ_FIRST(&t->prio_sendq)) { + msg = TAILQ_FIRST(&t->prio_sendq); + TAILQ_REMOVE(&t->prio_sendq, msg, link); + } else { + msg = TAILQ_FIRST(&t->sendq); + TAILQ_REMOVE(&t->sendq, msg, link); + } + + msg->flags &= ~MSG_IN_TRANSIT; + exchange = msg->exchange; + exchange->in_transit = 0; + + /* + * We disregard the potential error message here, hoping that the + * retransmit will go better. + * XXX Consider a retry/fatal error discriminator. + */ + t->vtbl->send_message(msg); + msg->xmits++; + + /* + * This piece of code has been proven to be quite delicate. + * Think twice for before altering. Here's an outline: + * + * If this message is not the one which finishes an exchange, + * check if we have reached the number of retransmit before + * queuing it up for another. + * + * If it is a finishing message we still may have to keep it + * around for an on-demand retransmit when seeing a duplicate + * of our peer's previous message. + * + * If we have no previous message from our peer, we need not + * to keep the message around. + */ + if ((msg->flags & MSG_LAST) == 0) { + if (msg->xmits > conf_get_num("General", "retransmits", + RETRANSMIT_DEFAULT)) { + log_print("transport_send_messages: giving up on " + "message %p, exchange %s", msg, + exchange->name ? exchange->name : "<unnamed>"); + /* Be more verbose here. */ + if (exchange->phase == 1) { + log_print("transport_send_messages: either this " + "message did not reach the other peer"); + if (exchange->initiator) + log_print("transport_send_messages: or the response" + "message did not reach us back"); + else + log_print("transport_send_messages: or this is " + "an attempted IKE scan"); + } + exchange->last_sent = 0; + } else { + gettimeofday(&expiration, 0); + + /* + * XXX Calculate from round trip timings and a backoff func. + */ + expiry = msg->xmits * 2 + 5; + expiration.tv_sec += expiry; + LOG_DBG((LOG_TRANSPORT, 30, + "transport_send_messages: message %p " + "scheduled for retransmission %d in %d secs", + msg, msg->xmits, expiry)); + if (msg->retrans) + timer_remove_event(msg->retrans); + msg->retrans + = timer_add_event("message_send_expire", + (void (*) (void *)) message_send_expire, + msg, &expiration); + /* + * If we cannot retransmit, we + * cannot... + */ + exchange->last_sent = msg->retrans ? msg : 0; + } + } else + exchange->last_sent = exchange->last_received ? msg : 0; + + /* + * If this message is not referred to for later retransmission + * it will be ok for us to drop it after the post-send function. + * But as the post-send function may remove the exchange, we need + * to remember this fact here. + */ + ok_to_drop_message = exchange->last_sent == 0; + + /* + * If this is not a retransmit call post-send functions that allows + * parallel work to be done while the network and peer does their + * share of the job. Note that a post-send function may take + * away the exchange we belong to, but only if no retransmits + * are possible. + */ + if (msg->xmits == 1) + message_post_send(msg); + + if (ok_to_drop_message) + message_free(msg); } - else - { - gettimeofday (&expiration, 0); - - /* - * XXX Calculate from round trip timings and a backoff func. - */ - expiry = msg->xmits * 2 + 5; - expiration.tv_sec += expiry; - LOG_DBG ((LOG_TRANSPORT, 30, - "transport_send_messages: message %p " - "scheduled for retransmission %d in %d secs", - msg, msg->xmits, expiry)); - if (msg->retrans) - timer_remove_event (msg->retrans); - msg->retrans - = timer_add_event ("message_send_expire", - (void (*) (void *))message_send_expire, - msg, &expiration); - /* If we cannot retransmit, we cannot... */ - exchange->last_sent = msg->retrans ? msg : 0; - } - } - else - exchange->last_sent = exchange->last_received ? msg : 0; - - /* - * If this message is not referred to for later retransmission - * it will be ok for us to drop it after the post-send function. - * But as the post-send function may remove the exchange, we need - * to remember this fact here. - */ - ok_to_drop_message = exchange->last_sent == 0; - - /* - * If this is not a retransmit call post-send functions that allows - * parallel work to be done while the network and peer does their - * share of the job. Note that a post-send function may take - * away the exchange we belong to, but only if no retransmits - * are possible. - */ - if (msg->xmits == 1) - message_post_send (msg); - - if (ok_to_drop_message) - message_free (msg); } - } - for (t = LIST_FIRST (&transport_list); t; t = next) - { - next = LIST_NEXT (t, link); - transport_release (t); - } + for (t = LIST_FIRST(&transport_list); t; t = next) { + next = LIST_NEXT(t, link); + transport_release(t); + } } /* @@ -373,13 +366,13 @@ transport_send_messages (fd_set *fds) * specific string format. */ struct transport * -transport_create (char *name, char *addr) +transport_create(char *name, char *addr) { - struct transport_vtbl *method; + struct transport_vtbl *method; - for (method = LIST_FIRST (&transport_method_list); method; - method = LIST_NEXT (method, link)) - if (strcmp (method->name, name) == 0) - return (*method->create) (addr); - return 0; + for (method = LIST_FIRST(&transport_method_list); method; + method = LIST_NEXT(method, link)) + if (strcmp(method->name, name) == 0) + return (*method->create) (addr); + return 0; } diff --git a/sbin/isakmpd/transport.h b/sbin/isakmpd/transport.h index d7f25b5013c..809dea118ca 100644 --- a/sbin/isakmpd/transport.h +++ b/sbin/isakmpd/transport.h @@ -1,5 +1,5 @@ -/* $OpenBSD: transport.h,v 1.13 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: transport.h,v 1.16 2000/07/17 18:57:59 provos Exp $ */ +/* $OpenBSD: transport.h,v 1.14 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: transport.h,v 1.16 2000/07/17 18:57:59 provos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -49,79 +49,79 @@ struct transport; /* This describes a tranport "method" like UDP or similar. */ struct transport_vtbl { - /* All transport methods are linked together. */ - LIST_ENTRY (transport_vtbl) link; + /* All transport methods are linked together. */ + LIST_ENTRY(transport_vtbl) link; - /* A textual name of the transport method. */ - char *name; + /* A textual name of the transport method. */ + char *name; - /* Create a transport instance of this method. */ - struct transport *(*create) (char *); + /* Create a transport instance of this method. */ + struct transport *(*create) (char *); - /* Reinitialize specific transport. */ - void (*reinit) (void); + /* Reinitialize specific transport. */ + void (*reinit) (void); - /* Remove a transport instance of this method. */ - void (*remove) (struct transport *); + /* Remove a transport instance of this method. */ + void (*remove) (struct transport *); - /* Report status of given transport */ - void (*report) (struct transport *); + /* Report status of given transport */ + void (*report) (struct transport *); - /* Let the given transport set it's bit in the fd_set passed in. */ - int (*fd_set) (struct transport *, fd_set *, int); + /* Let the given transport set it's bit in the fd_set passed in. */ + int (*fd_set) (struct transport *, fd_set *, int); - /* Is the given transport ready for I/O? */ - int (*fd_isset) (struct transport *, fd_set *); + /* Is the given transport ready for I/O? */ + int (*fd_isset) (struct transport *, fd_set *); - /* - * Read a message from the transport's incoming pipe and start - * handling it. - */ - void (*handle_message) (struct transport *); + /* + * Read a message from the transport's incoming pipe and start + * handling it. + */ + void (*handle_message) (struct transport *); - /* Send a message through the outgoing pipe. */ - int (*send_message) (struct message *); + /* Send a message through the outgoing pipe. */ + int (*send_message) (struct message *); - /* - * Fill out a sockaddr structure with the transport's destination end's - * address info. - */ - void (*get_dst) (struct transport *, struct sockaddr **); + /* + * Fill out a sockaddr structure with the transport's destination end's + * address info. + */ + void (*get_dst) (struct transport *, struct sockaddr **); - /* - * Fill out a sockaddr structure with the transport's source end's - * address info. - */ - void (*get_src) (struct transport *, struct sockaddr **); + /* + * Fill out a sockaddr structure with the transport's source end's + * address info. + */ + void (*get_src) (struct transport *, struct sockaddr **); - /* - * Return a string with decoded src and dst information - */ - char *(*decode_ids) (struct transport *); + /* + * Return a string with decoded src and dst information + */ + char *(*decode_ids) (struct transport *); }; struct transport { - /* All transports used are linked together. */ - LIST_ENTRY (transport) link; + /* All transports used are linked together. */ + LIST_ENTRY(transport) link; - /* What transport method is this an instance of? */ - struct transport_vtbl *vtbl; + /* What transport method is this an instance of? */ + struct transport_vtbl *vtbl; - /* The queue holding messages to send on this transport. */ - struct msg_head sendq; + /* The queue holding messages to send on this transport. */ + struct msg_head sendq; - /* - * Prioritized send queue. Messages in this queue will be transmitted - * before the normal sendq, they will also all be transmitted prior - * to a daemon shutdown. Currently only used for DELETE notifications. - */ - struct msg_head prio_sendq; + /* + * Prioritized send queue. Messages in this queue will be transmitted + * before the normal sendq, they will also all be transmitted prior + * to a daemon shutdown. Currently only used for DELETE notifications. + */ + struct msg_head prio_sendq; - /* Flags describing the transport. */ - int flags; + /* Flags describing the transport. */ + int flags; - /* References counter. */ - int refcnt; + /* References counter. */ + int refcnt; }; /* Set if this is a transport we want to listen on. */ @@ -129,18 +129,18 @@ struct transport { /* Used for mark-and-sweep-type garbage collection of transports */ #define TRANSPORT_MARK 2 -extern void transport_add (struct transport *); -extern struct transport *transport_create (char *, char *); -extern int transport_fd_set (fd_set *); -extern void transport_handle_messages (fd_set *); -extern void transport_init (void); -extern void transport_map (void (*) (struct transport *)); -extern void transport_method_add (struct transport_vtbl *); -extern int transport_pending_wfd_set (fd_set *); -extern void transport_reference (struct transport *); -extern void transport_release (struct transport *); -extern void transport_report (void); -extern void transport_send_messages (fd_set *); -extern void transport_reinit (void); -extern int transport_prio_sendqs_empty (void); -#endif /* _TRANSPORT_H_ */ +extern void transport_add(struct transport *); +extern struct transport *transport_create(char *, char *); +extern int transport_fd_set(fd_set *); +extern void transport_handle_messages(fd_set *); +extern void transport_init(void); +extern void transport_map(void (*) (struct transport *)); +extern void transport_method_add(struct transport_vtbl *); +extern int transport_pending_wfd_set(fd_set *); +extern void transport_reference(struct transport *); +extern void transport_release(struct transport *); +extern void transport_report(void); +extern void transport_send_messages(fd_set *); +extern void transport_reinit(void); +extern int transport_prio_sendqs_empty(void); +#endif /* _TRANSPORT_H_ */ diff --git a/sbin/isakmpd/udp.c b/sbin/isakmpd/udp.c index afc63cba16b..f695dd58fa5 100644 --- a/sbin/isakmpd/udp.c +++ b/sbin/isakmpd/udp.c @@ -1,5 +1,5 @@ -/* $OpenBSD: udp.c,v 1.68 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */ +/* $OpenBSD: udp.c,v 1.69 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -62,204 +62,189 @@ #define UDP_SIZE 65536 -/* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */ +/* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */ #ifndef SO_REUSEPORT #define SO_REUSEPORT SO_REUSEADDR #endif struct udp_transport { - struct transport transport; - struct sockaddr *src; - struct sockaddr *dst; - int s; - LIST_ENTRY (udp_transport) link; + struct transport transport; + struct sockaddr *src, *dst; + int s; + LIST_ENTRY(udp_transport) link; }; -static struct transport *udp_clone (struct udp_transport *, struct sockaddr *); -static struct transport *udp_create (char *); -static void udp_reinit (void); -static void udp_remove (struct transport *); -static void udp_report (struct transport *); -static int udp_fd_set (struct transport *, fd_set *, int); -static int udp_fd_isset (struct transport *, fd_set *); -static void udp_handle_message (struct transport *); -static struct transport *udp_make (struct sockaddr *); -static int udp_send_message (struct message *); -static void udp_get_dst (struct transport *, struct sockaddr **); -static void udp_get_src (struct transport *, struct sockaddr **); -static char *udp_decode_ids (struct transport *); +static struct transport *udp_clone(struct udp_transport *, struct sockaddr *); +static struct transport *udp_create(char *); +static void udp_reinit(void); +static void udp_remove(struct transport *); +static void udp_report(struct transport *); +static int udp_fd_set(struct transport *, fd_set *, int); +static int udp_fd_isset(struct transport *, fd_set *); +static void udp_handle_message(struct transport *); +static struct transport *udp_make(struct sockaddr *); +static int udp_send_message(struct message *); +static void udp_get_dst(struct transport *, struct sockaddr **); +static void udp_get_src(struct transport *, struct sockaddr **); +static char *udp_decode_ids(struct transport *); #if 0 -static in_port_t udp_decode_port (char *); +static in_port_t udp_decode_port(char *); #endif static struct transport_vtbl udp_transport_vtbl = { - { 0 }, "udp", - udp_create, - udp_reinit, - udp_remove, - udp_report, - udp_fd_set, - udp_fd_isset, - udp_handle_message, - udp_send_message, - udp_get_dst, - udp_get_src, - udp_decode_ids + {0}, "udp", + udp_create, + udp_reinit, + udp_remove, + udp_report, + udp_fd_set, + udp_fd_isset, + udp_handle_message, + udp_send_message, + udp_get_dst, + udp_get_src, + udp_decode_ids }; /* A list of UDP transports we listen for messages on. */ -static LIST_HEAD (udp_listen_list, udp_transport) udp_listen_list; +static +LIST_HEAD(udp_listen_list, udp_transport) udp_listen_list; -char *udp_default_port = 0; -char *udp_bind_port = 0; -int bind_family = 0; static struct transport *default_transport, *default_transport6; +char *udp_default_port = 0; +char *udp_bind_port = 0; +int bind_family = 0; /* Find an UDP transport listening on ADDR:PORT. */ static struct udp_transport * -udp_listen_lookup (struct sockaddr *addr) +udp_listen_lookup(struct sockaddr *addr) { - struct udp_transport *u; + struct udp_transport *u; - for (u = LIST_FIRST (&udp_listen_list); u; u = LIST_NEXT (u, link)) - if (sysdep_sa_len (u->src) == sysdep_sa_len (addr) - && memcmp (u->src, addr, sysdep_sa_len (addr)) == 0) - return u; - return 0; + for (u = LIST_FIRST(&udp_listen_list); u; u = LIST_NEXT(u, link)) + if (sysdep_sa_len(u->src) == sysdep_sa_len(addr) && + memcmp(u->src, addr, sysdep_sa_len(addr)) == 0) + return u; + return 0; } /* Create a UDP transport structure bound to LADDR just for listening. */ static struct transport * -udp_make (struct sockaddr *laddr) +udp_make(struct sockaddr *laddr) { - struct udp_transport *t = 0; - int s, on, wildcardaddress = 0; - - t = calloc (1, sizeof *t); - if (!t) - { - log_print ("udp_make: malloc (%lu) failed", (unsigned long)sizeof *t); - return 0; - } - - s = monitor_socket (laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP); - if (s == -1) - { - log_error ("udp_make: socket (%d, %d, %d)", laddr->sa_family, SOCK_DGRAM, - IPPROTO_UDP); - goto err; - } - - /* Make sure we don't get our traffic encrypted. */ - if (sysdep_cleartext (s, laddr->sa_family) == -1) - goto err; - - /* Wildcard address ? */ - switch (laddr->sa_family) - { - case AF_INET: - if (((struct sockaddr_in *)laddr)->sin_addr.s_addr == INADDR_ANY) - wildcardaddress = 1; - break; - case AF_INET6: - if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr)) - wildcardaddress = 1; - break; - } - - /* - * In order to have several bound specific address-port combinations - * with the same port SO_REUSEADDR is needed. - * If this is a wildcard socket and we are not listening there, but only - * sending from it make sure it is entirely reuseable with SO_REUSEPORT. - */ - on = 1; - if (monitor_setsockopt (s, SOL_SOCKET, - wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, - (void *)&on, sizeof on) == -1) - { - log_error ("udp_make: setsockopt (%d, %d, %d, %p, %lu)", s, SOL_SOCKET, - wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, - &on, (unsigned long)sizeof on); - goto err; - } - - t->transport.vtbl = &udp_transport_vtbl; - t->src = laddr; - if (monitor_bind (s, t->src, sysdep_sa_len (t->src))) - { - char *tstr; - if (sockaddr2text (t->src, &tstr, 0)) - log_error ("udp_make: bind (%d, %p, %lu)", s, &t->src, - (unsigned long)sizeof t->src); - else - { - log_error ("udp_make: bind (%d, %s, %lu)", s, tstr, - (unsigned long)sizeof t->src); - free (tstr); - } - goto err; - } - - t->s = s; - transport_add (&t->transport); - transport_reference (&t->transport); - t->transport.flags |= TRANSPORT_LISTEN; - return &t->transport; + struct udp_transport *t = 0; + int s, on, wildcardaddress = 0; + + t = calloc(1, sizeof *t); + if (!t) { + log_print("udp_make: malloc (%lu) failed", (unsigned long) sizeof *t); + return 0; + } + s = monitor_socket(laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (s == -1) { + log_error("udp_make: socket (%d, %d, %d)", laddr->sa_family, + SOCK_DGRAM, IPPROTO_UDP); + goto err; + } + /* Make sure we don't get our traffic encrypted. */ + if (sysdep_cleartext(s, laddr->sa_family) == -1) + goto err; + + /* Wildcard address ? */ + switch (laddr->sa_family) { + case AF_INET: + if (((struct sockaddr_in *) laddr)->sin_addr.s_addr == INADDR_ANY) + wildcardaddress = 1; + break; + case AF_INET6: + if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) laddr)->sin6_addr)) + wildcardaddress = 1; + break; + } + + /* + * In order to have several bound specific address-port combinations + * with the same port SO_REUSEADDR is needed. + * If this is a wildcard socket and we are not listening there, but only + * sending from it make sure it is entirely reuseable with SO_REUSEPORT. + */ + on = 1; + if (monitor_setsockopt(s, SOL_SOCKET, + wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, + (void *) &on, sizeof on) == -1) { + log_error("udp_make: setsockopt (%d, %d, %d, %p, %lu)", s, SOL_SOCKET, + wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, + &on, (unsigned long) sizeof on); + goto err; + } + t->transport.vtbl = &udp_transport_vtbl; + t->src = laddr; + if (monitor_bind(s, t->src, sysdep_sa_len(t->src))) { + char *tstr; + + if (sockaddr2text(t->src, &tstr, 0)) + log_error("udp_make: bind (%d, %p, %lu)", s, &t->src, + (unsigned long) sizeof t->src); + else { + log_error("udp_make: bind (%d, %s, %lu)", s, tstr, + (unsigned long) sizeof t->src); + free(tstr); + } + goto err; + } + t->s = s; + transport_add(&t->transport); + transport_reference(&t->transport); + t->transport.flags |= TRANSPORT_LISTEN; + return &t->transport; err: - if (s >= 0) - close (s); - if (t) - { - /* Already closed. */ - t->s = -1; - udp_remove (&t->transport); - } - return 0; + if (s >= 0) + close(s); + if (t) { + /* Already closed. */ + t->s = -1; + udp_remove(&t->transport); + } + return 0; } /* Clone a listen transport U, record a destination RADDR for outbound use. */ static struct transport * -udp_clone (struct udp_transport *u, struct sockaddr *raddr) +udp_clone(struct udp_transport *u, struct sockaddr *raddr) { - struct transport *t; - struct udp_transport *u2; - - t = malloc (sizeof *u); - if (!t) - { - log_error ("udp_clone: malloc (%lu) failed", (unsigned long)sizeof *u); - return 0; - } - u2 = (struct udp_transport *)t; - - memcpy (u2, u, sizeof *u); - - u2->src = malloc (sysdep_sa_len (u->src)); - if (!u2->src) - { - log_error ("udp_clone: malloc (%d) failed", sysdep_sa_len (u->src)); - free (t); - return 0; - } - memcpy (u2->src, u->src, sysdep_sa_len (u->src)); - - u2->dst = malloc (sysdep_sa_len (raddr)); - if (!u2->dst) - { - log_error ("udp_clone: malloc (%d) failed", sysdep_sa_len (raddr)); - free (u2->src); - free (t); - return 0; - } - memcpy (u2->dst, raddr, sysdep_sa_len (raddr)); - - t->flags &= ~TRANSPORT_LISTEN; - - transport_add (t); - - return t; + struct udp_transport *u2; + struct transport *t; + + t = malloc(sizeof *u); + if (!t) { + log_error("udp_clone: malloc (%lu) failed", (unsigned long) sizeof *u); + return 0; + } + u2 = (struct udp_transport *) t; + + memcpy(u2, u, sizeof *u); + + u2->src = malloc(sysdep_sa_len(u->src)); + if (!u2->src) { + log_error("udp_clone: malloc (%d) failed", sysdep_sa_len(u->src)); + free(t); + return 0; + } + memcpy(u2->src, u->src, sysdep_sa_len(u->src)); + + u2->dst = malloc(sysdep_sa_len(raddr)); + if (!u2->dst) { + log_error("udp_clone: malloc (%d) failed", sysdep_sa_len(raddr)); + free(u2->src); + free(t); + return 0; + } + memcpy(u2->dst, raddr, sysdep_sa_len(raddr)); + + t->flags &= ~TRANSPORT_LISTEN; + transport_add(t); + return t; } /* @@ -269,15 +254,15 @@ udp_clone (struct udp_transport *u, struct sockaddr *raddr) * system-wide pools of known ISAKMP transports. */ static struct transport * -udp_bind (const struct sockaddr *addr) +udp_bind(const struct sockaddr *addr) { - struct sockaddr *src = malloc (sysdep_sa_len ((struct sockaddr *)addr)); + struct sockaddr *src = malloc(sysdep_sa_len((struct sockaddr *) addr)); - if (!src) - return 0; + if (!src) + return 0; - memcpy (src, addr, sysdep_sa_len ((struct sockaddr *)addr)); - return udp_make (src); + memcpy(src, addr, sysdep_sa_len((struct sockaddr *) addr)); + return udp_make(src); } /* @@ -286,179 +271,162 @@ udp_bind (const struct sockaddr *addr) * Return 0 if successful, -1 otherwise. */ static int -udp_bind_if (char *ifname, struct sockaddr *if_addr, void *arg) +udp_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) { - char *port = (char *)arg; - struct sockaddr_storage saddr_st; - struct sockaddr *saddr = (struct sockaddr *)&saddr_st; - struct conf_list *listen_on; - struct udp_transport *u; - struct conf_list_node *address; - struct sockaddr *addr; - struct transport *t; - struct ifreq flags_ifr; - char *addr_str, *ep; - int s, error; - long lport; - - /* - * Well, UDP is an internet protocol after all so drop other ifreqs. - */ - if ((if_addr->sa_family != AF_INET - || sysdep_sa_len (if_addr) != sizeof (struct sockaddr_in)) - && (if_addr->sa_family != AF_INET6 - || sysdep_sa_len (if_addr) != sizeof (struct sockaddr_in6))) - return 0; - - /* - * Only create sockets for families we should listen to. - */ - if (bind_family) - switch (if_addr->sa_family) - { - case AF_INET: - if ((bind_family & BIND_FAMILY_INET4) == 0) - return 0; - break; - case AF_INET6: - if ((bind_family & BIND_FAMILY_INET6) == 0) - return 0; - break; - default: - return 0; - } - - /* - * These special addresses are not useable as they have special meaning - * in the IP stack. - */ - if (if_addr->sa_family == AF_INET - && (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY - || (((struct sockaddr_in *)if_addr)->sin_addr.s_addr - == INADDR_NONE)) ) - return 0; - - /* - * Go through the list of transports and see if we already have this - * address bound. If so, unmark the transport and skip it; this allows - * us to call this function when we suspect a new address has appeared. - */ - if (sysdep_sa_len (if_addr) > sizeof saddr_st) - return 0; - memcpy (saddr, if_addr, sysdep_sa_len (if_addr)); - switch (saddr->sa_family) /* Add the port number to the sockaddr. */ - { - case AF_INET: - ((struct sockaddr_in *)saddr)->sin_port - = htons (strtol (port, &ep, 10)); - break; - case AF_INET6: - ((struct sockaddr_in6 *)saddr)->sin6_port - = htons (strtol (port, &ep, 10)); - break; - } - - if ((u = udp_listen_lookup (saddr)) != 0) - { - u->transport.flags &= ~TRANSPORT_MARK; - return 0; - } - - /* Don't bother with interfaces that are down. */ - s = monitor_socket (if_addr->sa_family, SOCK_DGRAM, 0); - if (s == -1) - { - log_error ("udp_bind_if: socket (%d, SOCK_DGRAM, 0) failed", - if_addr->sa_family); - return -1; - } - strlcpy (flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name); - if (ioctl (s, SIOCGIFFLAGS, (caddr_t)&flags_ifr) == -1) - { - log_error ("udp_bind_if: ioctl (%d, SIOCGIFFLAGS, ...) failed", s); - return -1; - } - close (s); - if (!(flags_ifr.ifr_flags & IFF_UP)) - return 0; - - /* - * Set port. - * XXX Use getservbyname too. - */ - lport = strtol (port, &ep, 10); - if (*ep != '\0' || lport < (long)0 || lport > (long)USHRT_MAX) - { - log_print ("udp_bind_if: " - "port string \"%s\" not convertible to in_port_t", port); - return -1; - } - - switch (if_addr->sa_family) - { - case AF_INET: - ((struct sockaddr_in *)if_addr)->sin_port = htons (lport); - break; - case AF_INET6: - ((struct sockaddr_in6 *)if_addr)->sin6_port = htons (lport); - break; - default: - log_print ("udp_bind_if: unsupported protocol family %d", - if_addr->sa_family); - break; - } - - /* - * If we are explicit about what addresses we can listen to, be sure - * to respect that option. - * This is quite wasteful redoing the list-run for every interface, - * but who cares? This is not an operation that needs to be fast. - */ - listen_on = conf_get_list ("General", "Listen-on"); - if (listen_on) - { - for (address = TAILQ_FIRST (&listen_on->fields); address; - address = TAILQ_NEXT (address, link)) - { - if (text2sockaddr (address->field, port, &addr)) - { - log_print ("udp_bind_if: invalid address %s in \"Listen-on\"", - address->field); - continue; - } - - /* If found, take the easy way out. */ - if (memcmp (addr, if_addr, sysdep_sa_len (addr)) == 0) - { - free (addr); - break; - } - free (addr); - } - conf_free_list (listen_on); - - /* - * If address is zero then we did not find the address among the ones - * we should listen to. - * XXX We do not discover if we do not find our listen addresses... - * Maybe this should be the other way round. - */ - if (!address) + char *port = (char *) arg, *addr_str, *ep; + struct sockaddr_storage saddr_st; + struct sockaddr *saddr = (struct sockaddr *) & saddr_st; + struct conf_list *listen_on; + struct udp_transport *u; + struct conf_list_node *address; + struct sockaddr *addr; + struct transport *t; + struct ifreq flags_ifr; + int s, error; + long lport; + + /* + * Well, UDP is an internet protocol after all so drop other ifreqs. + */ + if ((if_addr->sa_family != AF_INET || + sysdep_sa_len(if_addr) != sizeof(struct sockaddr_in)) && + (if_addr->sa_family != AF_INET6 || + sysdep_sa_len(if_addr) != sizeof(struct sockaddr_in6))) + return 0; + + /* + * Only create sockets for families we should listen to. + */ + if (bind_family) { + switch (if_addr->sa_family) { + case AF_INET: + if ((bind_family & BIND_FAMILY_INET4) == 0) + return 0; + break; + case AF_INET6: + if ((bind_family & BIND_FAMILY_INET6) == 0) + return 0; + break; + default: + return 0; + } + } + + /* + * These special addresses are not useable as they have special meaning + * in the IP stack. + */ + if (if_addr->sa_family == AF_INET && + (((struct sockaddr_in *) if_addr)->sin_addr.s_addr == INADDR_ANY || + (((struct sockaddr_in *) if_addr)->sin_addr.s_addr == INADDR_NONE))) + return 0; + + /* + * Go through the list of transports and see if we already have this + * address bound. If so, unmark the transport and skip it; this allows + * us to call this function when we suspect a new address has appeared. + */ + if (sysdep_sa_len(if_addr) > sizeof saddr_st) + return 0; + memcpy(saddr, if_addr, sysdep_sa_len(if_addr)); + switch (saddr->sa_family) { /* Add the port number to the sockaddr. */ + case AF_INET: + ((struct sockaddr_in *) saddr)->sin_port = + htons(strtol(port, &ep, 10)); + break; + case AF_INET6: + ((struct sockaddr_in6 *) saddr)->sin6_port = + htons(strtol(port, &ep, 10)); + break; + } + + if ((u = udp_listen_lookup(saddr)) != 0) { + u->transport.flags &= ~TRANSPORT_MARK; + return 0; + } + /* Don't bother with interfaces that are down. */ + s = monitor_socket(if_addr->sa_family, SOCK_DGRAM, 0); + if (s == -1) { + log_error("udp_bind_if: socket (%d, SOCK_DGRAM, 0) failed", + if_addr->sa_family); + return -1; + } + strlcpy(flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name); + if (ioctl(s, SIOCGIFFLAGS, (caddr_t) & flags_ifr) == -1) { + log_error("udp_bind_if: ioctl (%d, SIOCGIFFLAGS, ...) failed", s); + return -1; + } + close(s); + if (!(flags_ifr.ifr_flags & IFF_UP)) + return 0; + + /* + * Set port. + * XXX Use getservbyname too. + */ + lport = strtol(port, &ep, 10); + if (*ep != '\0' || lport < (long) 0 || lport > (long) USHRT_MAX) { + log_print("udp_bind_if: " + "port string \"%s\" not convertible to in_port_t", port); + return -1; + } + switch (if_addr->sa_family) { + case AF_INET: + ((struct sockaddr_in *) if_addr)->sin_port = htons(lport); + break; + case AF_INET6: + ((struct sockaddr_in6 *) if_addr)->sin6_port = htons(lport); + break; + default: + log_print("udp_bind_if: unsupported protocol family %d", + if_addr->sa_family); + break; + } + + /* + * If we are explicit about what addresses we can listen to, be sure + * to respect that option. + * This is quite wasteful redoing the list-run for every interface, + * but who cares? This is not an operation that needs to be fast. + */ + listen_on = conf_get_list("General", "Listen-on"); + if (listen_on) { + for (address = TAILQ_FIRST(&listen_on->fields); address; + address = TAILQ_NEXT(address, link)) { + if (text2sockaddr(address->field, port, &addr)) { + log_print("udp_bind_if: invalid address %s in \"Listen-on\"", + address->field); + continue; + } + /* If found, take the easy way out. */ + if (memcmp(addr, if_addr, sysdep_sa_len(addr)) == 0) { + free(addr); + break; + } + free(addr); + } + conf_free_list(listen_on); + + /* + * If address is zero then we did not find the address among the ones + * we should listen to. + * XXX We do not discover if we do not find our listen addresses... + * Maybe this should be the other way round. + */ + if (!address) + return 0; + } + t = udp_bind(if_addr); + if (!t) { + error = sockaddr2text(if_addr, &addr_str, 0); + log_print("udp_bind_if: failed to create a socket on %s:%s", + error ? "unknown" : addr_str, port); + if (!error) + free(addr_str); + return -1; + } + LIST_INSERT_HEAD(&udp_listen_list, (struct udp_transport *) t, link); return 0; - } - - t = udp_bind (if_addr); - if (!t) - { - error = sockaddr2text (if_addr, &addr_str, 0); - log_print ("udp_bind_if: failed to create a socket on %s:%s", - error ? "unknown" : addr_str, port); - if (!error) - free (addr_str); - return -1; - } - LIST_INSERT_HEAD (&udp_listen_list, (struct udp_transport *)t, link); - return 0; } /* @@ -466,119 +434,108 @@ udp_bind_if (char *ifname, struct sockaddr *if_addr, void *arg) * a transport useable to talk to the peer specified by that name. */ static struct transport * -udp_create (char *name) +udp_create(char *name) { - struct udp_transport *u; - struct transport *rv; - struct sockaddr *dst, *addr; - char *addr_str, *port_str; - - port_str = conf_get_str (name, "Port"); - if (!port_str) - port_str = udp_default_port; - if (!port_str) - port_str = "500"; - - addr_str = conf_get_str (name, "Address"); - if (!addr_str) - { - log_print ("udp_create: no address configured for \"%s\"", name); - return 0; - } - if (text2sockaddr (addr_str, port_str, &dst)) - { - log_print ("udp_create: address \"%s\" not understood", addr_str); - return 0; - } - - addr_str = conf_get_str (name, "Local-address"); - if (!addr_str) - addr_str = conf_get_str ("General", "Listen-on"); - if (!addr_str) - { - if ((dst->sa_family == AF_INET && !default_transport) - || (dst->sa_family == AF_INET6 && !default_transport6)) - { - log_print ("udp_create: no default transport"); - rv = 0; - goto ret; - } - else - { - /* XXX Ugly! */ - rv = udp_clone ((struct udp_transport *)(dst->sa_family == AF_INET - ? default_transport - : default_transport6), dst); - goto ret; - } - } - - if (text2sockaddr (addr_str, port_str, &addr)) - { - log_print ("udp_create: address \"%s\" not understood", addr_str); - rv = 0; - goto ret; - } - u = udp_listen_lookup (addr); - free (addr); - if (!u) - { - log_print ("udp_create: %s:%s must exist as a listener too", addr_str, - port_str); - rv = 0; - goto ret; - } - rv = udp_clone (u, dst); - - ret: - free (dst); - return rv; + struct udp_transport *u; + struct transport *rv; + struct sockaddr *dst, *addr; + char *addr_str, *port_str; + + port_str = conf_get_str(name, "Port"); + if (!port_str) + port_str = udp_default_port; + if (!port_str) + port_str = "500"; + + addr_str = conf_get_str(name, "Address"); + if (!addr_str) { + log_print("udp_create: no address configured for \"%s\"", name); + return 0; + } + if (text2sockaddr(addr_str, port_str, &dst)) { + log_print("udp_create: address \"%s\" not understood", addr_str); + return 0; + } + addr_str = conf_get_str(name, "Local-address"); + if (!addr_str) + addr_str = conf_get_str("General", "Listen-on"); + if (!addr_str) { + if ((dst->sa_family == AF_INET && !default_transport) || + (dst->sa_family == AF_INET6 && !default_transport6)) { + log_print("udp_create: no default transport"); + rv = 0; + goto ret; + } else { + /* XXX Ugly! */ + rv = udp_clone((struct udp_transport *) + (dst->sa_family == AF_INET ? default_transport : + default_transport6), dst); + goto ret; + } + } + if (text2sockaddr(addr_str, port_str, &addr)) { + log_print("udp_create: address \"%s\" not understood", addr_str); + rv = 0; + goto ret; + } + u = udp_listen_lookup(addr); + free(addr); + if (!u) { + log_print("udp_create: %s:%s must exist as a listener too", addr_str, + port_str); + rv = 0; + goto ret; + } + rv = udp_clone(u, dst); + +ret: + free(dst); + return rv; } void -udp_remove (struct transport *t) +udp_remove(struct transport * t) { - struct udp_transport *u = (struct udp_transport *)t; - - if (u->src) - free (u->src); - if (u->dst) - free (u->dst); - if (t->flags & TRANSPORT_LISTEN) - { - if (u->s >= 0) - close (u->s); - if (t == default_transport) - default_transport = 0; - else if (t == default_transport6) - default_transport6 = 0; - if (u->link.le_prev) - LIST_REMOVE (u, link); - } - free (t); + struct udp_transport *u = (struct udp_transport *) t; + + if (u->src) + free(u->src); + if (u->dst) + free(u->dst); + if (t->flags & TRANSPORT_LISTEN) { + if (u->s >= 0) + close(u->s); + if (t == default_transport) + default_transport = 0; + else if (t == default_transport6) + default_transport6 = 0; + if (u->link.le_prev) + LIST_REMOVE(u, link); + } + free(t); } -/* Report transport-method specifics of the T transport. */ +/* Report transport-method specifics of the T transport. */ void -udp_report (struct transport *t) +udp_report(struct transport * t) { - struct udp_transport *u = (struct udp_transport *)t; - char *src, *dst; + struct udp_transport *u = (struct udp_transport *) t; + char *src, *dst; - if (sockaddr2text (u->src, &src, 0)) - goto ret; + if (sockaddr2text(u->src, &src, 0)) + goto ret; - if (!u->dst || sockaddr2text (u->dst, &dst, 0)) - dst = 0; + if (!u->dst || sockaddr2text(u->dst, &dst, 0)) + dst = 0; - LOG_DBG ((LOG_REPORT, 0, "udp_report: fd %d src %s dst %s", u->s, src, + LOG_DBG((LOG_REPORT, 0, "udp_report: fd %d src %s dst %s", u->s, src, dst ? dst : "<none>")); - ret: - if (dst) - free (dst); - if (src) - free (src); +ret: + if (dst) + free(dst); + if (src) + free(src); } /* @@ -591,42 +548,39 @@ udp_report (struct transport *t) * transports that have not been unmarked. */ static void -udp_reinit (void) +udp_reinit(void) { - struct udp_transport *u, *u2; - char *port; - - /* Initialize the protocol and port numbers. */ - port = udp_default_port ? udp_default_port : "500"; - - /* Mark all UDP transports, except the default ones. */ - for (u = LIST_FIRST (&udp_listen_list); u; u = LIST_NEXT (u, link)) - if (&u->transport != default_transport - && &u->transport != default_transport6) - u->transport.flags |= TRANSPORT_MARK; - - /* Re-probe interface list. */ - if (if_map (udp_bind_if, port) == -1) - log_print ("udp_init: Could not bind the ISAKMP UDP port %s on all " - "interfaces", port); - - /* - * Release listening transports for local addresses that no - * longer exist. udp_bind_if () will have left those still marked. - */ - u = LIST_FIRST (&udp_listen_list); - while (u) - { - u2 = LIST_NEXT (u, link); - - if (u->transport.flags & TRANSPORT_MARK) - { - LIST_REMOVE (u, link); - transport_release (&u->transport); - } - - u = u2; - } + struct udp_transport *u, *u2; + char *port; + + /* Initialize the protocol and port numbers. */ + port = udp_default_port ? udp_default_port : "500"; + + /* Mark all UDP transports, except the default ones. */ + for (u = LIST_FIRST(&udp_listen_list); u; u = LIST_NEXT(u, link)) + if (&u->transport != default_transport && + &u->transport != default_transport6) + u->transport.flags |= TRANSPORT_MARK; + + /* Re-probe interface list. */ + if (if_map(udp_bind_if, port) == -1) + log_print("udp_init: Could not bind the ISAKMP UDP port %s on all " + "interfaces", port); + + /* + * Release listening transports for local addresses that no + * longer exist. udp_bind_if () will have left those still marked. + */ + u = LIST_FIRST(&udp_listen_list); + while (u) { + u2 = LIST_NEXT(u, link); + + if (u->transport.flags & TRANSPORT_MARK) { + LIST_REMOVE(u, link); + transport_release(&u->transport); + } + u = u2; + } } /* @@ -635,93 +589,84 @@ udp_reinit (void) * for the generic case when we are the initiator. */ void -udp_init (void) +udp_init(void) { - struct sockaddr_storage dflt_stor; - struct sockaddr_in *dflt = (struct sockaddr_in *)&dflt_stor; - struct conf_list *listen_on; - char *port; - long lport; - char *ep; - - /* Initialize the protocol and port numbers. */ - port = udp_default_port ? udp_default_port : "500"; - - LIST_INIT (&udp_listen_list); - - transport_method_add (&udp_transport_vtbl); - - /* Bind the ISAKMP UDP port on all network interfaces we have. */ - if (if_map (udp_bind_if, port) == -1) - log_fatal ("udp_init: Could not bind the ISAKMP UDP port %s on all " - "interfaces", port); - - /* Only listen to the specified address if Listen-on is configured */ - listen_on = conf_get_list ("General", "Listen-on"); - if (listen_on) - { - LOG_DBG ((LOG_TRANSPORT, 50, - "udp_init: not binding ISAKMP UDP port to INADDR_ANY")); - conf_free_list (listen_on); - return; - } - - /* - * Get port. - * XXX Use getservbyname too. - */ - lport = strtol (port, &ep, 10); - if (*ep != '\0' || lport < (long)0 || lport > (long)USHRT_MAX) - { - log_print ("udp_init: port string \"%s\" not convertible to in_port_t", - port); - return; - } - - /* - * Bind to INADDR_ANY in case of new addresses popping up. - * Packet reception on this transport is taken as a hint to reprobe the - * interface list. - */ - if (!bind_family || (bind_family & BIND_FAMILY_INET4)) - { - memset (&dflt_stor, 0, sizeof dflt_stor); - dflt->sin_family = AF_INET; + struct sockaddr_storage dflt_stor; + struct sockaddr_in *dflt = (struct sockaddr_in *) & dflt_stor; + struct conf_list *listen_on; + char *port; + long lport; + char *ep; + + /* Initialize the protocol and port numbers. */ + port = udp_default_port ? udp_default_port : "500"; + + LIST_INIT(&udp_listen_list); + + transport_method_add(&udp_transport_vtbl); + + /* Bind the ISAKMP UDP port on all network interfaces we have. */ + if (if_map(udp_bind_if, port) == -1) + log_fatal("udp_init: Could not bind the ISAKMP UDP port %s on all " + "interfaces", port); + + /* Only listen to the specified address if Listen-on is configured */ + listen_on = conf_get_list("General", "Listen-on"); + if (listen_on) { + LOG_DBG((LOG_TRANSPORT, 50, + "udp_init: not binding ISAKMP UDP port to INADDR_ANY")); + conf_free_list(listen_on); + return; + } + /* + * Get port. + * XXX Use getservbyname too. + */ + lport = strtol(port, &ep, 10); + if (*ep != '\0' || lport < (long) 0 || lport > (long) USHRT_MAX) { + log_print("udp_init: port string \"%s\" not convertible to in_port_t", + port); + return; + } + /* + * Bind to INADDR_ANY in case of new addresses popping up. + * Packet reception on this transport is taken as a hint to reprobe the + * interface list. + */ + if (!bind_family || (bind_family & BIND_FAMILY_INET4)) { + memset(&dflt_stor, 0, sizeof dflt_stor); + dflt->sin_family = AF_INET; #if !defined (LINUX_IPSEC) - ((struct sockaddr_in *)dflt)->sin_len = sizeof (struct sockaddr_in); + ((struct sockaddr_in *) dflt)->sin_len = sizeof(struct sockaddr_in); #endif - ((struct sockaddr_in *)dflt)->sin_port = htons (lport); - - default_transport = udp_bind ((struct sockaddr *)&dflt_stor); - if (!default_transport) - { - log_error ("udp_init: could not allocate default " - "IPv4 ISAKMP UDP port"); - return; - } - LIST_INSERT_HEAD (&udp_listen_list, - (struct udp_transport *)default_transport, link); - } - - if (!bind_family || (bind_family & BIND_FAMILY_INET6)) - { - memset (&dflt_stor, 0, sizeof dflt_stor); - dflt->sin_family = AF_INET6; + ((struct sockaddr_in *) dflt)->sin_port = htons(lport); + + default_transport = udp_bind((struct sockaddr *) & dflt_stor); + if (!default_transport) { + log_error("udp_init: could not allocate default " + "IPv4 ISAKMP UDP port"); + return; + } + LIST_INSERT_HEAD(&udp_listen_list, + (struct udp_transport *) default_transport, link); + } + if (!bind_family || (bind_family & BIND_FAMILY_INET6)) { + memset(&dflt_stor, 0, sizeof dflt_stor); + dflt->sin_family = AF_INET6; #if !defined (LINUX_IPSEC) - ((struct sockaddr_in6 *)dflt)->sin6_len = sizeof (struct sockaddr_in6); + ((struct sockaddr_in6 *) dflt)->sin6_len = sizeof(struct sockaddr_in6); #endif - ((struct sockaddr_in6 *)dflt)->sin6_port = htons (lport); - - default_transport6 = udp_bind ((struct sockaddr *)&dflt_stor); - if (!default_transport6) - { - log_error ("udp_init: could not allocate default " - "IPv6 ISAKMP UDP port"); - return; - } - LIST_INSERT_HEAD (&udp_listen_list, - (struct udp_transport *)default_transport6, link); - } + ((struct sockaddr_in6 *) dflt)->sin6_port = htons(lport); + + default_transport6 = udp_bind((struct sockaddr *) & dflt_stor); + if (!default_transport6) { + log_error("udp_init: could not allocate default " + "IPv6 ISAKMP UDP port"); + return; + } + LIST_INSERT_HEAD(&udp_listen_list, + (struct udp_transport *) default_transport6, link); + } } /* @@ -729,25 +674,25 @@ udp_init (void) * as the number of file descriptors to check. */ static int -udp_fd_set (struct transport *t, fd_set *fds, int bit) +udp_fd_set(struct transport * t, fd_set * fds, int bit) { - struct udp_transport *u = (struct udp_transport *)t; + struct udp_transport *u = (struct udp_transport *) t; - if (bit) - FD_SET (u->s, fds); - else - FD_CLR (u->s, fds); + if (bit) + FD_SET(u->s, fds); + else + FD_CLR(u->s, fds); - return u->s + 1; + return u->s + 1; } /* Check if transport T's socket is set in FDS. */ static int -udp_fd_isset (struct transport *t, fd_set *fds) +udp_fd_isset(struct transport * t, fd_set * fds) { - struct udp_transport *u = (struct udp_transport *)t; + struct udp_transport *u = (struct udp_transport *) t; - return FD_ISSET (u->s, fds); + return FD_ISSET(u->s, fds); } /* @@ -757,84 +702,78 @@ udp_fd_isset (struct transport *t, fd_set *fds) * module. */ static void -udp_handle_message (struct transport *t) +udp_handle_message(struct transport * t) { - struct udp_transport *u = (struct udp_transport *)t; - u_int8_t buf[UDP_SIZE]; - struct sockaddr_storage from; - u_int32_t len = sizeof from; - ssize_t n; - struct message *msg; - - n = recvfrom (u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len); - if (n == -1) - { - log_error ("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf, UDP_SIZE, 0, - &from, &len); - return; - } - - /* - * If we received the packet over the default transports, reprobe the - * interfaces. - */ - if (t == default_transport || t == default_transport6) - { - udp_reinit (); - - /* - * As we don't know the actual destination address of the packet, - * we can't really deal with it. So, just ignore it and hope we - * catch the retransmission. - */ - return; - } - - /* - * Make a specialized UDP transport structure out of the incoming - * transport and the address information we got from recvfrom(2). - */ - t = udp_clone (u, (struct sockaddr *)&from); - if (!t) - return; - - msg = message_alloc (t, buf, n); - if (!msg) - { - log_error ("failed to allocate message structure, dropping packet " - "received on transport %p", u); - return; - } - message_recv (msg); + struct udp_transport *u = (struct udp_transport *) t; + u_int8_t buf[UDP_SIZE]; + struct sockaddr_storage from; + u_int32_t len = sizeof from; + ssize_t n; + struct message *msg; + + n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *) & from, &len); + if (n == -1) { + log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf, UDP_SIZE, 0, + &from, &len); + return; + } + /* + * If we received the packet over the default transports, reprobe the + * interfaces. + */ + if (t == default_transport || t == default_transport6) { + udp_reinit(); + + /* + * As we don't know the actual destination address of the packet, + * we can't really deal with it. So, just ignore it and hope we + * catch the retransmission. + */ + return; + } + /* + * Make a specialized UDP transport structure out of the incoming + * transport and the address information we got from recvfrom(2). + */ + t = udp_clone(u, (struct sockaddr *) & from); + if (!t) + return; + + msg = message_alloc(t, buf, n); + if (!msg) { + log_error("failed to allocate message structure, dropping packet " + "received on transport %p", u); + return; + } + message_recv(msg); } /* Physically send the message MSG over its associated transport. */ static int -udp_send_message (struct message *msg) +udp_send_message(struct message * msg) { - struct udp_transport *u = (struct udp_transport *)msg->transport; - ssize_t n; - struct msghdr m; - - /* - * Sending on connected sockets requires that no destination address is - * given, or else EISCONN will occur. - */ - m.msg_name = (caddr_t)u->dst; - m.msg_namelen = sysdep_sa_len (u->dst); - m.msg_iov = msg->iov; - m.msg_iovlen = msg->iovlen; - m.msg_control = 0; - m.msg_controllen = 0; - m.msg_flags = 0; - n = sendmsg (u->s, &m, 0); - if (n == -1) - { - /* XXX We should check whether the address has gone away */ - log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0); - return -1; - } - return 0; + struct udp_transport *u = (struct udp_transport *) msg->transport; + ssize_t n; + struct msghdr m; + + /* + * Sending on connected sockets requires that no destination address is + * given, or else EISCONN will occur. + */ + m.msg_name = (caddr_t) u->dst; + m.msg_namelen = sysdep_sa_len(u->dst); + m.msg_iov = msg->iov; + m.msg_iovlen = msg->iovlen; + m.msg_control = 0; + m.msg_controllen = 0; + m.msg_flags = 0; + n = sendmsg(u->s, &m, 0); + if (n == -1) { + /* XXX We should check whether the address has gone away */ + log_error("sendmsg (%d, %p, %d)", u->s, &m, 0); + return -1; + } + return 0; } /* @@ -842,9 +781,9 @@ udp_send_message (struct message *msg) * to by DST. */ static void -udp_get_dst (struct transport *t, struct sockaddr **dst) +udp_get_dst(struct transport * t, struct sockaddr ** dst) { - *dst = ((struct udp_transport *)t)->dst; + *dst = ((struct udp_transport *) t)->dst; } /* @@ -852,41 +791,37 @@ udp_get_dst (struct transport *t, struct sockaddr **dst) * to by SRC. Put its length into SRC_LEN. */ static void -udp_get_src (struct transport *t, struct sockaddr **src) +udp_get_src(struct transport * t, struct sockaddr ** src) { - *src = ((struct udp_transport *)t)->src; + *src = ((struct udp_transport *) t)->src; } static char * -udp_decode_ids (struct transport *t) +udp_decode_ids(struct transport * t) { - static char result[1024]; - char idsrc[256], iddst[256]; + static char result[1024]; + char idsrc[256], iddst[256]; #ifdef HAVE_GETNAMEINFO - if (getnameinfo (((struct udp_transport *)t)->src, - sysdep_sa_len (((struct udp_transport *)t)->src), - idsrc, sizeof idsrc, NULL, 0, NI_NUMERICHOST) != 0) - { - log_print ("udp_decode_ids: getnameinfo () failed for 'src'"); - strlcpy (idsrc, "<error>", 256); - } - - if (getnameinfo (((struct udp_transport *)t)->dst, - sysdep_sa_len (((struct udp_transport *)t)->dst), - iddst, sizeof iddst, NULL, 0, NI_NUMERICHOST) != 0) - { - log_print ("udp_decode_ids: getnameinfo () failed for 'dst'"); - strlcpy (iddst, "<error>", 256); - } + if (getnameinfo(((struct udp_transport *) t)->src, + sysdep_sa_len(((struct udp_transport *) t)->src), + idsrc, sizeof idsrc, NULL, 0, NI_NUMERICHOST) != 0) { + log_print("udp_decode_ids: getnameinfo () failed for 'src'"); + strlcpy(idsrc, "<error>", 256); + } + if (getnameinfo(((struct udp_transport *) t)->dst, + sysdep_sa_len(((struct udp_transport *) t)->dst), + iddst, sizeof iddst, NULL, 0, NI_NUMERICHOST) != 0) { + log_print("udp_decode_ids: getnameinfo () failed for 'dst'"); + strlcpy(iddst, "<error>", 256); + } #else - strlcpy (idsrc, inet_ntoa (((struct udp_transport *)t)->src.sin_addr), 256); - strlcpy (iddst, inet_ntoa (((struct udp_transport *)t)->dst.sin_addr), 256); -#endif /* HAVE_GETNAMEINFO */ - - snprintf (result, sizeof result, "src: %s dst: %s", idsrc, iddst); + strlcpy(idsrc, inet_ntoa(((struct udp_transport *) t)->src.sin_addr), 256); + strlcpy(iddst, inet_ntoa(((struct udp_transport *) t)->dst.sin_addr), 256); +#endif /* HAVE_GETNAMEINFO */ - return result; + snprintf(result, sizeof result, "src: %s dst: %s", idsrc, iddst); + return result; } #if 0 @@ -896,29 +831,25 @@ udp_decode_ids (struct transport *t) * XXX Currently unused. */ static in_port_t -udp_decode_port (char *port_str) +udp_decode_port(char *port_str) { - char *port_str_end; - long port_long; - struct servent *service; - - port_long = ntohl (strtol (port_str, &port_str_end, 0)); - if (port_str == port_str_end) - { - service = getservbyname (port_str, "udp"); - if (!service) - { - log_print ("udp_decode_port: service \"%s\" unknown", port_str); - return 0; - } - return ntohs (service->s_port); - } - else if (port_long < 1 || port_long > 65535) - { - log_print ("udp_decode_port: port %ld out of range", port_long); - return 0; - } - - return port_long; + char *port_str_end; + long port_long; + struct servent *service; + + port_long = ntohl(strtol(port_str, &port_str_end, 0)); + if (port_str == port_str_end) { + service = getservbyname(port_str, "udp"); + if (!service) { + log_print("udp_decode_port: service \"%s\" unknown", + port_str); + return 0; + } + return ntohs(service->s_port); + } else if (port_long < 1 || port_long > 65535) { + log_print("udp_decode_port: port %ld out of range", port_long); + return 0; + } + return port_long; } #endif diff --git a/sbin/isakmpd/udp.h b/sbin/isakmpd/udp.h index 43fdf419872..923461f3af7 100644 --- a/sbin/isakmpd/udp.h +++ b/sbin/isakmpd/udp.h @@ -1,5 +1,5 @@ -/* $OpenBSD: udp.h,v 1.7 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: udp.h,v 1.4 1998/12/22 02:23:43 niklas Exp $ */ +/* $OpenBSD: udp.h,v 1.8 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: udp.h,v 1.4 1998/12/22 02:23:43 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -32,16 +32,16 @@ #ifndef _UDP_H_ #define _UDP_H_ -extern char *udp_default_port; -extern char *udp_bind_port; -extern int bind_family; +extern char *udp_default_port; +extern char *udp_bind_port; +extern int bind_family; #define BIND_FAMILY_INET4 0x0001 #define BIND_FAMILY_INET6 0x0002 #if 0 -extern in_port_t udp_decode_port (char *); +extern in_port_t udp_decode_port(char *); #endif -extern void udp_init (void); +extern void udp_init(void); -#endif /* _UDP_H_ */ +#endif /* _UDP_H_ */ diff --git a/sbin/isakmpd/ui.c b/sbin/isakmpd/ui.c index 9940788f0fb..97207a4a5d2 100644 --- a/sbin/isakmpd/ui.c +++ b/sbin/isakmpd/ui.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ui.c,v 1.37 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: ui.c,v 1.43 2000/10/05 09:25:12 niklas Exp $ */ +/* $OpenBSD: ui.c,v 1.38 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: ui.c,v 1.43 2000/10/05 09:25:12 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -57,48 +57,50 @@ #define BUF_SZ 256 /* from isakmpd.c */ -void daemon_shutdown_now (int); +void daemon_shutdown_now(int); /* Report all SA configuration information. */ -void ui_report_sa (char *cmd); +void ui_report_sa(char *cmd); -char *ui_fifo = FIFO; -int ui_socket; +char *ui_fifo = FIFO; +int ui_socket; /* Create and open the FIFO used for user control. */ void -ui_init (void) +ui_init(void) { - struct stat st; - - /* -f- means control messages comes in via stdin. */ - if (strcmp (ui_fifo, "-") == 0) - ui_socket = 0; - else - { - /* Don't overwrite a file, i.e '-f /etc/isakmpd/isakmpd.conf'. */ + struct stat st; + + /* -f- means control messages comes in via stdin. */ + if (strcmp(ui_fifo, "-") == 0) { + ui_socket = 0; + return; + } + /* + * Don't overwrite a file, i.e '-f + * /etc/isakmpd/isakmpd.conf'. + */ #if defined (USE_PRIVSEP) - /* XXX This is a fstat! */ - if (monitor_stat (ui_fifo, &st) == 0) + /* XXX This is a fstat! */ + if (monitor_stat(ui_fifo, &st) == 0) { #else - if (lstat (ui_fifo, &st) == 0) + if (lstat(ui_fifo, &st) == 0) { #endif - if ((st.st_mode & S_IFMT) == S_IFREG) - { - errno = EEXIST; - log_fatal ("ui_init: could not create FIFO \"%s\"", ui_fifo); - } - - /* No need to know about errors. */ - unlink (ui_fifo); - if (monitor_mkfifo (ui_fifo, 0600) == -1) - log_fatal ("ui_init: mkfifo (\"%s\", 0600) failed", ui_fifo); - - ui_socket = monitor_open (ui_fifo, O_RDWR | O_NONBLOCK, 0); - if (ui_socket == -1) - log_fatal ("ui_init: open (\"%s\", O_RDWR | O_NONBLOCK, 0) failed", - ui_fifo); - } + if ((st.st_mode & S_IFMT) == S_IFREG) { + errno = EEXIST; + log_fatal("ui_init: could not create FIFO \"%s\"", ui_fifo); + } + } + + /* No need to know about errors. */ + unlink(ui_fifo); + if (monitor_mkfifo(ui_fifo, 0600) == -1) + log_fatal("ui_init: mkfifo (\"%s\", 0600) failed", ui_fifo); + + ui_socket = monitor_open(ui_fifo, O_RDWR | O_NONBLOCK, 0); + if (ui_socket == -1) + log_fatal("ui_init: open (\"%s\", O_RDWR | O_NONBLOCK, 0) failed", + ui_fifo); } /* @@ -106,43 +108,41 @@ ui_init (void) * XXX Maybe phase 1 works too, but teardown won't work then, fix? */ static void -ui_connect (char *cmd) +ui_connect(char *cmd) { - char name[81]; - - if (sscanf (cmd, "c %80s", name) != 1) - { - log_print ("ui_connect: command \"%s\" malformed", cmd); - return; - } - LOG_DBG ((LOG_UI, 10, "ui_connect: setup connection \"%s\"", name)); - connection_setup (name); + char name[81]; + + if (sscanf(cmd, "c %80s", name) != 1) { + log_print("ui_connect: command \"%s\" malformed", cmd); + return; + } + LOG_DBG((LOG_UI, 10, "ui_connect: setup connection \"%s\"", name)); + connection_setup(name); } /* Tear down a phase 2 connection. */ static void -ui_teardown (char *cmd) +ui_teardown(char *cmd) { - char name[81]; - struct sa *sa; - - if (sscanf (cmd, "t %80s", name) != 1) - { - log_print ("ui_teardown: command \"%s\" malformed", cmd); - return; - } - LOG_DBG ((LOG_UI, 10, "ui_teardown: teardown connection \"%s\"", name)); - connection_teardown (name); - while ((sa = sa_lookup_by_name (name, 2)) != 0) - sa_delete (sa, 1); + char name[81]; + struct sa *sa; + + if (sscanf(cmd, "t %80s", name) != 1) { + log_print("ui_teardown: command \"%s\" malformed", cmd); + return; + } + LOG_DBG((LOG_UI, 10, "ui_teardown: teardown connection \"%s\"", name)); + connection_teardown(name); + while ((sa = sa_lookup_by_name(name, 2)) != 0) + sa_delete(sa, 1); } /* Tear down all phase 2 connections. */ static void -ui_teardown_all (char *cmd) +ui_teardown_all(char *cmd) { - /* Skip 'cmd' as arg. */ - sa_teardown_all (); + /* Skip 'cmd' as arg. */ + sa_teardown_all(); } /* @@ -151,182 +151,158 @@ ui_teardown_all (char *cmd) * limit on the parameters? */ static void -ui_config (char *cmd) +ui_config(char *cmd) { - char subcmd[81], section[81], tag[81], value[81], tmp[81]; - int trans = 0, items; - - if (sscanf (cmd, "C %80s", subcmd) != 1) - goto fail; - - trans = conf_begin (); - if (strcasecmp (subcmd, "set") == 0) - { - items = sscanf (cmd, "C %*s [%80[^]]]:%80[^=]=%80s %80s", section, tag, - value, tmp); - if (!(items == 3 || items == 4)) - goto fail; - conf_set (trans, section, tag, value, items == 4 ? 1 : 0, 0); - } - else if (strcasecmp (subcmd, "rm") == 0) - { - if (sscanf (cmd, "C %*s [%80[^]]]:%80s", section, tag) != 2) - goto fail; - conf_remove (trans, section, tag); - } - else if (strcasecmp (subcmd, "rms") == 0) - { - if (sscanf (cmd, "C %*s [%80[^]]]", section) != 1) - goto fail; - conf_remove_section (trans, section); - } - else - goto fail; - - LOG_DBG ((LOG_UI, 30, "ui_config: \"%s\"", cmd)); - conf_end (trans, 1); - return; - - fail: - if (trans) - conf_end (trans, 0); - log_print ("ui_config: command \"%s\" malformed", cmd); + char subcmd[81], section[81], tag[81], value[81], tmp[81]; + int trans = 0, items; + + if (sscanf(cmd, "C %80s", subcmd) != 1) + goto fail; + + trans = conf_begin(); + if (strcasecmp(subcmd, "set") == 0) { + items = sscanf(cmd, "C %*s [%80[^]]]:%80[^=]=%80s %80s", + section, tag, value, tmp); + if (!(items == 3 || items == 4)) + goto fail; + conf_set(trans, section, tag, value, items == 4 ? 1 : 0, 0); + } else if (strcasecmp(subcmd, "rm") == 0) { + if (sscanf(cmd, "C %*s [%80[^]]]:%80s", section, tag) != 2) + goto fail; + conf_remove(trans, section, tag); + } else if (strcasecmp(subcmd, "rms") == 0) { + if (sscanf(cmd, "C %*s [%80[^]]]", section) != 1) + goto fail; + conf_remove_section(trans, section); + } else + goto fail; + + LOG_DBG((LOG_UI, 30, "ui_config: \"%s\"", cmd)); + conf_end(trans, 1); + return; + +fail: + if (trans) + conf_end(trans, 0); + log_print("ui_config: command \"%s\" malformed", cmd); } static void -ui_delete (char *cmd) +ui_delete(char *cmd) { - char cookies_str[ISAKMP_HDR_COOKIES_LEN * 2 + 1]; - char message_id_str[ISAKMP_HDR_MESSAGE_ID_LEN * 2 + 1]; - u_int8_t cookies[ISAKMP_HDR_COOKIES_LEN]; - u_int8_t message_id_buf[ISAKMP_HDR_MESSAGE_ID_LEN]; - u_int8_t *message_id = message_id_buf; - struct sa *sa; - - if (sscanf (cmd, "d %32s %8s", cookies_str, message_id_str) != 2) - { - log_print ("ui_delete: command \"%s\" malformed", cmd); - return; - } - - if (strcmp (message_id_str, "-") == 0) - message_id = 0; - - if (hex2raw (cookies_str, cookies, ISAKMP_HDR_COOKIES_LEN) == -1 - || (message_id && hex2raw (message_id_str, message_id_buf, - ISAKMP_HDR_MESSAGE_ID_LEN) == -1)) - { - log_print ("ui_delete: command \"%s\" has bad arguments", cmd); - return; - } - - sa = sa_lookup (cookies, message_id); - if (!sa) - { - log_print ("ui_delete: command \"%s\" found no SA", cmd); - return; - } - LOG_DBG ((LOG_UI, 20, + char cookies_str[ISAKMP_HDR_COOKIES_LEN * 2 + 1]; + char message_id_str[ISAKMP_HDR_MESSAGE_ID_LEN * 2 + 1]; + u_int8_t cookies[ISAKMP_HDR_COOKIES_LEN]; + u_int8_t message_id_buf[ISAKMP_HDR_MESSAGE_ID_LEN]; + u_int8_t *message_id = message_id_buf; + struct sa *sa; + + if (sscanf(cmd, "d %32s %8s", cookies_str, message_id_str) != 2) { + log_print("ui_delete: command \"%s\" malformed", cmd); + return; + } + if (strcmp(message_id_str, "-") == 0) + message_id = 0; + + if (hex2raw(cookies_str, cookies, ISAKMP_HDR_COOKIES_LEN) == -1 || + (message_id && hex2raw(message_id_str, message_id_buf, + ISAKMP_HDR_MESSAGE_ID_LEN) == -1)) { + log_print("ui_delete: command \"%s\" has bad arguments", cmd); + return; + } + sa = sa_lookup(cookies, message_id); + if (!sa) { + log_print("ui_delete: command \"%s\" found no SA", cmd); + return; + } + LOG_DBG((LOG_UI, 20, "ui_delete: deleting SA for cookie \"%s\" msgid \"%s\"", cookies_str, message_id_str)); - sa_delete (sa, 1); + sa_delete(sa, 1); } #ifdef USE_DEBUG /* Parse the debug command found in CMD. */ static void -ui_debug (char *cmd) +ui_debug(char *cmd) { - int cls, level; - char subcmd[3]; - - if (sscanf (cmd, "D %d %d", &cls, &level) == 2) - { - log_debug_cmd (cls, level); - return; - } - else if (sscanf (cmd, "D %2s %d", subcmd, &level) == 2) - { - switch (subcmd[0]) - { - case 'A': - for (cls = 0; cls < LOG_ENDCLASS; cls++) - log_debug_cmd (cls, level); - return; - } - } - else if (sscanf (cmd, "D %2s", subcmd) == 1) - { - switch (subcmd[0]) - { - case 'T': - log_debug_toggle (); - return; + int cls, level; + char subcmd[3]; + + if (sscanf(cmd, "D %d %d", &cls, &level) == 2) { + log_debug_cmd(cls, level); + return; + } else if (sscanf(cmd, "D %2s %d", subcmd, &level) == 2) { + switch (subcmd[0]) { + case 'A': + for (cls = 0; cls < LOG_ENDCLASS; cls++) + log_debug_cmd(cls, level); + return; + } + } else if (sscanf(cmd, "D %2s", subcmd) == 1) { + switch (subcmd[0]) { + case 'T': + log_debug_toggle(); + return; + } } - } - - log_print ("ui_debug: command \"%s\" malformed", cmd); - return; + log_print("ui_debug: command \"%s\" malformed", cmd); + return; } static void -ui_packetlog (char *cmd) +ui_packetlog(char *cmd) { - char subcmd[81]; - - if (sscanf (cmd, "p %80s", subcmd) != 1) - goto fail; - - if (strncasecmp (subcmd, "on=", 3) == 0) - { - /* Start capture to a new file. */ - if (subcmd[strlen (subcmd) - 1] == '\n') - subcmd[strlen (subcmd) - 1] = 0; - log_packet_restart (subcmd + 3); - } - else if (strcasecmp (subcmd, "on") == 0) - log_packet_restart (NULL); - else if (strcasecmp (subcmd, "off") == 0) - log_packet_stop (); - - return; - - fail: - log_print ("ui_packetlog: command \"%s\" malformed", cmd); + char subcmd[81]; + + if (sscanf(cmd, "p %80s", subcmd) != 1) + goto fail; + + if (strncasecmp(subcmd, "on=", 3) == 0) { + /* Start capture to a new file. */ + if (subcmd[strlen(subcmd) - 1] == '\n') + subcmd[strlen(subcmd) - 1] = 0; + log_packet_restart(subcmd + 3); + } else if (strcasecmp(subcmd, "on") == 0) + log_packet_restart(NULL); + else if (strcasecmp(subcmd, "off") == 0) + log_packet_stop(); + return; + +fail: + log_print("ui_packetlog: command \"%s\" malformed", cmd); } -#endif /* USE_DEBUG */ +#endif /* USE_DEBUG */ static void -ui_shutdown_daemon (char *cmd) +ui_shutdown_daemon(char *cmd) { - if (strlen (cmd) == 1) - { - log_print ("ui_shutdown_daemon: received shutdown command"); - daemon_shutdown_now (0); - } - else - log_print ("ui_shutdown_daemon: command \"%s\" malformed", cmd); + if (strlen(cmd) == 1) { + log_print("ui_shutdown_daemon: received shutdown command"); + daemon_shutdown_now(0); + } else + log_print("ui_shutdown_daemon: command \"%s\" malformed", cmd); } /* Report SAs and ongoing exchanges. */ void -ui_report (char *cmd) +ui_report(char *cmd) { - /* XXX Skip 'cmd' as arg? */ - sa_report (); - exchange_report (); - transport_report (); - connection_report (); - timer_report (); - conf_report (); + /* XXX Skip 'cmd' as arg? */ + sa_report(); + exchange_report(); + transport_report(); + connection_report(); + timer_report(); + conf_report(); } /* Report all SA configuration information. */ void -ui_report_sa (char *cmd) +ui_report_sa(char *cmd) { - /* Skip 'cmd' as arg? */ - sa_report_all (); + /* Skip 'cmd' as arg? */ + sa_report_all(); } /* @@ -334,60 +310,59 @@ ui_report_sa (char *cmd) * line (the command). */ static void -ui_handle_command (char *line) +ui_handle_command(char *line) { - /* Find out what one-letter command was sent. */ - switch (line[0]) - { - case 'c': - ui_connect (line); - break; + /* Find out what one-letter command was sent. */ + switch (line[0]) { + case 'c': + ui_connect(line); + break; - case 'C': - ui_config (line); - break; + case 'C': + ui_config(line); + break; - case 'd': - ui_delete (line); - break; + case 'd': + ui_delete(line); + break; #ifdef USE_DEBUG - case 'D': - ui_debug (line); - break; + case 'D': + ui_debug(line); + break; - case 'p': - ui_packetlog (line); - break; + case 'p': + ui_packetlog(line); + break; #endif - case 'Q': - ui_shutdown_daemon (line); - break; + case 'Q': + ui_shutdown_daemon(line); + break; - case 'R': - reinit (); - break; + case 'R': + reinit(); + break; - case 'S': - ui_report_sa (line); - break; + case 'S': + ui_report_sa(line); + break; - case 'r': - ui_report (line); - break; + case 'r': + ui_report(line); + break; - case 't': - ui_teardown (line); - break; + case 't': + ui_teardown(line); + break; - case 'T': - ui_teardown_all (line); - break; + case 'T': + ui_teardown_all(line); + break; - default: - log_print ("ui_handle_messages: unrecognized command: '%c'", line[0]); - } + default: + log_print("ui_handle_messages: unrecognized command: '%c'", line[0]); + } } /* @@ -396,73 +371,64 @@ ui_handle_command (char *line) * troubles with non-blocking fifos. */ void -ui_handler (void) +ui_handler(void) { - static char *buf = 0; - static char *p; - static size_t sz; - static size_t resid; - ssize_t n; - char *new_buf; - - /* If no buffer, set it up. */ - if (!buf) - { - sz = BUF_SZ; - buf = malloc (sz); - if (!buf) - { - log_print ("ui_handler: malloc (%lu) failed", (unsigned long)sz); - return; + static char *buf = 0; + static char *p; + static size_t sz; + static size_t resid; + ssize_t n; + char *new_buf; + + /* If no buffer, set it up. */ + if (!buf) { + sz = BUF_SZ; + buf = malloc(sz); + if (!buf) { + log_print("ui_handler: malloc (%lu) failed", + (unsigned long) sz); + return; + } + p = buf; + resid = sz; + } + /* If no place left in the buffer reallocate twice as large. */ + if (!resid) { + new_buf = realloc(buf, sz * 2); + if (!new_buf) { + log_print("ui_handler: realloc (%p, %lu) failed", buf, + (unsigned long) sz * 2); + free(buf); + buf = 0; + return; + } + buf = new_buf; + p = buf + sz; + resid = sz; + sz *= 2; } - p = buf; - resid = sz; - } - - /* If no place left in the buffer reallocate twice as large. */ - if (!resid) - { - new_buf = realloc (buf, sz * 2); - if (!new_buf) - { - log_print ("ui_handler: realloc (%p, %lu) failed", buf, - (unsigned long)sz * 2); - free (buf); - buf = 0; - return; + n = read(ui_socket, p, resid); + if (n == -1) { + log_error("ui_handler: read (%d, %p, %lu)", ui_socket, p, + (unsigned long) resid); + return; } - buf = new_buf; - p = buf + sz; - resid = sz; - sz *= 2; - } - - n = read (ui_socket, p, resid); - if (n == -1) - { - log_error ("ui_handler: read (%d, %p, %lu)", ui_socket, p, - (unsigned long)resid); - return; - } - - if (!n) - return; - resid -= n; - while (n--) - { - /* - * When we find a newline, cut off the line and feed it to the - * command processor. Then move the rest up-front. - */ - if (*p == '\n') - { - *p = '\0'; - ui_handle_command (buf); - memcpy (buf, p + 1, n); - p = buf; - resid = sz - n; - continue; + if (!n) + return; + resid -= n; + while (n--) { + /* + * When we find a newline, cut off the line and feed it to the + * command processor. Then move the rest up-front. + */ + if (*p == '\n') { + *p = '\0'; + ui_handle_command(buf); + memcpy(buf, p + 1, n); + p = buf; + resid = sz - n; + continue; + } + p++; } - p++; - } } diff --git a/sbin/isakmpd/ui.h b/sbin/isakmpd/ui.h index 9a2ddc0f69f..3876e8d1bdf 100644 --- a/sbin/isakmpd/ui.h +++ b/sbin/isakmpd/ui.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ui.h,v 1.5 2003/06/03 14:28:16 ho Exp $ */ -/* $EOM: ui.h,v 1.5 1998/12/01 10:20:12 niklas Exp $ */ +/* $OpenBSD: ui.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: ui.h,v 1.5 1998/12/01 10:20:12 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -34,11 +34,11 @@ #define FIFO "/var/run/isakmpd.fifo" -extern char *ui_fifo; -extern int ui_socket; +extern char *ui_fifo; +extern int ui_socket; -extern void ui_handler (void); -extern void ui_init (void); -extern void ui_report (char *); +extern void ui_handler(void); +extern void ui_init(void); +extern void ui_report(char *); -#endif /* _UI_H_ */ +#endif /* _UI_H_ */ diff --git a/sbin/isakmpd/util.c b/sbin/isakmpd/util.c index 7e2ec63ce50..c343bd0fec5 100644 --- a/sbin/isakmpd/util.c +++ b/sbin/isakmpd/util.c @@ -1,5 +1,5 @@ -/* $OpenBSD: util.c,v 1.36 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $ */ +/* $OpenBSD: util.c,v 1.37 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -55,41 +55,41 @@ * Set if -N is given, allowing name lookups to be done, possibly stalling * the daemon for quite a while. */ -int allow_name_lookups = 0; +int allow_name_lookups = 0; /* * This is set to true in case of regression-test mode, when it will * cause predictable random numbers be generated. */ -int regrand = 0; +int regrand = 0; /* * If in regression-test mode, this is the seed used. */ -unsigned long seed; +u_long seed; /* * XXX These might be turned into inlines or macros, maybe even * machine-dependent ones, for performance reasons. */ u_int16_t -decode_16 (u_int8_t *cp) +decode_16(u_int8_t *cp) { - return cp[0] << 8 | cp[1]; + return cp[0] << 8 | cp[1]; } u_int32_t -decode_32 (u_int8_t *cp) +decode_32(u_int8_t *cp) { - return cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; + return cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; } u_int64_t -decode_64 (u_int8_t *cp) +decode_64(u_int8_t *cp) { - return (u_int64_t)cp[0] << 56 | (u_int64_t)cp[1] << 48 - | (u_int64_t)cp[2] << 40 | (u_int64_t)cp[3] << 32 - | cp[4] << 24 | cp[5] << 16 | cp[6] << 8 | cp[7]; + return (u_int64_t) cp[0] << 56 | (u_int64_t) cp[1] << 48 | + (u_int64_t) cp[2] << 40 | (u_int64_t) cp[3] << 32 | + cp[4] << 24 | cp[5] << 16 | cp[6] << 8 | cp[7]; } #if 0 @@ -99,15 +99,15 @@ decode_64 (u_int8_t *cp) */ void -decode_128 (u_int8_t *cp, u_int8_t *cpp) +decode_128(u_int8_t *cp, u_int8_t *cpp) { #if BYTE_ORDER == LITTLE_ENDIAN - int i; + int i; - for (i = 0; i < 16; i++) - cpp[i] = cp[15 - i]; + for (i = 0; i < 16; i++) + cpp[i] = cp[15 - i]; #elif BYTE_ORDER == BIG_ENDIAN - bcopy (cp, cpp, 16); + bcopy(cp, cpp, 16); #else #error "Byte order unknown!" #endif @@ -115,32 +115,32 @@ decode_128 (u_int8_t *cp, u_int8_t *cpp) #endif void -encode_16 (u_int8_t *cp, u_int16_t x) +encode_16(u_int8_t *cp, u_int16_t x) { - *cp++ = x >> 8; - *cp = x & 0xff; + *cp++ = x >> 8; + *cp = x & 0xff; } void -encode_32 (u_int8_t *cp, u_int32_t x) +encode_32(u_int8_t *cp, u_int32_t x) { - *cp++ = x >> 24; - *cp++ = (x >> 16) & 0xff; - *cp++ = (x >> 8) & 0xff; - *cp = x & 0xff; + *cp++ = x >> 24; + *cp++ = (x >> 16) & 0xff; + *cp++ = (x >> 8) & 0xff; + *cp = x & 0xff; } void -encode_64 (u_int8_t *cp, u_int64_t x) +encode_64(u_int8_t *cp, u_int64_t x) { - *cp++ = x >> 56; - *cp++ = (x >> 48) & 0xff; - *cp++ = (x >> 40) & 0xff; - *cp++ = (x >> 32) & 0xff; - *cp++ = (x >> 24) & 0xff; - *cp++ = (x >> 16) & 0xff; - *cp++ = (x >> 8) & 0xff; - *cp = x & 0xff; + *cp++ = x >> 56; + *cp++ = (x >> 48) & 0xff; + *cp++ = (x >> 40) & 0xff; + *cp++ = (x >> 32) & 0xff; + *cp++ = (x >> 24) & 0xff; + *cp++ = (x >> 16) & 0xff; + *cp++ = (x >> 8) & 0xff; + *cp = x & 0xff; } #if 0 @@ -150,63 +150,62 @@ encode_64 (u_int8_t *cp, u_int64_t x) */ void -encode_128 (u_int8_t *cp, u_int8_t *cpp) +encode_128(u_int8_t *cp, u_int8_t *cpp) { - decode_128 (cpp, cp); + decode_128(cpp, cp); } #endif /* Check a buffer for all zeroes. */ int -zero_test (const u_int8_t *p, size_t sz) +zero_test(const u_int8_t *p, size_t sz) { - while (sz-- > 0) - if (*p++ != 0) - return 0; - return 1; + while (sz-- > 0) + if (*p++ != 0) + return 0; + return 1; } /* Check a buffer for all ones. */ int -ones_test (const u_int8_t *p, size_t sz) +ones_test(const u_int8_t *p, size_t sz) { - while (sz-- > 0) - if (*p++ != 0xff) - return 0; - return 1; + while (sz-- > 0) + if (*p++ != 0xff) + return 0; + return 1; } /* * Generate a random data, len bytes long. */ u_int8_t * -getrandom (u_int8_t *buf, size_t len) +getrandom(u_int8_t *buf, size_t len) { - u_int32_t tmp = 0; - size_t i; + u_int32_t tmp = 0; + size_t i; - for (i = 0; i < len; i++) - { - if (i % sizeof tmp == 0) - tmp = sysdep_random (); + for (i = 0; i < len; i++) { + if (i % sizeof tmp == 0) + tmp = sysdep_random(); - buf[i] = tmp & 0xff; - tmp >>= 8; - } + buf[i] = tmp & 0xff; + tmp >>= 8; + } - return buf; + return buf; } static __inline int -hex2nibble (char c) +hex2nibble(char c) { - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; } /* @@ -214,99 +213,92 @@ hex2nibble (char c) * bytes. Return 0 if everything is OK, -1 otherwise. */ int -hex2raw (char *s, u_int8_t *buf, size_t sz) +hex2raw(char *s, u_int8_t *buf, size_t sz) { - char *p; - u_int8_t *bp; - int tmp; - - if (strlen (s) > sz * 2) - return -1; - for (p = s + strlen (s) - 1, bp = &buf[sz - 1]; bp >= buf; bp--) - { - *bp = 0; - if (p >= s) - { - tmp = hex2nibble (*p--); - if (tmp == -1) - return -1; - *bp = tmp; - } - if (p >= s) - { - tmp = hex2nibble (*p--); - if (tmp == -1) - return -1; - *bp |= tmp << 4; + u_int8_t *bp; + char *p; + int tmp; + + if (strlen(s) > sz * 2) + return -1; + for (p = s + strlen(s) - 1, bp = &buf[sz - 1]; bp >= buf; bp--) { + *bp = 0; + if (p >= s) { + tmp = hex2nibble(*p--); + if (tmp == -1) + return -1; + *bp = tmp; + } + if (p >= s) { + tmp = hex2nibble(*p--); + if (tmp == -1) + return -1; + *bp |= tmp << 4; + } } - } - return 0; + return 0; } int -text2sockaddr (char *address, char *port, struct sockaddr **sa) +text2sockaddr(char *address, char *port, struct sockaddr ** sa) { #ifdef HAVE_GETNAMEINFO - struct addrinfo *ai, hints; + struct addrinfo *ai, hints; - memset (&hints, 0, sizeof hints); - if (!allow_name_lookups) - hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; + memset(&hints, 0, sizeof hints); + if (!allow_name_lookups) + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; - if (getaddrinfo (address, port, &hints, &ai)) - return -1; + if (getaddrinfo(address, port, &hints, &ai)) + return -1; - *sa = malloc (sysdep_sa_len (ai->ai_addr)); - if (!sa) - return -1; + *sa = malloc(sysdep_sa_len(ai->ai_addr)); + if (!sa) + return -1; - memcpy (*sa, ai->ai_addr, sysdep_sa_len (ai->ai_addr)); - freeaddrinfo (ai); - return 0; + memcpy(*sa, ai->ai_addr, sysdep_sa_len(ai->ai_addr)); + freeaddrinfo(ai); + return 0; #else - int af = strchr (address, ':') != NULL ? AF_INET6 : AF_INET; - size_t sz = af == AF_INET - ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6); - long lport; - struct servent *sp; - char *ep; - - *sa = calloc (1, sz); - if (!*sa) - return -1; + int af = strchr(address, ':') != NULL ? AF_INET6 : AF_INET; + size_t sz = af == AF_INET ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6); + long lport; + struct servent *sp; + char *ep; + + *sa = calloc(1, sz); + if (!*sa) + return -1; #ifndef USE_OLD_SOCKADDR - (*sa)->sa_len = sz; + (*sa)->sa_len = sz; #endif - (*sa)->sa_family = af; - if (inet_pton (af, address, sockaddr_addrdata (*sa)) != 1) - { - free (*sa); - return -1; - } - if (!port) - return 0; - sp = getservbyname (port, "udp"); - if (!sp) - { - lport = strtol (port, &ep, 10); - if (ep == port || lport < 0 || lport > (long)USHRT_MAX) - { - free (*sa); - return -1; + (*sa)->sa_family = af; + if (inet_pton(af, address, sockaddr_addrdata(*sa)) != 1) { + free(*sa); + return -1; } - lport = htons (lport); - } - else - lport = sp->s_port; - if ((*sa)->sa_family == AF_INET) - ((struct sockaddr_in *)*sa)->sin_port = lport; - else - ((struct sockaddr_in6 *)*sa)->sin6_port = lport; - return 0; + if (!port) + return 0; + sp = getservbyname(port, "udp"); + if (!sp) { + lport = strtol(port, &ep, 10); + if (ep == port || lport < 0 || lport > (long) USHRT_MAX) { + free(*sa); + return -1; + } + lport = htons(lport); + } else + lport = sp->s_port; + if ((*sa)->sa_family == AF_INET) + ((struct sockaddr_in *) *sa)->sin_port = lport; + else + ((struct sockaddr_in6 *) *sa)->sin6_port = lport; + return 0; #endif } @@ -315,104 +307,94 @@ text2sockaddr (char *address, char *port, struct sockaddr **sa) * i.e 10.0.0.10 --> "010.000.000.010" */ int -sockaddr2text (struct sockaddr *sa, char **address, int zflag) +sockaddr2text(struct sockaddr *sa, char **address, int zflag) { - char buf[NI_MAXHOST]; - char *token, *bstart, *ep; - int addrlen; - long val; - int i, j; + char buf[NI_MAXHOST], *token, *bstart, *ep; + int addrlen, i, j; + long val; #ifdef HAVE_GETNAMEINFO - if (getnameinfo (sa, sysdep_sa_len (sa), buf, sizeof buf, 0, 0, - allow_name_lookups ? 0 : NI_NUMERICHOST)) - return -1; + if (getnameinfo(sa, sysdep_sa_len(sa), buf, sizeof buf, 0, 0, + allow_name_lookups ? 0 : NI_NUMERICHOST)) + return -1; #else - switch (sa->sa_family) - { - case AF_INET: - case AF_INET6: - if (inet_ntop (sa->sa_family, sa->sa_data, buf, NI_MAXHOST - 1) == NULL) - { - log_error ("sockaddr2text: inet_ntop (%d, %p, %p, %d) failed", - sa->sa_family, sa->sa_data, buf, NI_MAXHOST - 1); - return -1; + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: + if (inet_ntop(sa->sa_family, sa->sa_data, buf, NI_MAXHOST - 1) == NULL) { + log_error("sockaddr2text: inet_ntop (%d, %p, %p, %d) failed", + sa->sa_family, sa->sa_data, buf, NI_MAXHOST - 1); + return -1; + } + buf[NI_MAXHOST - 1] = '\0'; + break; + + default: + log_print("sockaddr2text: unsupported protocol family %d\n", + sa->sa_family); + return -1; } - buf[NI_MAXHOST - 1] = '\0'; - break; - - default: - log_print ("sockaddr2text: unsupported protocol family %d\n", - sa->sa_family); - return -1; - } #endif - if (zflag == 0) - { - *address = strdup (buf); - if (!*address) - return -1; - } - else - switch (sa->sa_family) - { - case AF_INET: - addrlen = sizeof "000.000.000.000"; - *address = malloc (addrlen); - if (!*address) - return -1; - buf[addrlen] = '\0'; - bstart = buf; - **address = '\0'; - while ((token = strsep (&bstart, ".")) != NULL) - { - if (strlen (*address) > 12) - { - free (*address); - return -1; - } - val = strtol (token, &ep, 10); - if (ep == token || val < (long)0 || val > (long)UCHAR_MAX) - { - free (*address); - return -1; - } - snprintf (*address + strlen (*address), - addrlen - strlen (*address), "%03ld", val); - if (bstart) - strlcat (*address, ".", addrlen); - } - break; - - case AF_INET6: - /* - * XXX In the algorithm below there are some magic numbers we - * probably could give explaining names. - */ - addrlen = sizeof "0000:0000:0000:0000:0000:0000:0000:0000"; - *address = malloc (addrlen); - if (!*address) - return -1; - - for (i = 0, j = 0; i < 8; i++) - { - snprintf ((*address) + j, addrlen - j, "%02x%02x", - ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2 * i], - ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2 * i + 1]); - j += 4; - (*address)[j] = (j < (addrlen - 1)) ? ':' : '\0'; - j++; - } - break; - - default: - *address = strdup ("<error>"); - if (!*address) - return -1; - } - - return 0; + if (zflag == 0) { + *address = strdup(buf); + if (!*address) + return -1; + } else + switch (sa->sa_family) { + case AF_INET: + addrlen = sizeof "000.000.000.000"; + *address = malloc(addrlen); + if (!*address) + return -1; + buf[addrlen] = '\0'; + bstart = buf; + **address = '\0'; + while ((token = strsep(&bstart, ".")) != NULL) { + if (strlen(*address) > 12) { + free(*address); + return -1; + } + val = strtol(token, &ep, 10); + if (ep == token || val < (long) 0 || + val > (long) UCHAR_MAX) { + free(*address); + return -1; + } + snprintf(*address + strlen(*address), + addrlen - strlen(*address), "%03ld", val); + if (bstart) + strlcat(*address, ".", addrlen); + } + break; + + case AF_INET6: + /* + * XXX In the algorithm below there are some magic numbers we + * probably could give explaining names. + */ + addrlen = sizeof "0000:0000:0000:0000:0000:0000:0000:0000"; + *address = malloc(addrlen); + if (!*address) + return -1; + + for (i = 0, j = 0; i < 8; i++) { + snprintf((*address) + j, addrlen - j, "%02x%02x", + ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2*i], + ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2*i + 1]); + j += 4; + (*address)[j] = (j < (addrlen - 1)) ? ':' : '\0'; + j++; + } + break; + + default: + *address = strdup("<error>"); + if (!*address) + return -1; + } + + return 0; } /* @@ -420,51 +402,48 @@ sockaddr2text (struct sockaddr *sa, char **address, int zflag) * depending on address family. Useful to keep other code shorter(/clearer?). */ int -sockaddr_addrlen (struct sockaddr *sa) +sockaddr_addrlen(struct sockaddr *sa) { - switch (sa->sa_family) - { - case AF_INET6: - return sizeof ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr; - case AF_INET: - return sizeof ((struct sockaddr_in *)sa)->sin_addr.s_addr; - default: - log_print ("sockaddr_addrlen: unsupported protocol family %d", - sa->sa_family); - return 0; - } + switch (sa->sa_family) { + case AF_INET6: + return sizeof((struct sockaddr_in6 *) sa)->sin6_addr.s6_addr; + case AF_INET: + return sizeof((struct sockaddr_in *) sa)->sin_addr.s_addr; + default: + log_print("sockaddr_addrlen: unsupported protocol family %d", + sa->sa_family); + return 0; + } } u_int8_t * -sockaddr_addrdata (struct sockaddr *sa) +sockaddr_addrdata(struct sockaddr *sa) { - switch (sa->sa_family) - { - case AF_INET6: - return (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr; - case AF_INET: - return (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr.s_addr; - default: - log_print ("sockaddr_addrdata: unsupported protocol family %d", - sa->sa_family); - return 0; - } + switch (sa->sa_family) { + case AF_INET6: + return (u_int8_t *) & ((struct sockaddr_in6 *) sa)->sin6_addr.s6_addr; + case AF_INET: + return (u_int8_t *) & ((struct sockaddr_in *) sa)->sin_addr.s_addr; + default: + log_print("sockaddr_addrdata: unsupported protocol family %d", + sa->sa_family); + return 0; + } } in_port_t -sockaddr_port (struct sockaddr *sa) +sockaddr_port(struct sockaddr *sa) { - switch (sa->sa_family) - { - case AF_INET6: - return ((struct sockaddr_in6 *)sa)->sin6_port; - case AF_INET: - return ((struct sockaddr_in *)sa)->sin_port; - default: - log_print ("sockaddr_port: unsupported protocol family %d", - sa->sa_family); - return 0; - } + switch (sa->sa_family) { + case AF_INET6: + return ((struct sockaddr_in6 *) sa)->sin6_port; + case AF_INET: + return ((struct sockaddr_in *) sa)->sin_port; + default: + log_print("sockaddr_port: unsupported protocol family %d", + sa->sa_family); + return 0; + } } /* @@ -472,33 +451,31 @@ sockaddr_port (struct sockaddr *sa) * to be properly aligned. */ void -util_ntoa (char **buf, int af, u_int8_t *addr) +util_ntoa(char **buf, int af, u_int8_t *addr) { - struct sockaddr_storage from; - struct sockaddr *sfrom = (struct sockaddr *)&from; - socklen_t fromlen = sizeof from; + struct sockaddr_storage from; + struct sockaddr *sfrom = (struct sockaddr *) & from; + socklen_t fromlen = sizeof from; - memset (&from, 0, fromlen); - sfrom->sa_family = af; + memset(&from, 0, fromlen); + sfrom->sa_family = af; #ifndef USE_OLD_SOCKADDR - switch (af) - { - case AF_INET: - sfrom->sa_len = sizeof (struct sockaddr_in); - break; - case AF_INET6: - sfrom->sa_len = sizeof (struct sockaddr_in6); - break; - } + switch (af) { + case AF_INET: + sfrom->sa_len = sizeof(struct sockaddr_in); + break; + case AF_INET6: + sfrom->sa_len = sizeof(struct sockaddr_in6); + break; + } #endif - memcpy (sockaddr_addrdata (sfrom), addr, sockaddr_addrlen (sfrom)); - - if (sockaddr2text (sfrom, buf, 0)) - { - log_print ("util_ntoa: " - "could not make printable address out of sockaddr %p", sfrom); - *buf = 0; - } + memcpy(sockaddr_addrdata(sfrom), addr, sockaddr_addrlen(sfrom)); + + if (sockaddr2text(sfrom, buf, 0)) { + log_print("util_ntoa: " + "could not make printable address out of sockaddr %p", sfrom); + *buf = 0; + } } /* @@ -507,32 +484,28 @@ util_ntoa (char **buf, int af, u_int8_t *addr) * Also, if FILE_SIZE is a not a null pointer, store file size here. */ int -check_file_secrecy (char *name, size_t *file_size) +check_file_secrecy(char *name, size_t *file_size) { - struct stat st; - - if (monitor_stat (name, &st) == -1) - { - log_error ("check_file_secrecy: stat (\"%s\") failed", name); - return -1; - } - if (st.st_uid != 0 && st.st_uid != getuid ()) - { - log_print ("check_file_secrecy: " - "not loading %s - file owner is not process user", name); - errno = EPERM; - return -1; - } - if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) - { - log_print ("conf_file_secrecy: not loading %s - too open permissions", - name); - errno = EPERM; - return -1; - } - - if (file_size) - *file_size = (size_t)st.st_size; - - return 0; + struct stat st; + + if (monitor_stat(name, &st) == -1) { + log_error("check_file_secrecy: stat (\"%s\") failed", name); + return -1; + } + if (st.st_uid != 0 && st.st_uid != getuid()) { + log_print("check_file_secrecy: " + "not loading %s - file owner is not process user", name); + errno = EPERM; + return -1; + } + if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + log_print("conf_file_secrecy: not loading %s - too open permissions", + name); + errno = EPERM; + return -1; + } + if (file_size) + *file_size = (size_t) st.st_size; + + return 0; } diff --git a/sbin/isakmpd/util.h b/sbin/isakmpd/util.h index d3d94461f30..5c04880e2c5 100644 --- a/sbin/isakmpd/util.h +++ b/sbin/isakmpd/util.h @@ -1,5 +1,5 @@ -/* $OpenBSD: util.h,v 1.17 2004/03/10 23:08:49 hshoexer Exp $ */ -/* $EOM: util.h,v 1.10 2000/10/24 13:33:39 niklas Exp $ */ +/* $OpenBSD: util.h,v 1.18 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: util.h,v 1.10 2000/10/24 13:33:39 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -35,35 +35,35 @@ #include <sys/types.h> -extern int allow_name_lookups; -extern int regrand; +extern int allow_name_lookups; +extern int regrand; extern unsigned long seed; struct message; struct sockaddr; -extern int check_file_secrecy (char *, size_t *); -extern u_int16_t decode_16 (u_int8_t *); -extern u_int32_t decode_32 (u_int8_t *); -extern u_int64_t decode_64 (u_int8_t *); +extern int check_file_secrecy(char *, size_t *); +extern u_int16_t decode_16(u_int8_t *); +extern u_int32_t decode_32(u_int8_t *); +extern u_int64_t decode_64(u_int8_t *); #if 0 -extern void decode_128 (u_int8_t *, u_int8_t *); +extern void decode_128(u_int8_t *, u_int8_t *); #endif -extern void encode_16 (u_int8_t *, u_int16_t); -extern void encode_32 (u_int8_t *, u_int32_t); -extern void encode_64 (u_int8_t *, u_int64_t); +extern void encode_16(u_int8_t *, u_int16_t); +extern void encode_32(u_int8_t *, u_int32_t); +extern void encode_64(u_int8_t *, u_int64_t); #if 0 -extern void encode_128 (u_int8_t *, u_int8_t *); +extern void encode_128(u_int8_t *, u_int8_t *); #endif -extern u_int8_t *getrandom (u_int8_t *, size_t); -extern int hex2raw (char *, u_int8_t *, size_t); -extern int ones_test (const u_int8_t *, size_t); -extern int sockaddr2text (struct sockaddr *, char **, int); -extern u_int8_t *sockaddr_addrdata (struct sockaddr *); -extern int sockaddr_addrlen (struct sockaddr *); -extern in_port_t sockaddr_port (struct sockaddr *); -extern int text2sockaddr (char *, char *, struct sockaddr **); -extern void util_ntoa (char **, int, u_int8_t *); -extern int zero_test (const u_int8_t *, size_t); +extern u_int8_t *getrandom(u_int8_t *, size_t); +extern int hex2raw(char *, u_int8_t *, size_t); +extern int ones_test(const u_int8_t *, size_t); +extern int sockaddr2text(struct sockaddr *, char **, int); +extern u_int8_t *sockaddr_addrdata(struct sockaddr *); +extern int sockaddr_addrlen(struct sockaddr *); +extern in_port_t sockaddr_port(struct sockaddr *); +extern int text2sockaddr(char *, char *, struct sockaddr **); +extern void util_ntoa(char **, int, u_int8_t *); +extern int zero_test(const u_int8_t *, size_t); -#endif /* _UTIL_H_ */ +#endif /* _UTIL_H_ */ diff --git a/sbin/isakmpd/x509.c b/sbin/isakmpd/x509.c index be0f7a88bae..dda7dda0197 100644 --- a/sbin/isakmpd/x509.c +++ b/sbin/isakmpd/x509.c @@ -1,5 +1,5 @@ -/* $OpenBSD: x509.c,v 1.87 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $ */ +/* $OpenBSD: x509.c,v 1.88 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niels Provos. All rights reserved. @@ -47,7 +47,7 @@ #ifdef USE_POLICY #include <regex.h> #include <keynote.h> -#endif /* USE_POLICY */ +#endif /* USE_POLICY */ #include "sysdep.h" @@ -65,10 +65,10 @@ #include "util.h" #include "x509.h" -static u_int16_t x509_hash (u_int8_t *, size_t); -static void x509_hash_init (void); -static X509 *x509_hash_find (u_int8_t *, size_t); -static int x509_hash_enter (X509 *); +static u_int16_t x509_hash(u_int8_t *, size_t); +static void x509_hash_init(void); +static X509 *x509_hash_find(u_int8_t *, size_t); +static int x509_hash_enter(X509 *); /* * X509_STOREs do not support subjectAltNames, so we have to build @@ -87,15 +87,16 @@ static X509_STORE *x509_cas = 0; #define INITIAL_BUCKET_BITS 6 struct x509_hash { - LIST_ENTRY (x509_hash) link; + LIST_ENTRY(x509_hash) link; - X509 *cert; + X509 *cert; }; -static LIST_HEAD (x509_list, x509_hash) *x509_tab = 0; +static +LIST_HEAD(x509_list, x509_hash) * x509_tab = 0; /* Works both as a maximum index and a mask. */ -static int bucket_mask; + static int bucket_mask; #ifdef USE_POLICY /* @@ -104,1128 +105,996 @@ static int bucket_mask; * XXX RSA-specific. */ int -x509_generate_kn (int id, X509 *cert) +x509_generate_kn(int id, X509 *cert) { - char *fmt = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s\"\n" - "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; - char *ikey, *skey, *buf, isname[256], subname[256]; - char *fmt2 = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n" - "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; - X509_NAME *issuer, *subject; - struct keynote_deckey dc; - X509_STORE_CTX csc; - X509_OBJECT obj; - X509 *icert; - RSA *key; - time_t tt; - char before[15], after[15]; - ASN1_TIME *tm; - char *timecomp, *timecomp2; - int i, buf_len; - - LOG_DBG ((LOG_POLICY, 90, + char *fmt = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s\"\n" + "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; + char *ikey, *skey, *buf, isname[256], subname[256]; + char *fmt2 = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n" + "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; + X509_NAME *issuer, *subject; + struct keynote_deckey dc; + X509_STORE_CTX csc; + X509_OBJECT obj; + X509 *icert; + RSA *key; + time_t tt; + char before[15], after[15], *timecomp, *timecomp2; + ASN1_TIME *tm; + int i, buf_len; + + LOG_DBG((LOG_POLICY, 90, "x509_generate_kn: generating KeyNote policy for certificate %p", cert)); - issuer = X509_get_issuer_name (cert); - subject = X509_get_subject_name (cert); - - /* Missing or self-signed, ignore cert but don't report failure. */ - if (!issuer || !subject || !X509_name_cmp (issuer, subject)) - return 1; - - if (!x509_cert_get_key (cert, &key)) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to get public key from cert")); - return 0; - } - - dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; - dc.dec_key = key; - ikey = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, - KEYNOTE_PUBLIC_KEY); - if (keynote_errno == ERROR_MEMORY) - { - log_print ("x509_generate_kn: failed to get memory for public key"); - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); - return 0; - } - if (!ikey) - { - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); - return 0; - } - RSA_free (key); - - /* Now find issuer's certificate so we can get the public key. */ - X509_STORE_CTX_init (&csc, x509_cas, cert, NULL); - if (X509_STORE_get_by_subject (&csc, X509_LU_X509, issuer, &obj) != - X509_LU_X509) - { - X509_STORE_CTX_cleanup (&csc); - X509_STORE_CTX_init (&csc, x509_certs, cert, NULL); - if (X509_STORE_get_by_subject (&csc, X509_LU_X509, issuer, &obj) != - X509_LU_X509) - { - X509_STORE_CTX_cleanup (&csc); - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: no certificate found for issuer")); - return 0; + issuer = X509_get_issuer_name(cert); + subject = X509_get_subject_name(cert); + + /* Missing or self-signed, ignore cert but don't report failure. */ + if (!issuer || !subject || !X509_name_cmp(issuer, subject)) + return 1; + + if (!x509_cert_get_key(cert, &key)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to get public key from cert")); + return 0; } - } - - X509_STORE_CTX_cleanup (&csc); - icert = obj.data.x509; - - if (icert == NULL) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: " - "missing certificates, cannot construct X509 chain")); - free (ikey); - return 0; - } - - if (!x509_cert_get_key (icert, &key)) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to get public key from cert")); - free (ikey); - return 0; - } - - X509_OBJECT_free_contents (&obj); - - dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; - dc.dec_key = key; - skey = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, - KEYNOTE_PUBLIC_KEY); - if (keynote_errno == ERROR_MEMORY) - { - log_error ("x509_generate_kn: failed to get memory for public key"); - free (ikey); - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); - return 0; - } - - if (!skey) - { - free (ikey); - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); - return 0; - } - RSA_free (key); - - buf_len = strlen (fmt) + strlen (ikey) + strlen (skey) + 56; - buf = calloc (buf_len, sizeof (char)); - buf_len *= sizeof (char); - if (!buf) - { - log_error ("x509_generate_kn: " - "failed to allocate memory for KeyNote credential"); - free (ikey); - free (skey); - return 0; - } - - if (((tm = X509_get_notBefore (cert)) == NULL) || - (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) - { - tt = time (0); - strftime (before, 14, "%Y%m%d%H%M%S", localtime (&tt)); - timecomp = "LocalTimeOfDay"; - } - else - { - if (tm->data[tm->length - 1] == 'Z') - { - timecomp = "GMTTimeOfDay"; - i = tm->length - 2; + dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; + dc.dec_key = key; + ikey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, + KEYNOTE_PUBLIC_KEY); + if (keynote_errno == ERROR_MEMORY) { + log_print("x509_generate_kn: failed to get memory for public key"); + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); + return 0; } - else - { - timecomp = "LocalTimeOfDay"; - i = tm->length - 1; + if (!ikey) { + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); + return 0; } - - for (; i >= 0; i--) - { - if (tm->data[i] < '0' || tm->data[i] > '9') - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid data in " - "NotValidBefore time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } + RSA_free(key); + + /* Now find issuer's certificate so we can get the public key. */ + X509_STORE_CTX_init(&csc, x509_cas, cert, NULL); + if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) != + X509_LU_X509) { + X509_STORE_CTX_cleanup(&csc); + X509_STORE_CTX_init(&csc, x509_certs, cert, NULL); + if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) != + X509_LU_X509) { + X509_STORE_CTX_cleanup(&csc); + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: no certificate found for issuer")); + return 0; + } } - - if (tm->type == V_ASN1_UTCTIME) - { - if ((tm->length < 10) || (tm->length > 13)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length " - "of NotValidBefore time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[2] != '0' && tm->data[2] != '1') - || (tm->data[2] == '0' && tm->data[3] == '0') - || (tm->data[2] == '1' && tm->data[3] > '2') - || (tm->data[4] > '3') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '3' && tm->data[5] > '1') - || (tm->data[6] > '2') - || (tm->data[6] == '2' && tm->data[7] > '3') - || (tm->data[8] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidBefore time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Stupid UTC tricks. */ - if (tm->data[0] < '5') - snprintf (before, sizeof before, "20%s", tm->data); - else - snprintf (before, sizeof before, "19%s", tm->data); + X509_STORE_CTX_cleanup(&csc); + icert = obj.data.x509; + + if (icert == NULL) { + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: " + "missing certificates, cannot construct X509 chain")); + free(ikey); + return 0; } - else - { /* V_ASN1_GENERICTIME */ - if ((tm->length < 12) || (tm->length > 15)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length of " - "NotValidBefore time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[4] != '0' && tm->data[4] != '1') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '1' && tm->data[5] > '2') - || (tm->data[6] > '3') - || (tm->data[6] == '0' && tm->data[7] == '0') - || (tm->data[6] == '3' && tm->data[7] > '1') - || (tm->data[8] > '2') - || (tm->data[8] == '2' && tm->data[9] > '3') - || (tm->data[10] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidBefore time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - snprintf (before, sizeof before, "%s", tm->data); + if (!x509_cert_get_key(icert, &key)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to get public key from cert")); + free(ikey); + return 0; } - - /* Fix missing seconds. */ - if (tm->length < 12) - { - before[12] = '0'; - before[13] = '0'; + X509_OBJECT_free_contents(&obj); + + dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; + dc.dec_key = key; + skey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, + KEYNOTE_PUBLIC_KEY); + if (keynote_errno == ERROR_MEMORY) { + log_error("x509_generate_kn: failed to get memory for public key"); + free(ikey); + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); + return 0; } - - /* This will overwrite trailing 'Z'. */ - before[14] = '\0'; - } - - tm = X509_get_notAfter (cert); - if (tm == NULL - && (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) - { - tt = time (0); - strftime (after, 14, "%Y%m%d%H%M%S", localtime (&tt)); - timecomp2 = "LocalTimeOfDay"; - } - else - { - if (tm->data[tm->length - 1] == 'Z') - { - timecomp2 = "GMTTimeOfDay"; - i = tm->length - 2; + if (!skey) { + free(ikey); + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); + return 0; } - else - { - timecomp2 = "LocalTimeOfDay"; - i = tm->length - 1; + RSA_free(key); + + buf_len = strlen(fmt) + strlen(ikey) + strlen(skey) + 56; + buf = calloc(buf_len, sizeof(char)); + buf_len *= sizeof(char); + if (!buf) { + log_error("x509_generate_kn: " + "failed to allocate memory for KeyNote credential"); + free(ikey); + free(skey); + return 0; } - - for (; i >= 0; i--) - { - if (tm->data[i] < '0' || tm->data[i] > '9') - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid data in " - "NotValidAfter time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } + if (((tm = X509_get_notBefore(cert)) == NULL) || + (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) { + tt = time(0); + strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt)); + timecomp = "LocalTimeOfDay"; + } else { + if (tm->data[tm->length - 1] == 'Z') { + timecomp = "GMTTimeOfDay"; + i = tm->length - 2; + } else { + timecomp = "LocalTimeOfDay"; + i = tm->length - 1; + } + + for (; i >= 0; i--) { + if (tm->data[i] < '0' || tm->data[i] > '9') { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid data in " + "NotValidBefore time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + } + + if (tm->type == V_ASN1_UTCTIME) { + if ((tm->length < 10) || (tm->length > 13)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length " + "of NotValidBefore time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[2] != '0' && tm->data[2] != '1') || + (tm->data[2] == '0' && tm->data[3] == '0') || + (tm->data[2] == '1' && tm->data[3] > '2') || + (tm->data[4] > '3') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '3' && tm->data[5] > '1') || + (tm->data[6] > '2') || + (tm->data[6] == '2' && tm->data[7] > '3') || + (tm->data[8] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidBefore time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Stupid UTC tricks. */ + if (tm->data[0] < '5') + snprintf(before, sizeof before, "20%s", tm->data); + else + snprintf(before, sizeof before, "19%s", tm->data); + } else { /* V_ASN1_GENERICTIME */ + if ((tm->length < 12) || (tm->length > 15)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length of " + "NotValidBefore time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[4] != '0' && tm->data[4] != '1') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '1' && tm->data[5] > '2') || + (tm->data[6] > '3') || + (tm->data[6] == '0' && tm->data[7] == '0') || + (tm->data[6] == '3' && tm->data[7] > '1') || + (tm->data[8] > '2') || + (tm->data[8] == '2' && tm->data[9] > '3') || + (tm->data[10] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidBefore time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + snprintf(before, sizeof before, "%s", tm->data); + } + + /* Fix missing seconds. */ + if (tm->length < 12) { + before[12] = '0'; + before[13] = '0'; + } + /* This will overwrite trailing 'Z'. */ + before[14] = '\0'; } - if (tm->type == V_ASN1_UTCTIME) - { - if ((tm->length < 10) || (tm->length > 13)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length of " - "NotValidAfter time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[2] != '0' && tm->data[2] != '1') - || (tm->data[2] == '0' && tm->data[3] == '0') - || (tm->data[2] == '1' && tm->data[3] > '2') - || (tm->data[4] > '3') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '3' && tm->data[5] > '1') - || (tm->data[6] > '2') - || (tm->data[6] == '2' && tm->data[7] > '3') - || (tm->data[8] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidAfter time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Stupid UTC tricks. */ - if (tm->data[0] < '5') - snprintf (after, sizeof after, "20%s", tm->data); - else - snprintf (after, sizeof after, "19%s", tm->data); + tm = X509_get_notAfter(cert); + if (tm == NULL && + (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) { + tt = time(0); + strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt)); + timecomp2 = "LocalTimeOfDay"; + } else { + if (tm->data[tm->length - 1] == 'Z') { + timecomp2 = "GMTTimeOfDay"; + i = tm->length - 2; + } else { + timecomp2 = "LocalTimeOfDay"; + i = tm->length - 1; + } + + for (; i >= 0; i--) { + if (tm->data[i] < '0' || tm->data[i] > '9') { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid data in " + "NotValidAfter time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + } + + if (tm->type == V_ASN1_UTCTIME) { + if ((tm->length < 10) || (tm->length > 13)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length of " + "NotValidAfter time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[2] != '0' && tm->data[2] != '1') || + (tm->data[2] == '0' && tm->data[3] == '0') || + (tm->data[2] == '1' && tm->data[3] > '2') || + (tm->data[4] > '3') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '3' && tm->data[5] > '1') || + (tm->data[6] > '2') || + (tm->data[6] == '2' && tm->data[7] > '3') || + (tm->data[8] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidAfter time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Stupid UTC tricks. */ + if (tm->data[0] < '5') + snprintf(after, sizeof after, "20%s", tm->data); + else + snprintf(after, sizeof after, "19%s", tm->data); + } else { /* V_ASN1_GENERICTIME */ + if ((tm->length < 12) || (tm->length > 15)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length of " + "NotValidAfter time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[4] != '0' && tm->data[4] != '1') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '1' && tm->data[5] > '2') || + (tm->data[6] > '3') || + (tm->data[6] == '0' && tm->data[7] == '0') || + (tm->data[6] == '3' && tm->data[7] > '1') || + (tm->data[8] > '2') || + (tm->data[8] == '2' && tm->data[9] > '3') || + (tm->data[10] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidAfter time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + snprintf(after, sizeof after, "%s", tm->data); + } + + /* Fix missing seconds. */ + if (tm->length < 12) { + after[12] = '0'; + after[13] = '0'; + } + after[14] = '\0'; /* This will overwrite trailing 'Z' */ } - else - { /* V_ASN1_GENERICTIME */ - if ((tm->length < 12) || (tm->length > 15)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length of " - "NotValidAfter time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[4] != '0' && tm->data[4] != '1') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '1' && tm->data[5] > '2') - || (tm->data[6] > '3') - || (tm->data[6] == '0' && tm->data[7] == '0') - || (tm->data[6] == '3' && tm->data[7] > '1') - || (tm->data[8] > '2') - || (tm->data[8] == '2' && tm->data[9] > '3') - || (tm->data[10] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidAfter time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - snprintf (after, sizeof after, "%s", tm->data); - } - - /* Fix missing seconds. */ - if (tm->length < 12) - { - after[12] = '0'; - after[13] = '0'; + + snprintf(buf, buf_len, fmt, skey, ikey, timecomp, before, timecomp2, after); + free(ikey); + free(skey); + + if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to add new KeyNote credential")); + free(buf); + return 0; } + /* We could print the assertion here, but log_print() truncates... */ + LOG_DBG((LOG_POLICY, 60, "x509_generate_kn: added credential")); - after[14] = '\0'; /* This will overwrite trailing 'Z' */ - } - - snprintf (buf, buf_len, fmt, skey, ikey, timecomp, before, timecomp2, after); - free (ikey); - free (skey); - - if (kn_add_assertion (id, buf, strlen (buf), ASSERT_FLAG_LOCAL) == -1) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to add new KeyNote credential")); - free (buf); - return 0; - } - - /* We could print the assertion here, but log_print() truncates... */ - LOG_DBG ((LOG_POLICY, 60, "x509_generate_kn: added credential")); - - free (buf); - - if (!X509_NAME_oneline (issuer, isname, 256)) - { - LOG_DBG ((LOG_POLICY, 50, - "x509_generate_kn: X509_NAME_oneline (issuer, ...) failed")); - return 0; - } - - if (!X509_NAME_oneline (subject, subname, 256)) - { - LOG_DBG ((LOG_POLICY, 50, - "x509_generate_kn: X509_NAME_oneline (subject, ...) failed")); - return 0; - } - - buf_len = strlen (fmt2) + strlen (isname) + strlen (subname) + 56; - buf = malloc (buf_len); - if (!buf) - { - log_error ("x509_generate_kn: malloc (%d) failed", buf_len); - return 0; - } - - snprintf (buf, buf_len, fmt2, isname, subname, timecomp, before, timecomp2, - after); + free(buf); - if (kn_add_assertion (id, buf, strlen (buf), ASSERT_FLAG_LOCAL) == -1) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to add new KeyNote credential")); - free (buf); - return 0; - } + if (!X509_NAME_oneline(issuer, isname, 256)) { + LOG_DBG((LOG_POLICY, 50, + "x509_generate_kn: X509_NAME_oneline (issuer, ...) failed")); + return 0; + } + if (!X509_NAME_oneline(subject, subname, 256)) { + LOG_DBG((LOG_POLICY, 50, + "x509_generate_kn: X509_NAME_oneline (subject, ...) failed")); + return 0; + } + buf_len = strlen(fmt2) + strlen(isname) + strlen(subname) + 56; + buf = malloc(buf_len); + if (!buf) { + log_error("x509_generate_kn: malloc (%d) failed", buf_len); + return 0; + } + snprintf(buf, buf_len, fmt2, isname, subname, timecomp, before, timecomp2, + after); - LOG_DBG ((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s", buf)); + if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to add new KeyNote credential")); + free(buf); + return 0; + } + LOG_DBG((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s", buf)); - free (buf); - return 1; + free(buf); + return 1; } -#endif /* USE_POLICY */ +#endif /* USE_POLICY */ static u_int16_t -x509_hash (u_int8_t *id, size_t len) +x509_hash(u_int8_t *id, size_t len) { - size_t i; - u_int16_t bucket = 0; - - /* XXX We might resize if we are crossing a certain threshold. */ - for (i = 4; i < (len & ~1); i += 2) - { - /* Doing it this way avoids alignment problems. */ - bucket ^= (id[i] + 1) * (id[i + 1] + 257); - } - /* Hash in the last character of odd length IDs too. */ - if (i < len) - bucket ^= (id[i] + 1) * (id[i] + 257); - - bucket &= bucket_mask; - - return bucket; + u_int16_t bucket = 0; + size_t i; + + /* XXX We might resize if we are crossing a certain threshold. */ + for (i = 4; i < (len & ~1); i += 2) { + /* Doing it this way avoids alignment problems. */ + bucket ^= (id[i] + 1) * (id[i + 1] + 257); + } + /* Hash in the last character of odd length IDs too. */ + if (i < len) + bucket ^= (id[i] + 1) * (id[i] + 257); + + bucket &= bucket_mask; + return bucket; } static void -x509_hash_init (void) +x509_hash_init(void) { - struct x509_hash *certh; - int i; - - bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1; - - /* If reinitializing, free existing entries. */ - if (x509_tab) - { - for (i = 0; i <= bucket_mask; i++) - for (certh = LIST_FIRST (&x509_tab[i]); certh; - certh = LIST_FIRST (&x509_tab[i])) - { - LIST_REMOVE (certh, link); - free (certh); - } - - free (x509_tab); - } - - x509_tab = malloc ((bucket_mask + 1) * sizeof (struct x509_list)); - if (!x509_tab) - log_fatal ("x509_hash_init: malloc (%lu) failed", - (bucket_mask + 1) * (unsigned long)sizeof (struct x509_list)); - for (i = 0; i <= bucket_mask; i++) - { - LIST_INIT (&x509_tab[i]); - } + struct x509_hash *certh; + int i; + + bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1; + + /* If reinitializing, free existing entries. */ + if (x509_tab) { + for (i = 0; i <= bucket_mask; i++) + for (certh = LIST_FIRST(&x509_tab[i]); certh; + certh = LIST_FIRST(&x509_tab[i])) { + LIST_REMOVE(certh, link); + free(certh); + } + free(x509_tab); + } + x509_tab = malloc((bucket_mask + 1) * sizeof(struct x509_list)); + if (!x509_tab) + log_fatal("x509_hash_init: malloc (%lu) failed", + (bucket_mask + 1) * (unsigned long) sizeof(struct x509_list)); + for (i = 0; i <= bucket_mask; i++) { + LIST_INIT(&x509_tab[i]); + } } /* Lookup a certificate by an ID blob. */ static X509 * -x509_hash_find (u_int8_t *id, size_t len) +x509_hash_find(u_int8_t *id, size_t len) { - struct x509_hash *cert; - u_int8_t **cid; - u_int32_t *clen; - int n, i, id_found; - - for (cert = LIST_FIRST (&x509_tab[x509_hash (id, len)]); cert; - cert = LIST_NEXT (cert, link)) - { - if (!x509_cert_get_subjects (cert->cert, &n, &cid, &clen)) - continue; - - id_found = 0; - for (i = 0; i < n; i++) - { - LOG_DBG_BUF ((LOG_CRYPTO, 70, "cert_cmp", id, len)); - LOG_DBG_BUF ((LOG_CRYPTO, 70, "cert_cmp", cid[i], clen[i])); - /* XXX This identity predicate needs to be understood. */ - if (clen[i] == len && id[0] == cid[i][0] - && memcmp (id + 4, cid[i] + 4, len - 4) == 0) - { - id_found++; - break; - } + struct x509_hash *cert; + u_int8_t **cid; + u_int32_t *clen; + int n, i, id_found; + + for (cert = LIST_FIRST(&x509_tab[x509_hash(id, len)]); cert; + cert = LIST_NEXT(cert, link)) { + if (!x509_cert_get_subjects(cert->cert, &n, &cid, &clen)) + continue; + + id_found = 0; + for (i = 0; i < n; i++) { + LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", id, len)); + LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", cid[i], clen[i])); + /* + * XXX This identity predicate needs to be + * understood. + */ + if (clen[i] == len && id[0] == cid[i][0] && + memcmp(id + 4, cid[i] + 4, len - 4) == 0) { + id_found++; + break; + } + } + cert_free_subjects(n, cid, clen); + if (!id_found) + continue; + + LOG_DBG((LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", + cert->cert)); + return cert->cert; } - cert_free_subjects (n, cid, clen); - if (!id_found) - continue; - LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", - cert->cert)); - return cert->cert; - } - - LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query")); - return 0; + LOG_DBG((LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query")); + return 0; } static int -x509_hash_enter (X509 *cert) +x509_hash_enter(X509 *cert) { - u_int16_t bucket = 0; - u_int8_t **id; - u_int32_t *len; - struct x509_hash *certh; - int n, i; - - if (!x509_cert_get_subjects (cert, &n, &id, &len)) - { - log_print ("x509_hash_enter: cannot retrieve subjects"); - return 0; - } - - for (i = 0; i < n; i++) - { - certh = calloc (1, sizeof *certh); - if (!certh) - { - cert_free_subjects (n, id, len); - log_error ("x509_hash_enter: calloc (1, %lu) failed", - (unsigned long)sizeof *certh); - return 0; - } - - certh->cert = cert; - - bucket = x509_hash (id[i], len[i]); - - LIST_INSERT_HEAD (&x509_tab[bucket], certh, link); - LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d", - cert, bucket)); - } - cert_free_subjects (n, id, len); - - return 1; + u_int16_t bucket = 0; + u_int8_t **id; + u_int32_t *len; + struct x509_hash *certh; + int n, i; + + if (!x509_cert_get_subjects(cert, &n, &id, &len)) { + log_print("x509_hash_enter: cannot retrieve subjects"); + return 0; + } + for (i = 0; i < n; i++) { + certh = calloc(1, sizeof *certh); + if (!certh) { + cert_free_subjects(n, id, len); + log_error("x509_hash_enter: calloc (1, %lu) failed", + (unsigned long) sizeof *certh); + return 0; + } + certh->cert = cert; + + bucket = x509_hash(id[i], len[i]); + + LIST_INSERT_HEAD(&x509_tab[bucket], certh, link); + LOG_DBG((LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d", + cert, bucket)); + } + cert_free_subjects(n, id, len); + + return 1; } /* X509 Certificate Handling functions. */ int -x509_read_from_dir (X509_STORE *ctx, char *name, int hash) +x509_read_from_dir(X509_STORE *ctx, char *name, int hash) { - struct dirent *file; + struct dirent *file; #if defined (USE_PRIVSEP) - struct monitor_dirents *dir; - FILE *certfp; + struct monitor_dirents *dir; + FILE *certfp; #else - DIR *dir; - BIO *certh; + DIR *dir; + BIO *certh; #endif - X509 *cert; - char fullname[PATH_MAX]; - int off, size; + X509 *cert; + char fullname[PATH_MAX]; + int off, size; - if (strlen (name) >= sizeof fullname - 1) - { - log_print ("x509_read_from_dir: directory name too long"); - return 0; - } + if (strlen(name) >= sizeof fullname - 1) { + log_print("x509_read_from_dir: directory name too long"); + return 0; + } + LOG_DBG((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s", + name)); + + dir = monitor_opendir(name); + if (!dir) { + LOG_DBG((LOG_CRYPTO, 10, + "x509_read_from_dir: opendir (\"%s\") failed: " + "%s", name, strerror(errno))); + return 0; + } + strlcpy(fullname, name, sizeof fullname); + off = strlen(fullname); + size = sizeof fullname - off; - LOG_DBG ((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s", - name)); + while ((file = monitor_readdir(dir)) != NULL) { + strlcpy(fullname + off, file->d_name, size); - dir = monitor_opendir (name); - if (!dir) - { - LOG_DBG ((LOG_CRYPTO, 10, "x509_read_from_dir: opendir (\"%s\") failed: " - "%s", name, strerror (errno))); - return 0; - } - - strlcpy (fullname, name, sizeof fullname); - off = strlen (fullname); - size = sizeof fullname - off; - - while ((file = monitor_readdir (dir)) != NULL) - { - strlcpy (fullname + off, file->d_name, size); - - if (file->d_type != DT_UNKNOWN) - { - if (file->d_type != DT_REG && file->d_type != DT_LNK) - continue; - } - else - { - struct stat sb; - - if (monitor_stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG)) - continue; - } - - LOG_DBG ((LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s", - file->d_name)); + if (file->d_type != DT_UNKNOWN) { + if (file->d_type != DT_REG && file->d_type != DT_LNK) + continue; + } else { + struct stat sb; -#if defined (USE_PRIVSEP) - certfp = monitor_fopen (fullname, "r"); - if (!certfp) - { - log_error ("x509_read_from_dir: monitor_fopen (\"%s\", \"r\") failed", - fullname); - continue; - } + if (monitor_stat(fullname, &sb) == -1 || + !(sb.st_mode & S_IFREG)) + continue; + } + + LOG_DBG((LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s", + file->d_name)); +#if defined (USE_PRIVSEP) + certfp = monitor_fopen(fullname, "r"); + if (!certfp) { + log_error("x509_read_from_dir: monitor_fopen " + "(\"%s\", \"r\") failed", + fullname); + continue; + } #if SSLEAY_VERSION_NUMBER >= 0x00904100L - cert = PEM_read_X509 (certfp, NULL, NULL, NULL); + cert = PEM_read_X509(certfp, NULL, NULL, NULL); #else - cert = PEM_read_X509 (certfp, NULL, NULL); + cert = PEM_read_X509(certfp, NULL, NULL); #endif - fclose (certfp); + fclose(certfp); #else - certh = BIO_new (BIO_s_file ()); - if (!certh) - { - log_error ("x509_read_from_dir: BIO_new (BIO_s_file ()) failed"); - continue; - } - - if (BIO_read_filename (certh, fullname) == -1) - { - BIO_free (certh); - log_error ("x509_read_from_dir: " - "BIO_read_filename (certh, \"%s\") failed", - fullname); - continue; - } - + certh = BIO_new(BIO_s_file()); + if (!certh) { + log_error("x509_read_from_dir: BIO_new (BIO_s_file ()) failed"); + continue; + } + if (BIO_read_filename(certh, fullname) == -1) { + BIO_free(certh); + log_error("x509_read_from_dir: " + "BIO_read_filename (certh, \"%s\") failed", + fullname); + continue; + } #if SSLEAY_VERSION_NUMBER >= 0x00904100L - cert = PEM_read_bio_X509 (certh, NULL, NULL, NULL); + cert = PEM_read_bio_X509(certh, NULL, NULL, NULL); #else - cert = PEM_read_bio_X509 (certh, NULL, NULL); + cert = PEM_read_bio_X509(certh, NULL, NULL); #endif - BIO_free (certh); -#endif /* USE_PRIVSEP */ - if (cert == NULL) - { - log_print ("x509_read_from_dir: PEM_read_bio_X509 failed for %s", - file->d_name); - continue; - } - - if (!X509_STORE_add_cert (ctx, cert)) - { - /* - * This is actually expected if we have several certificates only - * differing in subjectAltName, which is not an something that is - * strange. Consider multi-homed machines. - */ - LOG_DBG ((LOG_CRYPTO, 50, - "x509_read_from_dir: X509_STORE_add_cert failed for %s", - file->d_name)); + BIO_free(certh); +#endif /* USE_PRIVSEP */ + if (cert == NULL) { + log_print("x509_read_from_dir: PEM_read_bio_X509 failed for %s", + file->d_name); + continue; + } + if (!X509_STORE_add_cert(ctx, cert)) { + /* + * This is actually expected if we have several + * certificates only differing in subjectAltName, which + * is not an something that is strange. Consider + * multi-homed machines. + */ + LOG_DBG((LOG_CRYPTO, 50, + "x509_read_from_dir: X509_STORE_add_cert failed for %s", + file->d_name)); + } + if (hash) + if (!x509_hash_enter(cert)) + log_print("x509_read_from_dir: x509_hash_enter " + "(%s) failed", + file->d_name); } - if (hash) - if (!x509_hash_enter (cert)) - log_print ("x509_read_from_dir: x509_hash_enter (%s) failed", - file->d_name); - } - - monitor_closedir (dir); + monitor_closedir(dir); - return 1; + return 1; } /* XXX share code with x509_read_from_dir() ? */ int -x509_read_crls_from_dir (X509_STORE *ctx, char *name) +x509_read_crls_from_dir(X509_STORE *ctx, char *name) { #if OPENSSL_VERSION_NUMBER >= 0x00907000L - struct dirent *file; + struct dirent *file; #if defined (USE_PRIVSEP) - struct monitor_dirents *dir; - FILE *crlfp; + struct monitor_dirents *dir; + FILE *crlfp; #else - DIR *dir; - BIO *crlh; + DIR *dir; + BIO *crlh; #endif - X509_CRL *crl; - char fullname[PATH_MAX]; - int off, size; + X509_CRL *crl; + char fullname[PATH_MAX]; + int off, size; - if (strlen (name) >= sizeof fullname - 1) - { - log_print ("x509_read_crls_from_dir: directory name too long"); - return 0; - } - - LOG_DBG ((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs from %s", + if (strlen(name) >= sizeof fullname - 1) { + log_print("x509_read_crls_from_dir: directory name too long"); + return 0; + } + LOG_DBG((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs from %s", name)); - dir = monitor_opendir (name); - if (!dir) - { - LOG_DBG ((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir (\"%s\") " - "failed: %s", name, strerror (errno))); - return 0; - } - - strlcpy (fullname, name, sizeof fullname); - off = strlen (fullname); - size = sizeof fullname - off; - - while ((file = monitor_readdir (dir)) != NULL) - { - strlcpy (fullname + off, file->d_name, size); - - if (file->d_type != DT_UNKNOWN) - { - if (file->d_type != DT_REG && file->d_type != DT_LNK) - continue; - } - else - { - struct stat sb; - - if (monitor_stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG)) - continue; - } - - LOG_DBG ((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading CRL %s", - file->d_name)); - -#if defined (USE_PRIVSEP) - crlfp = monitor_fopen (fullname, "r"); - if (!crlfp) - { - log_error ("x509_read_crls_from_dir: monitor_fopen (\"%s\", \"r\") " - "failed", fullname); - continue; + dir = monitor_opendir(name); + if (!dir) { + LOG_DBG((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir (\"%s\") " + "failed: %s", name, strerror(errno))); + return 0; } + strlcpy(fullname, name, sizeof fullname); + off = strlen(fullname); + size = sizeof fullname - off; - crl = PEM_read_X509_CRL (crlfp, NULL, NULL, NULL); - fclose (crlfp); -#else - crlh = BIO_new (BIO_s_file ()); - if (!crlh) - { - log_error ("x509_read_crls_from_dir: " - "BIO_new (BIO_s_file ()) failed"); - continue; - } + while ((file = monitor_readdir(dir)) != NULL) { + strlcpy(fullname + off, file->d_name, size); - if (BIO_read_filename (crlh, fullname) == -1) - { - BIO_free (crlh); - log_error ("x509_read_crls_from_dir: " - "BIO_read_filename (crlh, \"%s\") failed", fullname); - continue; - } + if (file->d_type != DT_UNKNOWN) { + if (file->d_type != DT_REG && file->d_type != DT_LNK) + continue; + } else { + struct stat sb; - crl = PEM_read_bio_X509_CRL (crlh, NULL, NULL, NULL); + if (monitor_stat(fullname, &sb) == -1 || !(sb.st_mode & S_IFREG)) + continue; + } - BIO_free (crlh); -#endif /* USE_PRIVSEP */ - if (crl == NULL) - { - log_print ("x509_read_crls_from_dir: " - "PEM_read_bio_X509_CRL failed for %s", file->d_name); - continue; - } + LOG_DBG((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading CRL %s", + file->d_name)); - if (!X509_STORE_add_crl (ctx, crl)) - { - LOG_DBG ((LOG_CRYPTO, 50, "x509_read_crls_from_dir: " - "X509_STORE_add_crl failed for %s", file->d_name)); - continue; +#if defined (USE_PRIVSEP) + crlfp = monitor_fopen(fullname, "r"); + if (!crlfp) { + log_error("x509_read_crls_from_dir: monitor_fopen " + "(\"%s\", \"r\") failed", fullname); + continue; + } + crl = PEM_read_X509_CRL(crlfp, NULL, NULL, NULL); + fclose(crlfp); +#else + crlh = BIO_new(BIO_s_file()); + if (!crlh) { + log_error("x509_read_crls_from_dir: " + "BIO_new (BIO_s_file ()) failed"); + continue; + } + if (BIO_read_filename(crlh, fullname) == -1) { + BIO_free(crlh); + log_error("x509_read_crls_from_dir: " + "BIO_read_filename (crlh, \"%s\") failed", fullname); + continue; + } + crl = PEM_read_bio_X509_CRL(crlh, NULL, NULL, NULL); + + BIO_free(crlh); +#endif /* USE_PRIVSEP */ + if (crl == NULL) { + log_print("x509_read_crls_from_dir: " + "PEM_read_bio_X509_CRL failed for %s", file->d_name); + continue; + } + if (!X509_STORE_add_crl(ctx, crl)) { + LOG_DBG((LOG_CRYPTO, 50, "x509_read_crls_from_dir: " + "X509_STORE_add_crl failed for %s", file->d_name)); + continue; + } + /* + * XXX This is to make x509_cert_validate set this (and another) flag + * XXX when validating certificates. Currently, OpenSSL defaults to + * XXX reject an otherwise valid certificate (chain) if these flags + * XXX are set but there are no CRLs to check. The current workaround + * XXX is to only set the flags if we actually loaded some CRL data. + */ + X509_STORE_set_flags(ctx, X509_V_FLAG_CRL_CHECK); } - /* - * XXX This is to make x509_cert_validate set this (and another) flag - * XXX when validating certificates. Currently, OpenSSL defaults to - * XXX reject an otherwise valid certificate (chain) if these flags - * XXX are set but there are no CRLs to check. The current workaround - * XXX is to only set the flags if we actually loaded some CRL data. - */ - X509_STORE_set_flags (ctx, X509_V_FLAG_CRL_CHECK); - } - - monitor_closedir (dir); -#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */ + monitor_closedir(dir); +#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */ - return 1; + return 1; } /* Initialize our databases and load our own certificates. */ int -x509_cert_init (void) +x509_cert_init(void) { - char *dirname; - - x509_hash_init (); - - /* Process CA certificates we will trust. */ - dirname = conf_get_str ("X509-certificates", "CA-directory"); - if (!dirname) - { - log_print ("x509_cert_init: no CA-directory"); - return 0; - } - - /* Free if already initialized. */ - if (x509_cas) - X509_STORE_free (x509_cas); - - x509_cas = X509_STORE_new (); - if (!x509_cas) - { - log_print ("x509_cert_init: creating new X509_STORE failed"); - return 0; - } - - if (!x509_read_from_dir (x509_cas, dirname, 0)) - { - log_print ("x509_cert_init: x509_read_from_dir failed"); - return 0; - } - - /* Process client certificates we will accept. */ - dirname = conf_get_str ("X509-certificates", "Cert-directory"); - if (!dirname) - { - log_print ("x509_cert_init: no Cert-directory"); - return 0; - } - - /* Free if already initialized. */ - if (x509_certs) - X509_STORE_free (x509_certs); - - x509_certs = X509_STORE_new (); - if (!x509_certs) - { - log_print ("x509_cert_init: creating new X509_STORE failed"); - return 0; - } - - if (!x509_read_from_dir (x509_certs, dirname, 1)) - { - log_print ("x509_cert_init: x509_read_from_dir failed"); - return 0; - } - - return 1; + char *dirname; + + x509_hash_init(); + + /* Process CA certificates we will trust. */ + dirname = conf_get_str("X509-certificates", "CA-directory"); + if (!dirname) { + log_print("x509_cert_init: no CA-directory"); + return 0; + } + /* Free if already initialized. */ + if (x509_cas) + X509_STORE_free(x509_cas); + + x509_cas = X509_STORE_new(); + if (!x509_cas) { + log_print("x509_cert_init: creating new X509_STORE failed"); + return 0; + } + if (!x509_read_from_dir(x509_cas, dirname, 0)) { + log_print("x509_cert_init: x509_read_from_dir failed"); + return 0; + } + /* Process client certificates we will accept. */ + dirname = conf_get_str("X509-certificates", "Cert-directory"); + if (!dirname) { + log_print("x509_cert_init: no Cert-directory"); + return 0; + } + /* Free if already initialized. */ + if (x509_certs) + X509_STORE_free(x509_certs); + + x509_certs = X509_STORE_new(); + if (!x509_certs) { + log_print("x509_cert_init: creating new X509_STORE failed"); + return 0; + } + if (!x509_read_from_dir(x509_certs, dirname, 1)) { + log_print("x509_cert_init: x509_read_from_dir failed"); + return 0; + } + return 1; } int -x509_crl_init (void) +x509_crl_init(void) { - /* - * XXX I'm not sure if the method to use CRLs in certificate validation - * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not - * support it. - */ + /* + * XXX I'm not sure if the method to use CRLs in certificate validation + * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not + * support it. + */ #if OPENSSL_VERSION_NUMBER >= 0x00907000L - char *dirname; - dirname = conf_get_str ("X509-certificates", "CRL-directory"); - if (!dirname) - { - log_print ("x509_crl_init: no CRL-directory"); - return 0; - } - - if (!x509_read_crls_from_dir (x509_cas, dirname)) - { - LOG_DBG ((LOG_MISC, 10, "x509_crl_init: x509_read_crls_from_dir failed")); - return 0; - } + char *dirname; + dirname = conf_get_str("X509-certificates", "CRL-directory"); + if (!dirname) { + log_print("x509_crl_init: no CRL-directory"); + return 0; + } + if (!x509_read_crls_from_dir(x509_cas, dirname)) { + LOG_DBG((LOG_MISC, 10, + "x509_crl_init: x509_read_crls_from_dir failed")); + return 0; + } #else - LOG_DBG ((LOG_CRYPTO, 10, "x509_crl_init: CRL support only " + LOG_DBG((LOG_CRYPTO, 10, "x509_crl_init: CRL support only " "with OpenSSL v0.9.7 or later")); #endif - return 1; + return 1; } void * -x509_cert_get (u_int8_t *asn, u_int32_t len) +x509_cert_get(u_int8_t *asn, u_int32_t len) { - return x509_from_asn (asn, len); + return x509_from_asn(asn, len); } int -x509_cert_validate (void *scert) +x509_cert_validate(void *scert) { - X509_STORE_CTX csc; - X509_NAME *issuer, *subject; - X509 *cert = (X509 *)scert; - EVP_PKEY *key; - int res, err; - - /* - * Validate the peer certificate by checking with the CA certificates we - * trust. - */ - X509_STORE_CTX_init (&csc, x509_cas, cert, NULL); + X509_STORE_CTX csc; + X509_NAME *issuer, *subject; + X509 *cert = (X509 *) scert; + EVP_PKEY *key; + int res, err; + + /* + * Validate the peer certificate by checking with the CA certificates we + * trust. + */ + X509_STORE_CTX_init(&csc, x509_cas, cert, NULL); #if OPENSSL_VERSION_NUMBER >= 0x00907000L - /* XXX See comment in x509_read_crls_from_dir. */ - if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) - { - X509_STORE_CTX_set_flags (&csc, X509_V_FLAG_CRL_CHECK); - X509_STORE_CTX_set_flags (&csc, X509_V_FLAG_CRL_CHECK_ALL); - } + /* XXX See comment in x509_read_crls_from_dir. */ + if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) { + X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK); + X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL); + } #endif - res = X509_verify_cert (&csc); - err = csc.error; - X509_STORE_CTX_cleanup (&csc); - - /* Return if validation succeeded or self-signed certs are not accepted. */ - if (res) - return 1; - else if (!conf_get_str ("X509-certificates", "Accept-self-signed")) - { - if (err) - log_print ("x509_cert_validate: %.100s", - X509_verify_cert_error_string (err)); - return res; - } - - issuer = X509_get_issuer_name (cert); - subject = X509_get_subject_name (cert); - - if (!issuer || !subject || X509_name_cmp (issuer, subject)) - return 0; - - key = X509_get_pubkey (cert); - if (!key) - { - log_print ("x509_cert_validate: could not get public key from " - "self-signed cert"); - return 0; - } - - if (X509_verify (cert, key) == -1) - { - log_print ("x509_cert_validate: self-signed cert is bad"); - return 0; - } - - return 1; + res = X509_verify_cert(&csc); + err = csc.error; + X509_STORE_CTX_cleanup(&csc); + + /* + * Return if validation succeeded or self-signed certs are not + * accepted. + */ + if (res) + return 1; + else if (!conf_get_str("X509-certificates", "Accept-self-signed")) { + if (err) + log_print("x509_cert_validate: %.100s", + X509_verify_cert_error_string(err)); + return res; + } + issuer = X509_get_issuer_name(cert); + subject = X509_get_subject_name(cert); + + if (!issuer || !subject || X509_name_cmp(issuer, subject)) + return 0; + + key = X509_get_pubkey(cert); + if (!key) { + log_print("x509_cert_validate: could not get public key from " + "self-signed cert"); + return 0; + } + if (X509_verify(cert, key) == -1) { + log_print("x509_cert_validate: self-signed cert is bad"); + return 0; + } + return 1; } int -x509_cert_insert (int id, void *scert) +x509_cert_insert(int id, void *scert) { - X509 *cert; - int res; - - cert = X509_dup ((X509 *)scert); - if (!cert) - { - log_print ("x509_cert_insert: X509_dup failed"); - return 0; - } + X509 *cert; + int res; + cert = X509_dup((X509 *) scert); + if (!cert) { + log_print("x509_cert_insert: X509_dup failed"); + return 0; + } #ifdef USE_POLICY - if (x509_generate_kn (id, cert) == 0) - { - LOG_DBG ((LOG_POLICY, 50, - "x509_cert_insert: x509_generate_kn failed")); - X509_free (cert); - return 0; - } -#endif /* USE_POLICY */ - - res = x509_hash_enter (cert); - if (!res) - X509_free (cert); - - return res; + if (x509_generate_kn(id, cert) == 0) { + LOG_DBG((LOG_POLICY, 50, + "x509_cert_insert: x509_generate_kn failed")); + X509_free(cert); + return 0; + } +#endif /* USE_POLICY */ + + res = x509_hash_enter(cert); + if (!res) + X509_free(cert); + + return res; } static struct x509_hash * -x509_hash_lookup (X509 *cert) +x509_hash_lookup(X509 *cert) { - int i; - struct x509_hash *certh; - - for (i = 0; i <= bucket_mask; i++) - for (certh = LIST_FIRST (&x509_tab[i]); certh; - certh = LIST_NEXT (certh, link)) - if (certh->cert == cert) - return certh; - return 0; + int i; + struct x509_hash *certh; + + for (i = 0; i <= bucket_mask; i++) + for (certh = LIST_FIRST(&x509_tab[i]); certh; + certh = LIST_NEXT(certh, link)) + if (certh->cert == cert) + return certh; + return 0; } void -x509_cert_free (void *cert) +x509_cert_free(void *cert) { - struct x509_hash *certh = x509_hash_lookup ((X509 *)cert); + struct x509_hash *certh = x509_hash_lookup((X509 *) cert); - if (certh) - LIST_REMOVE (certh, link); - X509_free ((X509 *)cert); + if (certh) + LIST_REMOVE(certh, link); + X509_free((X509 *) cert); } /* Validate the BER Encoding of a RDNSequence in the CERT_REQ payload. */ int -x509_certreq_validate (u_int8_t *asn, u_int32_t len) +x509_certreq_validate(u_int8_t *asn, u_int32_t len) { - int res = 1; + int res = 1; #if 0 - struct norm_type name = SEQOF ("issuer", RDNSequence); - - if (!asn_template_clone (&name, 1) - || (asn = asn_decode_sequence (asn, len, &name)) == 0) - { - log_print ("x509_certreq_validate: can not decode 'acceptable CA' info"); - res = 0; - } - asn_free (&name); + struct norm_type name = SEQOF("issuer", RDNSequence); + + if (!asn_template_clone(&name, 1) || + (asn = asn_decode_sequence(asn, len, &name)) == 0) { + log_print("x509_certreq_validate: can not decode 'acceptable CA' info"); + res = 0; + } + asn_free(&name); #endif - /* XXX - not supported directly in SSL - later. */ + /* XXX - not supported directly in SSL - later. */ - return res; + return res; } /* Decode the BER Encoding of a RDNSequence in the CERT_REQ payload. */ void * -x509_certreq_decode (u_int8_t *asn, u_int32_t len) +x509_certreq_decode(u_int8_t *asn, u_int32_t len) { #if 0 - /* XXX This needs to be done later. */ - struct norm_type aca = SEQOF ("aca", RDNSequence); - struct norm_type *tmp; - struct x509_aca naca, *ret; - - if (!asn_template_clone (&aca, 1) - || (asn = asn_decode_sequence (asn, len, &aca)) == 0) - { - log_print ("x509_certreq_decode: can not decode 'acceptable CA' info"); - goto fail; - } - memset (&naca, 0, sizeof (naca)); - - tmp = asn_decompose ("aca.RelativeDistinguishedName.AttributeValueAssertion", - &aca); - if (!tmp) - goto fail; - x509_get_attribval (tmp, &naca.name1); - - tmp = asn_decompose ("aca.RelativeDistinguishedName[1]" - ".AttributeValueAssertion", &aca); - if (tmp) - x509_get_attribval (tmp, &naca.name2); - - asn_free (&aca); - - ret = malloc (sizeof (struct x509_aca)); - if (ret) - memcpy (ret, &naca, sizeof (struct x509_aca)); - else - { - log_error ("x509_certreq_decode: malloc (%lu) failed", - (unsigned long)sizeof (struct x509_aca)); - x509_free_aca (&aca); - } - - return ret; - - fail: - asn_free (&aca); + /* XXX This needs to be done later. */ + struct norm_type aca = SEQOF("aca", RDNSequence); + struct norm_type *tmp; + struct x509_aca naca, *ret; + + if (!asn_template_clone(&aca, 1) || + (asn = asn_decode_sequence(asn, len, &aca)) == 0) { + log_print("x509_certreq_decode: can not decode 'acceptable CA' info"); + goto fail; + } + memset(&naca, 0, sizeof(naca)); + + tmp = asn_decompose("aca.RelativeDistinguishedName.AttributeValueAssertion", + &aca); + if (!tmp) + goto fail; + x509_get_attribval(tmp, &naca.name1); + + tmp = asn_decompose("aca.RelativeDistinguishedName[1]" + ".AttributeValueAssertion", &aca); + if (tmp) + x509_get_attribval(tmp, &naca.name2); + + asn_free(&aca); + + ret = malloc(sizeof(struct x509_aca)); + if (ret) + memcpy(ret, &naca, sizeof(struct x509_aca)); + else { + log_error("x509_certreq_decode: malloc (%lu) failed", + (unsigned long) sizeof(struct x509_aca)); + x509_free_aca(&aca); + } + + return ret; + +fail: + asn_free(&aca); #endif - return 0; + return 0; } void -x509_free_aca (void *blob) +x509_free_aca(void *blob) { - struct x509_aca *aca = blob; + struct x509_aca *aca = blob; - if (aca->name1.type) - free (aca->name1.type); - if (aca->name1.val) - free (aca->name1.val); + if (aca->name1.type) + free(aca->name1.type); + if (aca->name1.val) + free(aca->name1.val); - if (aca->name2.type) - free (aca->name2.type); - if (aca->name2.val) - free (aca->name2.val); + if (aca->name2.type) + free(aca->name2.type); + if (aca->name2.val) + free(aca->name2.val); } X509 * -x509_from_asn (u_char *asn, u_int len) +x509_from_asn(u_char *asn, u_int len) { - BIO *certh; - X509 *scert = 0; - - certh = BIO_new (BIO_s_mem ()); - if (!certh) - { - log_error ("x509_from_asn: BIO_new (BIO_s_mem ()) failed"); - return 0; - } - - if (BIO_write (certh, asn, len) == -1) - { - log_error ("x509_from_asn: BIO_write failed\n"); - goto end; - } - - scert = d2i_X509_bio (certh, NULL); - if (!scert) - { - log_print ("x509_from_asn: d2i_X509_bio failed\n"); - goto end; - } - - end: - BIO_free (certh); - return scert; + BIO *certh; + X509 *scert = 0; + + certh = BIO_new(BIO_s_mem()); + if (!certh) { + log_error("x509_from_asn: BIO_new (BIO_s_mem ()) failed"); + return 0; + } + if (BIO_write(certh, asn, len) == -1) { + log_error("x509_from_asn: BIO_write failed\n"); + goto end; + } + scert = d2i_X509_bio(certh, NULL); + if (!scert) { + log_print("x509_from_asn: d2i_X509_bio failed\n"); + goto end; + } +end: + BIO_free(certh); + return scert; } /* @@ -1233,338 +1102,304 @@ x509_from_asn (u_char *asn, u_int len) * XXX We don't check if the certificate we find is from an accepted CA. */ int -x509_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, - u_int32_t *certlen) +x509_cert_obtain(u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, + u_int32_t *certlen) { - struct x509_aca *aca = data; - X509 *scert; - - if (aca) - LOG_DBG ((LOG_CRYPTO, 60, - "x509_cert_obtain: acceptable certificate authorities here")); - - /* We need our ID to find a certificate. */ - if (!id) - { - log_print ("x509_cert_obtain: ID is missing"); - return 0; - } - - scert = x509_hash_find (id, id_len); - if (!scert) - return 0; - - x509_serialize (scert, cert, certlen); - if (!*cert) - return 0; - return 1; + struct x509_aca *aca = data; + X509 *scert; + + if (aca) + LOG_DBG((LOG_CRYPTO, 60, + "x509_cert_obtain: acceptable certificate authorities here")); + + /* We need our ID to find a certificate. */ + if (!id) { + log_print("x509_cert_obtain: ID is missing"); + return 0; + } + scert = x509_hash_find(id, id_len); + if (!scert) + return 0; + + x509_serialize(scert, cert, certlen); + if (!*cert) + return 0; + return 1; } /* Returns a pointer to the subjectAltName information of X509 certificate. */ int -x509_cert_subjectaltname (X509 *scert, u_int8_t **altname, u_int32_t *len) +x509_cert_subjectaltname(X509 *scert, u_int8_t **altname, u_int32_t *len) { - X509_EXTENSION *subjectaltname; - u_int8_t *sandata; - int extpos; - int santype, sanlen; - - extpos = X509_get_ext_by_NID (scert, NID_subject_alt_name, -1); - if (extpos == -1) - { - log_print ("x509_cert_subjectaltname: " - "certificate does not contain subjectAltName"); - return 0; - } - - subjectaltname = X509_get_ext (scert, extpos); - - if (!subjectaltname || !subjectaltname->value - || !subjectaltname->value->data || subjectaltname->value->length < 4) - { - log_print ("x509_cert_subjectaltname: invalid subjectaltname extension"); - return 0; - } - - /* SSL does not handle unknown ASN stuff well, do it by hand. */ - sandata = subjectaltname->value->data; - santype = sandata[2] & 0x3f; - sanlen = sandata[3]; - sandata += 4; - - if (sanlen + 4 != subjectaltname->value->length) - { - log_print ("x509_cert_subjectaltname: subjectaltname invalid length"); - return 0; - } - - *len = sanlen; - *altname = sandata; - - return santype; + X509_EXTENSION *subjectaltname; + u_int8_t *sandata; + int extpos; + int santype, sanlen; + + extpos = X509_get_ext_by_NID(scert, NID_subject_alt_name, -1); + if (extpos == -1) { + log_print("x509_cert_subjectaltname: " + "certificate does not contain subjectAltName"); + return 0; + } + subjectaltname = X509_get_ext(scert, extpos); + + if (!subjectaltname || !subjectaltname->value || + !subjectaltname->value->data || subjectaltname->value->length < 4) { + log_print("x509_cert_subjectaltname: invalid subjectaltname extension"); + return 0; + } + /* SSL does not handle unknown ASN stuff well, do it by hand. */ + sandata = subjectaltname->value->data; + santype = sandata[2] & 0x3f; + sanlen = sandata[3]; + sandata += 4; + + if (sanlen + 4 != subjectaltname->value->length) { + log_print("x509_cert_subjectaltname: subjectaltname invalid length"); + return 0; + } + *len = sanlen; + *altname = sandata; + return santype; } int -x509_cert_get_subjects (void *scert, int *cnt, u_int8_t ***id, - u_int32_t **id_len) +x509_cert_get_subjects(void *scert, int *cnt, u_int8_t ***id, + u_int32_t **id_len) { - X509 *cert = scert; - X509_NAME *subject; - int type; - u_int8_t *altname; - u_int32_t altlen; - u_int8_t *buf = 0; - unsigned char *ubuf; - int i; - - *id = 0; - *id_len = 0; - - /* - * XXX There can be a collection of subjectAltNames, but for now - * I only return the subjectName and a single subjectAltName, if present. - */ - type = x509_cert_subjectaltname (cert, &altname, &altlen); - if (!type) - { - *cnt = 1; - altlen = 0; - } - else - *cnt = 2; - - *id = calloc (*cnt, sizeof **id); - if (!*id) - { - log_print ("x509_cert_get_subject: malloc (%lu) failed", - *cnt * (unsigned long)sizeof **id); - goto fail; - } - - *id_len = malloc (*cnt * sizeof **id_len); - if (!*id_len) - { - log_print ("x509_cert_get_subject: malloc (%lu) failed", - *cnt * (unsigned long)sizeof **id_len); - goto fail; - } - - /* Stash the subjectName into the first slot. */ - subject = X509_get_subject_name (cert); - if (!subject) - goto fail; - - (*id_len)[0] = - ISAKMP_ID_DATA_OFF + i2d_X509_NAME (subject, NULL) - ISAKMP_GEN_SZ; - (*id)[0] = malloc ((*id_len)[0]); - if (!(*id)[0]) - { - log_print ("x509_cert_get_subject: malloc (%d) failed", (*id_len)[0]); - goto fail; - } - SET_ISAKMP_ID_TYPE ((*id)[0] - ISAKMP_GEN_SZ, IPSEC_ID_DER_ASN1_DN); - ubuf = (*id)[0] + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; - i2d_X509_NAME (subject, &ubuf); - - if (altlen) - { - /* Stash the subjectAltName into the second slot. */ - buf = malloc (altlen + ISAKMP_ID_DATA_OFF); - if (!buf) - { - log_print ("x509_cert_get_subject: malloc (%d) failed", - altlen + ISAKMP_ID_DATA_OFF); - goto fail; + X509 *cert = scert; + X509_NAME *subject; + int type; + u_int8_t *altname; + u_int32_t altlen; + u_int8_t *buf = 0; + unsigned char *ubuf; + int i; + + *id = 0; + *id_len = 0; + + /* + * XXX There can be a collection of subjectAltNames, but for now + * I only return the subjectName and a single subjectAltName, if present. + */ + type = x509_cert_subjectaltname(cert, &altname, &altlen); + if (!type) { + *cnt = 1; + altlen = 0; + } else + *cnt = 2; + + *id = calloc(*cnt, sizeof **id); + if (!*id) { + log_print("x509_cert_get_subject: malloc (%lu) failed", + *cnt * (unsigned long) sizeof **id); + goto fail; } - - switch (type) - { - case X509v3_DNS_NAME: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_FQDN); - break; - - case X509v3_RFC_NAME: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_USER_FQDN); - break; - - case X509v3_IP_ADDR: - /* - * XXX I dislike the numeric constants, but I don't know what we - * should use otherwise. - */ - switch (altlen) - { - case 4: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR); - break; - - case 16: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV6_ADDR); - break; - - default: - log_print ("x509_cert_get_subject: " - "invalid subjectAltName IPaddress length %d ", altlen); - goto fail; - } - break; + *id_len = malloc(*cnt * sizeof **id_len); + if (!*id_len) { + log_print("x509_cert_get_subject: malloc (%lu) failed", + *cnt * (unsigned long) sizeof **id_len); + goto fail; } - - SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - memcpy (buf + ISAKMP_ID_DATA_OFF, altname, altlen); - - (*id_len)[1] = ISAKMP_ID_DATA_OFF + altlen - ISAKMP_GEN_SZ; - (*id)[1] = malloc ((*id_len)[1]); - if (!(*id)[1]) - { - log_print ("x509_cert_get_subject: malloc (%d) failed", - (*id_len)[1]); - goto fail; + /* Stash the subjectName into the first slot. */ + subject = X509_get_subject_name(cert); + if (!subject) + goto fail; + + (*id_len)[0] = + ISAKMP_ID_DATA_OFF + i2d_X509_NAME(subject, NULL) - ISAKMP_GEN_SZ; + (*id)[0] = malloc((*id_len)[0]); + if (!(*id)[0]) { + log_print("x509_cert_get_subject: malloc (%d) failed", (*id_len)[0]); + goto fail; + } + SET_ISAKMP_ID_TYPE((*id)[0] - ISAKMP_GEN_SZ, IPSEC_ID_DER_ASN1_DN); + ubuf = (*id)[0] + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + i2d_X509_NAME(subject, &ubuf); + + if (altlen) { + /* Stash the subjectAltName into the second slot. */ + buf = malloc(altlen + ISAKMP_ID_DATA_OFF); + if (!buf) { + log_print("x509_cert_get_subject: malloc (%d) failed", + altlen + ISAKMP_ID_DATA_OFF); + goto fail; + } + switch (type) { + case X509v3_DNS_NAME: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_FQDN); + break; + + case X509v3_RFC_NAME: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_USER_FQDN); + break; + + case X509v3_IP_ADDR: + /* + * XXX I dislike the numeric constants, but I don't know what we + * should use otherwise. + */ + switch (altlen) { + case 4: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV4_ADDR); + break; + + case 16: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV6_ADDR); + break; + + default: + log_print("x509_cert_get_subject: " + "invalid subjectAltName IPaddress length %d ", + altlen); + goto fail; + } + break; + } + + SET_IPSEC_ID_PROTO(buf + ISAKMP_ID_DOI_DATA_OFF, 0); + SET_IPSEC_ID_PORT(buf + ISAKMP_ID_DOI_DATA_OFF, 0); + memcpy(buf + ISAKMP_ID_DATA_OFF, altname, altlen); + + (*id_len)[1] = ISAKMP_ID_DATA_OFF + altlen - ISAKMP_GEN_SZ; + (*id)[1] = malloc((*id_len)[1]); + if (!(*id)[1]) { + log_print("x509_cert_get_subject: malloc (%d) failed", + (*id_len)[1]); + goto fail; + } + memcpy((*id)[1], buf + ISAKMP_GEN_SZ, (*id_len)[1]); + + free(buf); + buf = 0; } - memcpy ((*id)[1], buf + ISAKMP_GEN_SZ, (*id_len)[1]); - - free (buf); - buf = 0; - } - - return 1; - - fail: - for (i = 0; i < *cnt; i++) - if ((*id)[i]) - free ((*id)[i]); - if (*id) - free (*id); - if (*id_len) - free (*id_len); - if (buf) - free (buf); - return 0; + return 1; + +fail: + for (i = 0; i < *cnt; i++) + if ((*id)[i]) + free((*id)[i]); + if (*id) + free(*id); + if (*id_len) + free(*id_len); + if (buf) + free(buf); + return 0; } int -x509_cert_get_key (void *scert, void *keyp) +x509_cert_get_key(void *scert, void *keyp) { - X509 *cert = scert; - EVP_PKEY *key; + X509 *cert = scert; + EVP_PKEY *key; - key = X509_get_pubkey (cert); + key = X509_get_pubkey(cert); - /* Check if we got the right key type. */ - if (key->type != EVP_PKEY_RSA) - { - log_print ("x509_cert_get_key: public key is not a RSA key"); - X509_free (cert); - return 0; - } - - *(RSA **)keyp = RSAPublicKey_dup (key->pkey.rsa); + /* Check if we got the right key type. */ + if (key->type != EVP_PKEY_RSA) { + log_print("x509_cert_get_key: public key is not a RSA key"); + X509_free(cert); + return 0; + } + *(RSA **) keyp = RSAPublicKey_dup(key->pkey.rsa); - return *(RSA **)keyp == NULL ? 0 : 1; + return *(RSA **) keyp == NULL ? 0 : 1; } void * -x509_cert_dup (void *scert) +x509_cert_dup(void *scert) { - return X509_dup (scert); + return X509_dup(scert); } void -x509_serialize (void *scert, u_int8_t **data, u_int32_t *datalen) +x509_serialize(void *scert, u_int8_t **data, u_int32_t *datalen) { - u_int8_t *p; - - *datalen = i2d_X509 ((X509 *) scert, NULL); - *data = p = malloc (*datalen); - if (!p) - { - log_error ("x509_serialize: malloc (%d) failed", *datalen); - return; - } + u_int8_t *p; - *datalen = i2d_X509 ((X509 *)scert, &p); + *datalen = i2d_X509((X509 *) scert, NULL); + *data = p = malloc(*datalen); + if (!p) { + log_error("x509_serialize: malloc (%d) failed", *datalen); + return; + } + *datalen = i2d_X509((X509 *) scert, &p); } /* From cert to printable */ char * -x509_printable (void *cert) +x509_printable(void *cert) { - char *s; - u_int8_t *data; - u_int32_t datalen, i; - - x509_serialize (cert, &data, &datalen); - if (!data) - return 0; - - s = malloc (datalen * 2 + 1); - if (!s) - { - free (data); - log_error ("x509_printable: malloc (%d) failed", datalen * 2 + 1); - return 0; - } - - for (i = 0; i < datalen; i++) - snprintf (s + (2 * i), 2 * (datalen - i) + 1, "%02x", data[i]); - free (data); - return s; + char *s; + u_int8_t *data; + u_int32_t datalen, i; + + x509_serialize(cert, &data, &datalen); + if (!data) + return 0; + + s = malloc(datalen * 2 + 1); + if (!s) { + free(data); + log_error("x509_printable: malloc (%d) failed", datalen * 2 + 1); + return 0; + } + for (i = 0; i < datalen; i++) + snprintf(s + (2 * i), 2 * (datalen - i) + 1, "%02x", data[i]); + free(data); + return s; } /* From printable to cert */ void * -x509_from_printable (char *cert) +x509_from_printable(char *cert) { - u_int8_t *buf; - int plen, ret; - void *foo; - - plen = (strlen (cert) + 1) / 2; - buf = malloc (plen); - if (!buf) - { - log_error ("x509_from_printable: malloc (%d) failed", plen); - return 0; - } - - ret = hex2raw (cert, buf, plen); - if (ret == -1) - { - free (buf); - log_print ("x509_from_printable: badly formatted cert"); - return 0; - } - - foo = x509_cert_get (buf, plen); - free (buf); - if (!foo) - log_print ("x509_from_printable: could not retrieve certificate"); - return foo; + u_int8_t *buf; + int plen, ret; + void *foo; + + plen = (strlen(cert) + 1) / 2; + buf = malloc(plen); + if (!buf) { + log_error("x509_from_printable: malloc (%d) failed", plen); + return 0; + } + ret = hex2raw(cert, buf, plen); + if (ret == -1) { + free(buf); + log_print("x509_from_printable: badly formatted cert"); + return 0; + } + foo = x509_cert_get(buf, plen); + free(buf); + if (!foo) + log_print("x509_from_printable: could not retrieve certificate"); + return foo; } char * -x509_DN_string (u_int8_t *asn1, size_t sz) +x509_DN_string(u_int8_t *asn1, size_t sz) { - X509_NAME *name; - u_int8_t *p = asn1; - /* XXX Just a guess at a maximum length. */ - char buf[256]; - - name = d2i_X509_NAME (NULL, &p, sz); - if (!name) - { - log_print ("x509_DN_string: d2i_X509_NAME failed"); - return 0; - } - if (!X509_NAME_oneline (name, buf, sizeof buf - 1)) - { - log_print ("x509_DN_string: X509_NAME_oneline failed"); - X509_NAME_free (name); - return 0; - } - X509_NAME_free (name); - buf[sizeof buf - 1] = '\0'; - return strdup (buf); + X509_NAME *name; + u_int8_t *p = asn1; + /* XXX Just a guess at a maximum length. */ + char buf[256]; + + name = d2i_X509_NAME(NULL, &p, sz); + if (!name) { + log_print("x509_DN_string: d2i_X509_NAME failed"); + return 0; + } + if (!X509_NAME_oneline(name, buf, sizeof buf - 1)) { + log_print("x509_DN_string: X509_NAME_oneline failed"); + X509_NAME_free(name); + return 0; + } + X509_NAME_free(name); + buf[sizeof buf - 1] = '\0'; + return strdup(buf); } -#endif /* USE_X509 */ +#endif /* USE_X509 */ diff --git a/sbin/isakmpd/x509.h b/sbin/isakmpd/x509.h index c24e8c9c3d7..3ed64feff86 100644 --- a/sbin/isakmpd/x509.h +++ b/sbin/isakmpd/x509.h @@ -1,5 +1,5 @@ -/* $OpenBSD: x509.h,v 1.19 2003/11/06 16:12:08 ho Exp $ */ -/* $EOM: x509.h,v 1.11 2000/09/28 12:53:27 niklas Exp $ */ +/* $OpenBSD: x509.h,v 1.20 2004/04/15 18:39:27 deraadt Exp $ */ +/* $EOM: x509.h,v 1.11 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niels Provos. All rights reserved. @@ -41,8 +41,8 @@ #define X509v3_IP_ADDR 7 struct x509_attribval { - char *type; - char *val; + char *type; + char *val; }; /* @@ -51,8 +51,8 @@ struct x509_attribval { * be dynamic but we don't care for now. */ struct x509_aca { - struct x509_attribval name1; - struct x509_attribval name2; + struct x509_attribval name1; + struct x509_attribval name2; }; struct X509; @@ -60,30 +60,30 @@ struct X509_STORE; /* Functions provided by cert handler. */ -int x509_certreq_validate (u_int8_t *, u_int32_t); -void *x509_certreq_decode (u_int8_t *, u_int32_t); -void x509_cert_free (void *); -void *x509_cert_get (u_int8_t *, u_int32_t); -int x509_cert_get_key (void *, void *); -int x509_cert_get_subjects (void *, int *, u_int8_t ***, u_int32_t **); -int x509_cert_init (void); -int x509_crl_init (void); -int x509_cert_obtain (u_int8_t *, size_t, void *, u_int8_t **, u_int32_t *); -int x509_cert_validate (void *); -void x509_free_aca (void *); -void *x509_cert_dup (void *); -void x509_serialize (void *, u_int8_t **, u_int32_t *); -char *x509_printable (void *); -void *x509_from_printable (char *); +int x509_certreq_validate(u_int8_t *, u_int32_t); +void *x509_certreq_decode(u_int8_t *, u_int32_t); +void x509_cert_free(void *); +void *x509_cert_get(u_int8_t *, u_int32_t); +int x509_cert_get_key(void *, void *); +int x509_cert_get_subjects(void *, int *, u_int8_t ***, u_int32_t **); +int x509_cert_init(void); +int x509_crl_init(void); +int x509_cert_obtain(u_int8_t *, size_t, void *, u_int8_t **, u_int32_t *); +int x509_cert_validate(void *); +void x509_free_aca(void *); +void *x509_cert_dup(void *); +void x509_serialize(void *, u_int8_t **, u_int32_t *); +char *x509_printable(void *); +void *x509_from_printable(char *); /* Misc. X509 certificate functions. */ -char *x509_DN_string (u_int8_t *, size_t); -int x509_cert_insert (int, void *); -int x509_cert_subjectaltname (X509 *cert, u_char **, u_int *); -X509 *x509_from_asn (u_char *, u_int); -int x509_generate_kn (int, X509 *); -int x509_read_from_dir (X509_STORE *, char *, int); -int x509_read_crls_from_dir (X509_STORE *, char *); +char *x509_DN_string(u_int8_t *, size_t); +int x509_cert_insert(int, void *); +int x509_cert_subjectaltname(X509 * cert, u_char **, u_int *); +X509 *x509_from_asn(u_char *, u_int); +int x509_generate_kn(int, X509 *); +int x509_read_from_dir(X509_STORE *, char *, int); +int x509_read_crls_from_dir(X509_STORE *, char *); -#endif /* _X509_H_ */ +#endif /* _X509_H_ */ |