diff options
author | Niels Provos <provos@cvs.openbsd.org> | 1998-03-04 11:43:56 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 1998-03-04 11:43:56 +0000 |
commit | 4be2eb12506cf065e68c51750f45f81ba3d63717 (patch) | |
tree | b4cb6a032a89a159e425ace730b3bda6a7b1c25f /sbin | |
parent | 8b1bb75ad56e072dc58c33715385fa7e439b2503 (diff) |
compliance with draft-simpson-photuris-18.txt, better packet structure
checking, better support for new esp and ah, documentation ...
Diffstat (limited to 'sbin')
37 files changed, 1515 insertions, 744 deletions
diff --git a/sbin/ipsec/photurisd/INSTALL b/sbin/ipsec/photurisd/INSTALL index b86c90058e9..a43abf7b6c8 100644 --- a/sbin/ipsec/photurisd/INSTALL +++ b/sbin/ipsec/photurisd/INSTALL @@ -14,7 +14,7 @@ add -DIPSEC to the CFLAGS. Run make. After starting the photurisd on two machines, you can start the program -startkey <ip-number-of-the-other-machine> to start a key exchange. +startkey dst=<ip-number-of-the-other-machine> to start a key exchange. For the daemon to work with other IPSec implementations you should look in the sources for #ifdef IPSEC. diff --git a/sbin/ipsec/photurisd/README b/sbin/ipsec/photurisd/README index d77f1f9d03c..59f7880e55e 100644 --- a/sbin/ipsec/photurisd/README +++ b/sbin/ipsec/photurisd/README @@ -1,7 +1,7 @@ This is an implementation of the Photuris keymanagement protocol according to the drafts: - draft-simpson-photuris-12.txt - draft-simpson-photuris-schemes-01.txt + draft-simpson-photuris-18.txt + draft-simpson-photuris-schemes-04.txt For quick installation instructions read INSTALL, or otherwise README.howtouse for more complete information. diff --git a/sbin/ipsec/photurisd/README.howtouse b/sbin/ipsec/photurisd/README.howtouse index 9e14f4bd67a..49c0c819741 100644 --- a/sbin/ipsec/photurisd/README.howtouse +++ b/sbin/ipsec/photurisd/README.howtouse @@ -34,7 +34,7 @@ How to get it working ? happens, or remove -DIPSEC if you dont want to actually setup encrypted and authenticated connections within the kernel) 6. start ./photurid on two hosts. -7. ./startkey host1 (for example ./startkey 134.100.33.22) +7. ./startkey dst=host1 (for example ./startkey dst=134.100.33.22) If you compiled the photuris daemon with -DDEBUG you should see an exchange of values now and finally the shared secret from which the @@ -58,7 +58,7 @@ How to get it working ? Add the following two lines into your kernel config file: config IPSEC -pseudo-device enc 4 +pseudo-device enc 1 Possible configuration diff --git a/sbin/ipsec/photurisd/api.c b/sbin/ipsec/photurisd/api.c index fde4257a3d8..b60382d6c78 100644 --- a/sbin/ipsec/photurisd/api.c +++ b/sbin/ipsec/photurisd/api.c @@ -37,7 +37,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: api.c,v 1.3 1997/09/14 10:37:48 deraadt Exp $"; +static char rcsid[] = "$Id: api.c,v 1.4 1998/03/04 11:43:07 provos Exp $"; #endif #define _API_C_ @@ -95,6 +95,7 @@ process_api(int fd, int sendsock) startup_parse(st, buffer); +#ifndef DEBUG if (addresses != (char **) NULL && strlen(st->address)) for (i = 0; i<num_ifs; i++) { if (addresses[i] == (char *)NULL) @@ -107,6 +108,7 @@ process_api(int fd, int sendsock) return; } } +#endif startup_end(st); diff --git a/sbin/ipsec/photurisd/attributes.c b/sbin/ipsec/photurisd/attributes.c index 28052e6d3cf..bc3e84b347d 100644 --- a/sbin/ipsec/photurisd/attributes.c +++ b/sbin/ipsec/photurisd/attributes.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: attributes.c,v 1.2 1997/07/19 12:07:40 provos Exp $"; +static char rcsid[] = "$Id: attributes.c,v 1.3 1998/03/04 11:43:08 provos Exp $"; #endif #define _ATTRIBUTES_C_ @@ -47,7 +47,44 @@ static char rcsid[] = "$Id: attributes.c,v 1.2 1997/07/19 12:07:40 provos Exp $" #include "config.h" #include "attributes.h" -static struct attribute_list *attribob = NULL; +static attribute_list *attribob = NULL; +static attrib_t *attribhash[ATTRIBHASHMOD]; + +/* Put or get attribute properties from the hashtable */ + +void +putattrib(attrib_t *attrib) +{ + int hashval = attrib->id % ATTRIBHASHMOD; + attrib->next = attribhash[hashval]; + attribhash[hashval] = attrib; +} + +attrib_t * +getattrib(int id) +{ + int hashval = id % ATTRIBHASHMOD; + attrib_t *attrib; + + for(attrib=attribhash[hashval]; attrib; attrib = attrib->next) + if (attrib->id == id) + break; + + return attrib; +} + +void +clearattrib(void) +{ + int i; + attrib_t *attrib; + + for (i=0; i<ATTRIBHASHMOD; i++) + while ((attrib=attribhash[i]) != NULL) { + attribhash[i] = attrib->next; + free(attrib); + } +} int isinattrib(u_int8_t *attributes, u_int16_t attribsize, u_int8_t attribute) @@ -64,6 +101,41 @@ isinattrib(u_int8_t *attributes, u_int16_t attribsize, u_int8_t attribute) return 0; } +void +get_attrib_section(u_int8_t *set, u_int16_t setsize, + u_int8_t **subset, u_int16_t *subsetsize, + u_int8_t section) +{ + int i = 0; + u_int8_t *tset; + u_int16_t tsetsize; + + while (i < setsize) { + if (set[i] == section) + break; + i += set[i+1] + 2; + } + + if ((i >= setsize) || (i+set[i+1] + 2 > setsize)) { + *subset = NULL; + *subsetsize = 0; + return; + } + + tset = *subset = set+i+set[i+1]+2; + tsetsize = *subsetsize = setsize - i - set[i+1] - 2; + + i = 0; + while (i < tsetsize) { + if (tset[i] == AT_ESP_ATTRIB || tset[i] == AT_AH_ATTRIB) { + *subsetsize = i; + return; + } + i += tset[i+1]+2; + } +} + + int isattribsubset(u_int8_t *set, u_int16_t setsize, u_int8_t *subset, u_int16_t subsetsize) @@ -80,9 +152,9 @@ isattribsubset(u_int8_t *set, u_int16_t setsize, } int -attrib_insert(struct attribute_list *ob) +attrib_insert(attribute_list *ob) { - struct attribute_list *tmp; + attribute_list *tmp; ob->next = NULL; @@ -100,9 +172,9 @@ attrib_insert(struct attribute_list *ob) } int -attrib_unlink(struct attribute_list *ob) +attrib_unlink(attribute_list *ob) { - struct attribute_list *tmp; + attribute_list *tmp; if(attribob == ob) { attribob = ob->next; free(ob); @@ -119,26 +191,26 @@ attrib_unlink(struct attribute_list *ob) return 0; } -struct attribute_list * +attribute_list * attrib_new(void) { - struct attribute_list *p; + attribute_list *p; - if((p = calloc(1, sizeof(struct attribute_list)))==NULL) + if((p = calloc(1, sizeof(attribute_list)))==NULL) return NULL; return p; } int -attrib_value_reset(struct attribute_list *ob) +attrib_value_reset(attribute_list *ob) { if (ob->address != NULL) free(ob->address); if (ob->attributes != NULL) free(ob->attributes); - bzero(ob, sizeof(struct attribute_list)); + bzero(ob, sizeof(attribute_list)); return 1; } @@ -148,11 +220,11 @@ attrib_value_reset(struct attribute_list *ob) * list. */ -struct attribute_list * +attribute_list * attrib_find(char *address) { - struct attribute_list *tmp = attribob; - struct attribute_list *null = NULL; + attribute_list *tmp = attribob; + attribute_list *null = NULL; while(tmp!=NULL) { if (tmp->address == NULL) { null = tmp; @@ -172,8 +244,8 @@ attrib_find(char *address) void attrib_cleanup() { - struct attribute_list *p; - struct attribute_list *tmp = attribob; + attribute_list *p; + attribute_list *tmp = attribob; while(tmp!=NULL) { p = tmp; tmp = tmp->next; diff --git a/sbin/ipsec/photurisd/attributes.h b/sbin/ipsec/photurisd/attributes.h index aaafd307eee..93bc01dc552 100644 --- a/sbin/ipsec/photurisd/attributes.h +++ b/sbin/ipsec/photurisd/attributes.h @@ -42,18 +42,13 @@ #define EXTERN extern #endif -#define AT_PAD 0 -#define AT_AH_ATTRIB 1 -#define AT_ESP_ATTRIB 2 -#define AT_MD5_DP 3 -#define AT_SHA1_DP 4 -#define AT_MD5_KDP 5 -#define AT_SHA1_KDP 6 -#define AT_DES_CBC 8 -#define AT_ORG 255 +#define AT_ID 1 +#define AT_ENC 2 +#define AT_AUTH 4 -#define MD5_KEYLEN 384 -#define DES_KEYLEN 64 +#define AT_PAD 0 +#define AT_AH_ATTRIB 1 +#define AT_ESP_ATTRIB 2 /* XXX - Only for the moment */ #define DH_G_2_MD5 2 @@ -69,23 +64,40 @@ #define DH_G_5_3DES_SHA1 20 #define DH_G_VAR_3DES_SHA1 28 -struct attribute_list { - struct attribute_list *next; +typedef struct _attribute_list { + struct _attribute_list *next; char *address; in_addr_t netmask; u_int8_t *attributes; u_int16_t attribsize; -}; +} attribute_list; + +typedef struct _attrib_t { + struct _attrib_t *next; + int id; /* Photuris Attribute ID */ + int koff; /* Offset into kernel data structure */ + int type; /* Type of attribute: ident, enc, auth */ + int klen; /* required key length */ +} attrib_t; + +#define ATTRIBHASHMOD 17 + +EXTERN void putattrib(attrib_t *attrib); +EXTERN attrib_t *getattrib(int id); +EXTERN void clearattrib(void); + +EXTERN void get_attrib_section(u_int8_t *, u_int16_t, u_int8_t **, u_int16_t *, + u_int8_t); EXTERN int isinattrib(u_int8_t *attributes, u_int16_t attribsize, u_int8_t attribute); EXTERN int isattribsubset(u_int8_t *set, u_int16_t setsize, u_int8_t *subset, u_int16_t subsetsize); -EXTERN struct attribute_list *attrib_new(void); -EXTERN int attrib_insert(struct attribute_list *); -EXTERN int attrib_unlink(struct attribute_list *); -EXTERN int attrib_value_reset(struct attribute_list *); -EXTERN struct attribute_list *attrib_find(char *); +EXTERN attribute_list *attrib_new(void); +EXTERN int attrib_insert(attribute_list *); +EXTERN int attrib_unlink(attribute_list *); +EXTERN int attrib_value_reset(attribute_list *); +EXTERN attribute_list *attrib_find(char *); EXTERN void attrib_cleanup(void); #endif /* ATTRIBUTES_H */ diff --git a/sbin/ipsec/photurisd/buffer.c b/sbin/ipsec/photurisd/buffer.c index 5794e28118f..afc3a22d383 100644 --- a/sbin/ipsec/photurisd/buffer.c +++ b/sbin/ipsec/photurisd/buffer.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: buffer.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +static char rcsid[] = "$Id: buffer.c,v 1.2 1998/03/04 11:43:11 provos Exp $"; #endif #include <sys/types.h> @@ -42,5 +42,5 @@ static char rcsid[] = "$Id: buffer.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; #include "buffer.h" int packet_size; -char buffer[BUFFER_SIZE]; -char packet_buffer[PACKET_BUFFER_SIZE]; +u_char buffer[BUFFER_SIZE]; +u_char packet_buffer[PACKET_BUFFER_SIZE]; diff --git a/sbin/ipsec/photurisd/buffer.h b/sbin/ipsec/photurisd/buffer.h index fa4eaf34bff..e208582b353 100644 --- a/sbin/ipsec/photurisd/buffer.h +++ b/sbin/ipsec/photurisd/buffer.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: buffer.h,v 1.1 1997/07/18 22:48:51 provos Exp $ */ +/* $Id: buffer.h,v 1.2 1998/03/04 11:43:12 provos Exp $ */ /* * buffer.h: * variables with buffers. @@ -40,8 +40,8 @@ #define BUFFER_SIZE 8192 #ifndef _BUFFER_C -extern char buffer[]; -extern char packet_buffer[]; +extern u_char buffer[]; +extern u_char packet_buffer[]; extern int packet_size; #endif diff --git a/sbin/ipsec/photurisd/compute_secrets.c b/sbin/ipsec/photurisd/compute_secrets.c index f52feae8110..a2e5a3294e8 100644 --- a/sbin/ipsec/photurisd/compute_secrets.c +++ b/sbin/ipsec/photurisd/compute_secrets.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: compute_secrets.c,v 1.4 1997/09/02 17:26:35 provos Exp $"; +static char rcsid[] = "$Id: compute_secrets.c,v 1.5 1998/03/04 11:43:14 provos Exp $"; #endif #define _SECRETS_C_ @@ -62,12 +62,13 @@ static char rcsid[] = "$Id: compute_secrets.c,v 1.4 1997/09/02 17:26:35 provos E #include "errlog.h" int privacykey(struct stateob *st, struct idxform *hash, u_int8_t *key, - u_int8_t *packet, u_int16_t bytes, u_int16_t order, int owner); + u_int8_t *packet, u_int16_t bytes, u_int16_t *order, int owner); int compute_shared_secret(struct stateob *st, u_int8_t **shared, u_int16_t *sharedsize) { struct moduli_cache *mod; + int header; mpz_t tmp, bits, tex; @@ -94,11 +95,21 @@ compute_shared_secret(struct stateob *st, mpz_clear(bits); mpz_clear(tmp); + /* The shared secret is not used with the size part */ + if (buffer[0] == 255 && buffer[1] == 255) + header = 8; + else if (buffer[0] == 255) + header = 4; + else + header = 2; + + *sharedsize -= header; + if((*shared = calloc(*sharedsize,sizeof(u_int8_t))) == NULL) { log_error(0, "Not enough memory for shared secret in compute_shared_secret()"); return -1; } - bcopy(buffer, *shared, *sharedsize); + bcopy(buffer+header, *shared, *sharedsize); return 0; } @@ -167,20 +178,23 @@ make_session_keys(struct stateob *st, struct spiob *spi) return 0; } +/* + * Return length of requried session key in bits. + * DES would be 64 bits. + */ int get_session_key_length(u_int8_t *attribute) { - switch(*attribute) { - case AT_MD5_KDP: - return MD5_KEYLEN; - case AT_DES_CBC: - return DES_KEYLEN; - default: + attrib_t *ob; + + if ((ob = getattrib(*attribute)) == NULL) { log_error(0, "Unknown attribute %d in get_session_key_length()", *attribute); return -1; } + + return ob->klen << 3; } /* @@ -197,7 +211,7 @@ compute_session_key(struct stateob *st, u_int8_t *key, struct idxform *hash; u_int16_t size, i, n; u_int8_t digest[HASH_MAX]; - int bits, hbits; + int bits; switch(ntohs(*((u_int16_t *)st->scheme))) { case DH_G_2_MD5: @@ -230,11 +244,8 @@ compute_session_key(struct stateob *st, u_int8_t *key, if(bits & 0x7) size++; - hbits = (hash->hashsize << 3); - *order += (*order%hbits) ? hbits - (*order%hbits) : 0; - /* As many shared secrets we used already */ - n = *order/hbits; + n = *order; hash->Init(hash->ctx); hash->Update(hash->ctx, st->icookie, COOKIE_SIZE); @@ -259,6 +270,9 @@ compute_session_key(struct stateob *st, u_int8_t *key, bcopy(hash->ctx2, hash->ctx, hash->ctxsize); hash->Final(digest, hash->ctx2); + /* One iteration more */ + n++; + bcopy(digest, key, size>hash->hashsize ? hash->hashsize : size); key += size>hash->hashsize ? hash->hashsize : size; @@ -266,7 +280,7 @@ compute_session_key(struct stateob *st, u_int8_t *key, size -= size>hash->hashsize ? hash->hashsize : size; } while(size > 0); - *order += bits + (bits%hbits ? hbits - (bits%hbits) : 0 ); + *order = n; return bits; } @@ -333,12 +347,12 @@ init_privacy_key(struct stateob *st, int owner) } /* - * order gives the number of bits already used for keys + * order gives the number of iterations already done for keys */ int compute_privacy_key(struct stateob *st, u_int8_t *key, u_int8_t *packet, - u_int16_t bits, u_int16_t order, int owner) + u_int16_t bits, u_int16_t *order, int owner) { u_int16_t size; struct idxform *hash; @@ -376,9 +390,9 @@ compute_privacy_key(struct stateob *st, u_int8_t *key, u_int8_t *packet, int privacykey(struct stateob *st, struct idxform *hash, u_int8_t *key, u_int8_t *packet, - u_int16_t bytes, u_int16_t order, int owner) + u_int16_t bytes, u_int16_t *order, int owner) { - u_int16_t i, n, hbits; + u_int16_t i, n; u_int8_t digest[HASH_MAX]; /* SPIprivacyctx contains the hashed exchangevalues */ @@ -388,8 +402,7 @@ privacykey(struct stateob *st, struct idxform *hash, hash->Update(hash->ctx2, packet, 2*COOKIE_SIZE + 4 + SPI_SIZE); /* As many shared secrets we used already */ - hbits = (hash->hashsize << 3); - n = order/hbits + (order%hbits ? 1 : 0); + n = *order; for(i=0; i<n; i++) hash->Update(hash->ctx2, st->shared, st->sharedsize); @@ -404,8 +417,12 @@ privacykey(struct stateob *st, struct idxform *hash, /* Unsigned integer arithmetic */ bytes -= bytes>hash->hashsize ? hash->hashsize : bytes; + + /* Increment the times we called Final */ + i++; } while(bytes > 0); + *order = i; return 0; } diff --git a/sbin/ipsec/photurisd/config.c b/sbin/ipsec/photurisd/config.c index d3a24512921..1dbd1c02c4a 100644 --- a/sbin/ipsec/photurisd/config.c +++ b/sbin/ipsec/photurisd/config.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: config.c,v 1.5 1997/09/14 10:37:49 deraadt Exp $"; +static char rcsid[] = "$Id: config.c,v 1.6 1998/03/04 11:43:15 provos Exp $"; #endif #define _CONFIG_C_ @@ -68,9 +68,13 @@ static char rcsid[] = "$Id: config.c,v 1.5 1997/09/14 10:37:49 deraadt Exp $"; #include "buffer.h" #include "scheme.h" #include "api.h" +#ifdef IPSEC +#include "kernel.h" +#endif static FILE *config_fp; +static struct cfgx *cfgxroot; static void open_config_file(char *file) @@ -120,18 +124,93 @@ config_get(char *token) } int +cfgx_insert(char *name, int id) +{ + struct cfgx *ob; + + if ((ob = malloc(sizeof(struct cfgx))) == NULL) + return -1; + + ob->name = strdup(name); + ob->id = id; + + ob->next = cfgxroot; + cfgxroot = ob; + + return 0; +} + +struct cfgx * +cfgx_get(char *name) +{ + struct cfgx *ob; + + for(ob = cfgxroot; ob; ob = ob->next) + if (ob->name && !strcmp(name, ob->name)) + break; + + return ob; +} + +void +cfgx_clear(void) +{ + struct cfgx *ob; + while(cfgxroot) { + ob = cfgxroot; + cfgxroot = cfgxroot->next; + free(ob); + } +} + +/* + * Parses the type of an attribute: ident|enc|auth. + */ + +int +parse_type(char *line) +{ + + int type = 0; + while (*line) { + if (!strncmp(line, "ident", 5)) { + type |= AT_ID; + line += 5; + } else if (!strncmp(line, "enc", 3)) { + type |= AT_ENC; + line += 3; + } else if (!strncmp(line, "auth", 4)) { + type |= AT_AUTH; + line += 4; + } else + return -1; + while (isspace(*line)) + line++; + if (*line && *line++ != '|') + return -1; + } + + return type; +} + +int init_attributes(void) { char *p, *p2; - struct attribute_list *ob = NULL; + attribute_list *ob = NULL; struct in_addr in; - int def_flag = 0; + int i, def_flag = 0; char attrib[257]; + struct cfgx *cfgattrib = NULL; #ifdef DEBUG printf("[Setting up attributes]\n"); #endif + /* Set up attribute delimeter */ + cfgx_insert("AT_AH_ATTRIB", AT_AH_ATTRIB); + cfgx_insert("AT_ESP_ATTRIB", AT_ESP_ATTRIB); + open_config_file(attrib_file); while((p2 = config_get("")) != NULL) { p = strsep(&p2, " "); @@ -141,35 +220,84 @@ init_attributes(void) if (p2 == NULL || inet_addr(p) == -1 || inet_network(p2) == -1) { /* Attributes follow now */ - if (ob == NULL && (ob = attrib_new()) == NULL) - crit_error(1, "attribute_new() in init_attributes()"); - else - def_flag = 1; + cfgattrib = cfgx_get(p); + if (cfgattrib == NULL && strchr(p, ',') != NULL) { + char *name, *p3, *p4; + attrib_t tmpatt, *ob; + + p4 = p; + + if (p2 != NULL) + p4[strlen(p4)] = ' '; + + name = strsep(&p4, ","); + while (isspace(*name)) + name++; + i = strlen(name) - 1; + while (isspace(name[i]) && i > 0) + name[i--] = 0; + + if ((p2 = strsep(&p4, ",")) == NULL || + (p3 = strsep(&p4, ",")) == NULL) { + log_error(0, "Mal formated attribute definition for %s in init_attributess()", name); + continue; + } + + if ((tmpatt.id = atoi(p2)) <= 0) { + log_error(0, "Bad id %s for %s in init_attributes()", p2, name); + continue; + } + + if ((tmpatt.klen = atoi(p4)) < 0) { + log_error(0, "Bad key length %s for %s in init_attributes()", p4, name); + continue; + } + + while (isspace(*p3)) + p3++; + i = strlen(p3) - 1; + while (isspace(p3[i]) && i > 0) + p3[i--] = 0; + + if ((tmpatt.type = parse_type(p3)) == -1) { + log_error(0, "Unkown attribute type %s for %s in init_attributes()", p3, name); + continue; + } + +#ifdef IPSEC + if ((tmpatt.type & ~AT_ID) && + (tmpatt.koff = kernel_get_offset(tmpatt.id)) == -1) { + log_error(0, "Attribute %s not supported by kernel in init_attributes()", name); + continue; + } +#endif + + if ((ob = calloc(1, sizeof(attrib_t))) == NULL) + crit_error(1, "calloc() in init_attributes()"); + + *ob = tmpatt; + putattrib(ob); + cfgx_insert(name, ob->id); + cfgattrib = cfgx_get(name); +#ifdef DEBUG + printf("New attribute: %s, id: %d, type: %d, klen: %d\n", name, ob->id, ob->type, ob->klen); +#endif + } - if (!strcmp(p, "AT_AH_ATTRIB")) { - attrib[0] = AT_AH_ATTRIB; - attrib[1] = 0; - } else if (!strcmp(p, "AT_ESP_ATTRIB")) { - attrib[0] = AT_ESP_ATTRIB; - attrib[1] = 0; - } else if (!strcmp(p, "AT_MD5_DP")) { - attrib[0] = AT_MD5_DP; - attrib[1] = 0; - } else if (!strcmp(p, "AT_SHA1_DP")) { - attrib[0] = AT_SHA1_DP; - attrib[1] = 0; - } else if (!strcmp(p, "AT_MD5_KDP")) { - attrib[0] = AT_MD5_KDP; - attrib[1] = 0; - } else if (!strcmp(p, "AT_DES_CBC")) { - attrib[0] = AT_DES_CBC; - attrib[1] = 0; - } else { + if (cfgattrib == NULL) { log_error(0, "Unknown attribute %s in init_attributes()", p); continue; } + if (ob == NULL && (ob = attrib_new()) == NULL) + crit_error(1, "attribute_new() in init_attributes()"); + else + def_flag = 1; + + attrib[0] = cfgattrib->id; + attrib[1] = 0; + /* Copy attributes in object */ ob->attributes = realloc(ob->attributes, ob->attribsize + attrib[1] +2); @@ -209,6 +337,8 @@ init_attributes(void) if (!def_flag) crit_error(0, "No default attribute list in init_attributes()"); + + cfgx_clear(); return 1; } @@ -444,7 +574,7 @@ startup_parse(struct stateob *st, char *p2) char *p, *p3; struct hostent *hp; - while((p=strsep(&p2, " ")) != NULL) { + while((p=strsep(&p2, " ")) != NULL && strlen(p)) { if ((p3 = strchr(p, '=')) == NULL) { log_error(0, "missing = in %s in startup_parse()", p); continue; @@ -629,7 +759,9 @@ reconfig(int sig) { log_error(0, "Reconfiguring on SIGHUP"); - attrib_cleanup(); + clearattrib(); /* Clear attribute id hash */ + attrib_cleanup(); /* Clear list of offered attributes */ + identity_cleanup(NULL); mod_cleanup(); @@ -763,7 +895,7 @@ pick_scheme(u_int8_t **scheme, u_int16_t *schemesize, int pick_attrib(struct stateob *st, u_int8_t **attrib, u_int16_t *attribsize) { - struct attribute_list *ob; + attribute_list *ob; int mode = 0, i, n, count, first; if ((ob = attrib_find(st->address)) == NULL) { @@ -807,6 +939,154 @@ pick_attrib(struct stateob *st, u_int8_t **attrib, u_int16_t *attribsize) /* + * Select attributes we actually want to use for the SA. + */ + +int +select_attrib(struct stateob *st, u_int8_t **attributes, u_int16_t *attribsize) +{ + u_int16_t count = 0; + u_int8_t *wantesp, *wantah, *offeresp, *offerah, *p; + u_int16_t wantespsize, wantahsize, offerespsize, offerahsize; + attribute_list *ob; + attrib_t *attprop; + + if ((ob = attrib_find(NULL)) == NULL) { + log_error(0, "attrib_find() for default in select_attrib() in " + "exchange to %s", st->address); + return -1; + } + + /* Take from Owner */ + get_attrib_section(ob->attributes, ob->attribsize, + &wantesp, &wantespsize, AT_ESP_ATTRIB); + get_attrib_section(ob->attributes, ob->attribsize, + &wantah, &wantahsize, AT_AH_ATTRIB); + + + /* Take from User */ + get_attrib_section(st->uSPIoattrib, st->uSPIoattribsize, + &offeresp, &offerespsize, AT_ESP_ATTRIB); + get_attrib_section(st->uSPIoattrib, st->uSPIoattribsize, + &offerah, &offerahsize, AT_AH_ATTRIB); + + p = buffer; + if (wantesp != NULL && offeresp != NULL && (st->flags & IPSEC_OPT_ENC)) { + /* Take the ESP section */ + char *tp = wantesp, *ta = wantesp; + u_int16_t tpsize = 0, tasize = 0; + int res; + attrib_t *attah = NULL; + + attprop = NULL; + /* We travers the ESP section and look for the first ENC attribute */ + while (tpsize < wantespsize) { + if (isinattrib(offeresp, offerespsize, tp[tpsize])) { + attprop = getattrib(tp[tpsize]); + if (attprop != NULL && attprop->type == AT_ENC) + break; + } + tpsize += tp[tpsize+1]+2; + } + if (tpsize >= wantespsize) + attprop = NULL; + + /* If we find a fitting AH, we take it */ + while (attprop != NULL && tasize < wantespsize) { + if (isinattrib(offeresp, offerespsize, ta[tasize])) { + attah = getattrib(ta[tasize]); + if (attah != NULL && (attah->type & AT_AUTH)) { +#ifdef IPSEC + res = kernel_valid(attprop->koff, attah->koff); +#else + res = 0; +#endif + if (res == AT_ENC) { + /* + * Our ESP attribute does not allow AH, but + * since the ESP attribute is our first choice, + * dont try for other. + */ + attah = NULL; + break; + } else if (res != AT_AUTH) + break; + } + } + + tasize += ta[tasize+1]+2; + } + if (tasize >= wantespsize) + attah = NULL; + + if (attprop != NULL) { + /* Put proper header in there */ + p[0] = AT_ESP_ATTRIB; + p[1] = 0; + count += 2; + p += 2; + + /* We are using our own attributes, safe to proceed */ + bcopy(wantesp+tpsize, p, wantesp[tpsize+1] + 2); + count += wantesp[tpsize+1] + 2; + p += wantesp[tpsize+1] + 2; + + if (attah != NULL) { + /* We are using our own attributes, safe to proceed */ + bcopy(wantesp+tasize, p, wantesp[tasize+1] + 2); + count += wantesp[tasize+1] + 2; + p += wantesp[tasize+1] + 2; + } + } + } + + if (wantah != NULL && offerah != NULL && (st->flags & IPSEC_OPT_AUTH)) { + /* Take the AH section */ + u_int8_t *tp = wantah; + u_int16_t tpsize = 0; + + attprop = NULL; + /* We travers the AH section and look for the first AH attribute */ + while (tpsize < wantahsize) { + if (isinattrib(offerah, offerahsize, tp[tpsize])) { + attprop = getattrib(tp[tpsize]); + if (attprop != NULL && (attprop->type & AT_AUTH)) + break; + } + tpsize += tp[tpsize+1]+2; + } + if (tpsize >= wantahsize) + attprop = NULL; + + if (attprop != NULL) { + /* Put proper header in there */ + p[0] = AT_AH_ATTRIB; + p[1] = 0; + count += 2; + p += 2; + + /* We are using our own attributes, safe to proceed */ + bcopy(wantah+tpsize, p, wantah[tpsize+1] + 2); + count += wantah[tpsize+1] + 2; + p += wantah[tpsize+1] + 2; + } + } + + if (count == 0) { + log_error(0, "Offered and wanted list of attributes did not have a common subset in select_attrib()"); + return -1; + } + + if ((*attributes=calloc(count,sizeof(u_int8_t))) == NULL) { + log_error(1, "Out of memory for SPI attributes (%d)", count); + return -1; + } + *attribsize = count; + bcopy(buffer, *attributes, count); + + return 0; +} +/* * Removes whitespace from the end of a string */ diff --git a/sbin/ipsec/photurisd/config.h b/sbin/ipsec/photurisd/config.h index 5f54072e229..6f0dbfe8244 100644 --- a/sbin/ipsec/photurisd/config.h +++ b/sbin/ipsec/photurisd/config.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: config.h,v 1.3 1997/07/23 12:28:47 provos Exp $ */ +/* $Id: config.h,v 1.4 1998/03/04 11:43:17 provos Exp $ */ /* * config.h: * handling config @@ -99,6 +99,12 @@ void reconfig(int sig); #define OPT_TSRC "tsrc" #define OPT_TDST "tdst" +struct cfgx { + struct cfgx *next; + char *name; + int id; +}; + EXTERN int bin2hex(char *, int *, u_int8_t *, u_int16_t); EXTERN char *chomp(char *); @@ -113,6 +119,7 @@ EXTERN int init_signals(void); EXTERN int pick_scheme(u_int8_t **, u_int16_t *, u_int8_t *, u_int16_t); EXTERN int pick_attrib(struct stateob *, u_int8_t **, u_int16_t *); +EXTERN int select_attrib(struct stateob *, u_int8_t **, u_int16_t *); #endif /* _CONFIG_H_ */ diff --git a/sbin/ipsec/photurisd/encrypt.h b/sbin/ipsec/photurisd/encrypt.h index a9f8e99bade..5da050a1a8e 100644 --- a/sbin/ipsec/photurisd/encrypt.h +++ b/sbin/ipsec/photurisd/encrypt.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: encrypt.h,v 1.1 1997/07/18 22:48:48 provos Exp $ */ +/* $Id: encrypt.h,v 1.2 1998/03/04 11:43:18 provos Exp $ */ /* * encrypt.h: * prototypes for photuris_packet_encrypt.c @@ -46,8 +46,6 @@ #define EXTERN extern #endif -EXTERN int packet_make_iv(u_int32_t *iv, u_int32_t *packet); - EXTERN int packet_create_padding(struct stateob *st, u_int16_t size, u_int8_t *padd, u_int16_t *rsize); EXTERN int packet_encrypt(struct stateob *st, diff --git a/sbin/ipsec/photurisd/handle_identity_request.c b/sbin/ipsec/photurisd/handle_identity_request.c index 73ac171827a..fee093ad3e5 100644 --- a/sbin/ipsec/photurisd/handle_identity_request.c +++ b/sbin/ipsec/photurisd/handle_identity_request.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_identity_request.c,v 1.4 1997/09/02 17:26:36 provos Exp $"; +static char rcsid[] = "$Id: handle_identity_request.c,v 1.5 1998/03/04 11:43:20 provos Exp $"; #endif #include <stdio.h> @@ -55,19 +55,37 @@ static char rcsid[] = "$Id: handle_identity_request.c,v 1.4 1997/09/02 17:26:36 #include "errlog.h" #include "schedule.h" #include "attributes.h" +#include "md5.h" #ifdef IPSEC #include "kernel.h" #endif +#ifdef DEBUG +#include "packet.h" +#endif int handle_identity_request(u_char *packet, int size, char *address, char *local_address) { + struct packet_sub parts[] = { + { "IDChoice", FLD_ATTRIB, FMD_ATT_ONE, 0, }, + { "Identity", FLD_VARPRE, 0, 0, }, + { "Verification", FLD_VARPRE, 0, 0, }, + { "Attributes", FLD_ATTRIB, FMD_ATT_FILL, 0, }, + { NULL } + }; + + struct packet id_msg = { + "Identity Request", + IDENTITY_MESSAGE_MIN, 0, parts + }; + struct identity_message *header; struct stateob *st; struct spiob *spi; + MD5_CTX ctx; u_int8_t *p, *attributes; - u_int16_t i, asize, attribsize, tmp; + u_int16_t i, attribsize, tmp; u_int8_t signature[22]; /* XXX - constant */ if (size < IDENTITY_MESSAGE_MIN) @@ -95,31 +113,45 @@ handle_identity_request(u_char *packet, int size, char *address, goto verification_failed; } - /* Verify message */ - if (!(i = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)))) - goto verification_failed; +#ifdef DEBUG + printf("Identity-Request (after decryption):\n"); + packet_dump(packet, size, 0); +#endif + /* Verify message structure */ + if (packet_check((u_int8_t *)header, size - packet[size-1], &id_msg) == -1) { + log_error(0, "bad packet structure in handle_identity_request()"); + return -1; + } - asize = IDENTITY_MESSAGE_MIN; +#ifdef DEBUG + packet_ordered_dump(packet, size - packet[size-1], &id_msg); +#endif - p = IDENTITY_MESSAGE_CHOICE(header); - asize += p[1] + 2; - p += p[1] + 2; - asize += varpre2octets(p); - p += varpre2octets(p); + /* Create a signature of this packet */ + MD5Init(&ctx); + MD5Update(&ctx, packet, size); + MD5Final(signature, &ctx); - attributes = p + i; - asize += i; /* Verification size */ - asize += packet[size-1]; /* Padding size */ - attribsize = 0; - while(asize + attribsize < size) - attribsize += attributes[attribsize+1] + 2; + if (st->phase != VALUE_RESPONSE) { + /* + * Compare with the identity request which got verified + * initially. If matching resend our response. + */ - asize += attribsize; + if (bcmp(signature, st->packetsig, sizeof(st->packetsig))) + goto verification_failed; - if (asize != size) { - log_error(0, "wrong packet size in handle_identity_request()"); + /* We got send the old packet again */ + bcopy(st->packet, packet_buffer, st->packetlen); + packet_size = st->packetlen; + + send_packet(); return 0; - } + } else + bcopy(signature, st->packetsig, sizeof(st->packetsig)); + + attributes = parts[3].where; + attribsize = parts[3].size; if (!isattribsubset(st->oSPIoattrib,st->oSPIoattribsize, attributes, attribsize)) { @@ -127,86 +159,81 @@ handle_identity_request(u_char *packet, int size, char *address, return 0; } - if (i > sizeof(signature)) { - log_error(0, "verification too long in handle_identity_request()"); + i = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)); + if (!i || i != parts[2].size || i > sizeof(signature)) { + log_error(0, "verification size mismatch in handle_identity_request()"); goto verification_failed; } - bcopy(p, signature, i); - bzero(p, i); - - if (st->phase == VALUE_RESPONSE) { - /* Fill the state object, but only if we have not dont so before */ - if (st->uSPIidentver == NULL) { - if((st->uSPIidentver = calloc(i, sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_request()"); - goto verification_failed; - } - bcopy(signature, st->uSPIidentver, i); - st->uSPIidentversize = i; - } - - p = IDENTITY_MESSAGE_CHOICE(header); - if (st->uSPIidentchoice == NULL) { - if((st->uSPIidentchoice = calloc(p[1]+2, sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_request()"); - goto verification_failed; - } - bcopy(p, st->uSPIidentchoice, p[1]+2); - st->uSPIidentchoicesize = p[1]+2; - } + bcopy(parts[2].where, signature, i); - p += p[1] + 2; - if (st->uSPIident == NULL) { - if((st->uSPIident = calloc(varpre2octets(p), sizeof(u_int8_t))) == NULL) { - log_error(1,"calloc() in handle_identity_request()"); - goto verification_failed; - } - bcopy(p, st->uSPIident, varpre2octets(p)); + /* Fill the state object, but only if we have not dont so before */ + if (st->uSPIidentver == NULL) { + if((st->uSPIidentver = calloc(i, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_request()"); + goto verification_failed; } + bcopy(signature, st->uSPIidentver, i); + st->uSPIidentversize = i; + } - if (st->uSPIattrib == NULL) { - if((st->uSPIattrib = calloc(attribsize, sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_request()"); - return -1; - } - bcopy(attributes, st->uSPIattrib, attribsize); - st->uSPIattribsize = attribsize; + p = IDENTITY_MESSAGE_CHOICE(header); + if (st->uSPIidentchoice == NULL) { + if((st->uSPIidentchoice = calloc(p[1]+2, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_request()"); + goto verification_failed; } - - if (st->oSPIident == NULL && - get_secrets(st, (ID_REMOTE|ID_LOCAL)) == -1) { - log_error(0, "get_secrets() in in handle_identity_request()"); + bcopy(p, st->uSPIidentchoice, p[1]+2); + st->uSPIidentchoicesize = p[1]+2; + } + + p += p[1] + 2; + if (st->uSPIident == NULL) { + if((st->uSPIident = calloc(varpre2octets(p), sizeof(u_int8_t))) == NULL) { + log_error(1,"calloc() in handle_identity_request()"); goto verification_failed; } - + bcopy(p, st->uSPIident, varpre2octets(p)); } - - if (!verify_identity_verification(st, signature, packet, size)) { - if (st->phase != SPI_UPDATE) { - /* - * Clean up everything used from this packet - * but only if we did not get a valid packet before. - * Otherwise this could be used as Denial of Service. - */ - free(st->uSPIidentchoice); - st->uSPIidentchoice = NULL; st->uSPIidentchoicesize = 0; - free(st->uSPIidentver); - st->uSPIidentver = NULL; st->uSPIidentversize = 0; - free(st->uSPIattrib); - st->uSPIattrib = NULL; st->uSPIattribsize = 0; - free(st->uSPIident); - st->uSPIident = NULL; - free(st->oSPIident); - st->oSPIident = NULL; - - /* Clean up secrets */ - free(st->oSPIsecret); - st->oSPIsecret = NULL; st->oSPIsecretsize = 0; - free(st->uSPIsecret); - st->uSPIsecret = NULL; st->uSPIsecretsize = 0; + + if (st->uSPIattrib == NULL) { + if((st->uSPIattrib = calloc(attribsize, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_request()"); + return -1; } - + bcopy(attributes, st->uSPIattrib, attribsize); + st->uSPIattribsize = attribsize; + } + + if (st->oSPIident == NULL && + get_secrets(st, (ID_REMOTE|ID_LOCAL)) == -1) { + log_error(0, "get_secrets() in in handle_identity_request()"); + goto verification_failed; + } + + if (!verify_identity_verification(st, signature, packet, size)) { + /* + * Clean up everything used from this packet + * but only if we did not get a valid packet before. + * Otherwise this could be used as Denial of Service. + */ + free(st->uSPIidentchoice); + st->uSPIidentchoice = NULL; st->uSPIidentchoicesize = 0; + free(st->uSPIidentver); + st->uSPIidentver = NULL; st->uSPIidentversize = 0; + free(st->uSPIattrib); + st->uSPIattrib = NULL; st->uSPIattribsize = 0; + free(st->uSPIident); + st->uSPIident = NULL; + free(st->oSPIident); + st->oSPIident = NULL; + + /* Clean up secrets */ + free(st->oSPIsecret); + st->oSPIsecret = NULL; st->oSPIsecretsize = 0; + free(st->uSPIsecret); + st->uSPIsecret = NULL; st->uSPIsecretsize = 0; + verification_failed: log_error(0, "verification failed in handle_identity_request()"); packet_size = PACKET_BUFFER_SIZE; @@ -217,15 +244,6 @@ handle_identity_request(u_char *packet, int size, char *address, return 0; } - if (st->phase != VALUE_RESPONSE) { - /* We got send the old packet again */ - bcopy(st->packet, packet_buffer, st->packetlen); - packet_size = st->packetlen; - - send_packet(); - return 0; - } - /* Create SPI + choice of attributes */ if(make_spi(st, local_address, st->oSPI, &(st->olifetime), &(st->oSPIattrib), &(st->oSPIattribsize)) == -1) { diff --git a/sbin/ipsec/photurisd/handle_identity_response.c b/sbin/ipsec/photurisd/handle_identity_response.c index a0cbedb0839..8674421c8f7 100644 --- a/sbin/ipsec/photurisd/handle_identity_response.c +++ b/sbin/ipsec/photurisd/handle_identity_response.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_identity_response.c,v 1.4 1997/09/02 17:26:37 provos Exp $"; +static char rcsid[] = "$Id: handle_identity_response.c,v 1.5 1998/03/04 11:43:21 provos Exp $"; #endif #include <stdio.h> @@ -60,16 +60,32 @@ static char rcsid[] = "$Id: handle_identity_response.c,v 1.4 1997/09/02 17:26:37 #ifdef IPSEC #include "kernel.h" #endif +#ifdef DEBUG +#include "packet.h" +#endif int handle_identity_response(u_char *packet, int size, char *address, char *local_address) { + struct packet_sub parts[] = { + { "IDChoice", FLD_ATTRIB, FMD_ATT_ONE, 0, }, + { "Identity", FLD_VARPRE, 0, 0, }, + { "Verification", FLD_VARPRE, 0, 0, }, + { "Attributes", FLD_ATTRIB, FMD_ATT_FILL, 0, }, + { NULL } + }; + + struct packet id_msg = { + "Identity Response", + IDENTITY_MESSAGE_MIN, 0, parts + }; + struct identity_message *header; struct stateob *st; struct spiob *spi; - u_int8_t *p, *attributes; - u_int16_t i, asize, attribsize, tmp; + u_int8_t *attributes; + u_int16_t i, attribsize, tmp; u_int8_t signature[22]; /* XXX - constant */ if (size < IDENTITY_MESSAGE_MIN) @@ -91,31 +107,25 @@ handle_identity_response(u_char *packet, int size, char *address, goto verification_failed; } - /* Verify message */ - if (!(i = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)))) - goto verification_failed; - - asize = IDENTITY_MESSAGE_MIN; - - p = IDENTITY_MESSAGE_CHOICE(header); - asize += p[1] + 2; - p += p[1] + 2; - asize += varpre2octets(p); - p += varpre2octets(p); - - attributes = p + i; - asize += i; /* Verification size */ - asize += packet[size-1]; /* Padding size */ - attribsize = 0; - while(asize + attribsize < size) - attribsize += attributes[attribsize+1] + 2; - - asize += attribsize; +#ifdef DEBUG + printf("Identity Response (after decryption):\n"); + packet_dump((u_int8_t *)header, size, 0); +#endif + /* Verify message structure */ + if (packet_check(packet, size - packet[size-1], &id_msg) == -1) { + log_error(0, "bad packet structure in handle_identity_response()"); + return -1; + } - if (asize != size) { - log_error(0, "wrong packet size in handle_identity_response()"); - return 0; + i = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)); + if (!i || i != parts[2].size || i >sizeof(signature)) { + log_error(0, "verification size mismatch in handle_identity_response()"); + goto verification_failed; } + bcopy(parts[2].where, signature, parts[2].size); + + attributes = parts[3].where; + attribsize = parts[3].size; if (!isattribsubset(st->oSPIoattrib,st->oSPIoattribsize, attributes, attribsize)) { @@ -123,51 +133,34 @@ handle_identity_response(u_char *packet, int size, char *address, return 0; } - if (i > sizeof(signature)) { - log_error(0, "verification too long in handle_identity_response()"); - goto verification_failed; - } - - bcopy(p, signature, i); - bzero(p, i); /* Fill the state object */ - if (st->uSPIidentver == NULL) { - if((st->uSPIidentver = calloc(i, sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_response()"); - goto verification_failed; - } - bcopy(signature, st->uSPIidentver, i); - st->uSPIidentversize = i; + if((st->uSPIidentver = calloc(i, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_response()"); + goto verification_failed; } + bcopy(signature, st->uSPIidentver, i); + st->uSPIidentversize = i; - p = IDENTITY_MESSAGE_CHOICE(header); - if (st->uSPIidentchoice == NULL) { - if((st->uSPIidentchoice = calloc(p[1]+2, sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_response()"); - goto verification_failed; - } - bcopy(p, st->uSPIidentchoice, p[1]+2); - st->uSPIidentchoicesize = p[1]+2; + if((st->uSPIidentchoice = calloc(parts[0].size, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_response()"); + goto verification_failed; } + bcopy(parts[0].where, st->uSPIidentchoice, parts[0].size); + st->uSPIidentchoicesize = parts[0].size; - p += p[1] + 2; - if (st->uSPIident == NULL) { - if((st->uSPIident = calloc(varpre2octets(p), sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_response()"); - goto verification_failed; - } - bcopy(p, st->uSPIident, varpre2octets(p)); + if((st->uSPIident = calloc(parts[1].size, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_response()"); + goto verification_failed; } + bcopy(parts[1].where, st->uSPIident, parts[1].size); - if (st->uSPIattrib == NULL) { - if((st->uSPIattrib = calloc(attribsize, sizeof(u_int8_t))) == NULL) { - log_error(1, "calloc() in handle_identity_response()"); - goto verification_failed; - } - bcopy(attributes, st->uSPIattrib, attribsize); - st->uSPIattribsize = attribsize; + if((st->uSPIattrib = calloc(attribsize, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_response()"); + goto verification_failed; } + bcopy(attributes, st->uSPIattrib, attribsize); + st->uSPIattribsize = attribsize; if (get_secrets(st, ID_REMOTE) == -1) { log_error(0, "get_secrets() in in handle_identity_response()"); diff --git a/sbin/ipsec/photurisd/handle_spi_needed.c b/sbin/ipsec/photurisd/handle_spi_needed.c index 2db8f8e81cd..0cdb1946971 100644 --- a/sbin/ipsec/photurisd/handle_spi_needed.c +++ b/sbin/ipsec/photurisd/handle_spi_needed.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_spi_needed.c,v 1.4 1997/09/02 17:26:39 provos Exp $"; +static char rcsid[] = "$Id: handle_spi_needed.c,v 1.5 1998/03/04 11:43:23 provos Exp $"; #endif #include <stdio.h> @@ -63,11 +63,20 @@ int handle_spi_needed(u_char *packet, int size, char *address, char *local_address) { + struct packet_sub parts[] = { + { "Verification", FLD_VARPRE, 0, 0, }, + { "Attributes", FLD_ATTRIB, FMD_ATT_FILL, 0, }, + { NULL } + }; + struct packet spi_msg = { + "SPI Needed", + SPI_NEEDED_MIN, 0, parts + }; struct spi_needed *header; struct stateob *st; struct spiob *spi; - u_int8_t *p, *attributes; - u_int16_t i, asize, attribsize, tmp; + u_int8_t *attributes; + u_int16_t i, attribsize, tmp; u_int8_t signature[22]; /* XXX - constant */ if (size < SPI_NEEDED_MIN) @@ -95,26 +104,21 @@ handle_spi_needed(u_char *packet, int size, char *address, goto verification_failed; } - /* Verify message */ - if (!(i = get_validity_verification_size(st))) - goto verification_failed; - - asize = SPI_NEEDED_MIN + i; - - p = SPI_NEEDED_VERIFICATION(header); - - attributes = p + i; - asize += packet[size-1]; /* Padding size */ - attribsize = 0; - while(asize + attribsize < size) - attribsize += attributes[attribsize+1] + 2; - - asize += attribsize; + /* Verify message structure*/ + if (packet_check((u_int8_t *)header, size - packet[size-1], &spi_msg) == -1) { + log_error(0, "bad packet structure in handle_spi_update()"); + return -1; + } - if (asize != size) { - log_error(0, "wrong packet size in handle_spi_needed()"); - return 0; + i = get_validity_verification_size(st); + if (!i || i != parts[0].size || i > sizeof(signature)) { + log_error(0, "verification size mismatch in handle_spi_needed()"); + goto verification_failed; } + bcopy(parts[0].where, signature, i); + + attributes = parts[1].where; + attribsize = parts[1].size; if (!isattribsubset(st->oSPIoattrib,st->oSPIoattribsize, attributes, attribsize)) { @@ -122,14 +126,6 @@ handle_spi_needed(u_char *packet, int size, char *address, return 0; } - if (i > sizeof(signature)) { - log_error(0, "verification too long in handle_spi_needed()"); - goto verification_failed; - } - - bcopy(p, signature, i); - bzero(p, i); - if (!verify_validity_verification(st, signature, packet, size)) { verification_failed: log_error(0, "verification failed in handle_spi_needed()"); diff --git a/sbin/ipsec/photurisd/handle_spi_update.c b/sbin/ipsec/photurisd/handle_spi_update.c index 84ef551e5eb..3d5e284c867 100644 --- a/sbin/ipsec/photurisd/handle_spi_update.c +++ b/sbin/ipsec/photurisd/handle_spi_update.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_spi_update.c,v 1.4 1997/09/02 17:26:40 provos Exp $"; +static char rcsid[] = "$Id: handle_spi_update.c,v 1.5 1998/03/04 11:43:24 provos Exp $"; #endif #include <stdio.h> @@ -63,12 +63,21 @@ int handle_spi_update(u_char *packet, int size, char *address, char *local_address) { + struct packet_sub parts[] = { + { "Verification", FLD_VARPRE, 0, 0, }, + { "Attributes", FLD_ATTRIB, FMD_ATT_FILL, 0, }, + { NULL } + }; + struct packet spi_msg = { + "SPI Update", + SPI_UPDATE_MIN, 0, parts + }; struct spi_update *header; struct stateob *st; struct spiob *spi; time_t lifetime; - u_int8_t *p, *attributes; - u_int16_t i, asize, attribsize, tmp; + u_int8_t *attributes; + u_int16_t i, attribsize, tmp; u_int8_t signature[22]; /* XXX - constant */ if (size < SPI_UPDATE_MIN) @@ -96,26 +105,21 @@ handle_spi_update(u_char *packet, int size, char *address, goto verification_failed; } - /* Verify message */ - if (!(i = get_validity_verification_size(st))) - goto verification_failed; - - asize = SPI_UPDATE_MIN + i; - - p = SPI_UPDATE_VERIFICATION(header); - - attributes = p + i; - asize += packet[size-1]; /* Padding size */ - attribsize = 0; - while(asize + attribsize < size) - attribsize += attributes[attribsize+1] + 2; - - asize += attribsize; + /* Verify message structure*/ + if (packet_check((u_int8_t *)header, size - packet[size-1], &spi_msg) == -1) { + log_error(0, "bad packet structure in handle_spi_update()"); + return -1; + } - if (asize != size) { - log_error(0, "wrong packet size in handle_spi_update()"); - return 0; + i = get_validity_verification_size(st); + if (!i || i != parts[0].size || i > sizeof(signature)) { + log_error(0, "verification size mismatch in handle_spi_update()"); + goto verification_failed; } + bcopy(parts[0].where, signature, i); + + attributes = parts[1].where; + attribsize = parts[1].size; if (!isattribsubset(st->oSPIoattrib,st->oSPIoattribsize, attributes, attribsize)) { @@ -123,14 +127,6 @@ handle_spi_update(u_char *packet, int size, char *address, return 0; } - if (i > sizeof(signature)) { - log_error(0, "verification too long in handle_spi_update()"); - goto verification_failed; - } - - bcopy(p, signature, i); - bzero(p, i); - if (!verify_validity_verification(st, signature, packet, size)) { verification_failed: log_error(0, "verification failed in handle_spi_update()"); diff --git a/sbin/ipsec/photurisd/handle_value_request.c b/sbin/ipsec/photurisd/handle_value_request.c index b3df46b3639..614061a42de 100644 --- a/sbin/ipsec/photurisd/handle_value_request.c +++ b/sbin/ipsec/photurisd/handle_value_request.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_value_request.c,v 1.4 1997/09/02 17:26:40 provos Exp $"; +static char rcsid[] = "$Id: handle_value_request.c,v 1.5 1998/03/04 11:43:26 provos Exp $"; #endif #include <stdio.h> @@ -63,17 +63,31 @@ handle_value_request(u_char *packet, int size, u_int8_t *schemes, u_int16_t ssize) { + struct packet_sub parts[] = { + { "Exchange Value", FLD_VARPRE, 0, 0, }, + { "Offered Attributes", FLD_ATTRIB, FMD_ATT_FILL, 0, }, + { NULL } + }; + struct packet vr_msg = { + "Value Request", + VALUE_REQUEST_MIN, 0, parts + }; struct value_request *header; struct stateob *st; mpz_t test, gen, mod; u_int8_t *p, *modp, *refp, *genp = NULL; - u_int16_t i, sstart, vsize, asize, modsize, modflag; + u_int16_t sstart, vsize, modsize, modflag; u_int8_t scheme_ref[2]; u_int8_t rcookie[COOKIE_SIZE]; if (size < VALUE_REQUEST_MIN) return -1; /* packet too small */ + if (packet_check(packet, size, &vr_msg) == -1) { + log_error(0, "bad packet structure in handle_value_request()"); + return -1; + } + header = (struct value_request *) packet; st = state_find_cookies(address, header->icookie, header->rcookie); @@ -99,11 +113,7 @@ handle_value_request(u_char *packet, int size, } /* Check exchange value - XXX doesn't check long form */ - p = VALUE_REQUEST_VALUE(header); - vsize = varpre2octets(p); - asize = VALUE_REQUEST_MIN + vsize; - if (asize >= size) - return -1; /* Exchange value too big */ + vsize = parts[0].size; /* Check schemes - selected length is in exchange value*/ sstart = 0; @@ -137,19 +147,8 @@ handle_value_request(u_char *packet, int size, if (sstart >= ssize) return -1; /* Did not find a scheme - XXX log */ - p = VALUE_REQUEST_VALUE(header) + vsize; - - /* Check attributes */ - i = 0; - while(asize + i < size) - i += p[i+1] + 2; - - /* This 'i' is used below as well as p */ - if (asize + i != size) - return -1; /* attributes dont match udp length */ - /* now check the exchange value */ - mpz_init_set_varpre(test, VALUE_REQUEST_VALUE(header)); + mpz_init_set_varpre(test, parts[0].where); mpz_init_set_varpre(mod, modp); mpz_init(gen); if (exchange_set_generator(gen, header->scheme, genp) == -1 || @@ -170,13 +169,13 @@ handle_value_request(u_char *packet, int size, st->flags = IPSEC_OPT_ENC|IPSEC_OPT_AUTH; /* Fill the state object */ - st->uSPIoattrib = calloc(i, sizeof(u_int8_t)); + st->uSPIoattrib = calloc(parts[1].size, sizeof(u_int8_t)); if (st->uSPIoattrib == NULL) { state_value_reset(st); return -1; } - bcopy(p, st->uSPIoattrib, i); - st->uSPIoattribsize = i; + bcopy(parts[1].where, st->uSPIoattrib, parts[1].size); + st->uSPIoattribsize = parts[1].size; /* Save scheme, which will be used by both parties */ vsize = 2 + varpre2octets(modp); @@ -204,19 +203,19 @@ handle_value_request(u_char *packet, int size, #ifdef DEBUG { int i = BUFFER_SIZE; - bin2hex(buffer, &i, VALUE_REQUEST_VALUE(header), varpre2octets(VALUE_REQUEST_VALUE(header))); + bin2hex(buffer, &i, parts[0].where, varpre2octets(VALUE_REQUEST_VALUE(header))); printf("Got exchange value 0x%s\n", buffer); } #endif /* Set exchange value */ - st->texchangesize = varpre2octets(VALUE_REQUEST_VALUE(header)); + st->texchangesize = parts[0].size; st->texchange = calloc(st->texchangesize, sizeof(u_int8_t)); if (st->texchange == NULL) { log_error(1, "calloc() in handle_value_request()"); return -1; } - bcopy(VALUE_REQUEST_VALUE(header), st->texchange, st->texchangesize); + bcopy(parts[0].where, st->texchange, st->texchangesize); /* Fill in the state object with generic data */ @@ -225,6 +224,7 @@ handle_value_request(u_char *packet, int size, st->counter = header->counter; bcopy(header->icookie, st->icookie, COOKIE_SIZE); bcopy(header->rcookie, st->rcookie, COOKIE_SIZE); + bcopy(&header->counter, st->uSPITBV, 3); if ((st->roschemes = calloc(ssize, sizeof(u_int8_t))) == NULL) { state_value_reset(st); diff --git a/sbin/ipsec/photurisd/handle_value_response.c b/sbin/ipsec/photurisd/handle_value_response.c index 2ef53dd557c..cbd542c7310 100644 --- a/sbin/ipsec/photurisd/handle_value_response.c +++ b/sbin/ipsec/photurisd/handle_value_response.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: handle_value_response.c,v 1.3 1997/09/02 17:26:41 provos Exp $"; +static char rcsid[] = "$Id: handle_value_response.c,v 1.4 1998/03/04 11:43:27 provos Exp $"; #endif #include <stdlib.h> @@ -62,15 +62,27 @@ handle_value_response(u_char *packet, int size, char *address, char *local_address) { + struct packet_sub parts[] = { + { "Exchange Value", FLD_VARPRE, 0, 0, }, + { "Offered Attributes", FLD_ATTRIB, FMD_ATT_FILL, 0, }, + { NULL } + }; + struct packet vr_msg = { + "Value Response", + VALUE_RESPONSE_MIN, 0, parts + }; struct value_response *header; struct stateob *st; mpz_t test; - u_int8_t *p; - u_int16_t i, asize; if (size < VALUE_RESPONSE_MIN) return -1; /* packet too small */ + if (packet_check(packet, size, &vr_msg) == -1) { + log_error(0, "bad packet structure in handle_value_response()"); + return -1; + } + header = (struct value_response *) packet; st = state_find_cookies(address, header->icookie, header->rcookie); @@ -80,56 +92,43 @@ handle_value_response(u_char *packet, int size, char *address, if (st->phase != VALUE_REQUEST) return -1; /* We don't want this packet */ - /* Check exchange value - XXX doesn't check long form */ - p = VALUE_RESPONSE_VALUE(header); - asize = VALUE_RESPONSE_MIN + varpre2octets(p); - p += varpre2octets(p); - if (asize >= size) - return -1; /* Exchange value too big */ - - /* Check attributes */ - i = 0; - while(asize + i < size) - i += p[i+1] + 2; - - if (asize + i != size) - return -1; /* attributes dont match udp length */ - /* Now check the exchange value for defects */ - mpz_init_set_varpre(test, VALUE_RESPONSE_VALUE(header)); + mpz_init_set_varpre(test, parts[0].where); if (!exchange_check_value(test, st->generator, st->modulus)) { mpz_clear(test); return 0; } mpz_clear(test); + /* Reserved Field for TBV */ + bcopy(header->reserved, st->uSPITBV, 3); + /* Fill the state object */ - st->uSPIoattrib = calloc(i, sizeof(u_int8_t)); + st->uSPIoattrib = calloc(parts[1].size, sizeof(u_int8_t)); if (st->uSPIoattrib == NULL) { state_value_reset(st); state_unlink(st); return -1; } - bcopy(p, st->uSPIoattrib, i); - st->uSPIoattribsize = i; + bcopy(parts[1].where, st->uSPIoattrib, parts[1].size); + st->uSPIoattribsize = parts[1].size; #ifdef DEBUG { int i = BUFFER_SIZE; - bin2hex(buffer, &i, VALUE_RESPONSE_VALUE(header), - varpre2octets(VALUE_RESPONSE_VALUE(header))); + bin2hex(buffer, &i, parts[0].where, parts[0].size); printf("Got exchange value 0x%s\n", buffer); } #endif /* Set exchange value */ - st->texchangesize = varpre2octets(VALUE_RESPONSE_VALUE(header)); + st->texchangesize = parts[0].size; st->texchange = calloc(st->texchangesize, sizeof(u_int8_t)); if (st->texchange == NULL) { log_error(1, "calloc() in handle_value_response()"); return -1; } - bcopy(VALUE_RESPONSE_VALUE(header), st->texchange, st->texchangesize); + bcopy(parts[0].where, st->texchange, st->texchangesize); /* Compute the shared secret now */ compute_shared_secret(st, &(st->shared), &(st->sharedsize)); diff --git a/sbin/ipsec/photurisd/identity.c b/sbin/ipsec/photurisd/identity.c index f5517e4508c..e4ec661fcaf 100644 --- a/sbin/ipsec/photurisd/identity.c +++ b/sbin/ipsec/photurisd/identity.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: identity.c,v 1.4 1997/09/02 17:26:42 provos Exp $"; +static char rcsid[] = "$Id: identity.c,v 1.5 1998/03/04 11:43:29 provos Exp $"; #endif #define _IDENTITY_C_ @@ -78,12 +78,12 @@ static union { /* XXX - argh, cast the funtions */ static struct idxform idxform[] = { - { HASH_MD5, MD5_SIZE, (void *)&Ctx.md5ctx, + { HASH_MD5, 5, MD5_SIZE, (void *)&Ctx.md5ctx, sizeof(MD5_CTX), (void *)&Ctx2.md5ctx, (void (*)(void *))MD5Init, (void (*)(void *, unsigned char *, unsigned int))MD5Update, (void (*)(unsigned char *, void *))MD5Final }, - { HASH_SHA1, SHA1_SIZE, (void *)&Ctx.sha1ctx, + { HASH_SHA1, 6, SHA1_SIZE, (void *)&Ctx.sha1ctx, sizeof(SHA1_CTX), (void *)&Ctx2.sha1ctx, (void (*)(void *))SHA1Init, (void (*)(void *, unsigned char *, unsigned int))SHA1Update, @@ -364,19 +364,19 @@ get_secrets(struct stateob *st, int mode) st->oSPIident[0] = ((strlen(local_ident)+1) >> 5) & 0xFF; st->oSPIident[1] = ((strlen(local_ident)+1) << 3) & 0xFF; - st->oSPIsecret = calloc(strlen(local_secret)+1,sizeof(u_int8_t)); + st->oSPIsecretsize = strlen(local_secret); + st->oSPIsecret = calloc(st->oSPIsecretsize,sizeof(u_int8_t)); if(st->oSPIsecret == NULL) return -1; - strcpy(st->oSPIsecret,local_secret); - st->oSPIsecretsize = strlen(local_secret)+1; + strncpy(st->oSPIsecret, local_secret, st->oSPIsecretsize); } if(st->uSPIident != NULL && st->uSPIsecret == NULL && (mode & ID_REMOTE)) { - st->uSPIsecret = calloc(strlen(remote_secret)+1,sizeof(u_int8_t)); + st->uSPIsecretsize = strlen(remote_secret); + st->uSPIsecret = calloc(st->uSPIsecretsize,sizeof(u_int8_t)); if(st->uSPIsecret == NULL) return -1; - strcpy(st->uSPIsecret,remote_secret); - st->uSPIsecretsize = strlen(remote_secret)+1; + strncpy(st->uSPIsecret, remote_secret, st->uSPIsecretsize); } return 0; } @@ -386,31 +386,29 @@ choose_identity(struct stateob *st, u_int8_t *packet, u_int16_t *size, u_int8_t *attributes, u_int16_t attribsize) { u_int16_t rsize, asize, tmp; + attrib_t *ob; int mode = 0; rsize = *size; /* XXX - preference of identity choice ? */ tmp = 0; - while(attribsize>0 && !tmp) { - switch(*attributes) { - case AT_MD5_DP: - case AT_SHA1_DP: - tmp = 1; + while(attribsize>0) { + /* Check if we support this identity choice */ + if ((ob = getattrib(*attributes)) != NULL && + (ob->type & AT_ID)) break; - default: - if(attribsize -(*(attributes+1)+2) > attribsize) { - attribsize=0; - break; - } - attribsize -= *(attributes+1)+2; - attributes += *(attributes+1)+2; + + if(attribsize -(*(attributes+1)+2) > attribsize) { + attribsize=0; break; - } + } + attribsize -= *(attributes+1)+2; + attributes += *(attributes+1)+2; } if(attribsize == 0) { log_error(0, "No identity choice found in offered attributes " - "in choose_identity"); + "in choose_identity()"); return -1; } @@ -440,7 +438,7 @@ choose_identity(struct stateob *st, u_int8_t *packet, u_int16_t *size, return -1; /* oSPIident is varpre already */ - tmp = 2+strlen(st->oSPIident+2)+1; + tmp = varpre2octets(st->oSPIident); if(rsize < tmp) return -1; @@ -455,15 +453,27 @@ choose_identity(struct stateob *st, u_int8_t *packet, u_int16_t *size, u_int16_t get_identity_verification_size(struct stateob *st, u_int8_t *choice) { - switch(*choice) { - case AT_MD5_DP: - return (128/8)+2; - case AT_SHA1_DP: - return (160/8)+2; - default: + struct idxform *hash; + + if ((hash = get_hash_id(*choice)) == NULL) { log_error(0, "Unknown identity choice: %d\n", *choice); return 0; } + + return hash->hashsize+2; +} + +/* + * Gets a hash corresponding with a Photuris ID + */ + +struct idxform *get_hash_id(int id) +{ + int i; + for (i=0; i<sizeof(idxform)/sizeof(idxform[0]); i++) + if (id == idxform[i].id) + return &idxform[i]; + return NULL; } struct idxform *get_hash(enum hashes hashtype) @@ -481,23 +491,13 @@ create_verification_key(struct stateob *st, u_int8_t *buffer, u_int16_t *size, int owner) { struct idxform *hash; + int id = owner ? *(st->oSPIidentchoice) : *(st->uSPIidentchoice); - switch(owner ? *(st->oSPIidentchoice) : *(st->uSPIidentchoice)) { - case AT_MD5_DP: - hash = get_hash(HASH_MD5); - break; - case AT_SHA1_DP: - hash = get_hash(HASH_SHA1); - break; - default: - log_error(0, "Unkown identity choice %d in create_verification_key", - owner ? *(st->oSPIidentchoice):*(st->uSPIidentchoice)); + if ((hash = get_hash_id(id)) == NULL) { + log_error(0, "Unkown identity choice %d in create_verification_key", id); return -1; } - if (hash == NULL) - return -1; - if (*size < hash->hashsize) return -1; @@ -521,22 +521,12 @@ create_identity_verification(struct stateob *st, u_int8_t *buffer, int hash_size; struct idxform *hash; - switch(*(st->oSPIidentchoice)) { - case AT_MD5_DP: - hash = get_hash(HASH_MD5); - break; - case AT_SHA1_DP: - hash = get_hash(HASH_SHA1); - break; - default: + if ((hash = get_hash_id(*(st->oSPIidentchoice))) == NULL) { log_error(0, "Unkown identity choice %d in create_verification_key", *(st->oSPIidentchoice)); return 0; } - if (hash == NULL) - return 0; - hash_size = idsign(st, hash, buffer+2, packet,size); if(hash_size) { @@ -567,22 +557,12 @@ verify_identity_verification(struct stateob *st, u_int8_t *buffer, { struct idxform *hash; - switch(*(st->uSPIidentchoice)) { - case AT_MD5_DP: - hash = get_hash(HASH_MD5); - break; - case AT_SHA1_DP: - hash = get_hash(HASH_SHA1); - break; - default: + if ((hash = get_hash_id(*(st->uSPIidentchoice))) == NULL) { log_error(0, "Unkown identity choice %d in create_verification_key", *(st->uSPIidentchoice)); return 0; } - if (hash == NULL) - return 0; - if (varpre2octets(buffer) != hash->hashsize +2) return 0; @@ -596,7 +576,6 @@ int idsign(struct stateob *st, struct idxform *hash, u_int8_t *signature, u_int8_t *packet, u_int16_t psize) { - struct identity_message *p; u_int8_t key[HASH_MAX]; u_int16_t keylen = HASH_MAX; @@ -606,24 +585,15 @@ idsign(struct stateob *st, struct idxform *hash, u_int8_t *signature, /* Our verification key */ hash->Update(hash->ctx, key, keylen); + /* Key fill */ + hash->Final(NULL, hash->ctx); - hash->Update(hash->ctx, st->icookie, COOKIE_SIZE); - hash->Update(hash->ctx, st->rcookie, COOKIE_SIZE); - - /* Hash type, lifetime + spi fields */ - p = (struct identity_message *)packet; - hash->Update(hash->ctx, (char *)&(p->type), IDENTITY_MESSAGE_MIN - 2*COOKIE_SIZE); - - hash->Update(hash->ctx, st->roschemes, st->roschemesize); - - /* Our exchange value */ - hash->Update(hash->ctx, st->exchangevalue, st->exchangesize); - hash->Update(hash->ctx, st->oSPIoattrib, st->oSPIoattribsize); - hash->Update(hash->ctx, st->oSPIident, strlen(st->oSPIident)); - - /* Their exchange value */ - hash->Update(hash->ctx, st->texchange, st->texchangesize); - hash->Update(hash->ctx, st->uSPIoattrib, st->uSPIoattribsize); + /* + * Hash Cookies, type, lifetime + spi fields + + * SPI owner Identity Choice + Identity + */ + hash->Update(hash->ctx, packet, IDENTITY_MESSAGE_MIN + + st->oSPIidentchoicesize + varpre2octets(st->oSPIident)); if(st->uSPIident != NULL) { hash->Update(hash->ctx, st->uSPIidentver, st->uSPIidentversize); @@ -633,11 +603,24 @@ idsign(struct stateob *st, struct idxform *hash, u_int8_t *signature, packet += IDENTITY_MESSAGE_MIN; psize -= IDENTITY_MESSAGE_MIN + packet[1] + 2; packet += packet[1] + 2; - psize -= varpre2octets(packet) + 2 + MD5_SIZE; - packet += varpre2octets(packet) + 2 + MD5_SIZE; + psize -= varpre2octets(packet) + 2 + hash->hashsize; + packet += varpre2octets(packet) + 2 + hash->hashsize; hash->Update(hash->ctx, packet, psize); + /* Our exchange value */ + hash->Update(hash->ctx, st->oSPITBV, 3); + hash->Update(hash->ctx, st->exchangevalue, st->exchangesize); + hash->Update(hash->ctx, st->oSPIoattrib, st->oSPIoattribsize); + + /* Their exchange value */ + hash->Update(hash->ctx, st->uSPITBV, 3); + hash->Update(hash->ctx, st->texchange, st->texchangesize); + hash->Update(hash->ctx, st->uSPIoattrib, st->uSPIoattribsize); + + /* Responder offered schemes */ + hash->Update(hash->ctx, st->roschemes, st->roschemesize); + /* Data fill */ hash->Final(NULL, hash->ctx); @@ -654,35 +637,25 @@ idverify(struct stateob *st, struct idxform *hash, u_int8_t *signature, u_int8_t *packet, u_int16_t psize) { u_int8_t digest[HASH_MAX]; - struct identity_message *p; u_int8_t key[HASH_MAX]; u_int16_t keylen = HASH_MAX; + struct identity_message *p = (struct identity_message *)packet; create_verification_key(st, key, &keylen, 0); /* User direction */ - p = (struct identity_message *)packet; - hash->Init(hash->ctx); /* Their verification key */ hash->Update(hash->ctx, key, keylen); + /* Key fill */ + hash->Final(NULL, hash->ctx); - hash->Update(hash->ctx, st->icookie, COOKIE_SIZE); - hash->Update(hash->ctx, st->rcookie, COOKIE_SIZE); - - /* Hash type, lifetime + spi fields */ - hash->Update(hash->ctx, (char *)&(p->type), IDENTITY_MESSAGE_MIN - 2*COOKIE_SIZE); - - hash->Update(hash->ctx, st->roschemes, st->roschemesize); - - /* Their exchange value */ - hash->Update(hash->ctx, st->texchange, st->texchangesize); - hash->Update(hash->ctx, st->uSPIoattrib, st->uSPIoattribsize); - hash->Update(hash->ctx, st->uSPIident, strlen(st->uSPIident)); - - /* Our exchange value */ - hash->Update(hash->ctx, st->exchangevalue, st->exchangesize); - hash->Update(hash->ctx, st->oSPIoattrib, st->oSPIoattribsize); + /* + * Hash Cookies, type, lifetime + spi fields + + * SPI owner Identity Choice + Identity + */ + hash->Update(hash->ctx, packet, IDENTITY_MESSAGE_MIN + + st->uSPIidentchoicesize + varpre2octets(st->uSPIident)); /* Determine if the sender knew our secret already */ if(p->type != IDENTITY_REQUEST) { @@ -692,10 +665,23 @@ idverify(struct stateob *st, struct idxform *hash, u_int8_t *signature, packet += IDENTITY_MESSAGE_MIN; psize -= IDENTITY_MESSAGE_MIN + packet[1] + 2; packet += packet[1] + 2; - psize -= varpre2octets(packet) + 2 + MD5_SIZE; - packet += varpre2octets(packet) + 2 + MD5_SIZE; + psize -= varpre2octets(packet) + 2 + hash->hashsize; + packet += varpre2octets(packet) + 2 + hash->hashsize; hash->Update(hash->ctx, packet, psize); + /* Their exchange value */ + hash->Update(hash->ctx, st->uSPITBV, 3); + hash->Update(hash->ctx, st->texchange, st->texchangesize); + hash->Update(hash->ctx, st->uSPIoattrib, st->uSPIoattribsize); + + /* Our exchange value */ + hash->Update(hash->ctx, st->oSPITBV, 3); + hash->Update(hash->ctx, st->exchangevalue, st->exchangesize); + hash->Update(hash->ctx, st->oSPIoattrib, st->oSPIoattribsize); + + /* Responder offered schemes */ + hash->Update(hash->ctx, st->roschemes, st->roschemesize); + /* Data fill */ hash->Final(NULL, hash->ctx); diff --git a/sbin/ipsec/photurisd/identity.h b/sbin/ipsec/photurisd/identity.h index 141a8412845..46802c16bfc 100644 --- a/sbin/ipsec/photurisd/identity.h +++ b/sbin/ipsec/photurisd/identity.h @@ -51,11 +51,12 @@ enum hashes { HASH_SHA1 }; struct idxform { - enum hashes type; /* Type of the transform */ - u_int8_t hashsize; /* Size of the hash */ - void *ctx; /* Pointer to a context */ + enum hashes type; /* Type of the transform */ + int id; /* Photuris Attribute ID */ + u_int8_t hashsize; /* Size of the hash */ + void *ctx; /* Pointer to a context */ int ctxsize; - void *ctx2; /* Pointer to a 2nd context for speedup */ + void *ctx2; /* Pointer to a 2nd context for speedup */ void (*Init)(void *); void (*Update)(void *, unsigned char *, unsigned int); void (*Final)(unsigned char *, void *); @@ -109,6 +110,7 @@ int create_identity_verification(struct stateob *st, u_int8_t *buffer, int verify_identity_verification(struct stateob *st, u_int8_t *buffer, u_int8_t *packet, u_int16_t size); +struct idxform *get_hash_id(int id); struct idxform *get_hash(enum hashes hashtype); int create_verification_key(struct stateob *, u_int8_t *, u_int16_t *, int); diff --git a/sbin/ipsec/photurisd/kernel.c b/sbin/ipsec/photurisd/kernel.c index 09d33c7116b..d36d287b580 100644 --- a/sbin/ipsec/photurisd/kernel.c +++ b/sbin/ipsec/photurisd/kernel.c @@ -29,7 +29,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: kernel.c,v 1.4 1997/09/14 10:37:51 deraadt Exp $"; +static char rcsid[] = "$Id: kernel.c,v 1.5 1998/03/04 11:43:32 provos Exp $"; #endif #include <sys/param.h> @@ -73,13 +73,80 @@ static char rcsid[] = "$Id: kernel.c,v 1.4 1997/09/14 10:37:51 deraadt Exp $"; #include "config.h" #endif +#ifdef DEBUG +time_t now; + +#define kernel_debug(x) {time(&now); printf("%.24s", ctime(&now)); printf x;} +#else +#define kernel_debug(x) +#endif + static int sd; +typedef struct { + int photuris_id; + int kernel_id, flags; +} transform; + +/* + * Translation from Photuris Attributes to Kernel Transforms. + * For the actual ids see: draft-simpson-photuris-*.txt and + * draft-simpson-photuris-schemes-*.txt + */ + +transform xf[] = { + { 5, ALG_AUTH_MD5, XF_AUTH|AH_OLD}, + { 6, ALG_AUTH_SHA1, XF_AUTH|AH_OLD}, + { 8, ALG_ENC_DES, XF_ENC|ESP_OLD}, + {100, ALG_ENC_3DES, XF_ENC|ESP_NEW}, + {101, ALG_ENC_BLF, XF_ENC|ESP_NEW}, + {102, ALG_ENC_CAST, XF_ENC|ESP_NEW}, + {105, ALG_AUTH_MD5, XF_AUTH|AH_NEW|ESP_NEW}, + {106, ALG_AUTH_SHA1, XF_AUTH|AH_NEW|ESP_NEW}, + {107, ALG_AUTH_RMD160, XF_AUTH|AH_NEW|ESP_NEW}, +}; + +/* + * Translate a Photuris ID to an offset into a data structure for the + * corresponding Kernel transform. + * This makes is easier to write kernel modules for different IPSec + * implementations. + */ + +int +kernel_get_offset(int id) +{ + int i; + + for (i=sizeof(xf)/sizeof(transform)-1; i >= 0; i--) + if (xf[i].photuris_id == id) + return i; + + return -1; +} + +/* + * For ESP, we can specify an additional AH transform. + * Not all combinations are possible. + * Returns AT_ENC, when the ESP transform does not allow this AH. + * Returns AT_AUTH, when the AH transform does not work with ESP. + */ + +int +kernel_valid(int encoff, int authoff) +{ + if (xf[encoff].flags & ESP_OLD) + return AT_ENC; + if (!(xf[authoff].flags & ESP_NEW)) + return AT_AUTH; + return 0; +} + int init_kernel(void) { if ((sd = socket(AF_ENCAP, SOCK_RAW, AF_UNSPEC)) < 0) - crit_error(1, "socket() in init_kernel()"); + crit_error(1, "socket() for IPSec in init_kernel()"); return 1; } @@ -92,10 +159,8 @@ kernel_get_socket(void) int kernel_xf_set(struct encap_msghdr *em) { - if (write(sd, (char *)em, em->em_msglen) != em->em_msglen) { - log_error(1, "write() in kernel_xf_set()"); + if (write(sd, (char *)em, em->em_msglen) != em->em_msglen) return 0; - } return 1; } @@ -115,6 +180,8 @@ kernel_reserve_spi(char *srcaddress, int options) u_int32_t spi; int proto; + kernel_debug(("kernel_reserve_spi: %s\n", srcaddress)); + if ((options & (IPSEC_OPT_ENC|IPSEC_OPT_AUTH)) != (IPSEC_OPT_ENC|IPSEC_OPT_AUTH)) { switch(options & (IPSEC_OPT_ENC|IPSEC_OPT_AUTH)) { @@ -144,6 +211,8 @@ kernel_reserve_single_spi(char *srcaddress, u_int32_t spi, int proto) { struct encap_msghdr *em; + kernel_debug(("kernel_reserve_single_spi: %s, %08x\n", srcaddress, spi)); + bzero(buffer, EMT_ENABLESPI_FLEN); em = (struct encap_msghdr *)buffer; @@ -156,8 +225,10 @@ kernel_reserve_single_spi(char *srcaddress, u_int32_t spi, int proto) em->em_gen_dst.s_addr = inet_addr(srcaddress); em->em_gen_sproto = proto; - if (!kernel_xf_set(em)) + if (!kernel_xf_set(em)) { + log_error(1, "kernel_xf_set() in kernel_reserve_single_spi()"); return 0; + } if (!kernel_xf_read(em, EMT_RESERVESPI_FLEN)) return 0; @@ -166,88 +237,173 @@ kernel_reserve_single_spi(char *srcaddress, u_int32_t spi, int proto) } int -kernel_md5(char *srcaddress, char *dstaddress, u_int8_t *spi, u_int8_t *secret, - int tunnel) +kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets) { struct encap_msghdr *em; - struct ah_old_xencap *xd; - int klen; + struct ah_old_xencap *xdo; + struct ah_new_xencap *xdn; - klen = MD5_KEYLEN/8; - - bzero(buffer, EMT_SETSPI_FLEN + 4 + klen); + if (!(xf[ob->koff].flags & XF_AUTH)) { + log_error(0, "%d is not an auth transform in kernel_ah()", ob->id); + return -1; + } em = (struct encap_msghdr *)buffer; + + if (xf[ob->koff].flags & AH_OLD) { + bzero(buffer, EMT_SETSPI_FLEN + 4 + ob->klen); + + em->em_msglen = EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN + ob->klen; + + em->em_alg = XF_OLD_AH; + + xdo = (struct ah_old_xencap *)(em->em_dat); + + xdo->amx_hash_algorithm = xf[ob->koff].kernel_id; + xdo->amx_keylen = ob->klen; - em->em_msglen = EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN + klen; + bcopy(secrets, xdo->amx_key, ob->klen); + + } else { + bzero(buffer, EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN + ob->klen); + + em->em_msglen = EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN + ob->klen; + + em->em_alg = XF_NEW_AH; + + xdn = (struct ah_new_xencap *)(em->em_dat); + + xdn->amx_hash_algorithm = xf[ob->koff].kernel_id; + xdn->amx_wnd = 16; + xdn->amx_keylen = ob->klen; + + bcopy(secrets, xdn->amx_key, ob->klen); + } + em->em_version = PFENCAP_VERSION_1; em->em_type = EMT_SETSPI; - em->em_spi = htonl((spi[0]<<24) + (spi[1]<<16) + - (spi[2]<<8) + spi[3]); - em->em_src.s_addr = inet_addr(srcaddress); - em->em_dst.s_addr = inet_addr(dstaddress); - - if (tunnel) { - em->em_osrc.s_addr = inet_addr(srcaddress); - em->em_odst.s_addr = inet_addr(dstaddress); + em->em_spi = htonl((SPI->SPI[0]<<24) + (SPI->SPI[1]<<16) + + (SPI->SPI[2]<<8) + SPI->SPI[3]); + em->em_src.s_addr = inet_addr(SPI->local_address); + em->em_dst.s_addr = inet_addr(SPI->flags & SPI_OWNER ? + SPI->local_address : SPI->address); + + if (SPI->flags & SPI_TUNNEL) { + em->em_osrc.s_addr = inet_addr(SPI->local_address); + em->em_odst.s_addr = inet_addr(SPI->flags & SPI_OWNER ? + SPI->local_address : SPI->address); } - - em->em_alg = XF_OLD_AH; em->em_sproto = IPPROTO_AH; - xd = (struct ah_old_xencap *)(em->em_dat); + kernel_debug(("kernel_ah: %08x.\n", em->em_spi)); - xd->amx_hash_algorithm = ALG_AUTH_MD5; - xd->amx_keylen = klen; - - bcopy(secret, xd->amx_key, klen); - - if (!kernel_xf_set(em)) + if (!kernel_xf_set(em)) { + log_error(1, "kernel_xf_set() in kernel_ah()"); return -1; - - return MD5_KEYLEN/8; + } + return ob->klen; } int -kernel_des(char *srcaddress, char *dstaddress, u_int8_t *spi, u_int8_t *secret, - int tunnel) +kernel_esp(attrib_t *ob, attrib_t *ob2, struct spiob *SPI, u_int8_t *secrets) { struct encap_msghdr *em; - struct esp_old_xencap *xd; + struct esp_old_xencap *xdo; + struct esp_new_xencap *xdn; + attrib_t *attenc, *attauth = NULL; + u_int8_t *sec1, *sec2 = NULL; + + if (ob->type & AT_AUTH) { + if (ob2 == NULL || ob2->type != AT_ENC) { + log_error(0, "No encryption after auth given in kernel_esp()"); + return -1; + } + attenc = ob2; + attauth = ob; + sec2 = secrets; + sec1 = secrets + ob->klen; + } else if (ob->type == AT_ENC) { + attenc = ob; + sec1 = secrets; + if (ob2 != NULL && (ob2->type & AT_AUTH)) { + attauth = ob2; + sec2 = secrets + ob->klen; + } + } else { + log_error(0, "No encryption transform given in kernel_esp()"); + return -1; + } - bzero(buffer, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN + 4 + 8); + if ((xf[attenc->koff].flags & ESP_OLD) && attauth != NULL) { + log_error(0, "Old ESP does not support AH in kernel_esp()"); + return -1; + } em = (struct encap_msghdr *)buffer; - - em->em_msglen = EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN + 4 + 8; + + if (xf[attenc->koff].flags & ESP_OLD) { + bzero(buffer, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN +4+attenc->klen); + + em->em_msglen = EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN +4+attenc->klen; + + em->em_alg = XF_OLD_ESP; + + xdo = (struct esp_old_xencap *)(em->em_dat); + + xdo->edx_enc_algorithm = ALG_ENC_DES; + xdo->edx_ivlen = 4; + xdo->edx_keylen = attenc->klen; + + bcopy(SPI->SPI, xdo->edx_data, 4); + bcopy(sec1, xdo->edx_data+4, attenc->klen); + } else { + bzero(buffer, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + attenc->klen + + (attauth ? attauth->klen : 0)); + + em->em_msglen = EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + + attenc->klen + (attauth ? attauth->klen : 0); + + em->em_alg = XF_NEW_ESP; + + xdn = (struct esp_new_xencap *)(em->em_dat); + + xdn->edx_enc_algorithm = xf[attenc->koff].kernel_id; + xdn->edx_hash_algorithm = attauth ? xf[attauth->koff].kernel_id : 0; + xdn->edx_ivlen = 0; + xdn->edx_confkeylen = attenc->klen; + xdn->edx_authkeylen = attauth ? attauth->klen : 0; + xdn->edx_wnd = 16; + xdn->edx_flags = attauth ? ESP_NEW_FLAG_AUTH : 0; + + bcopy(sec1, xdn->edx_data, attenc->klen); + if (attauth != NULL) + bcopy(sec2, xdn->edx_data + attenc->klen, attauth->klen); + } + /* Common settings shared by ESP_OLD and ESP_NEW */ + em->em_version = PFENCAP_VERSION_1; em->em_type = EMT_SETSPI; - em->em_spi = htonl((spi[0]<<24) + (spi[1]<<16) + - (spi[2]<<8) + spi[3]); - em->em_src.s_addr = inet_addr(srcaddress); - em->em_dst.s_addr = inet_addr(dstaddress); + em->em_spi = htonl((SPI->SPI[0]<<24) + (SPI->SPI[1]<<16) + + (SPI->SPI[2]<<8) + SPI->SPI[3]); + em->em_src.s_addr = inet_addr(SPI->local_address); + em->em_dst.s_addr = inet_addr(SPI->flags & SPI_OWNER ? + SPI->local_address : SPI->address); + em->em_sproto = IPPROTO_ESP; - if (tunnel) { - em->em_osrc.s_addr = inet_addr(srcaddress); - em->em_odst.s_addr = inet_addr(dstaddress); + if (SPI->flags & SPI_TUNNEL) { + em->em_osrc.s_addr = inet_addr(SPI->local_address); + em->em_odst.s_addr = inet_addr(SPI->flags & SPI_OWNER ? + SPI->local_address : SPI->address); } - em->em_alg = XF_OLD_ESP; - em->em_sproto = IPPROTO_ESP; - - xd = (struct esp_old_xencap *)(em->em_dat); - - xd->edx_enc_algorithm = ALG_ENC_DES; - xd->edx_ivlen = 4; - xd->edx_keylen = 8; - - bcopy(spi, xd->edx_data, 4); - bcopy(secret, xd->edx_data + 8, 8); + kernel_debug(("kernel_esp: %08x\n", em->em_spi)); - if (!kernel_xf_set(em)) + if (!kernel_xf_set(em)) { + log_error(1, "kernel_xf_set() in kernel_esp()"); return -1; + } - return 8; + return attenc->klen + (attauth ? attauth->klen : 0); } /* Group an ESP SPI with an AH SPI */ @@ -260,6 +416,9 @@ kernel_group_spi(char *address, u_int8_t *spi) u_int32_t SPI; SPI = (spi[0]<<24) + (spi[1]<<16) + (spi[2]<<8) + spi[3]; + + kernel_debug(("kernel_group_spi: %s, %08x\n", address, SPI)); + addr = inet_addr(address); bzero(buffer, EMT_GRPSPIS_FLEN); @@ -277,8 +436,10 @@ kernel_group_spi(char *address, u_int8_t *spi) em->em_rel_dst2.s_addr = addr; em->em_rel_sproto2 = IPPROTO_AH; - if (!kernel_xf_set(em)) + if (!kernel_xf_set(em)) { + log_error(1, "kernel_xf_set() in kernel_group_spi()"); return -1; + } return 1; } @@ -293,6 +454,8 @@ kernel_enable_spi(in_addr_t isrc, in_addr_t ismask, SPI = (spi[0]<<24) + (spi[1]<<16) + (spi[2]<<8) + spi[3]; + kernel_debug(("kernel_enable_spi: %08x\n", SPI)); + bzero(buffer, EMT_ENABLESPI_FLEN); em = (struct encap_msghdr *)buffer; @@ -311,8 +474,10 @@ kernel_enable_spi(in_addr_t isrc, in_addr_t ismask, em->em_ena_sproto = proto; em->em_ena_flags = flags; - if (!kernel_xf_set(em)) + if (!kernel_xf_set(em)) { + log_error(1, "kernel_xf_set() in kernel_enable_spi()"); return -1; + } return 1; } @@ -327,6 +492,8 @@ kernel_disable_spi(in_addr_t isrc, in_addr_t ismask, SPI = (spi[0]<<24) + (spi[1]<<16) + (spi[2]<<8) + spi[3]; + kernel_debug(("kernel_disable_spi: %08x\n", SPI)); + bzero(buffer, EMT_DISABLESPI_FLEN); em = (struct encap_msghdr *)buffer; @@ -345,8 +512,10 @@ kernel_disable_spi(in_addr_t isrc, in_addr_t ismask, em->em_ena_sproto = proto; em->em_ena_flags = flags; - if (!kernel_xf_set(em)) +/* if (!kernel_xf_set(em) && errno != ENOENT) { + log_error(1, "kernel_xf_set() in kernel_disable_spi()"); return -1; + }*/ return 1; } @@ -368,8 +537,12 @@ kernel_delete_spi(char *address, u_int8_t *spi, int proto) em->em_gen_dst.s_addr = inet_addr(address); em->em_gen_sproto = proto; - if (!kernel_xf_set(em)) + kernel_debug(("kernel_delete_spi: %08x\n", em->em_gen_spi)); + + if (!kernel_xf_set(em)) { + log_error(1, "kernel_xf_set() in kernel_delete_spi()"); return -1; + } return 1; } @@ -381,7 +554,9 @@ kernel_insert_spi(struct spiob *SPI) u_int8_t *attributes; u_int16_t attribsize; u_int8_t *secrets; + attrib_t *attprop, *attprop2; int i, n, offset, proto = 0; + int phase = 0; spi = SPI->SPI; attributes = SPI->attributes; @@ -391,35 +566,51 @@ kernel_insert_spi(struct spiob *SPI) for(n=0, i=0; n<attribsize; n += attributes[n+1] + 2) { switch(attributes[n]) { case AT_AH_ATTRIB: + phase = AT_AH_ATTRIB; + break; case AT_ESP_ATTRIB: + phase = AT_ESP_ATTRIB; break; - case AT_MD5_KDP: - offset = kernel_md5(SPI->local_address, SPI->flags & SPI_OWNER ? - SPI->local_address : SPI->address, - spi, secrets, SPI->flags & SPI_TUNNEL); - if (offset == -1) + default: + if (phase == 0) { + log_error(0, "Unaligned attribute %d in kernel_insert_spi()", attributes[n]); return -1; - secrets += offset; - i++; - if (!proto) - proto = IPPROTO_AH; - break; - case AT_DES_CBC: - offset = kernel_des(SPI->local_address, SPI->flags & SPI_OWNER ? - SPI->local_address : SPI->address, - spi, secrets, SPI->flags & SPI_TUNNEL); - if (offset == -1) + } + if ((attprop = getattrib(attributes[n])) == NULL) { + log_error(0, "Unknown attribute %d in kernel_insert_spi()", + attributes[n]); return -1; - secrets += offset; - i++; - if (!proto) - proto = IPPROTO_ESP; - break; - default: - log_error(0, "Unknown attribute %d in kernel_insert_spi()", - attributes[n]); - return -1; + } + switch (phase) { + case AT_AH_ATTRIB: + offset = kernel_ah(attprop, SPI, secrets); + if (offset == -1) + return -1; + phase = 0; + secrets += offset; + i++; + if (!proto) + proto = IPPROTO_AH; + break; + case AT_ESP_ATTRIB: + offset = attributes[n+1] + 2; + attprop2 = NULL; + if (n+offset < attribsize) + attprop2 = getattrib(attributes[n+offset]); + if (attprop2 != NULL) + n += offset; + offset = kernel_esp(attprop, attprop2, SPI, secrets); + if (offset == -1) + return -1; + phase = 0; + secrets += offset; + i++; + if (!proto) + proto = IPPROTO_ESP; + break; + } } + } /* Group the SPIs for User */ @@ -448,6 +639,8 @@ int kernel_unlink_spi(struct spiob *ospi) { int n, proto = 0; + int phase = 0, offset; + attrib_t *attprop; u_int32_t spi; u_int8_t SPI[SPI_SIZE], *p; @@ -467,39 +660,54 @@ kernel_unlink_spi(struct spiob *ospi) SPI[3] = spi & 0xFF; switch(ospi->attributes[n]) { case AT_AH_ATTRIB: + phase = AT_AH_ATTRIB; + break; case AT_ESP_ATTRIB: + phase = AT_ESP_ATTRIB; break; - case AT_MD5_KDP: - if (!proto) { - proto = IPPROTO_AH; - if (!(ospi->flags & SPI_OWNER) && - kernel_disable_spi(ospi->isrc, ospi->ismask, - ospi->idst, ospi->idmask, - ospi->address, ospi->SPI, proto, - ENABLE_FLAG_LOCAL) == -1) - log_error(0, "kernel_disable_spi() in kernel_unlink_spi()"); + default: + if (phase == 0) { + log_error(0, "Unaligned attribute %d in kernel_unlink_spi()", ospi->attributes[n]); + return -1; + } + if ((attprop = getattrib(ospi->attributes[n])) == NULL) { + log_error(0, "Unknown attribute %d in kernel_unlink_spi()", + ospi->attributes[n]); + return -1; + } + switch (phase) { + case AT_AH_ATTRIB: + if (!proto) { + proto = IPPROTO_AH; + if (!(ospi->flags & SPI_OWNER) && + kernel_disable_spi(ospi->isrc, ospi->ismask, + ospi->idst, ospi->idmask, + ospi->address, ospi->SPI, proto, + ENABLE_FLAG_LOCAL) == -1) + log_error(0, "kernel_disable_spi() in kernel_unlink_spi()"); } if (kernel_delete_spi(p, SPI, IPPROTO_AH) == -1) log_error(0, "kernel_delete_spi() in kernel_unlink_spi()"); break; - case AT_DES_CBC: - if (!proto) { - proto = IPPROTO_ESP; - if (!(ospi->flags & SPI_OWNER) && - kernel_disable_spi(ospi->isrc, ospi->ismask, - ospi->idst, ospi->idmask, - ospi->address, ospi->SPI, proto, - ENABLE_FLAG_LOCAL) == -1) - log_error(0, "kernel_disable_spi() in kernel_unlink_spi()"); + case AT_ESP_ATTRIB: + if (!proto) { + proto = IPPROTO_ESP; + if (!(ospi->flags & SPI_OWNER) && + kernel_disable_spi(ospi->isrc, ospi->ismask, + ospi->idst, ospi->idmask, + ospi->address, ospi->SPI, proto, + ENABLE_FLAG_LOCAL) == -1) + log_error(0, "kernel_disable_spi() in kernel_unlink_spi()"); + } + if (kernel_delete_spi(p, SPI, IPPROTO_ESP) == -1) + log_error(0, "kernel_delete_spi() in kernel_unlink_spi()"); + offset = ospi->attributes[n+1] + 2; + if ((n + offset < ospi->attribsize) && + getattrib(ospi->attributes[n+offset]) != NULL) + n += offset; + break; } - if (kernel_delete_spi(p, SPI, IPPROTO_ESP) == -1) - log_error(0, "kernel_delete_spi() in kernel_unlink_spi()"); - break; - default: - log_error(0, "Unknown attribute %d in kernel_unlink_spi()", - ospi->attributes[n]); - return -1; } } diff --git a/sbin/ipsec/photurisd/kernel.h b/sbin/ipsec/photurisd/kernel.h index ad1ac0020d4..d30ceb6b7af 100644 --- a/sbin/ipsec/photurisd/kernel.h +++ b/sbin/ipsec/photurisd/kernel.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: kernel.h,v 1.3 1997/07/26 20:55:16 provos Exp $ */ +/* $Id: kernel.h,v 1.4 1998/03/04 11:43:33 provos Exp $ */ /* * kernel.h: * security paramter index creation. @@ -40,13 +40,21 @@ #ifdef _KERNEL_C_ #define EXTERN +#define ESP_OLD 0x01 +#define ESP_NEW 0x02 +#define AH_OLD 0x04 +#define AH_NEW 0x08 + +#define XF_ENC 0x10 +#define XF_AUTH 0x20 + + int kernel_xf_set(struct encap_msghdr *em); int kernel_xf_read(struct encap_msghdr *em, int msglen); -int kernel_des(char *srcaddress, char *dstaddress, - u_int8_t *spi, u_int8_t *secret, int tunnel); -int kernel_md5(char *srcaddress, char *dstaddress, - u_int8_t *spi, u_int8_t *secret, int tunnel); +int kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets); +int kernel_esp(attrib_t *ob, attrib_t *ob2, struct spiob *SPI, + u_int8_t *secrets); int kernel_group_spi(char *address, u_int8_t *spi); @@ -62,6 +70,9 @@ int kernel_delete_spi(char *address, u_int8_t *spi, int proto); #define EXTERN extern #endif +EXTERN int kernel_get_offset(int id); +EXTERN int kernel_valid(int encoff, int authoff); + EXTERN u_int32_t kernel_reserve_spi( char *srcaddress, int options); EXTERN u_int32_t kernel_reserve_single_spi(char *srcaddress, u_int32_t spi, int proto); diff --git a/sbin/ipsec/photurisd/packet.c b/sbin/ipsec/photurisd/packet.c index 4eb182d0ca4..9b1ced8041b 100644 --- a/sbin/ipsec/photurisd/packet.c +++ b/sbin/ipsec/photurisd/packet.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: packet.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +static char rcsid[] = "$Id: packet.c,v 1.2 1998/03/04 11:43:35 provos Exp $"; #endif #define _PACKET_C_ @@ -41,6 +41,7 @@ static char rcsid[] = "$Id: packet.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <ctype.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -52,6 +53,7 @@ static char rcsid[] = "$Id: packet.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; #include "errlog.h" #include "buffer.h" #include "config.h" +#include "scheme.h" #include "packet.h" #include "server.h" @@ -207,6 +209,72 @@ send_packet(void) } } +/* + * packet_check() checks the format of the received packet against + * the specified logical format. The position and size of the fields + * are returned. + */ + +int +packet_check(u_char *packet, u_int16_t size, struct packet *format) +{ + struct packet_sub *parts = format->parts; + u_int16_t off, val, fsize; + + if (format->max != 0 && size > format->max) + return -1; + if (size < format->min) + return -1; + + off = format->min; + packet += off; + + while (off < size && parts != NULL && parts->field != NULL) { + parts->where = packet; + switch (parts->type) { + case FLD_CONST: + off += parts->size; + packet += parts->size; + fsize = parts->size; + break; + case FLD_VARPRE: + val = varpre2octets(packet); + off += val; + packet += val; + fsize = val; + break; + case FLD_ATTRIB: + if (parts->mod == FMD_ATT_FILL) { + fsize = 0; + while (off < size) { + val = packet[1] + 2; + off += val; + packet += val; + fsize += val; + } + } else { + val = packet[1] + 2; + off += val; + packet += val; + fsize = val; + } + break; + default: + return -1; + } + if (parts->size == 0) + parts->size = fsize; + else if(parts->size != fsize) + return -1; + parts++; + } + + if (off != size || (parts != NULL && parts->field != NULL)) + return -1; + + return 0; +} + void packet_save(struct stateob *st, u_int8_t *buffer, u_int16_t len) { @@ -221,3 +289,53 @@ packet_save(struct stateob *st, u_int8_t *buffer, u_int16_t len) bcopy(buffer, st->packet, len); st->packetlen = len; } + +#ifdef DEBUG +void +packet_ordered_dump(u_int8_t *packet, u_int16_t size, struct packet *format) +{ + struct packet_sub *parts = format->parts; + u_int16_t off = 0; + + printf("Packet Header (%s):\n", format->name); + packet_dump(packet, format->min, off); + + off += format->min; + packet += format->min; + while (off < size) { + printf("%s (%d):\n", parts->field, parts->size); + packet_dump(packet, parts->size, off); + off += parts->size; + packet += parts->size; + + parts++; + } +} + +void +packet_dump(u_int8_t *packet, u_int16_t plen, u_int16_t start) +{ + char tmp[73], dump[33]; + int i, size, len, off; + + off = 0; + while (off < plen) { + memset(tmp, ' ', sizeof(tmp)); + tmp[72] = 0; + + sprintf(tmp, "%04x ", (u_int32_t)(off + start)); + + len = 33; + size = plen - off > 16 ? 16 : plen - off; + bin2hex(dump, &len, packet, size); + for (i=0; i<size; i++) { + bcopy(dump+i*2, tmp+5+i*3, 2); + tmp[5 + 16*3 + 3 + i] = isprint(packet[i]) ? packet[i] : '.'; + } + printf("%s\n", tmp); + + off += size; + packet += size; + } +} +#endif diff --git a/sbin/ipsec/photurisd/packet.h b/sbin/ipsec/photurisd/packet.h index 389e9b54ddf..ae1753d7929 100644 --- a/sbin/ipsec/photurisd/packet.h +++ b/sbin/ipsec/photurisd/packet.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: packet.h,v 1.1 1997/07/18 22:48:50 provos Exp $ */ +/* $Id: packet.h,v 1.2 1998/03/04 11:43:36 provos Exp $ */ /* * packet.h: * prototyped for receiving and anwsering packets @@ -45,6 +45,11 @@ EXTERN int handle_packet(int, char *); EXTERN void send_packet(void); +EXTERN int packet_check(u_char *packet, u_int16_t size, struct packet *format); EXTERN void packet_save(struct stateob *, u_int8_t *, u_int16_t); +#ifdef DEBUG +EXTERN void packet_ordered_dump(u_int8_t *packet, u_int16_t size, struct packet *format); +EXTERN void packet_dump(u_int8_t *packet, u_int16_t plen, u_int16_t start); +#endif #endif /* _STATE_H */ diff --git a/sbin/ipsec/photurisd/packets.h b/sbin/ipsec/photurisd/packets.h index 7d8ed7ee4f7..4fd87c4ec90 100644 --- a/sbin/ipsec/photurisd/packets.h +++ b/sbin/ipsec/photurisd/packets.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: packets.h,v 1.1 1997/07/18 22:48:49 provos Exp $ */ +/* $Id: packets.h,v 1.2 1998/03/04 11:43:37 provos Exp $ */ /* * packets.h: */ @@ -53,6 +53,29 @@ #define COOKIE_SIZE 16 #define SPI_SIZE 4 +/* General packet definition */ + +#define FLD_CONST 0 +#define FLD_VARPRE 1 +#define FLD_ATTRIB 2 + +#define FMD_ATT_ONE 0 +#define FMD_ATT_FILL 1 + +struct packet_sub { + char *field; /* Name of Field */ + int type; /* Type of Field */ + int mod; /* Modifier: */ + u_int16_t size; /* Pointer to start of Field */ + void *where; /* Pointer to start of Field */ +}; + +struct packet { + char *name; + int min, max; + struct packet_sub *parts; +}; + struct cookie_request { u_int8_t icookie[COOKIE_SIZE]; u_int8_t rcookie[COOKIE_SIZE]; diff --git a/sbin/ipsec/photurisd/photuris_identity_request.c b/sbin/ipsec/photurisd/photuris_identity_request.c index 4a6296a02ef..abf34aae699 100644 --- a/sbin/ipsec/photurisd/photuris_identity_request.c +++ b/sbin/ipsec/photurisd/photuris_identity_request.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photuris_identity_request.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +static char rcsid[] = "$Id: photuris_identity_request.c,v 1.2 1998/03/04 11:43:39 provos Exp $"; #endif #include <stdio.h> @@ -45,6 +45,9 @@ static char rcsid[] = "$Id: photuris_identity_request.c,v 1.1 1997/07/18 22:48:4 #include "state.h" #include "identity.h" #include "encrypt.h" +#ifdef DEBUG +#include "packet.h" +#endif int photuris_identity_request(struct stateob *st, u_char *buffer, int *size) @@ -115,6 +118,11 @@ photuris_identity_request(struct stateob *st, u_char *buffer, int *size) /* Create verification data */ create_identity_verification(st, verifyp, (u_int8_t *)header, asize); +#ifdef DEBUG + printf("Identity-Request (before encryption):\n"); + packet_dump((u_int8_t *)header, asize, 0); +#endif + /* Encrypt the packet after SPI if wished for */ packet_encrypt(st, IDENTITY_MESSAGE_CHOICE(header), asize - IDENTITY_MESSAGE_MIN); diff --git a/sbin/ipsec/photurisd/photuris_identity_response.c b/sbin/ipsec/photurisd/photuris_identity_response.c index 550fa0d25ec..ebc5ce56f41 100644 --- a/sbin/ipsec/photurisd/photuris_identity_response.c +++ b/sbin/ipsec/photurisd/photuris_identity_response.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photuris_identity_response.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +static char rcsid[] = "$Id: photuris_identity_response.c,v 1.2 1998/03/04 11:43:40 provos Exp $"; #endif #include <stdio.h> @@ -45,6 +45,9 @@ static char rcsid[] = "$Id: photuris_identity_response.c,v 1.1 1997/07/18 22:48: #include "state.h" #include "identity.h" #include "encrypt.h" +#ifdef DEBUG +#include "packet.h" +#endif int photuris_identity_response(struct stateob *st, u_char *buffer, int *size) @@ -114,6 +117,11 @@ photuris_identity_response(struct stateob *st, u_char *buffer, int *size) /* Create verification data */ create_identity_verification(st, verifyp, (u_int8_t *)header, asize); + +#ifdef DEBUG + printf("Identity-Response (before encryption):\n"); + packet_dump((u_int8_t *)header, asize, 0); +#endif /* Encrypt the packet after SPI if wished for */ packet_encrypt(st, IDENTITY_MESSAGE_CHOICE(header), diff --git a/sbin/ipsec/photurisd/photuris_packet_encrypt.c b/sbin/ipsec/photurisd/photuris_packet_encrypt.c index f614cede679..f0b2e7bbc3b 100644 --- a/sbin/ipsec/photurisd/photuris_packet_encrypt.c +++ b/sbin/ipsec/photurisd/photuris_packet_encrypt.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photuris_packet_encrypt.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +static char rcsid[] = "$Id: photuris_packet_encrypt.c,v 1.2 1998/03/04 11:43:41 provos Exp $"; #endif #define _ENCRYPT_C_ @@ -66,15 +66,6 @@ packet_mask(u_int8_t *packet, u_int16_t len, u_int8_t *key) } int -packet_make_iv(u_int32_t *iv, u_int32_t *packet) -{ - iv[0] = iv[0] ^ packet[0]; - iv[1] = iv[1] ^ packet[1]; - - return 1; -} - -int packet_create_padding(struct stateob *st, u_int16_t size, u_int8_t *padd, u_int16_t *rsize) { @@ -113,6 +104,8 @@ packet_encrypt(struct stateob *st, u_int8_t *payload, u_int16_t payloadlen) des_cblock keys[4], *input; des_key_schedule key1,key2,key3; u_int8_t *pkey; + u_int16_t order = 0; + int i; input = (des_cblock *)payload; @@ -131,7 +124,7 @@ packet_encrypt(struct stateob *st, u_int8_t *payload, u_int16_t payloadlen) } if(compute_privacy_key(st, pkey, payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, - payloadlen*8, 0, 1) == -1) + payloadlen*8, &order, 1) == -1) return -1; #ifdef DEBUG { @@ -150,34 +143,40 @@ packet_encrypt(struct stateob *st, u_int8_t *payload, u_int16_t payloadlen) #ifdef DEBUG printf("[Packet encryption: DES]\n"); #endif - pkey = calloc(payloadlen + 16, sizeof(u_int8_t)); + pkey = calloc(payloadlen + 8, sizeof(u_int8_t)); if(pkey == NULL) { log_error(1, "Not enough memory for privacy secret"); return -1; } + /* XOR Mask */ if(compute_privacy_key(st, pkey, payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, - payloadlen*8+128, 0, 1) == -1) + payloadlen*8, &order, 1) == -1) + return -1; + /* DES Key */ + if(compute_privacy_key(st, pkey+payloadlen, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + 64, &order, 1) == -1) return -1; #ifdef DEBUG { int i; char buffer[3000]; i = 3000; - bin2hex(buffer, &i, pkey, payloadlen+16); + bin2hex(buffer, &i, pkey, payloadlen+8); printf("Encrypt key: %s\n", buffer ); } #endif bcopy(pkey+payloadlen, &keys[0], 8); des_set_odd_parity(&keys[0]); - bcopy(pkey+payloadlen+8, &keys[1], 8); + + /* Zero IV, we will mask the packet instead */ + bzero(&keys[1], 8); des_set_key(&keys[0], key1); packet_mask(payload, payloadlen, pkey); - packet_make_iv((u_int32_t *)&keys[1], (u_int32_t *)(payload - 8)); - des_cbc_encrypt(input,input,payloadlen, key1,&keys[1], DES_ENCRYPT); break; case DH_G_2_3DES_SHA1: @@ -186,21 +185,29 @@ packet_encrypt(struct stateob *st, u_int8_t *payload, u_int16_t payloadlen) #ifdef DEBUG printf("[Packet encryption: 3DES]\n"); #endif - pkey = calloc(payloadlen+32, sizeof(u_int8_t)); + pkey = calloc(payloadlen+24, sizeof(u_int8_t)); if(pkey == NULL) { log_error(1, "Not enough memory for owner privacy secret"); return -1; } + /* XOR Mask */ if(compute_privacy_key(st, pkey, payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, - payloadlen*8+256, 0, 1) == -1) + payloadlen*8, &order, 1) == -1) return -1; + /* 3 DES Keys */ + for (i=0; i<3; i++) { + if(compute_privacy_key(st, pkey+payloadlen + (i<<3), + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + 64, &order, 1) == -1) + return -1; + } #ifdef DEBUG { int i; char buffer[3000]; i = 3000; - bin2hex(buffer, &i, pkey, payloadlen+32); + bin2hex(buffer, &i, pkey, payloadlen+24); printf("Encrypt key: %s\n", buffer ); } #endif @@ -210,7 +217,9 @@ packet_encrypt(struct stateob *st, u_int8_t *payload, u_int16_t payloadlen) des_set_odd_parity(&keys[1]); bcopy(pkey+payloadlen+16, &keys[2], 8); des_set_odd_parity(&keys[2]); - bcopy(pkey+payloadlen+24, &keys[3], 8); + + /* Zero IV, we will make the packet instead */ + bzero(&keys[3], 8); des_set_key(&keys[0], key1); des_set_key(&keys[1], key2); @@ -218,8 +227,6 @@ packet_encrypt(struct stateob *st, u_int8_t *payload, u_int16_t payloadlen) packet_mask(payload, payloadlen, pkey); - packet_make_iv((u_int32_t *)&keys[3], (u_int32_t *)(payload - 8)); - des_ede3_cbc_encrypt(input, input, payloadlen, key1, key2, key3, &keys[3], DES_ENCRYPT); break; @@ -241,6 +248,7 @@ packet_decrypt(struct stateob *st, u_int8_t *payload, u_int16_t *payloadlen) des_cblock keys[4], *input; des_key_schedule key1,key2,key3; u_int8_t *pkey; + u_int16_t order = 0; input = (des_cblock *)payload; @@ -259,7 +267,7 @@ packet_decrypt(struct stateob *st, u_int8_t *payload, u_int16_t *payloadlen) } if(compute_privacy_key(st, pkey, payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, - *payloadlen*8, 0, 0) == -1) + *payloadlen*8, &order, 0) == -1) return -1; #ifdef DEBUG { @@ -277,30 +285,36 @@ packet_decrypt(struct stateob *st, u_int8_t *payload, u_int16_t *payloadlen) #ifdef DEBUG printf("[Packet decryption: DES]\n"); #endif - pkey = calloc(*payloadlen+16, sizeof(u_int8_t)); + pkey = calloc(*payloadlen+8, sizeof(u_int8_t)); if(pkey == NULL) { log_error(1, "Not enough memory for privacy secret"); return -1; } + /* XOR Mask */ if(compute_privacy_key(st, pkey, payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, - *payloadlen*8+128, 0, 0) == -1) + *payloadlen*8, &order, 0) == -1) + return -1; + /* DES Key */ + if(compute_privacy_key(st, pkey + *payloadlen, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + 64, &order, 0) == -1) return -1; #ifdef DEBUG { int i = 3000; char buffer[3000]; - bin2hex(buffer, &i, pkey, *payloadlen+ 16); + bin2hex(buffer, &i, pkey, *payloadlen + 8); printf("Decrypt key: %s\n", buffer ); } #endif bcopy(pkey+*payloadlen, &keys[0], 8); des_set_odd_parity(&keys[0]); - bcopy(pkey+*payloadlen+8, &keys[1], 8); - des_set_key(&keys[0], key1); + /* Zero IV, we will mask the packet instead */ + bzero(&keys[1], 8); - packet_make_iv((u_int32_t *)&keys[1], (u_int32_t *)(payload - 8)); + des_set_key(&keys[0], key1); des_cbc_encrypt(input,input,*payloadlen, key1,&keys[1], DES_DECRYPT); @@ -312,20 +326,28 @@ packet_decrypt(struct stateob *st, u_int8_t *payload, u_int16_t *payloadlen) #ifdef DEBUG printf("[Packet decryption: 3DES]\n"); #endif - pkey = calloc(*payloadlen + 32, sizeof(u_int8_t)); + pkey = calloc(*payloadlen + 24, sizeof(u_int8_t)); if(pkey == NULL) { log_error(1, "Not enough memory for privacy secret"); return -1; } + /* XOR Mask */ if(compute_privacy_key(st, pkey, payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, - *payloadlen*8+256, 0, 0) == -1) + *payloadlen*8, &order, 0) == -1) return -1; + /* 3 DES keys + 1 DES IV */ + for (i=0; i<3; i++) { + if(compute_privacy_key(st, pkey + *payloadlen + (i<<3), + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + 64, &order, 0) == -1) + return -1; + } #ifdef DEBUG { int i = 3000; char buffer[3000]; - bin2hex(buffer, &i, pkey, *payloadlen+32); + bin2hex(buffer, &i, pkey, *payloadlen+24); printf("Decrypt key: %s\n", buffer ); } #endif @@ -335,14 +357,14 @@ packet_decrypt(struct stateob *st, u_int8_t *payload, u_int16_t *payloadlen) des_set_odd_parity(&keys[1]); bcopy(pkey+*payloadlen+16, &keys[2], 8); des_set_odd_parity(&keys[2]); - bcopy(pkey+*payloadlen+24, &keys[3], 8); + + /* Zero IV, we will mask the packet instead */ + bzero(&keys[3], 8); des_set_key(&keys[0], key1); des_set_key(&keys[1], key2); des_set_key(&keys[2], key3); - packet_make_iv((u_int32_t *)&keys[3], (u_int32_t *)(payload - 8)); - des_ede3_cbc_encrypt(input, input, *payloadlen, key1, key2, key3, &keys[3], DES_DECRYPT); diff --git a/sbin/ipsec/photurisd/photuris_value_request.c b/sbin/ipsec/photurisd/photuris_value_request.c index 92eb6bc34fe..a2b3318294d 100644 --- a/sbin/ipsec/photurisd/photuris_value_request.c +++ b/sbin/ipsec/photurisd/photuris_value_request.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photuris_value_request.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +static char rcsid[] = "$Id: photuris_value_request.c,v 1.2 1998/03/04 11:43:43 provos Exp $"; #endif #include <stdio.h> @@ -80,6 +80,8 @@ photuris_value_request(struct stateob *st, u_char *buffer, int *size) header->counter = st->counter; bcopy(st->scheme, header->scheme, 2 ); /* Only scheme */ + bcopy(&header->counter, st->oSPITBV, 3); + *size = asize; return 0; } diff --git a/sbin/ipsec/photurisd/photuris_value_response.c b/sbin/ipsec/photurisd/photuris_value_response.c index 78d20847915..090233c5e16 100644 --- a/sbin/ipsec/photurisd/photuris_value_response.c +++ b/sbin/ipsec/photurisd/photuris_value_response.c @@ -34,7 +34,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photuris_value_response.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +static char rcsid[] = "$Id: photuris_value_response.c,v 1.2 1998/03/04 11:43:44 provos Exp $"; #endif #include <stdio.h> @@ -78,6 +78,7 @@ photuris_value_response(struct stateob *st, u_char *buffer, int *size) bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); bzero(header->reserved, sizeof(header->reserved)); /* zero for now */ + bzero(st->oSPITBV, 3); *size = asize; return 0; diff --git a/sbin/ipsec/photurisd/photurisd.1 b/sbin/ipsec/photurisd/photurisd.1 index f607a7a2e30..66c34e2e6ce 100644 --- a/sbin/ipsec/photurisd/photurisd.1 +++ b/sbin/ipsec/photurisd/photurisd.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: photurisd.1,v 1.7 1997/12/02 10:57:37 provos Exp $ +.\" $OpenBSD: photurisd.1,v 1.8 1998/03/04 11:43:46 provos Exp $ .\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> .\" All rights reserved. .\" @@ -39,6 +39,7 @@ .Nm photurisd .Op Fl ci .Op Fl d Ar directory +.Op Fl p Ar port .Sh DESCRIPTION The .Nm photuris @@ -71,6 +72,10 @@ option specifies the directory in which .Nm photurisd looks for its startup files. The default is .Pa /etc/photuris/ . +.It Fl p +The +.Fl p +option specifies the local port the daemon shall bind to. .El .Pp The file @@ -114,26 +119,62 @@ The file contains the attributes, i.e. different choices of encryption and authenication, offered to the other peer. If a line starts with an ip address and a space seperated netmask the following attributes are only -offered to hosts lying in that net range. Possible attributes are: +offered to hosts lying in that net range. Only one attribute per line +is allowed. An attribute can either be an already defined tag or +an new definition of an attribute. In that case the line is followed by a +comma separated list: +.Nm attribute name , +.Nm Photuris id , +.Nm type of attribute +and +.Nm key length . +The name is only used as reference. A list of possible Photuris ids can +be found in +.Pa /usr/share/ipsec/attributes.conf . +The attribute type is one of the following: +.Nm enc , +.Nm ident , +.Nm auth +or +.Nm ident|auth . +The key length is so far only used by the encryption attributes and +specifies the number of keying bytes the daemon has to generate. +Predefined attributes are: .Bl -tag -width AT_ESP_ATTRIB -offset indent .It AT_AH_ATTRIB Starts the list of authentication attributes. .It AT_ESP_ATTRIB Starts the list of encryption attributes. -.It AT_MD5_DP -MD5 symmetric identification. This attribute must be offered. -.It AT_SHA1_DP -SHA1 symmetric identification. -.It AT_MD5_KDP -Simple MD5 keyed authentication. -.It AT_DES_CBC -DES CBC encryption. .El .Pp The file .Pa secrets.conf contains the party preconfigured symmetric secrets for the -identity exchange. User secrets files can be included. +identity exchange. +.Bl -tag -width identity_pair_local -offset indent +.It identity local +Defines the identity the local daemon will assume and the according +password. Both name and secret are braced by quotation marks and follow +the +.Nm identity local +directive. +.It identity remote +Defines the parties the daemon can communicate with and their secrets. +Both name and secret are braced by quotation marks and follow the +.Nm identity remote +directive. The name and secret are the same as the identity local +on the remote site. +.It identity pair local +If the identity of the remote site is already known, +.Nm identity pair local +enables the daemon to assume an identity and secret based on +the remote identity. The directive is followed by the +remote identity, a new local identity and an according secret. +In that way the secrets are not shared with all other parties. +.El +.Pp +Once DNSSEC or other public key infrastructures are available, those will +be supported also. .Pp Finally the file .Pa photuris.startup diff --git a/sbin/ipsec/photurisd/photurisd.c b/sbin/ipsec/photurisd/photurisd.c index 0b9aef231ce..5668ede6050 100644 --- a/sbin/ipsec/photurisd/photurisd.c +++ b/sbin/ipsec/photurisd/photurisd.c @@ -32,7 +32,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: photurisd.c,v 1.5 1997/09/14 10:37:52 deraadt Exp $"; +static char rcsid[] = "$Id: photurisd.c,v 1.6 1998/03/04 11:43:47 provos Exp $"; #endif #define _PHOTURIS_C_ @@ -67,10 +67,11 @@ usage(void) { FILE *f = stderr; - fprintf(f, "usage: photurisd [-ci] [-d directory]\n"); + fprintf(f, "usage: photurisd [-ci] [-d directory] [-p port]\n"); fprintf(f, "\t-c check primes on startup\n"); - fprintf(f, "\t-t ignore startup file %s\n", PHOTURIS_STARTUP); + fprintf(f, "\t-i ignore startup file %s\n", PHOTURIS_STARTUP); fprintf(f, "\t-d specifies the startup dir\n"); + fprintf(f, "\t-p specifies the local port to bind to\n"); exit(1); } @@ -115,8 +116,9 @@ main(int argc, char **argv) char *dir = PHOTURIS_DIR; daemon_mode = 0; + global_port = 0; - while ((ch = getopt(argc, argv, "cid:")) != -1) + while ((ch = getopt(argc, argv, "cid:p:")) != -1) switch((char)ch) { case 'c': primes = 1; @@ -127,6 +129,9 @@ main(int argc, char **argv) case 'd': dir = optarg; break; + case 'p': + global_port = atoi(optarg); + break; case '?': default: usage(); diff --git a/sbin/ipsec/photurisd/schedule.c b/sbin/ipsec/photurisd/schedule.c index a5a1f89afda..a0749558ba3 100644 --- a/sbin/ipsec/photurisd/schedule.c +++ b/sbin/ipsec/photurisd/schedule.c @@ -35,7 +35,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: schedule.c,v 1.5 1997/09/03 08:44:41 provos Exp $"; +static char rcsid[] = "$Id: schedule.c,v 1.6 1998/03/04 11:43:49 provos Exp $"; #endif #define _SCHEDULE_C_ @@ -80,7 +80,7 @@ schedule_insert(int type, int off, u_int8_t *cookie, u_int16_t cookie_size) bin2hex(buffer, &i, cookie, cookie_size); } printf("Adding event type %d, due in %d seconds, cookie %s\n", - type, off, cookie == NULL ? "None" : buffer); + type, off, cookie == NULL ? "None" : (char *)buffer); } #endif @@ -199,7 +199,8 @@ schedule_process(int sock) switch(tmp->event) { case REKEY: #ifdef DEBUG - printf("Resetting secrets\n"); + if (state_root() != NULL) + printf("Resetting secrets\n"); #endif reset_secret(); tmp->tm = time(NULL) + REKEY_TIMEOUT; @@ -243,7 +244,7 @@ schedule_process(int sock) state_copy_flags(st, newst); #ifdef DEBUG printf("Starting a new exchange to %s:%d with updated rcookie and" - "counter.\n", newst->address, newst->port); + " counter.\n", newst->address, newst->port); #endif /* DEBUG */ start_exchange(sock, newst, st->address, st->port); state_insert(newst); @@ -300,7 +301,13 @@ schedule_process(int sock) break; } if ((st = state_find_cookies(spi->address, spi->icookie, NULL)) == NULL) { +#ifdef DEBUG2 + /* + * This happens always when an exchange expires but + * updates are still scheduled for it. + */ log_error(0, "state_find_cookies() in schedule_process()"); +#endif break; } diff --git a/sbin/ipsec/photurisd/secrets.h b/sbin/ipsec/photurisd/secrets.h index ed7e763dba4..71e3564cf33 100644 --- a/sbin/ipsec/photurisd/secrets.h +++ b/sbin/ipsec/photurisd/secrets.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: secrets.h,v 1.2 1997/09/02 17:26:48 provos Exp $ */ +/* $Id: secrets.h,v 1.3 1998/03/04 11:43:50 provos Exp $ */ /* * secrets.h: * prototypes for compute_secrets.c @@ -57,7 +57,7 @@ EXTERN int get_session_key_length(u_int8_t *attribute); EXTERN int init_privacy_key(struct stateob *st, int owner); EXTERN int compute_privacy_key(struct stateob *st, u_int8_t *key, u_int8_t *packet, u_int16_t bits, - u_int16_t order, int owner); + u_int16_t *order, int owner); EXTERN int make_session_keys(struct stateob *st, struct spiob *spi); #endif /* _SECRETS_H_ */ diff --git a/sbin/ipsec/photurisd/server.c b/sbin/ipsec/photurisd/server.c index e2228260b2c..c3062d19ffd 100644 --- a/sbin/ipsec/photurisd/server.c +++ b/sbin/ipsec/photurisd/server.c @@ -35,7 +35,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: server.c,v 1.2 1997/07/22 11:18:25 provos Exp $"; +static char rcsid[] = "$Id: server.c,v 1.3 1998/03/04 11:43:52 provos Exp $"; #endif #define _SERVER_C_ @@ -80,17 +80,18 @@ init_server(void) struct ifconf ifconf; char buf[1024]; + if (global_port == 0) { #ifndef PHOTURIS_PORT - struct servent *ser; + struct servent *ser; - if ((ser = getservbyname("photuris", "udp")) == (struct servent *) NULL) - crit_error(1, "getservbyname() in init_server()"); + if ((ser = getservbyname("photuris", "udp")) == (struct servent *) NULL) + crit_error(1, "getservbyname(\"photuris\") in init_server()"); - global_port = ser->s_port; + global_port = ser->s_port; #else - global_port = PHOTURIS_PORT; + global_port = PHOTURIS_PORT; #endif - + } if ((proto = getprotobyname("udp")) == (struct protoent *) NULL) crit_error(1, "getprotobyname() in init_server()"); diff --git a/sbin/ipsec/photurisd/spi.c b/sbin/ipsec/photurisd/spi.c index e6c8a4dbbeb..b106947946a 100644 --- a/sbin/ipsec/photurisd/spi.c +++ b/sbin/ipsec/photurisd/spi.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: spi.c,v 1.4 1997/07/26 20:55:17 provos Exp $"; +static char rcsid[] = "$Id: spi.c,v 1.5 1998/03/04 11:43:53 provos Exp $"; #endif #define _SPI_C_ @@ -76,80 +76,10 @@ make_spi(struct stateob *st, char *local_address, u_int16_t i; if(*attributes == NULL) { /* We are in need of attributes */ - u_int16_t count = 0; - u_int8_t *wanted, *offered, *p; - u_int16_t wantedsize, offeredsize; - u_int16_t mode = 0; /* We only take when in ah|esp mode */ - int first = 0; /* Obmit AH|ESP header if not needed*/ - struct attribute_list *ob; - - if ((ob = attrib_find(NULL)) == NULL) { - log_error(0, "attrib_find() for default in make_spi() in " - "exchange to %s", st->address); - return -1; - } - - /* Take from Owner */ - wanted = ob->attributes; - wantedsize = ob->attribsize; - - /* Take from User */ - offered = st->uSPIoattrib; - offeredsize = st->uSPIoattribsize; - - /* This should never happen */ - if(wantedsize>BUFFER_SIZE) - return -1; - - p = buffer; - while(wantedsize>0) { - /* Scan the offered attributes */ - if (*wanted == AT_AH_ATTRIB && - (st->flags & IPSEC_OPT_AUTH)) { - first = 1; - mode = AT_AH_ATTRIB; - } else if (*wanted == AT_ESP_ATTRIB && - (st->flags & IPSEC_OPT_ENC)) { - mode = AT_ESP_ATTRIB; - first = 1; - } - - /* - * Take attributes only from AH or ESP sections. - * Obmit AH or ESP header when there are no entries - * in that section. - * XXX - put && first && in if to take only one attrib - * in each section. - */ - - if (mode && first && - *wanted != AT_AH_ATTRIB && *wanted != AT_ESP_ATTRIB && - isinattrib(offered, offeredsize, *wanted)) { - - /* Put prober header in there */ - if (first) { - p[0] = mode; - p[1] = 0; - first = 0; - count += 2; - p += 2; - } - /* We are using our own attributes, safe to proceed */ - bcopy(wanted, p, *(wanted+1) + 2); - count += *(wanted+1) + 2; - p += *(wanted+1) + 2; - } - if(wantedsize - *(wanted+1) - 2 > wantedsize) - break; - wantedsize -= *(wanted+1) + 2; - wanted += *(wanted+1) + 2; - } - if((*attributes=calloc(count,sizeof(u_int8_t))) == NULL) { - log_error(1, "Out of memory for SPI attributes (%d)", count); + if (select_attrib(st, attributes, attribsize) == -1) { + log_error(0, "select_attrib() in make_spi()"); return -1; } - *attribsize = count; - bcopy(buffer, *attributes, count); } /* Just grab a random number, this should be uniq */ diff --git a/sbin/ipsec/photurisd/state.h b/sbin/ipsec/photurisd/state.h index 8cf69c98de3..2e82cb3a202 100644 --- a/sbin/ipsec/photurisd/state.h +++ b/sbin/ipsec/photurisd/state.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: state.h,v 1.4 1997/09/02 17:26:49 provos Exp $ */ +/* $Id: state.h,v 1.5 1998/03/04 11:43:55 provos Exp $ */ /* * state.h: * state object @@ -69,7 +69,6 @@ struct stateob { char address[16]; /* Remote address */ u_int16_t port; /* Remote port */ - u_int8_t icookie[COOKIE_SIZE]; /* Initator cookie */ u_int8_t rcookie[COOKIE_SIZE]; /* Responder cookie */ u_int8_t counter; /* Connection counter */ @@ -85,6 +84,7 @@ struct stateob { u_int16_t roschemesize; /* Responder offered schemes size */ u_int8_t oSPI[SPI_SIZE]; /* Owner SPI */ + u_int8_t oSPITBV[3]; /* Three Byte Value */ u_int8_t *oSPIident; /* Owner SPI identification */ u_int8_t *oSPIattrib; /* Owner SPI attributes */ u_int16_t oSPIattribsize; @@ -100,6 +100,7 @@ struct stateob { time_t olifetime; /* Owner SPI lifetime */ u_int8_t uSPI[SPI_SIZE]; /* User SPI */ + u_int8_t uSPITBV[3]; /* Three Byte Value */ u_int8_t *uSPIident; /* User SPI identification */ u_int8_t *uSPIattrib; /* User SPI attributes */ u_int16_t uSPIattribsize; @@ -126,6 +127,8 @@ struct stateob { int retries; /* Number of retransmits */ u_int8_t *packet; /* Buffer for retransmits */ u_int16_t packetlen; + u_int8_t packetsig[16]; /* MD5 hash of an old packet */ + time_t lifetime; /* Lifetime for the exchange */ time_t exchange_lifetime; /* Use this as default */ time_t spi_lifetime; /* Use this as default */ |