diff options
author | Niels Provos <provos@cvs.openbsd.org> | 1997-07-18 22:48:52 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 1997-07-18 22:48:52 +0000 |
commit | a182901164f2df77714485fcf4f81b0cdcb0e0b5 (patch) | |
tree | 080dc3e1b75e07f244a3f6c7a710c0e9e2782602 /sbin/ipsec | |
parent | abe3a6221fda054003729a6f7d6d61dbb31e77b0 (diff) |
initial import of the photuris keymanagement daemon
Diffstat (limited to 'sbin/ipsec')
73 files changed, 11473 insertions, 0 deletions
diff --git a/sbin/ipsec/photurisd/INSTALL b/sbin/ipsec/photurisd/INSTALL new file mode 100644 index 00000000000..b86c90058e9 --- /dev/null +++ b/sbin/ipsec/photurisd/INSTALL @@ -0,0 +1,31 @@ +In order to build the Photuris daemon you need the following libraries + - gmp-2.0.2 + - libdes-4.0.1 + +You can find the sources for the above library also at the following +location: http://www.physnet.uni-hamburg.de/provos/photuris/ + +Compile them and change the directories in the Makefile accordingly. +Look for the right definitions for your OS in the Makefile. At the moment +there are sections for AIX, Solaris, Linux and OpenBSD. +For Security Associations to be setup in the kernel you need to +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. + +For the daemon to work with other IPSec implementations you should look +in the sources for #ifdef IPSEC. + +You might also want to customize the following files: +photuris.conf +attributes.conf +secrets.conf + +If you compiled the daemon without -DDEBUG, you also need an +entry in /etc/services like that: +photuris 468/udp # photuris keymangement daemon + +More complete instructions can be found in README.howtouse diff --git a/sbin/ipsec/photurisd/Makefile b/sbin/ipsec/photurisd/Makefile new file mode 100644 index 00000000000..c3f144300c8 --- /dev/null +++ b/sbin/ipsec/photurisd/Makefile @@ -0,0 +1,23 @@ +PROG= photurisd +LDADD= -lgmp -ldes +SRCS= photuris_cookie_request.c photuris_cookie_response.c \ + photuris_value_request.c photuris_value_response.c \ + photuris_identity_request.c photuris_identity_response.c \ + photuris_spi_needed.c photuris_spi_update.c photuris_error_message.c \ + photuris_packet_encrypt.c \ + handle_cookie_request.c handle_value_request.c \ + handle_cookie_response.c handle_value_response.c \ + handle_identity_request.c handle_identity_response.c \ + handle_spi_needed.c handle_spi_update.c\ + handle_bad_cookie.c handle_resource_limit.c \ + handle_verification_failure.c handle_message_reject.c \ + errlog.c config.c scheme.c schedule.c server.c \ + buffer.c compute_secrets.c cookie.c exchange.c identity.c \ + modulus.c spi.c state.c validity.c attributes.c \ + photurisd.c packet.c api.c kernel.c + +#CFLAGS+= -g -I. -DDEBUG -DIPSEC +CFLAGS+= -I. -DIPSEC +MAN= photurisd.1 + +.include <bsd.prog.mk> diff --git a/sbin/ipsec/photurisd/README b/sbin/ipsec/photurisd/README new file mode 100644 index 00000000000..d77f1f9d03c --- /dev/null +++ b/sbin/ipsec/photurisd/README @@ -0,0 +1,18 @@ +This is an implementation of the Photuris keymanagement protocol +according to the drafts: + draft-simpson-photuris-12.txt + draft-simpson-photuris-schemes-01.txt + +For quick installation instructions read INSTALL, or otherwise +README.howtouse for more complete information. + +At the moment only the PF_ENCAP kernel interface for John Ioannidis' +and Angelos D. Keromytis' IPSec as to be found in OpenBSD is supported. +It should be fairly easy to adapt the daemon to other implementations, +just look at the sections found by 'grep IPSEC *.c' + +I am grateful for the help provided by Angelos D. Keromytis +and Theo de Raadt. + +This software was written in Germany May 1997 by Niels Provos. +Any questions are welcome at provos@physnet.uni-hamburg.de diff --git a/sbin/ipsec/photurisd/README.howtouse b/sbin/ipsec/photurisd/README.howtouse new file mode 100644 index 00000000000..ba8b337a1c1 --- /dev/null +++ b/sbin/ipsec/photurisd/README.howtouse @@ -0,0 +1,76 @@ + + How to use Photuris with IPSec ? + +What is IPSec ? + + IP Security is a framework providing authentication/integrity and + privacy to network traffic. Authenticated data can not be modified by + third parties and encryption conceals the content of packets. + +What has Photuris to do with IPSec ? + + In order to transmit encrypted or authenticated data between two + hosts, those two hosts have to aggree on session keys which are used + as input for the encryption and authenication functions. + + The Photuris protocol exchanges keys in such a way that no + eavesdropper will have knowledge of the session keys. It also allows + for frequent changes of the session keys, forward secrecy and party + privacy protection. + +How to get it working ? + + Compiling the daemon + + Get the Photuris sources and also the following libraries: + gmp-2.0.2 and libdes-4.01. Put those libraries in one dir and if + you like you can do the following steps afterwards: + +1. tar -xvzf Photuris-src.tar.gz +2. tar -xvzf gmp-2.0.2.tar.gz; cd gmp-2.0.2; ./configure; make +3. mkdir des; cd des; tar -xvzf ../libdes-4.01.tar.gz; make +4. cd Photuris +5. make (edit the Makefile and remove -DDEBUG, if you dont want to see what + 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) + + If you compiled the photuris daemon with -DDEBUG you should see an + exchange of values now and finally the shared secret from which the + session keys are derived. + + If you compiled the photuris daemon with -IPSEC and also have a kernel + with IPSEC compiled into it, you could start for example + +8. tcpdump proto 51 & +9. telnet host1 + + and see the authenticated packets flowing between the two hosts. Look + at the output of + +10. cat /kern/ipsec +11. netstat -rn + + will show you some information also. + + Enabling IPSEC in the OpenBSD kernel + + Add the following two lines into your kernel config file: +config IPSEC +pseudo-device enc 4 + + Possible configuration + + There are three files which can be configured locally. + * photuris.conf - contains the moduli for the Diffie-Hellmann + Keyexchange, the offered schemes and various timeouts. + * attributes.conf - the attributes which are offered to different + parties + * secrets.conf - the preconfigured symmetric secrets which should + hopefully soon be replaced by public keys. + + _________________________________________________________________ + + If you have any questions write mail to + provos@physnet.uni-hamburg.de diff --git a/sbin/ipsec/photurisd/api.c b/sbin/ipsec/photurisd/api.c new file mode 100644 index 00000000000..219f7b5c028 --- /dev/null +++ b/sbin/ipsec/photurisd/api.c @@ -0,0 +1,168 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Parts derived from code by Angelos D. Keromytis, kermit@forthnet.gr + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This is an experimental implementation of the Photuris Session Key Management + * Protocol, as of draft-ietf-ipsec-photuris-06.txt. + * + * The usual disclaimers/non-guarantees etc. etc. apply. + */ + +#ifndef lint +static char rcsid[] = "$Id: api.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _API_C_ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <string.h> +#include "state.h" +#include "photuris.h" +#include "api.h" +#include "errlog.h" +#include "buffer.h" +#include "schedule.h" +#include "server.h" +#include "packet.h" + + +/* + * process_api: + * process requests from user processes or kernel notify + */ + +void +process_api(int fd, int sendsock) +{ + struct stateob *st; + int sz, i; + +#ifdef DEBUG + printf("Entering API.\n"); +#endif + + bzero(buffer, BUFFER_SIZE); + + if ((sz = read(fd, buffer, BUFFER_SIZE)) == -1) + crit_error(1, "read() in process_api()"); + + buffer[sz >= BUFFER_SIZE ? BUFFER_SIZE -1 : sz] = 0; + + if (!sz) + return; + + if (addresses != (char **) NULL) + for (i = 0; i<num_ifs; i++) { + if (addresses[i] == (char *)NULL) + continue; + if (!strcmp(addresses[i], buffer)) { + /* XXX Code to notify kernel of failure here */ + log_error(0, "discarded request to initiate KES with localhost"); + return; + } + } + + if (inet_addr(buffer) == -1) { + /* XXX Code to notify kernel of failure */ + log_error(0, "invalid destination IP address: %s", buffer); + return; + } + +#ifdef DEBUG + printf("[Initiating KES with %s]\n", buffer); +#endif + + /* Set up a new state object */ + if ((st = state_new()) == NULL) { + log_error(1, "state_new() in process_api()"); + return; + } + + /* Default options */ + st->flags |= IPSEC_OPT_ENC | IPSEC_OPT_AUTH; + + if (start_exchange(sendsock, st, buffer, global_port) == -1) { + log_error(0, "start_exchange in process_api()"); + state_value_reset(st); + return; + } + + state_insert(st); +#ifdef DEBUG + printf("API finished.\n"); +#endif +} + +int +start_exchange(int sd, struct stateob *st, char *address, int port) +{ + struct sockaddr_in sin; + + /* Now fill it in */ + strncpy(st->address, address, 15); + st->address[15] = '\0'; + st->port = port; + st->initiator = 1; + + + /* Determine sender address before we invalidate buffer */ + sin.sin_addr.s_addr = inet_addr(st->address); + sin.sin_port = htons(st->port); + sin.sin_family = AF_INET; + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_cookie_request(st, packet_buffer, &packet_size) == -1) { + log_error(0, "photuris_cookie_request() in start_exchange() " + "for %s:%d", st->address, st->port); + return -1; + } + + /* Save the packets for later retransmits */ + packet_save(st, packet_buffer, packet_size); + + if (sendto(sd, packet_buffer, packet_size, 0, + (struct sockaddr *) &sin, sizeof(sin)) != packet_size) { + /* XXX Code to notify kernel of failure */ + log_error(1, "sendto() in start_exchange() for %s:%d", + st->address, st->port); + return -1; + } + + schedule_insert(TIMEOUT, retrans_timeout, st->icookie, COOKIE_SIZE); + + return 0; +} diff --git a/sbin/ipsec/photurisd/api.h b/sbin/ipsec/photurisd/api.h new file mode 100644 index 00000000000..35d89b2a5b9 --- /dev/null +++ b/sbin/ipsec/photurisd/api.h @@ -0,0 +1,60 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * This code is originally from Angelos D. Keromytis, kermit@forthnet.gr + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Header: /cvs/OpenBSD/src/sbin/ipsec/photurisd/Attic/api.h,v 1.1 1997/07/18 22:48:48 provos Exp $ + * + * $Author: provos $ + * + * $Log: api.h,v $ + * Revision 1.1 1997/07/18 22:48:48 provos + * Initial revision + * + * Revision 1.1 1997/05/22 17:36:07 provos + * Initial revision + * + */ + +#ifndef _API_H_ +#define _API_H_ + +#undef EXTERN +#ifdef _API_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN void process_api(int, int); +EXTERN int start_exchange(int sd, struct stateob *st, char *address, int port); + +#endif /* _API_H_ */ diff --git a/sbin/ipsec/photurisd/attributes.c b/sbin/ipsec/photurisd/attributes.c new file mode 100644 index 00000000000..1e9ff0f6605 --- /dev/null +++ b/sbin/ipsec/photurisd/attributes.c @@ -0,0 +1,155 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * attributes.c: + * functions for handling attributess + */ + +#ifndef lint +static char rcsid[] = "$Id: attributes.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _ATTRIBUTES_C_ + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "attributes.h" + +static struct attribute_list *attribob = NULL; + +int +attrib_insert(struct attribute_list *ob) +{ + struct attribute_list *tmp; + + ob->next = NULL; + + if(attribob == NULL) { + attribob = ob; + return 1; + } + + tmp=attribob; + while(tmp->next!=NULL) + tmp = tmp->next; + + tmp->next = ob; + return 1; +} + +int +attrib_unlink(struct attribute_list *ob) +{ + struct attribute_list *tmp; + if(attribob == ob) { + attribob = ob->next; + free(ob); + return 1; + } + + for(tmp=attribob; tmp!=NULL; tmp=tmp->next) { + if(tmp->next==ob) { + tmp->next=ob->next; + free(ob); + return 1; + } + } + return 0; +} + +struct attribute_list * +attrib_new(void) +{ + struct attribute_list *p; + + if((p = calloc(1, sizeof(struct attribute_list)))==NULL) + return NULL; + + return p; +} + +int +attrib_value_reset(struct attribute_list *ob) +{ + if (ob->address != NULL) + free(ob->address); + if (ob->attributes != NULL) + free(ob->attributes); + + bzero(ob, sizeof(struct attribute_list)); + return 1; +} + +/* + * find the attributes to the address or 0 address. + * if passed a null pointer as first argument we return our default + * list. + */ + +struct attribute_list * +attrib_find(char *address) +{ + struct attribute_list *tmp = attribob; + struct attribute_list *null = NULL; + while(tmp!=NULL) { + if (tmp->address == NULL) { + null = tmp; + if (address == NULL) + break; + } + else if (address != NULL && + (tmp->netmask & inet_addr(address)) == + inet_addr(tmp->address)) + return tmp; + + tmp = tmp->next; + } + return null; +} + +void +attrib_cleanup() +{ + struct attribute_list *p; + struct attribute_list *tmp = attribob; + while(tmp!=NULL) { + p = tmp; + tmp = tmp->next; + attrib_value_reset(p); + free(p); + } + attribob = NULL; +} + diff --git a/sbin/ipsec/photurisd/attributes.h b/sbin/ipsec/photurisd/attributes.h new file mode 100644 index 00000000000..87cedd1ed43 --- /dev/null +++ b/sbin/ipsec/photurisd/attributes.h @@ -0,0 +1,85 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * attributes.h: + * attributes for a security association + */ + +#ifndef _ATTRIBUTES_H_ +#define _ATTRIBUTES_H_ + +#undef EXTERN +#ifdef _ATTRIBUTES_C_ +#define EXTERN +#else +#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_MD5_KDP 5 +#define AT_DES_CBC 8 +#define AT_ORG 255 + +#define MD5_KEYLEN 384 +#define DES_KEYLEN 64 + +/* XXX - Only for the moment */ +#define DH_G_2_MD5 2 +#define DH_G_3_MD5 3 +#define DH_G_2_DES_MD5 4 +#define DH_G_5_MD5 5 +#define DH_G_3_DES_MD5 6 +#define DH_G_VAR_MD5 7 +#define DH_G_2_3DES_SHA1 8 +#define DH_G_5_DES_MD5 10 +#define DH_G_3_3DES_SHA1 12 +#define DH_G_VAR_DES_MD5 14 +#define DH_G_5_3DES_SHA1 20 +#define DH_G_VAR_3DES_SHA1 28 + +struct attribute_list { + struct attribute_list *next; + char *address; + in_addr_t netmask; + u_int8_t *attributes; + u_int16_t attribsize; +}; + +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 void attrib_cleanup(void); + +#endif /* ATTRIBUTES_H */ diff --git a/sbin/ipsec/photurisd/buffer.c b/sbin/ipsec/photurisd/buffer.c new file mode 100644 index 00000000000..5794e28118f --- /dev/null +++ b/sbin/ipsec/photurisd/buffer.c @@ -0,0 +1,46 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * buffer.c: + * buffer variables. + */ + +#ifndef lint +static char rcsid[] = "$Id: buffer.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <sys/types.h> + +#define _BUFFER_C +#include "buffer.h" + +int packet_size; +char buffer[BUFFER_SIZE]; +char packet_buffer[PACKET_BUFFER_SIZE]; diff --git a/sbin/ipsec/photurisd/buffer.h b/sbin/ipsec/photurisd/buffer.h new file mode 100644 index 00000000000..fa4eaf34bff --- /dev/null +++ b/sbin/ipsec/photurisd/buffer.h @@ -0,0 +1,48 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 $ */ +/* + * buffer.h: + * variables with buffers. + */ + +#ifndef _BUFFER_H_ +#define _BUFFER_H_ + +#define PACKET_BUFFER_SIZE 8192 +#define BUFFER_SIZE 8192 + +#ifndef _BUFFER_C +extern char buffer[]; +extern char packet_buffer[]; +extern int packet_size; +#endif + +#endif /* _BUFFER_H */ diff --git a/sbin/ipsec/photurisd/compute_secrets.c b/sbin/ipsec/photurisd/compute_secrets.c new file mode 100644 index 00000000000..9b87342eea6 --- /dev/null +++ b/sbin/ipsec/photurisd/compute_secrets.c @@ -0,0 +1,370 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * compute_secrets.c: + * shared secret with diffie-hellman key exchange + * cryptographic hashes for session keys + */ + +#ifndef lint +static char rcsid[] = "$Id: compute_secrets.c,v 1.1 1997/07/18 22:48:48 provos Exp $"; +#endif + +#define _SECRETS_C_ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <gmp.h> +#include <md5.h> +#include "state.h" +#include <sha1.h> +#include "config.h" +#include "attributes.h" +#include "modulus.h" +#include "secrets.h" +#include "buffer.h" +#include "spi.h" +#include "exchange.h" +#include "scheme.h" +#include "errlog.h" + +int MD5privacykey(struct stateob *st, u_int8_t *key, u_int8_t *packet, + u_int16_t bytes, u_int16_t order, int owner); +int SHA1privacykey(struct stateob *st, u_int8_t *key, 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; + + mpz_t tmp, bits, tex; + + mpz_init(tmp); + mpz_init(bits); + + if((mod=mod_find_modgen(st->modulus, st->generator)) == NULL) { + log_error(0, "Can't find exchange information in cache in compute_shared_secret()"); + return -1; + } + + /* Compute Diffie-Hellmann a^(xy) (mod n) */ + + mpz_init_set_varpre(tex, st->texchange); + mpz_powm(tmp, tex, mod->private_value, mod->modulus); + + mpz_clear(tex); + + varpre_get_number_bits(bits, scheme_get_mod(st->scheme)); + + *sharedsize = BUFFER_SIZE; + if(mpz_to_varpre(buffer, sharedsize, tmp, bits) == -1) + return -1; + mpz_clear(bits); + mpz_clear(tmp); + + 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); + return 0; +} + +/* + * Generate session keys for all attributes in given SPI. + */ + +int +make_session_keys(struct stateob *st, struct spiob *spi) +{ + u_int8_t *p, *attributes, **secret; + u_int16_t attribsize, *secretsize; + u_int16_t i, count = 0; + int bits; + + attributes = spi->attributes; + attribsize = spi->attribsize; + secret = &(spi->sessionkey); + secretsize = &(spi->sessionkeysize); + + if (*secret != NULL) + return 0; /* Already calculated */ + + p = attributes; + for (i = 0; i<attribsize; i += p[i+1] + 2) { + if (p[i] != AT_AH_ATTRIB && p[i] != AT_ESP_ATTRIB) { + bits = get_session_key_length(p+i); + if (bits == -1) { + log_error(0, "Invalid attribute choice for SPI in make_session_keys()"); + return -1; + } + count += bits & 7 ? (bits >> 3) + 1 : bits >> 3; + } + } + if ((*secret = calloc(count, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in make_session_keys()"); + return -1; + } + *secretsize = count; + + count = 0; + p = *secret; + for (i = 0; i<attribsize; i += attributes[i+1] + 2) { + if (attributes[i] != AT_AH_ATTRIB && + attributes[i] != AT_ESP_ATTRIB) { + bits = compute_session_key(st, p, attributes+i, spi->owner, + &count); + if (bits == -1) + return -1; +#ifdef DEBUG + { int d = BUFFER_SIZE; + printf("%s session key for AT %d: ", + spi->owner ? "Owner" : "User", (int)attributes[i]); + bin2hex(buffer, &d, p, + bits & 7 ? (bits >> 3) + 1 : bits >> 3); + printf("0x%s\n", buffer); + } +#endif /* DEBUG */ + + p += bits & 7 ? (bits >> 3) + 1 : bits >> 3; + } + } + + return 0; +} + + +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: + log_error(0, "Unknown attribute %d in get_session_key_length()", + *attribute); + return -1; + } +} + +/* + * Compute session keys for the attributes in the security association. + * owner determines the direction of the spi session key. + * order is the amount of bits we already used for other session keys. + */ + +int +compute_session_key(struct stateob *st, u_int8_t *key, + u_int8_t *attribute, int owner, + u_int16_t *order) +{ + u_int16_t size, i,n; + u_int8_t digest[16]; + int bits; + MD5_CTX ctx; + + if ((bits = get_session_key_length(attribute)) == -1) + return -1; + + size = bits >> 3; + if(bits & 0x7) + size++; + + /* XXX - we only do md5 at the moment */ + *order = (*order^(*order&0x7f)) + (*order & 0x7f ? 128 : 0); + + /* As many shared secrets we used already */ + n = *order >> 7; + + do { + MD5Init(&ctx); + MD5Update(&ctx, st->icookie, COOKIE_SIZE); + MD5Update(&ctx, st->rcookie, COOKIE_SIZE); + if(owner) { /* Session key for Owner SPI */ + MD5Update(&ctx,st->oSPIsecret,st->oSPIsecretsize); + MD5Update(&ctx,st->uSPIsecret,st->uSPIsecretsize); + MD5Update(&ctx,st->oSPIidentver, st->oSPIidentversize); + } else { /* Session key for User SPI */ + MD5Update(&ctx,st->uSPIsecret,st->uSPIsecretsize); + MD5Update(&ctx,st->oSPIsecret,st->oSPIsecretsize); + MD5Update(&ctx,st->uSPIidentver, st->uSPIidentversize); + } + for(i=0; i<n; i++) + MD5Update(&ctx,st->shared, st->sharedsize); + n++; + MD5Final(digest, &ctx); + bcopy(digest, key, size>16 ? 16 : size); + key += size>16 ? 16 : size; + + /* Unsigned integer arithmetic */ + size -= size>16 ? 16 : size; + } while(size > 0); + + *order += (bits^(bits&0x7f)) + (bits & 0x7f ? 128 : 0); + + return bits; +} + +/* + * order gives the number of bits already used 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 size; + + size = bits >> 3; + if(bits & 0x7) + size++; + + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: + case DH_G_2_DES_MD5: + case DH_G_3_DES_MD5: + case DH_G_5_DES_MD5: + return MD5privacykey(st, key, packet, size, order, owner); + case DH_G_2_3DES_SHA1: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: + return SHA1privacykey(st, key, packet, size, order, owner); + default: + log_error(0, "Unknown exchange scheme in compute_privacy_key()"); + return -1; + } +} + + +int +MD5privacykey(struct stateob *st, u_int8_t *key, u_int8_t *packet, + u_int16_t bytes, u_int16_t order, int owner) +{ + MD5_CTX ctx, ctxb; + u_int16_t i, n; + struct moduli_cache *mod; + u_int8_t digest[16]; + + MD5Init(&ctxb); + + MD5Update(&ctxb, packet, 2*COOKIE_SIZE + 4 + SPI_SIZE); + + if((mod=mod_find_modgen(st->modulus,st->generator)) == NULL) + return -1; + + if (owner) { + MD5Update(&ctxb, mod->exchangevalue, mod->exchangesize); + MD5Update(&ctxb, st->texchange, st->texchangesize); + } else { + MD5Update(&ctxb, st->texchange, st->texchangesize); + MD5Update(&ctxb, mod->exchangevalue, mod->exchangesize); + } + + /* As many shared secrets we used already */ + n = order&0x7f ? (order >> 7) + 1 : order >> 7; + for(i=0; i<n; i++) + MD5Update(&ctxb, st->shared, st->sharedsize); + + do { + ctx = ctxb; + MD5Update(&ctx, st->shared, st->sharedsize); + ctxb = ctx; + + MD5Final(digest, &ctx); + bcopy(digest, key, bytes>16 ? 16 : bytes); + key += bytes>16 ? 16 : bytes; + + /* Unsigned integer arithmetic */ + bytes -= bytes>16 ? 16 : bytes; + } while(bytes>=16); + + return 0; +} + +int +SHA1privacykey(struct stateob *st, u_int8_t *key, u_int8_t *packet, + u_int16_t bytes, u_int16_t order, int owner) +{ + SHA1_CTX ctx, ctxb; + u_int16_t i, n; + struct moduli_cache *mod; + u_int8_t digest[20]; + + SHA1Init(&ctxb); + + SHA1Update(&ctxb, packet, 2*COOKIE_SIZE + 4 + SPI_SIZE); + + if((mod=mod_find_modgen(st->modulus,st->generator)) == NULL) + return -1; + + if (owner) { + SHA1Update(&ctxb, mod->exchangevalue, mod->exchangesize); + SHA1Update(&ctxb, st->texchange, st->texchangesize); + } else { + SHA1Update(&ctxb, st->texchange, st->texchangesize); + SHA1Update(&ctxb, mod->exchangevalue, mod->exchangesize); + } + + + /* As many shared secrets we used already */ + n = order%160 ? order/160+1 : order/160; + for (i=0; i<n; i++) + SHA1Update(&ctxb, st->shared, st->sharedsize); + + do { + + ctx = ctxb; + SHA1Update(&ctx, st->shared, st->sharedsize); + ctxb = ctx; + + SHA1Final(digest, &ctx); + + bcopy(digest, key, bytes>20 ? 20 : bytes); + + key += bytes>20 ? 20 : bytes; + + /* Unsigned integer arithmetic */ + bytes -= bytes>20 ? 20 : bytes; + } while(bytes>0); + + return 0; +} diff --git a/sbin/ipsec/photurisd/config.c b/sbin/ipsec/photurisd/config.c new file mode 100644 index 00000000000..24d68d9888c --- /dev/null +++ b/sbin/ipsec/photurisd/config.c @@ -0,0 +1,815 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * config.c: + * config handling functions + */ + +#ifndef lint +static char rcsid[] = "$Id: config.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#define _CONFIG_C_ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <time.h> +#include <pwd.h> +#include <gmp.h> +#if defined(_AIX) || defined(NEED_STRSEP) +#include "strsep.h" +#endif +#include "config.h" +#include "photuris.h" +#include "modulus.h" +#include "exchange.h" +#include "attributes.h" +#include "buffer.h" +#include "state.h" +#include "identity.h" +#include "spi.h" +#include "server.h" +#include "errlog.h" +#include "buffer.h" +#include "scheme.h" +#include "api.h" + + +static FILE *config_fp; + +static void +open_config_file(char *file) +{ + char *p; + + if (file != NULL) + p = file; + else + p = config_file; + + if (p == NULL) + crit_error(0, "no file in open_config_file()"); + + config_fp = fopen(p, "r"); + if (config_fp == (FILE *) NULL) + crit_error(1, "can't open file %s in open_config_file()", p); +} + +static void +close_config_file(void) +{ + fclose(config_fp); +} + +static char * +config_get(char *token) +{ + char *p; + while(fgets(buffer, BUFFER_SIZE, config_fp)) { + p = buffer; + chomp(p); + while(isspace(*p)) + p++; + while(isspace(p[strlen(p)-1])) + p[strlen(p)-1] = '\0'; + + if (*p == '#') + continue; + + if (!strncmp(p, token, strlen(token))) + return p; + + } + + return NULL; +} + +int +init_attributes(void) +{ + char *p, *p2; + struct attribute_list *ob = NULL; + struct in_addr in; + int def_flag = 0; + char attrib[257]; + +#ifdef DEBUG + printf("[Setting up attributes]\n"); +#endif + + open_config_file(attrib_file); + while((p2 = config_get("")) != NULL) { + p = strsep(&p2, " "); + if (p == NULL) + continue; + + 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()"); + + 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_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 { + log_error(0, "Unknown attribute %s in init_attributes()", + p); + continue; + } + + /* Copy attributes in object */ + ob->attributes = realloc(ob->attributes, + ob->attribsize + attrib[1] +2); + if (ob->attributes == NULL) + crit_error(1, "realloc() in init_attributes()"); + + bcopy(attrib, ob->attributes + ob->attribsize, attrib[1] + 2); + ob->attribsize += attrib[1] + 2; + + } else { +#ifdef DEBUG + printf("Reading attributes for %s / %s\n", + p, p2); +#endif + /* Insert previous attribute */ + if (ob != NULL) { + attrib_insert(ob); + if (ob->address == NULL) + def_flag = 1; + } + + /* Get a new attribute object */ + if ((ob = attrib_new()) == NULL) + crit_error(1, "attribute_new() in init_attributes()"); + + ob->netmask = inet_addr(p2); + in.s_addr = inet_addr(p) & ob->netmask; + if ((ob->address = calloc(strlen(inet_ntoa(in))+1, + sizeof(char))) == NULL) + crit_error(1, "calloc() in init_attributes()"); + strcpy(ob->address, inet_ntoa(in)); + } + } + if (ob != NULL) + attrib_insert(ob); + close_config_file(); + + if (!def_flag) + crit_error(0, "No default attribute list in init_attributes()"); + return 1; +} + +int +init_schemes(void) +{ + struct moduli_cache *tmp; + mpz_t generator, bits; + u_int32_t scheme_bits; + + char *p, *p2; + u_int16_t size; + int gen_flag = 0; + +#ifdef DEBUG + printf("[Setting up exchange schemes]\n"); +#endif + + open_config_file(NULL); + + mpz_init(generator); + mpz_init(bits); + + while((p = config_get(CONFIG_EXCHANGE)) != NULL) { + p2 = p + strlen(CONFIG_EXCHANGE); + if (!isspace(*p2)) + continue; + while(isspace(*p2)) + p2++; + + /* Get exchange Scheme */ + if (!strncmp(p2, "DH_G_2_MD5", 10)) { + p = p2 + 11; + mpz_set_ui(generator, 2); + *(u_int16_t *)buffer = htons(DH_G_2_MD5); + } else if (!strncmp(p2, "DH_G_2_DES_MD5", 14)) { + p = p2 + 15; + mpz_set_ui(generator, 2); + *(u_int16_t *)buffer = htons(DH_G_2_DES_MD5); + } else if (!strncmp(p2, "DH_G_2_3DES_SHA1", 16)) { + p = p2 + 17; + mpz_set_ui(generator, 2); + *(u_int16_t *)buffer = htons(DH_G_2_3DES_SHA1); + } else { + log_error(0, "Unknown scheme %s in init_schemes()", p2); + continue; + } + + /* Base schemes need a modulus */ + if ((scheme_bits = strtol(p, NULL, 10)) == 0 && + ntohs(*(u_int16_t *)buffer) == scheme_get_ref(buffer) ) { + log_error(0, "No bits in scheme %s in init_schemes()", p2); + continue; + } + + if (scheme_bits != 0) { + + if ((tmp = mod_find_generator(generator)) == NULL) + continue; + + while(tmp != NULL) { + mpz_get_number_bits(bits, tmp->modulus); + if (mpz_get_ui(bits) == scheme_bits) + break; + tmp = mod_find_generator_next(tmp, generator); + } + if (tmp == NULL) { + log_error(0, "Could not find %d bit modulus in init_schemes()", + scheme_bits); + continue; + } + + size = BUFFER_SIZE - 2; + if (mpz_to_varpre(buffer+2, &size, tmp->modulus, bits) == -1) + continue; + } else { + size = 2; + buffer[2] = buffer[3] = 0; + } + + global_schemes = realloc(global_schemes, global_schemesize + + size + 2); + if (global_schemes == NULL) + crit_error(1, "out of memory in init_schems()"); + + /* DH_G_2_MD5 is a MUST, so we generate it if gen_flag == 0 */ + if (*(u_int16_t *)buffer == htons(DH_G_2_MD5)) + gen_flag = 1; + + bcopy(buffer, global_schemes + global_schemesize, size + 2); + global_schemesize += size + 2; + + } +#ifdef DEBUG + printf("Read %d bytes of exchange schemes.\n", global_schemesize); +#endif + close_config_file(); + + if (!gen_flag) { + log_error(0, "DH_G_2_MD5 not in config file, inserting it"); + mpz_set_ui(generator, 2); + if ((tmp = mod_find_generator(generator)) == NULL) + crit_error(0, "no modulus for generator 2 in init_schemes()"); + + mpz_get_number_bits(bits, tmp->modulus); + size = BUFFER_SIZE - 2; + if (mpz_to_varpre(buffer+2, &size, tmp->modulus, bits) == -1) + crit_error(0, "mpz_to_varpre() in init_schemes()"); + + *(u_int16_t *)buffer = htons(DH_G_2_MD5); + } + + mpz_clear(generator); + mpz_clear(bits); + + return 1; +} + +int +init_moduli(int primes) +{ + struct moduli_cache *tmp; + char *p, *p2; + mpz_t m, g; + + open_config_file(NULL); + +#ifdef DEBUG + printf("[Bootstrapping moduli]\n"); +#endif + + mpz_init(m); + mpz_init(g); + + while((p = config_get(CONFIG_MODULUS)) != NULL) { + p2 = p + strlen(CONFIG_MODULUS); + while(isspace(*p2)) + p2++; + + /* Get generator */ + if ((p=strsep(&p2, " ")) == NULL) + continue; + + /* Convert an ascii string to mpz, autodetect base */ + if (mpz_set_str(g, p, 0) == -1) + continue; + + /* Get modulus */ + if (mpz_set_str(m, p2, 0) == -1) + continue; + + if ((tmp = mod_new_modgen(m, g)) == NULL) + crit_error(0, "no memory in init_moduli()"); + + mod_insert(tmp); + + if (!primes) { + tmp->iterations = MOD_PRIME_MAX; + tmp->status = MOD_PRIME; + } + } + + close_config_file(); + + mpz_clear(m); + mpz_clear(g); + + /* Now check primality */ + if (primes) + mod_check_prime(MOD_PRIME_MAX, 0); + + return 0; +} + +int +init_times(void) +{ + char *p, *p2; + int i, *value; + open_config_file(NULL); + +#ifdef DEBUG + printf("[Setting up times]\n"); +#endif + + while((p2 = config_get(CONFIG_CONFIG)) != NULL) { + p2 += sizeof(CONFIG_CONFIG); + + if ((p=strsep(&p2, " ")) == NULL) + continue; + if (p2 == NULL) + continue; + + if (!strcmp(p, CONFIG_MAX_RETRIES)) + value = &max_retries; + else if (!strcmp(p, CONFIG_RET_TIMEOUT)) + value = &retrans_timeout; + else if (!strcmp(p, CONFIG_EX_TIMEOUT)) + value = &exchange_lifetime; + else if (!strcmp(p, CONFIG_EX_LIFETIME)) + value = &exchange_lifetime; + else if (!strcmp(p, CONFIG_SPI_LIFETIME)) + value = &spi_lifetime; + else { + log_error(0, "unkown options %s in init_times()", p); + continue; + } + + if ((i = atoi(p2)) < 1) { + log_error(0, "value %d too small in init_times()", i); + continue; + } + + *value = i; + } + + close_config_file(); + + /* Now some hard coded checks */ + if (exchange_timeout < max_retries*retrans_timeout) + crit_error(0, "Exchange Timeout < Retransmission * Retrans. Timeout"); + if (exchange_lifetime < 2*exchange_timeout) + crit_error(0, "Exchange Lifetime < 2 * Exchange Timeout"); + if (spi_lifetime < 3*exchange_timeout) + crit_error(0, "SPI Lifetime < 3 * Exchange Timeout"); + + return 0; +} + +int +init_startup(void) +{ + char *p, *p2, *p3; + struct stateob *st = NULL; + +#ifdef DEBUG + printf("[Starting initial exchanges]\n"); +#endif + + open_config_file(PHOTURIS_STARTUP); + while(1) { + p2 = config_get(""); + /* We read a newline or end of file */ + if((p2 == NULL || strlen(p2) == 0) && st != NULL) { + if (st->address == NULL) { + log_error(0, "no destination given in init_startip()"); + state_value_reset(st); + st = NULL; + if (p2 != NULL) + continue; + else + break; + } + if (st->port == 0) + st->port = global_port; + if (st->flags == 0) + st->flags = IPSEC_OPT_ENC | IPSEC_OPT_AUTH; + if (st->isrc != -1 && st->idst != -1 && + st->isrc && st->idst) + st->flags |= IPSEC_OPT_TUNNEL; + +#ifdef DEBUG + printf("Starting exchange with: %s:%d and options:", + st->address, st->port); + if (st->flags & IPSEC_OPT_ENC) + printf("%s ", OPT_ENC); + if (st->flags & IPSEC_OPT_AUTH) + printf("%s ", OPT_AUTH); + if (st->flags & IPSEC_OPT_TUNNEL) + printf("(tunnel mode) "); + else + printf("(transport mode) "); + if (st->user != NULL) + printf("for user %s", st->user); + printf("\n"); +#endif + if (start_exchange(global_socket, st, + st->address, st->port) == -1) { + log_error(0, "start_exchange in init_startup()"); + state_value_reset(st); + st = NULL; + } else { + state_insert(st); + st = NULL; + } + } + if (p2 == NULL) + break; + if (!strlen(p2)) + continue; + + if (st == NULL && ((st = state_new()) == NULL)) + crit_error(0, "state_new() in init_startup()"); + + while((p=strsep(&p2, " ")) != NULL) { + if ((p3 = strchr(p, '=')) == NULL) { + log_error(0, "missing = in %s in init_startup()", p); + continue; + } + if (strlen(++p3) == 0) { + log_error(0, "option missing after %s in init_startup()", + p); + continue; + } + if (!strncmp(p, OPT_DST, strlen(OPT_DST))) { + if (inet_addr(p3) == -1) { + log_error(0, "invalid destination IP address: %s", + p3); + continue; + } + strncpy(st->address, p3, 15); + st->address[15] = '\0'; + } else if (!strncmp(p, OPT_PORT, strlen(OPT_PORT))) { + if ((st->port = atoi(p3)) == 0) { + log_error(0, "invalid port number: %s", p3); + continue; + } + } else if (!strncmp(p, OPT_USER, strlen(OPT_USER))) { + struct passwd *pwd; + if ((st->user = strdup(p3)) == NULL) { + log_error(1, "strdup() in init_startup()"); + continue; + } + if ((pwd = getpwnam(st->user)) == NULL) { + log_error(1, "getpwnam() in init_startup()"); + continue; + } + } else if (!strncmp(p, OPT_OPTIONS, strlen(OPT_OPTIONS))) { + while((p = strsep(&p3, ",")) != NULL) { + if(!strcmp(p, OPT_ENC)) + st->flags |= IPSEC_OPT_ENC; + else if(!strcmp(p, OPT_AUTH)) + st->flags |= IPSEC_OPT_AUTH; + else { + log_error(0, "Unkown options %s in init_startup()", + p); + continue; + } + } + } else if (!strncmp(p, OPT_TSRC, strlen(OPT_TSRC))) { + p = strsep(&p3, "/"); + if (p == NULL || p3 == NULL) { + log_error(0, "tsrc missing addr/mask in init_startup()"); + continue; + } + if ((st->isrc = inet_addr(p)) == -1) { + log_error(0, "invalid tsrc addr %s in init_startup()", + p); + continue; + } + if ((st->ismask = inet_addr(p3)) == -1 && + strcmp(p3, "255.255.255.255")) { + log_error(0, "invalid tsrc mask %s in init_startup()", + p3); + st->isrc = -1; + continue; + } + } else if (!strncmp(p, OPT_TDST, strlen(OPT_TDST))) { + p = strsep(&p3, "/"); + if (p == NULL || p3 == NULL) { + log_error(0, "tdst missing addr/mask in init_startup()"); + continue; + } + if ((st->idst = inet_addr(p)) == -1) { + log_error(0, "invalid tdst addr %s in init_startup()", + p); + continue; + } + if ((st->idmask = inet_addr(p3)) == -1 && + strcmp(p3, "255.255.255.255")) { + log_error(0, "invalid tdst mask %s in init_startup()", + p3); + st->idst = -1; + continue; + } + } + } + } + close_config_file(); + + return 0; +} + +#ifndef DEBUG +void +reconfig(int sig, siginfo_t *sip, struct sigcontext *scp) +{ + log_error(0, "Reconfiguring on SIGHUP"); + + attrib_cleanup(); + identity_cleanup(NULL); + mod_cleanup(); + + free(global_schemes); global_schemes = NULL; + global_schemesize = 0; + + state_cleanup(); + + init_times(); + init_moduli(0); + init_schemes(); + init_attributes(); + init_identities(NULL, NULL); +} + +int +init_signals(void) +{ + struct sigaction sa, osa; + + bzero(&sa, sizeof(sa)); + sa.sa_mask = sigmask(SIGHUP); + sa.sa_handler = reconfig; + sigaction(SIGHUP, &sa, &osa); + + return 1; +} +#endif + +int +pick_scheme(u_int8_t **scheme, u_int16_t *schemesize, + u_int8_t *offered, u_int16_t offeredsize) +{ + u_int32_t size = 0; + u_int32_t osize, asize = 0; + u_int8_t *schemep = NULL; + u_int8_t *modp = NULL; /* Pointer to the modulus */ + u_int32_t modsize = 0, actsize = 0, gensize = 0; + u_int8_t scheme_ref[2]; + u_int8_t *p = NULL; + + while(size < global_schemesize) { + osize = 0; + while(osize < offeredsize) { + /* XXX - Policy? now take bigger moduli */ + p = scheme_get_mod(offered + osize); + actsize = varpre2octets(p); + + if (schemep == NULL && + !bcmp(offered+osize, global_schemes + size, 2)) { + /* We found a scheme we want use, now we need to get the + * modulus for it. + */ + schemep = offered + osize; + break; + } + osize += scheme_get_len(offered + osize); + } + if (schemep != NULL) + break; + size += scheme_get_len(global_schemes + size); + } + + if (schemep == NULL) { + log_error(0, "Found no scheme in pick_scheme()"); + return -1; + } + + if (actsize <= 2) { + if (ntohs(*(u_int16_t *)schemep) == scheme_get_ref(schemep)) { + log_error(0, "Base scheme has no modulus in pick_scheme()"); + return -1; + } + *(u_int16_t *)scheme_ref = htons(scheme_get_ref(schemep)); + osize = 0; + while(osize < offeredsize) { + /* XXX - Policy? now take bigger moduli */ + p = scheme_get_mod(offered + osize); + actsize = varpre2octets(p); + if (!bcmp(offered + osize, scheme_ref,2) && actsize > 2) { + if (actsize > modsize) { + modp = p; + modsize = actsize; + } + } + + osize += scheme_get_len(offered + osize); + } + } else { + modsize = actsize; + modp = p; + } + + if (*scheme != NULL) + free(*scheme); + + p = scheme_get_gen(schemep); + if (p != NULL) { + gensize = varpre2octets(p); + + /* XXX - VPN this works only for small numbers */ + asize = 2 + 2 + modsize + gensize; + + } else { + asize = 2 + modsize; + } + + if ((*scheme = calloc(asize, sizeof(u_int8_t))) == NULL) { + log_error(1, "No memory in pick_scheme()"); + return -1; + } + + bcopy(schemep, *scheme, 2); + /* XXX - VPN this works only for small numbers */ + if (p != NULL) { + (*scheme)[2] = gensize >> 8; + (*scheme)[3] = gensize & 0xFF; + bcopy(p, *scheme+2+2, gensize); + } + bcopy(modp, *scheme+2+(p == NULL ? 0 : 2 + gensize), modsize); + + *schemesize = asize; + return 0; +} + +/* + * Fills attrib, with attributes we offer to other parties, + * read the necessary values from some config file + */ + +int +pick_attrib(struct stateob *st, u_int8_t **attrib, u_int16_t *attribsize) +{ + struct attribute_list *ob; + int mode = 0, i, n, count, first; + + if ((ob = attrib_find(st->address)) == NULL) { + log_error(0, "attrib_find() in pick_attrib()"); + return -1; + } + + + /* Get the attributes in the right order */ + count = 0; + for (n=0; n<=AT_ESP_ATTRIB; n++) { + first = 1; mode = 0; + for (i=0; i<ob->attribsize; i += ob->attributes[i+1]+2) { + if (ob->attributes[i] == AT_AH_ATTRIB ) + mode = AT_AH_ATTRIB; + else if (ob->attributes[i] == AT_ESP_ATTRIB) + mode = AT_ESP_ATTRIB; + else if (n == mode) { + if (first && n > 0) { + buffer[count] = n; + buffer[count+1] = 0; + count += 2; + first = 0; + } + bcopy(ob->attributes+i, buffer+count, + ob->attributes[i+1]+2); + count += ob->attributes[i+1]+2; + } + } + } + + if ((*attrib = calloc(count, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in in pick_attrib()"); + return -1; + } + bcopy(buffer, *attrib, count); + *attribsize = count; + + return 0; +} + + +/* + * Removes whitespace from the end of a string + */ + +char * +chomp(char *p) +{ + if (!*p) + return p; + + while (*(p+1)) + p++; + + if (isspace(*p)) + *p = '\0'; + + return p; +} + +static const char hextab[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +int +bin2hex(char *buffer, int *size, u_int8_t *data, u_int16_t len) +{ + u_int16_t off; + + if (*size < 2*len+1) + return -1; + + off = 0; + while(len > 0) { + buffer[off++] = hextab[*data >> 4]; + buffer[off++] = hextab[*data & 0xF]; + data++; + len--; + } + buffer[off++] = '\0'; + + *size = off; + return 0; +} diff --git a/sbin/ipsec/photurisd/config.h b/sbin/ipsec/photurisd/config.h new file mode 100644 index 00000000000..78e700a242d --- /dev/null +++ b/sbin/ipsec/photurisd/config.h @@ -0,0 +1,116 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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.1 1997/07/18 22:48:50 provos Exp $ */ +/* + * config.h: + * handling config + */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include "userdefs.h" + +#ifdef MACHINE_ENDIAN +#include <machine/endian.h> +#endif + +#ifdef ENDIAN +#include <endian.h> +#endif + +#ifdef SYS_MACHINE +#include <sys/machine.h> +#endif + +#ifdef SYS_LTYPES +#include <sys/ltypes.h> +#endif + +#ifdef NEED_UTYPES +#include "utypes.h" +#endif + +#ifdef NEED_IN_ADDR +# ifndef _IN_ADDR_T_ +# define _IN_ADDR_T_ + typedef unsigned long in_addr_t; +# endif +#endif + + + +#include "state.h" + +#undef EXTERN +#ifdef _CONFIG_C_ +#define EXTERN + +#ifndef DEBUG +void reconfig(int sig, siginfo_t *sip, struct sigcontext *scp); +#endif + +#else +#define EXTERN extern +#endif + +#define CONFIG_MODULUS "modulus" +#define CONFIG_EXCHANGE "exchange" +#define CONFIG_CONFIG "config" +#define CONFIG_MAX_RETRIES "exchange_max_retransmits" +#define CONFIG_RET_TIMEOUT "exchange_retransmit_timeout" +#define CONFIG_EX_TIMEOUT "exchange_timeout" +#define CONFIG_EX_LIFETIME "exchange_lifetime" +#define CONFIG_SPI_LIFETIME "spi_lifetime" + +#define OPT_DST "dst" +#define OPT_PORT "port" +#define OPT_OPTIONS "options" +# define OPT_ENC "enc" +# define OPT_AUTH "auth" +#define OPT_USER "user" +#define OPT_TSRC "tsrc" +#define OPT_TDST "tdst" + +EXTERN int bin2hex(char *, int *, u_int8_t *, u_int16_t); +EXTERN char *chomp(char *); + +EXTERN int init_moduli(int); +EXTERN int init_schemes(void); +EXTERN int init_attributes(void); +EXTERN int init_times(void); +EXTERN int init_startup(void); +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 *); + +#endif /* _CONFIG_H_ */ + diff --git a/sbin/ipsec/photurisd/cookie.c b/sbin/ipsec/photurisd/cookie.c new file mode 100644 index 00000000000..70991e525e2 --- /dev/null +++ b/sbin/ipsec/photurisd/cookie.c @@ -0,0 +1,99 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * cookie.c: + * cookie generation + */ + +#ifndef lint +static char rcsid[] = "$Id: cookie.c,v 1.1 1997/07/18 22:48:48 provos Exp $"; +#endif + +#define _COOKIE_C_ + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <md5.h> +#include "state.h" +#include "cookie.h" + +void +reset_secret(void) +{ + secret_generate(rsecret, SECRET_SIZE); +} + +int +secret_generate(u_int8_t *secret, u_int16_t size) +{ + int i = 0; + long tmp = 0; + + while(size > 0) { + size--; + if (i++ % 4 == 0) + tmp = arc4random(); + + secret[size] = tmp & 0xFF; + tmp = tmp >> 8; + } + return 1; +} + +int +cookie_generate(struct stateob *st, u_int8_t *cookie, u_int16_t size) +{ + MD5_CTX ctx; + u_int8_t digest[16]; + u_int8_t tmpsecret[SECRET_SIZE], *secret; + + if (st->initiator) { + secret = tmpsecret; + secret_generate(tmpsecret, SECRET_SIZE); /* New secret each CookieReq */ + } else + secret = rsecret; + + /* Generate a cookie which depends on both parties and on local + * information, which is fast computed. + */ + MD5Init(&ctx); + MD5Update(&ctx, st->address, strlen(st->address)); + MD5Update(&ctx, (u_int8_t *)&st->port, sizeof(st->port)); + MD5Update(&ctx, (u_int8_t *)&st->counter, sizeof(st->counter)); + MD5Update(&ctx, secret, SECRET_SIZE); + MD5Update(&ctx, st->icookie, COOKIE_SIZE); + + MD5Final(digest, &ctx); + + bcopy(digest, cookie, size); + return 1; +} + diff --git a/sbin/ipsec/photurisd/cookie.h b/sbin/ipsec/photurisd/cookie.h new file mode 100644 index 00000000000..3da8ee490c9 --- /dev/null +++ b/sbin/ipsec/photurisd/cookie.h @@ -0,0 +1,55 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: cookie.h,v 1.1 1997/07/18 22:48:48 provos Exp $ */ +/* + * cookie.h: + * cookie generation header file + */ + +#ifndef _COOKIE_H_ +#define _COOKIE_H_ +#include "state.h" + +#define SECRET_SIZE 16 + +#undef EXTERN +#ifdef _COOKIE_C_ +#define EXTERN + +static u_int8_t rsecret[SECRET_SIZE]; /* Responder secret */ +#else +#define EXTERN extern +#endif + +EXTERN void reset_secret(void); +EXTERN int secret_generate(u_int8_t *secret, u_int16_t size); +EXTERN int cookie_generate(struct stateob *st, + u_int8_t *cookie, u_int16_t size); +#endif diff --git a/sbin/ipsec/photurisd/encrypt.h b/sbin/ipsec/photurisd/encrypt.h new file mode 100644 index 00000000000..a9f8e99bade --- /dev/null +++ b/sbin/ipsec/photurisd/encrypt.h @@ -0,0 +1,58 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 $ */ +/* + * encrypt.h: + * prototypes for photuris_packet_encrypt.c + */ + +#ifndef _ENCRYPT_H_ +#define _ENCRYPT_H_ + +#include "state.h" + +#undef EXTERN + +#ifdef _ENCRYPT_C_ +#define EXTERN +#else +#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, + u_int8_t *payload, u_int16_t payloadlen); +EXTERN int packet_decrypt(struct stateob *st, + u_int8_t *payload, u_int16_t *payloadlen); + +#endif /* _ENCRYPT_H_ */ diff --git a/sbin/ipsec/photurisd/errlog.c b/sbin/ipsec/photurisd/errlog.c new file mode 100644 index 00000000000..cb6c4a54ed4 --- /dev/null +++ b/sbin/ipsec/photurisd/errlog.c @@ -0,0 +1,166 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * This is partly derived from code by Angelos D. Keromytis, kermit@forthnet.gr + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Header: /cvs/OpenBSD/src/sbin/ipsec/photurisd/Attic/errlog.c,v 1.1 1997/07/18 22:48:49 provos Exp $ + * + * $Author: provos $ + * + * $Log: errlog.c,v $ + * Revision 1.1 1997/07/18 22:48:49 provos + * Initial revision + * + * Revision 1.1 1997/05/22 17:34:16 provos + * Initial revision + * + */ + +#ifndef lint +static char rcsid[] = "$Id: errlog.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#define _ERRLOG_C_ + +#include <stdio.h> +#include <stdlib.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <stdio.h> +#include <syslog.h> +#include <sys/types.h> +#include <errno.h> +#include "buffer.h" +#include "errlog.h" + +#ifdef NEED_SNPRINTF +#include "snprintf.h" +#endif + +#if defined(sun) || defined(_AIX) +extern char *sys_errlist[]; +extern int errno; +#endif + +#define LOG_SIZE 200 + +void _log_error(int flag, char *fmt, va_list ap); + +/* + * crit_error: + * log the error and exit + */ + +void +#if __STDC__ +crit_error(int flag, char *fmt, ...) +#else +crit_error(flag, fmt, va_alist) + int flag; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + _log_error(flag, fmt, ap); + va_end(ap); + exit(-1); +} + +/* + * log_error: + * log an error + */ + +void +#if __STDC__ +log_error(int flag, char *fmt, ...) +#else +log_error(flag, fmt, va_alist) + int flag; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + _log_error(flag, fmt, ap); + va_end(ap); +} + +void +_log_error(int flag, char *fmt, va_list ap) +{ + char *buffer = calloc(LOG_SIZE, sizeof(char)); +#ifdef __SWR + FILE f; +#endif + if(buffer == NULL) + return; + +#ifdef DEBUG + sprintf(buffer, "%s: ", (flag ? "Error" : "Warning")); +#else + buffer[0] = '\0'; +#endif + +#ifdef __SWR + f._flags = __SWR | __SSTR; + f._bf._base = f._p = buffer + strlen(buffer); + f._bf._size = f._w = LOG_SIZE-1-strlen(buffer); + vfprintf(&f, fmt, ap); +#else + vsprintf(buffer+strlen(buffer), fmt, ap); +#endif + buffer[LOG_SIZE-1] = '\0'; +#ifdef DEBUG + fprintf(stderr, buffer); + if (flag) + fprintf(stderr, " : %s", sys_errlist[errno]); + fprintf(stderr, ".\n"); +#else + syslog(LOG_WARNING, buffer); +#endif + free(buffer); + +} diff --git a/sbin/ipsec/photurisd/errlog.h b/sbin/ipsec/photurisd/errlog.h new file mode 100644 index 00000000000..ad429e83be6 --- /dev/null +++ b/sbin/ipsec/photurisd/errlog.h @@ -0,0 +1,67 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * This code is originally from Angelos D. Keromytis, kermit@forthnet.gr + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Header: /cvs/OpenBSD/src/sbin/ipsec/photurisd/Attic/errlog.h,v 1.1 1997/07/18 22:48:50 provos Exp $ + * + * $Author: provos $ + * + * $Log: errlog.h,v $ + * Revision 1.1 1997/07/18 22:48:50 provos + * Initial revision + * + * Revision 1.1 1997/05/22 17:36:07 provos + * Initial revision + * + */ + +#ifdef _ERRLOG_C_ + +#if __STDC__ +void crit_error __P((int, char *, ...)); +void log_error __P((int, char *, ...)); +#else +void crit_error(); +void log_error(); +#endif + +#else + +#if __STDC__ +extern void crit_error __P((int, char *, ...)); +extern void log_error __P((int, char *, ...)); +#else +extern void crit_error(); +extern void log_error(); +#endif + +#endif diff --git a/sbin/ipsec/photurisd/exchange.c b/sbin/ipsec/photurisd/exchange.c new file mode 100644 index 00000000000..0198bda91e1 --- /dev/null +++ b/sbin/ipsec/photurisd/exchange.c @@ -0,0 +1,369 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * exchange.c: + * + */ + +#ifndef lint +static char rcsid[] = "$Id: exchange.c,v 1.1 1997/07/18 22:48:48 provos Exp $"; +#endif + +#define _EXCHANGE_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "state.h" +#include "gmp.h" +#include "exchange.h" +#include "modulus.h" +#include "attributes.h" +#include "buffer.h" +#include "cookie.h" +#include "schedule.h" +#include "scheme.h" +#include "errlog.h" + +void +make_random_mpz(mpz_t a, mpz_t bits) +{ + mpz_t d; + + mpz_init_set_str(d, "0x100000000", 0); + + /* XXX - we generate too many bits */ + + mpz_set_ui(a, 0); + mpz_cdiv_q_ui(bits,bits,32); /* We work in 2^32 chucks */ + + while(mpz_cmp_ui(bits,0)>0) { + mpz_mul(a, a, d); /* c = a * 0x100000000 */ + mpz_add_ui(a, a, arc4random()); /* d = random */ + mpz_sub_ui(bits, bits, 1); + } + mpz_clear(d); +} + +/* + * Get the number of bits from a variable precision number + * according to draft-simpson-photuris-11 + */ + +u_int8_t * +varpre_get_number_bits(mpz_t bits, u_int8_t *varpre) +{ + u_int8_t blocks; + mpz_t a; + + mpz_init_set_ui(a,0); + + mpz_set_ui(bits, 0); + if (varpre == NULL) + return NULL; + + if(*varpre == 255 && *(varpre+1) == 255) { + blocks = 6; + varpre += 2; + mpz_set_ui(bits, 16776960); + } else if(*varpre == 255) { + blocks = 3; + mpz_set_ui(bits, 65280); + varpre++; + } else + blocks = 2; + + while(blocks-->0) { + mpz_mul_ui(a,a,256); + mpz_add_ui(a,a,*varpre); + varpre++; + } + mpz_add(bits,a,bits); /* Add the above bits */ + mpz_clear(a); + return varpre; +} + +/* + * Convert a variable precision number to a mpz number + */ + +u_int8_t * +mpz_set_varpre(mpz_t a, u_int8_t *varpre) +{ + u_int8_t *p; + mpz_t bytes; + + mpz_init(bytes); + mpz_set_ui(a, 0); + p = varpre_get_number_bits(bytes, varpre); + mpz_cdiv_q_ui(bytes,bytes,8); /* Number of bytes */ + while(mpz_cmp_ui(bytes,0)) { + mpz_mul_ui(a, a, 256); + mpz_sub_ui(bytes, bytes, 1); + mpz_add_ui(a, a, *p); + p++; + } + mpz_clear(bytes); + + return p; +} + +u_int8_t * +mpz_init_set_varpre(mpz_t a, u_int8_t *varpre) +{ + mpz_init(a); + return mpz_set_varpre(a,varpre); +} + +void +mpz_get_number_bits(mpz_t rop, mpz_t p) +{ + size_t bits; + + bits = mpz_sizeinbase(p, 2); + mpz_set_ui(rop, bits); +} + +int +mpz_to_varpre(u_int8_t *value, u_int16_t *size, mpz_t p, mpz_t gbits) +{ + u_int16_t header; + mpz_t a, tmp, bits, bytes; + u_int32_t count; + + mpz_init(bytes); + mpz_init(tmp); + mpz_init_set(bits, gbits); + + mpz_cdiv_q_ui(bytes, bits, 8); + + count = mpz_get_ui(bytes); + + /* XXX - only support 4 octets at the moment */ + if(mpz_cmp_ui(bits, 65279) > 0) { + mpz_sub_ui(bits,bits,65280); + value[0] = 255; + value[3] = mpz_fdiv_qr_ui(bits,tmp,bits,256) & 0xFF; + value[2] = mpz_fdiv_qr_ui(bits,tmp,bits,256) & 0xFF; + value[1] = mpz_fdiv_qr_ui(bits,tmp,bits,256) & 0xFF; + header = 4; + } else { + value[1] = mpz_fdiv_qr_ui(bits,tmp,bits,256) & 0xFF; + value[0] = mpz_fdiv_qr_ui(bits,tmp,bits,256) & 0xFF; + header = 2; + } + + if(mpz_cmp_ui(bytes, *size-header)>0) + return -1; /* Not enough buffer */ + + mpz_init_set(a, p); + + /* XXX - int16 vs. int32 */ + *size = count+header; + + while(count>0) { + count--; + value[count+header]=mpz_fdiv_qr_ui(a, tmp, a, 256); + } + mpz_clear(a); + mpz_clear(tmp); + mpz_clear(bits); + mpz_clear(bytes); + + return 0; +} + +/* + * Finds to a given modulus and generator cached information + * which is used to create the private value and exchange value + */ + +int +exchange_make_values(struct stateob *st, mpz_t modulus, mpz_t generator) +{ + struct moduli_cache *p, *tmp; + u_int8_t *mod; + time_t tm; + + tm = time(NULL); + + /* See if we have this cached already */ + if((p = mod_find_modgen(modulus,generator)) == NULL) { + /* Create a new modulus, generator pair */ + if((p = mod_new_modgen(modulus,generator)) == NULL) { + mpz_clear(generator); + mpz_clear(modulus); + log_error(1, "Not enough memory in exchange_make_values()"); + return -1; + } + mod_insert(p); + } + /* If we don't have a private value calculate a new one */ + if(p->lifetime < tm || !mpz_cmp_ui(p->private_value,0)) { + if (p->exchangevalue != NULL) + free(p->exchangevalue); + + /* See if we can find a cached private value */ + if((tmp = mod_find_modulus(modulus)) != NULL && + tmp->lifetime > tm && mpz_cmp_ui(tmp->private_value,0)) { + mpz_set(p->private_value, tmp->private_value); + + + /* Keep exchange value on same (gen,mod) pair */ + if (!mpz_cmp(p->generator, tmp->generator)) { + p->exchangevalue = calloc(tmp->exchangesize,sizeof(u_int8_t)); + if (p->exchangevalue == NULL) { + log_error(1, "calloc() in exchange_make_values()"); + return -1; + } + bcopy(tmp->exchangevalue, p->exchangevalue, + tmp->exchangesize); + p->exchangesize = tmp->exchangesize; + } else + p->exchangevalue = NULL; + + p->iterations = tmp->iterations; + p->status = tmp->status; + p->lifetime = tmp->lifetime; + } else { + mpz_t bits; + + /* + * Make a new private value and change responder secrets + * as required by draft. + */ + + schedule_remove(REKEY, NULL); + schedule_insert(REKEY, REKEY_TIMEOUT, NULL, 0); + reset_secret(); + + mpz_init(bits); + + p->lifetime = tm + MOD_TIMEOUT; + p->exchangevalue = NULL; + + /* Find pointer to the VPN containing the modulus */ + mod = scheme_get_mod(st->scheme); + varpre_get_number_bits(bits, mod); + make_random_mpz(p->private_value, bits); + mpz_clear(bits); + } + /* Do we need to generate a new exchange value */ + if (p->exchangevalue == NULL) { + mpz_t tmp, bits; + + mpz_init(tmp); + mpz_powm(tmp, p->generator, p->private_value, p->modulus); + + mpz_init(bits); + mod = scheme_get_mod(st->scheme); + varpre_get_number_bits(bits, mod); + + p->exchangesize = BUFFER_SIZE; + mpz_to_varpre(buffer, &(p->exchangesize), tmp, bits); + + p->exchangevalue = calloc(p->exchangesize, sizeof(u_int8_t)); + if (p->exchangevalue == NULL) { + log_error(1, "calloc() in exchange_make_value()"); + mpz_clear(bits); mpz_clear(tmp); + return -1; + } + bcopy(buffer, p->exchangevalue, p->exchangesize); + + mpz_clear(bits); + mpz_clear(tmp); + } + } + mpz_set(st->modulus, p->modulus); + mpz_set(st->generator, p->generator); + return 0; +} + +/* + * Generates the exchange values needed for the value_request + * and value_response packets. + */ + +int +exchange_value_generate(struct stateob *st, u_int8_t *value, u_int16_t *size) +{ + mpz_t modulus,generator; + struct moduli_cache *p; + u_int8_t *varpre; + + switch (ntohs(*((u_int16_t *) st->scheme))) { + case DH_G_2_MD5: /* DH: Generator of 2 */ + case DH_G_2_DES_MD5: /* DH: Generator of 2 + privacy */ + case DH_G_2_3DES_SHA1: + mpz_init_set_ui(generator,2); + break; + case DH_G_3_MD5: + case DH_G_3_DES_MD5: + case DH_G_3_3DES_SHA1: + mpz_init_set_ui(generator,3); + break; + case DH_G_5_MD5: + case DH_G_5_DES_MD5: + case DH_G_5_3DES_SHA1: + mpz_init_set_ui(generator,5); + break; + default: + log_error(0, "Unsupported exchange scheme: %d\n", + *((u_int16_t *)st->scheme)); + return -1; + } + + if ((varpre = scheme_get_mod(st->scheme)) == NULL) + return -1; + + mpz_init_set_varpre(modulus, varpre); + + if(exchange_make_values(st, modulus, generator) == -1) { + mpz_clear(modulus); + mpz_clear(generator); + return -1; + } + + p = mod_find_modgen(modulus,generator); + if (*size < p->exchangesize) + return -1; + + bcopy(p->exchangevalue, value, p->exchangesize); + mpz_clear(modulus); + mpz_clear(generator); + + *size = p->exchangesize; + return 1; +} diff --git a/sbin/ipsec/photurisd/exchange.h b/sbin/ipsec/photurisd/exchange.h new file mode 100644 index 00000000000..0d806cd754f --- /dev/null +++ b/sbin/ipsec/photurisd/exchange.h @@ -0,0 +1,56 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: exchange.h,v 1.1 1997/07/18 22:48:49 provos Exp $ */ +/* + * exchange.h: + * exchange generation header file + */ + +#ifndef _EXCHANGE_H_ +#define _EXCHANGE_H_ + +#undef EXTERN + +#ifdef _EXCHANGE_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN void make_random_mpz(mpz_t a, mpz_t bits); +EXTERN u_int8_t *varpre_get_number_bits(mpz_t bits, u_int8_t *varpre); +EXTERN u_int8_t *mpz_set_varpre(mpz_t a, u_int8_t *varpre); +EXTERN u_int8_t *mpz_init_set_varpre(mpz_t a, u_int8_t *varpre); +EXTERN void mpz_get_number_bits(mpz_t rop, mpz_t p); +EXTERN int mpz_to_varpre(u_int8_t *value, u_int16_t *size, mpz_t p, mpz_t bits); +EXTERN int exchange_make_values(struct stateob *, mpz_t, mpz_t ); +EXTERN int exchange_value_generate(struct stateob *, u_int8_t *, u_int16_t *); + +#endif diff --git a/sbin/ipsec/photurisd/handle_bad_cookie.c b/sbin/ipsec/photurisd/handle_bad_cookie.c new file mode 100644 index 00000000000..8767f555940 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_bad_cookie.c @@ -0,0 +1,117 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_bad_cookie: + * receive a BAD_COOKIE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_bad_cookie.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" +#include "server.h" +#include "packet.h" +#include "api.h" + +int +handle_bad_cookie(u_char *packet, int size, char *address) +{ + struct error_message *header; + struct stateob *st, *newst; + + if (size != ERROR_MESSAGE_PACKET_SIZE) + return -1; /* packet too small/big */ + + header = (struct error_message *) packet; + + if ((st = state_find_cookies(address, header->icookie, + header->rcookie)) == NULL) { + log_error(0, "No state for BAD_COOKIE message from %s", + address); + return -1; + } + + if ((st->retries < max_retries && + (st->phase == VALUE_REQUEST || st->phase == IDENTITY_REQUEST)) || + (st->phase != VALUE_REQUEST && st->phase != IDENTITY_REQUEST && + st->phase != SPI_NEEDED && st->phase != SPI_UPDATE)) { + log_error(0, "Ignored BAD_COOKIE message from %s", address); + + return 0; /* Nothing needs to be done */ + } + + if (st->phase == SPI_UPDATE) { + st->lifetime = time(NULL); + + log_error(0, "Expired exchange on BAD_COOKIE from %s", + address); + return 0; + } + + schedule_remove(TIMEOUT, st->icookie); + state_unlink(st); + + /* Set up a new state object */ + if ((newst = state_new()) == NULL) { + log_error(1, "state_new() in handle_bad_cookie()"); + return -1; + } + + newst->flags = st->flags; + if (st->user != NULL) + newst->user = strdup(st->user); + + state_value_reset(st); + + if (start_exchange(global_socket, newst, address, global_port) == -1) { + log_error(0, "start_exchange() in handle_bad_cookie()"); + state_value_reset(st); + return -1; + } + + state_insert(newst); + + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_cookie_request.c b/sbin/ipsec/photurisd/handle_cookie_request.c new file mode 100644 index 00000000000..10d736b7dd2 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_cookie_request.c @@ -0,0 +1,121 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_cookie_request: + * receive a COOKIE_REQUEST packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_cookie_request.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" + +int +handle_cookie_request(u_char *packet, int size, + u_int8_t *address, u_int16_t port, + u_int8_t *schemes, u_int16_t ssize) + +{ + struct cookie_request *header; + struct stateob *prev_st, *st; + time_t tm = 0; + + u_int8_t icookie[COOKIE_SIZE]; + + /* XXX - check resource limit */ + + if (size != COOKIE_REQUEST_PACKET_SIZE) + return -1; /* packet too small/big */ + + header = (struct cookie_request *) packet; + + if ((prev_st=state_find(address)) != NULL) { + int exceeded = 1; + + st = prev_st; + + /* + * Find exchanges which are not timed out and the rcookie doesnt + * match any exchange -> resource limit. + */ + + tm = time(NULL); + while(prev_st != NULL) { + if ((!prev_st->initiator && + !bcmp(prev_st->rcookie, header->rcookie, COOKIE_SIZE))|| + (prev_st->initiator && + !bcmp(prev_st->icookie, header->rcookie, COOKIE_SIZE))) + break; + if (prev_st->lifetime > tm) + exceeded = 0; + + if (prev_st->lifetime > st->lifetime) + st = prev_st; + + prev_st = state_find_next(prev_st, address); + } + if (prev_st == NULL && !exceeded) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + header->counter, RESOURCE_LIMIT); + send_packet(); + return 0; + } + } + + + bcopy(header->icookie, icookie, COOKIE_SIZE); + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_cookie_response(prev_st != NULL && + prev_st->lifetime < tm ? prev_st : NULL, + packet_buffer, &packet_size, + icookie, header->counter, + address, port, + schemes, ssize) == -1 ) + return -1; /* Some error happened */ + + send_packet(); + + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_cookie_response.c b/sbin/ipsec/photurisd/handle_cookie_response.c new file mode 100644 index 00000000000..2aec528e689 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_cookie_response.c @@ -0,0 +1,145 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_cookie_response: + * receive a COOKIE_RESPONSE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_cookie_response.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "scheme.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" +#include "config.h" + +int +handle_cookie_response(u_char *packet, int size, + char *address, int port) + +{ + struct cookie_response *header; + struct stateob *st; + u_int8_t *p; + u_int16_t i, n; + + if (size < COOKIE_RESPONSE_MIN) + return -1; /* packet too small */ + + header = (struct cookie_response *) packet; + + /* Take multi home hosts into account */ + st = state_root(); + while(st != NULL) { + if (!bcmp(header->icookie,st->icookie,COOKIE_SIZE)) + break; + st = st->next; + } + if (st == NULL) + return -1; /* Silently discard - XXX log perhaps ? */ + + if (st->phase != COOKIE_REQUEST) + return -1; /* We didn't want a cookie response */ + + if (strcmp(address, st->address)) { + /* XXX - is this a sane thing to do ? */ + log_error(0, "Response from multihomed host, address %s will " + "be changed to %s.", st->address, address); + strncpy(st->address, address, 15); + st->address[15] = '\0'; + } + + /* Check scheme size */ + p = COOKIE_RESPONSE_SCHEMES(header); + i = 0; + while(i<size-COOKIE_RESPONSE_MIN) { + if ((n = scheme_get_len(p + i)) == 0) + break; + i += n; + } + + if (i != size-COOKIE_RESPONSE_MIN) { + log_error(0, "schemes corrupt in handle_cookie_response()"); + return -1; /* Size didn't match UDP size */ + } + + /* Copy responder cookies and offered schemes */ + bcopy(header->rcookie, st->rcookie, COOKIE_SIZE); + if ((st->roschemes = calloc(i, sizeof(u_int8_t))) == NULL) { + state_value_reset(st); + state_unlink(st); + return -1; /* Not enough memory */ + } + bcopy(p, st->roschemes, i); + st->roschemesize = i; + + if (pick_scheme(&(st->scheme), &(st->schemesize), p, i) == -1) { + state_value_reset(st); + state_unlink(st); + return -1; + } + + if (pick_attrib(st, &(st->oSPIoattrib), + &(st->oSPIoattribsize)) == -1) { + state_value_reset(st); + state_unlink(st); + return -1; + } + + /* Take the counter from the cookie response */ + st->counter = header->counter; + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_value_request(st, packet_buffer, &packet_size) == -1) + return -1; + + packet_save(st, packet_buffer, packet_size); + + send_packet(); + + st->retries = 0; + st->phase = VALUE_REQUEST; + + schedule_remove(TIMEOUT, st->icookie); + schedule_insert(TIMEOUT, retrans_timeout, st->icookie, COOKIE_SIZE); + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_identity_request.c b/sbin/ipsec/photurisd/handle_identity_request.c new file mode 100644 index 00000000000..145594eaf5f --- /dev/null +++ b/sbin/ipsec/photurisd/handle_identity_request.c @@ -0,0 +1,323 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_identity_request: + * receive a IDENTITY_REQUEST packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_identity_request.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "encrypt.h" +#include "identity.h" +#include "spi.h" +#include "secrets.h" +#include "scheme.h" +#include "errlog.h" +#include "schedule.h" +#ifdef IPSEC +#include "kernel.h" +#endif + +int +handle_identity_request(u_char *packet, int size, char *address, + char *local_address) +{ + 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 signature[22]; /* XXX - constant */ + + if (size < IDENTITY_MESSAGE_MIN) + return -1; /* packet too small */ + + header = (struct identity_message *) packet; + + st = state_find_cookies(address, header->icookie, header->rcookie); + if (st == NULL) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, BAD_COOKIE); + send_packet(); + return 0; + } + + if (st->phase != VALUE_RESPONSE && st->phase != SPI_UPDATE) + return -1; /* We don't want this packet */ + + /* Decrypt message */ + tmp = size - IDENTITY_MESSAGE_MIN; + if (packet_decrypt(st, IDENTITY_MESSAGE_CHOICE(header), &tmp) == -1) { + log_error(0, "packet_decrypt() in handle_identity_request()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + /* Verify message */ + if (!(i = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)))) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + 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; + + if (asize != size) { + log_error(0, "wrong packet size in handle_identity_request()"); + return -1; + } + + if (i > sizeof(signature)) { + log_error(0, "verification too long in handle_identity_request()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + 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()"); + return -1; + } + 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()"); + return -1; + } + 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()"); + return -1; + } + bcopy(p, st->uSPIident, varpre2octets(p)); + } + + 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()"); + return -1; + } + + } + + 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; + } + + log_error(0, "verification failed in handle_identity_request()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + 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) { + log_error(0, "make_spi() in handle_identity_request()"); + return -1; + } + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_identity_response(st, packet_buffer, &packet_size) == -1) + return -1; + + send_packet(); + + packet_save(st, packet_buffer, packet_size); + + bcopy(header->SPI, st->uSPI, SPI_SIZE); + st->ulifetime = (header->lifetime[0] << 16) + + (header->lifetime[1] << 8) + header->lifetime[2]; + + if (st->oSPI[0] || st->oSPI[1] || st->oSPI[2] || st->oSPI[3]) { + /* Insert Owner SPI */ + if ((spi = spi_new(st->address, st->oSPI)) == NULL) { + log_error(0, "spi_new() in handle_identity_request()"); + return -1; + } + if ((spi->local_address = strdup(local_address)) == NULL) { + log_error(0, "strdup() in handle_identity_request()"); + return -1; + } + bcopy(st->icookie, spi->icookie, COOKIE_SIZE); + spi->owner = 1; + spi->attribsize = st->oSPIattribsize; + spi->attributes = calloc(spi->attribsize, sizeof(u_int8_t)); + if (spi->attributes == NULL) { + log_error(1, "calloc() in handle_identity_request()"); + spi_value_reset(spi); + return -1; + } + bcopy(st->oSPIattrib, spi->attributes, spi->attribsize); + spi->lifetime = time(NULL) + st->olifetime; + + /* Make session keys for Owner */ + make_session_keys(st, spi); + + spi_insert(spi); +#ifdef IPSEC + kernel_insert_spi(spi); +#endif + schedule_insert(UPDATE, st->olifetime/2, spi->SPI, SPI_SIZE); + } + + if (st->uSPI[0] || st->uSPI[1] || st->uSPI[2] || st->uSPI[3]) { + /* Insert User SPI */ + if ((spi = spi_new(st->address, st->uSPI)) == NULL) { + log_error(0, "spi_new() in handle_identity_request()"); + return -1; + } + if ((spi->local_address = strdup(local_address)) == NULL) { + log_error(1, "strdup() in handle_identity_request()"); + return -1; + } + bcopy(st->icookie, spi->icookie, COOKIE_SIZE); + spi->attribsize = st->uSPIattribsize; + spi->attributes = calloc(spi->attribsize, sizeof(u_int8_t)); + if (spi->attributes == NULL) { + log_error(1, "calloc() in handle_identity_request()"); + spi_value_reset(spi); + return -1; + } + bcopy(st->uSPIattrib, spi->attributes, spi->attribsize); + spi->lifetime = time(NULL) + st->ulifetime; + + /* Make session keys for User */ + make_session_keys(st, spi); + + spi_insert(spi); +#ifdef IPSEC + kernel_insert_spi(spi); +#endif + } + + st->lifetime = exchange_lifetime + time(NULL) + random() % 20; + + st->retries = 0; + st->phase = SPI_UPDATE; + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_identity_response.c b/sbin/ipsec/photurisd/handle_identity_response.c new file mode 100644 index 00000000000..ecd01ad7931 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_identity_response.c @@ -0,0 +1,292 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_identity_response: + * receive a IDENTITY_RESPONSE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_identity_response.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "schedule.h" +#include "encrypt.h" +#include "identity.h" +#include "secrets.h" +#include "scheme.h" +#include "errlog.h" +#include "spi.h" +#ifdef IPSEC +#include "kernel.h" +#endif + +int +handle_identity_response(u_char *packet, int size, char *address, + char *local_address) +{ + 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 signature[22]; /* XXX - constant */ + + if (size < IDENTITY_MESSAGE_MIN) + return -1; /* packet too small */ + + header = (struct identity_message *) packet; + + st = state_find_cookies(address, header->icookie, header->rcookie); + if (st == NULL) + return -1; /* Silently discard */ + + if (st->phase != IDENTITY_REQUEST) + return 0; /* We don't want this packet */ + + /* Decrypt message */ + tmp = size - IDENTITY_MESSAGE_MIN; + if (packet_decrypt(st, IDENTITY_MESSAGE_CHOICE(header), &tmp) == -1) { + log_error(0, "packet_decrypt() in handle_identity_response()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + /* Verify message */ + if (!(i = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)))) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + + return -1; + } + + 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; + + if (asize != size) { + log_error(0, "wrong packet size in handle_identity_response()"); + return -1; + } + + if (i > sizeof(signature)) { + log_error(0, "verification too long in handle_identity_response()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + 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()"); + return -1; + } + 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()"); + return -1; + } + 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_response()"); + return -1; + } + bcopy(p, st->uSPIident, varpre2octets(p)); + } + + if (st->uSPIattrib == NULL) { + if((st->uSPIattrib = calloc(attribsize, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_identity_response()"); + return -1; + } + 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()"); + return -1; + } + + if (!verify_identity_verification(st, signature, packet, size)) { + /* + * Clean up everything used from this packet + */ + 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; + + /* Clean up secrets */ + free(st->uSPIsecret); + st->uSPIsecret = NULL; st->uSPIsecretsize = 0; + + log_error(0, "verification failed in handle_identity_response()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return 0; + } + + bcopy(header->SPI, st->uSPI, SPI_SIZE); + st->ulifetime = (header->lifetime[0] << 16) + + (header->lifetime[1] << 8) + header->lifetime[2]; + + st->lifetime = exchange_lifetime + time(NULL) + random() % 20; + st->retries = 0; + st->phase = SPI_UPDATE; + + schedule_remove(TIMEOUT, st->icookie); + + /* We don't need the packet buffer anylonger */ + if (st->packet != NULL) { + free(st->packet); + st->packet = NULL; + st->packetlen = 0; + } + + + if (st->oSPI[0] || st->oSPI[1] || st->oSPI[2] || st->oSPI[3]) { + /* Insert Owner SPI */ + if ((spi = spi_new(st->address, st->oSPI)) == NULL) { + log_error(0, "spi_new() in handle_identity_response()"); + return -1; + } + if ((spi->local_address = strdup(local_address)) == NULL) { + log_error(1, "strdup() in handle_identity_response()"); + return -1; + } + bcopy(st->icookie, spi->icookie, COOKIE_SIZE); + spi->owner = 1; + spi->attribsize = st->oSPIattribsize; + spi->attributes = calloc(spi->attribsize, sizeof(u_int8_t)); + if (spi->attributes == NULL) { + log_error(0, "calloc() in handle_identity_response()"); + spi_value_reset(spi); + return -1; + } + bcopy(st->oSPIattrib, spi->attributes, spi->attribsize); + spi->lifetime = time(NULL) + st->olifetime; + + /* Make session keys for Owner */ + make_session_keys(st, spi); + + spi_insert(spi); +#ifdef IPSEC + kernel_insert_spi(spi); +#endif + schedule_insert(UPDATE, st->olifetime/2, spi->SPI, SPI_SIZE); + } + if (st->uSPI[0] || st->uSPI[1] || st->uSPI[2] || st->uSPI[3]) { + /* Insert User SPI */ + if ((spi = spi_new(st->address, st->uSPI)) == NULL) { + log_error(0, "spi_new() in handle_identity_response()"); + return -1; + } + if ((spi->local_address = strdup(local_address)) == NULL) { + log_error(1, "strdup() in handle_identity_response()"); + return -1; + } + bcopy(st->icookie, spi->icookie, COOKIE_SIZE); + spi->attribsize = st->uSPIattribsize; + spi->attributes = calloc(spi->attribsize, sizeof(u_int8_t)); + if (spi->attributes == NULL) { + log_error(1, "calloc() in handle_identity_response()"); + spi_value_reset(spi); + return -1; + } + bcopy(st->uSPIattrib, spi->attributes, spi->attribsize); + spi->lifetime = time(NULL) + st->ulifetime; + + /* Session keys for User */ + make_session_keys(st, spi); + + spi_insert(spi); +#ifdef IPSEC + kernel_insert_spi(spi); +#endif + } + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_message_reject.c b/sbin/ipsec/photurisd/handle_message_reject.c new file mode 100644 index 00000000000..6c6db7c5062 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_message_reject.c @@ -0,0 +1,75 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_message_reject: + * receive a MESSAGE_REJECT packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_message_reject.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" + +int +handle_message_reject(u_char *packet, int size, char *address) +{ + struct message_reject *header; + struct stateob *st; + + if (size != MESSAGE_REJECT_PACKET_SIZE) + return -1; /* packet too small/big */ + + header = (struct message_reject *) packet; + + if ((st = state_find_cookies(address, header->icookie, + header->rcookie)) == NULL) { + log_error(0, "No state for MESSAGE_REJECT message from %s", + address); + return -1; + } + + log_error(0, "Received MESSAGE_REJECT from %s on message type %d " + "offending offset %d", address, header->badtype, + header->offset); + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_resource_limit.c b/sbin/ipsec/photurisd/handle_resource_limit.c new file mode 100644 index 00000000000..d3b7b8c5946 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_resource_limit.c @@ -0,0 +1,98 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_resource_limit: + * receive a RESOURCE_LIMIT packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_resource_limit.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" + +int +handle_resource_limit(u_char *packet, int size, char *address) +{ + struct error_message *header; + struct stateob *st; + int offset, counter; + + if (size != ERROR_MESSAGE_PACKET_SIZE + 1) + return -1; /* packet too small/big */ + + header = (struct error_message *) packet; + counter = packet[ERROR_MESSAGE_PACKET_SIZE]; + + if ((st = state_find_cookies(NULL, header->icookie, + header->rcookie)) == NULL) { + log_error(0, "No state for RESOURCE_LIMIT message from %s", + address); + return -1; + } + + switch(st->phase) { + case COOKIE_REQUEST: + case VALUE_REQUEST: + offset = schedule_offset(TIMEOUT, st->icookie); + if (offset == -1) + offset = retrans_timeout; + else { + offset *= 2; + if (offset > exchange_timeout/2) + offset = exchange_timeout/2; + } + + schedule_remove(TIMEOUT, st->icookie); + schedule_insert(TIMEOUT, offset, st->icookie, COOKIE_SIZE); + break; + case SPI_UPDATE: + /* XXX - we have to wait for expiring of another SPI */ + break; + default: + log_error(0, "Wrong phase for RESOURCE_LIMIT from %s", + address); + return 0; + } + + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_spi_needed.c b/sbin/ipsec/photurisd/handle_spi_needed.c new file mode 100644 index 00000000000..307a0758b34 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_spi_needed.c @@ -0,0 +1,208 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_spi_needed: + * receive a SPI_NEEDED packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_spi_needed.c,v 1.1 1997/07/18 22:48:51 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "encrypt.h" +#include "validity.h" +#include "secrets.h" +#include "schedule.h" +#include "scheme.h" +#include "errlog.h" +#include "spi.h" +#ifdef IPSEC +#include "kernel.h" +#endif + +int +handle_spi_needed(u_char *packet, int size, char *address, + char *local_address) +{ + 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 signature[22]; /* XXX - constant */ + + if (size < SPI_NEEDED_MIN) + return -1; /* packet too small */ + + header = (struct spi_needed *) packet; + + st = state_find_cookies(address, header->icookie, header->rcookie); + if (st == NULL) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, BAD_COOKIE); + send_packet(); + return 0; + } + + if (st->phase != SPI_UPDATE && st->phase != SPI_NEEDED) + return 0; /* We don't want this packet */ + + /* Decrypt message */ + tmp = size - SPI_NEEDED_MIN; + if (packet_decrypt(st, SPI_NEEDED_VERIFICATION(header), &tmp) == -1) { + log_error(0, "packet_decrypt() in handle_spi_needed()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + /* Verify message */ + if (!(i = get_validity_verification_size(st))) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + 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; + + if (asize != size) { + log_error(0, "wrong packet size in handle_spi_needed()"); + return -1; + } + + if (i > sizeof(signature)) { + log_error(0, "verification too long in handle_spi_needed()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + bcopy(p, signature, i); + bzero(p, i); + + if (!verify_validity_verification(st, signature, packet, size)) { + log_error(0, "verification failed in handle_spi_needed()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return 0; + } + + if (st->uSPIoattrib != NULL) + free(st->uSPIoattrib); + + if((st->uSPIoattrib = calloc(attribsize, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_spi_needed()"); + return -1; + } + bcopy(attributes, st->uSPIoattrib, attribsize); + st->uSPIoattribsize = attribsize; + + /* Delete old attributes, make_spi will make new */ + if (st->oSPIattrib != NULL) { + free(st->oSPIattrib); + st->oSPIattrib = NULL; + st->oSPIattribsize = 0; + } + if (make_spi(st, local_address, st->oSPI, &(st->olifetime), + &(st->oSPIattrib), &(st->oSPIattribsize)) == -1) + return -1; + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_spi_update(st, packet_buffer, &packet_size) == -1) { + log_error(0, "photuris_spi_update() in handle_spi_needed()"); + return -1; + } + send_packet(); + + /* Insert Owner SPI */ + if ((spi = spi_new(st->address, st->oSPI)) == NULL) { + log_error(0, "spi_new() in handle_spi_needed()"); + return -1; + } + if ((spi->local_address = strdup(local_address)) == NULL) { + log_error(1, "strdup() in handle_spi_needed()"); + return -1; + } + bcopy(st->icookie, spi->icookie, COOKIE_SIZE); + spi->owner = 1; + spi->attribsize = st->oSPIattribsize; + spi->attributes = calloc(spi->attribsize, sizeof(u_int8_t)); + if (spi->attributes == NULL) { + log_error(1, "calloc() in handle_spi_needed()"); + spi_value_reset(spi); + return -1; + } + bcopy(st->oSPIattrib, spi->attributes, spi->attribsize); + spi->lifetime = time(NULL) + st->olifetime; + + make_session_keys(st, spi); + + spi_insert(spi); + schedule_insert(UPDATE, st->olifetime/2, spi->SPI, SPI_SIZE); +#ifdef IPSEC + kernel_insert_spi(spi); +#endif + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_spi_update.c b/sbin/ipsec/photurisd/handle_spi_update.c new file mode 100644 index 00000000000..6053b1feff3 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_spi_update.c @@ -0,0 +1,195 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_spi_update: + * receive a SPI_UPDATE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_spi_update.c,v 1.1 1997/07/18 22:48:51 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "encrypt.h" +#include "validity.h" +#include "secrets.h" +#include "schedule.h" +#include "scheme.h" +#include "errlog.h" +#include "spi.h" +#ifdef IPSEC +#include "kernel.h" +#endif + +int +handle_spi_update(u_char *packet, int size, char *address, + char *local_address) +{ + 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 signature[22]; /* XXX - constant */ + + if (size < SPI_UPDATE_MIN) + return -1; /* packet too small */ + + header = (struct spi_update *) packet; + + st = state_find_cookies(address, header->icookie, header->rcookie); + if (st == NULL) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, BAD_COOKIE); + send_packet(); + return 0; + } + + if (st->phase != SPI_UPDATE && st->phase != SPI_NEEDED) + return 0; /* We don't want this packet */ + + /* Decrypt message */ + tmp = size - SPI_UPDATE_MIN; + if (packet_decrypt(st, SPI_UPDATE_VERIFICATION(header), &tmp) == -1) { + log_error(0, "packet_decrypt() in handle_spi_update()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + /* Verify message */ + if (!(i = get_validity_verification_size(st))) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + + return -1; + } + + 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; + + if (asize != size) { + log_error(0, "wrong packet size in handle_spi_update()"); + return -1; + } + + if (i > sizeof(signature)) { + log_error(0, "verification too long in handle_spi_update()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return -1; + } + + bcopy(p, signature, i); + bzero(p, i); + + if (!verify_validity_verification(st, signature, packet, size)) { + log_error(0, "verification failed in handle_spi_update()"); + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(st, packet_buffer, &packet_size, + header->icookie, header->rcookie, + 0, VERIFICATION_FAILURE); + send_packet(); + return 0; + } + + lifetime = (header->lifetime[0]<<16) + (header->lifetime[1]<<8) + + header->lifetime[2]; + + if (lifetime == 0) { + /* Delete specified security association */ + if ((spi = spi_find(st->address, header->SPI)) == NULL) { + log_error(0, "spi_find() in handle_spi_update()"); + return -1; + } +#ifdef IPSEC + kernel_unlink_spi(spi); +#endif + spi_unlink(spi); + spi_value_reset(spi); + return 0; + } + + if ((spi = spi_new(st->address, header->SPI)) == NULL) { + log_error(0, "spi_new() in handle_spi_update()"); + return -1; + } + if ((spi->local_address = strdup(local_address)) == NULL) { + log_error(1, "strdup() in handle_spi_update()"); + return -1; + } + if((spi->attributes = calloc(attribsize, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in handle_spi_update()"); + return -1; + } + bcopy(attributes, spi->attributes, attribsize); + spi->attribsize = attribsize; + bcopy(st->icookie, spi->icookie, COOKIE_SIZE); + spi->lifetime = time(NULL) + lifetime; + + make_session_keys(st, spi); + + spi_insert(spi); +#ifdef IPSEC + kernel_insert_spi(spi); +#endif + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_value_request.c b/sbin/ipsec/photurisd/handle_value_request.c new file mode 100644 index 00000000000..4c6d5a28f30 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_value_request.c @@ -0,0 +1,248 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_value_request: + * receive a VALUE_REQUEST packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_value_request.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include <netinet/in.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "config.h" +#include "buffer.h" +#include "scheme.h" +#include "packet.h" +#include "exchange.h" +#include "secrets.h" +#include "errlog.h" + +int +handle_value_request(u_char *packet, int size, + char *address, u_short port, + u_int8_t *schemes, u_int16_t ssize) + +{ + struct value_request *header; + struct stateob *st; + u_int8_t *p, *modp, *refp, *genp = NULL; + u_int16_t i, sstart, vsize, asize, modsize, modflag; + u_int8_t scheme_ref[2]; + u_int8_t rcookie[COOKIE_SIZE]; + + if (size < VALUE_REQUEST_MIN) + return -1; /* packet too small */ + + header = (struct value_request *) packet; + + st = state_find_cookies(address, header->icookie, header->rcookie); + if (st == NULL) { + struct stateob tempst; + bzero((char *)&tempst, sizeof(tempst)); /* Set up temp. state */ + tempst.initiator = 0; /* We are the Responder */ + bcopy(header->icookie, tempst.icookie, COOKIE_SIZE); + strncpy(tempst.address, address, 15); + tempst.port = port; + tempst.counter = header->counter; + + cookie_generate(&tempst, rcookie, COOKIE_SIZE); + + /* Check for invalid cookie */ + if (bcmp(rcookie, header->rcookie, COOKIE_SIZE)) { + packet_size = PACKET_BUFFER_SIZE; + photuris_error_message(&tempst, packet_buffer, &packet_size, + header->icookie, header->rcookie, + header->counter, BAD_COOKIE); + send_packet(); + return 0; + } + + /* 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 */ + + /* Check schemes - selected length is in exchange value*/ + sstart = 0; + modflag = 0; + refp = modp = NULL; + *(u_int16_t *)scheme_ref = htons(scheme_get_ref(header->scheme)); + while(sstart < ssize) { + p = scheme_get_mod(schemes+sstart); + modsize = varpre2octets(p); + if (!bcmp(header->scheme, schemes + sstart, 2)) { + modflag = 1; + if (modsize == vsize) { + genp = scheme_get_gen(schemes+sstart); + modp = p; + break; /* On right scheme + right size */ + } else if (modsize <= 2 && refp != NULL) { + modp = refp; + break; + } + } else if (!bcmp(scheme_ref, schemes + sstart,2 ) && modsize == vsize) { + genp = scheme_get_gen(schemes+sstart); + if (modflag) { + modp = p; + break; + } + refp = p; + } + + sstart += scheme_get_len(schemes+sstart); + } + 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 */ + + if ((st = state_new()) == NULL) + return -1; + + /* Default options */ + st->flags = IPSEC_OPT_ENC|IPSEC_OPT_AUTH; + + /* Fill the state object */ + st->uSPIoattrib = calloc(i, sizeof(u_int8_t)); + if (st->uSPIoattrib == NULL) { + state_value_reset(st); + return -1; + } + bcopy(p, st->uSPIoattrib, i); + st->uSPIoattribsize = i; + + /* Save scheme, which will be used by both parties */ + vsize = 2 + varpre2octets(modp); + + /* XXX - VPN - only support two octets */ + if (genp != NULL) + vsize += 2 + varpre2octets(genp); + + st->scheme = calloc(vsize, sizeof(u_int8_t)); + if (st->scheme == NULL) { + state_value_reset(st); + return -1; + } + bcopy(header->scheme, st->scheme, 2); + if (genp != NULL) { + st->scheme[2] = (vsize-4) >> 8; + st->scheme[3] = (vsize-4) & 0xFF; + bcopy(genp, st->scheme+2+2, varpre2octets(genp)); + } + bcopy(modp, st->scheme + 2 + (genp == NULL ? 0 : 2 + varpre2octets(genp)), + varpre2octets(modp));; + + st->schemesize = vsize; + +#ifdef DEBUG + { + int i = BUFFER_SIZE; + bin2hex(buffer, &i, VALUE_REQUEST_VALUE(header), 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->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); + + strncpy(st->address, address, 15); + st->port = port; + st->counter = header->counter; + bcopy(header->icookie, st->icookie, COOKIE_SIZE); + bcopy(header->rcookie, st->rcookie, COOKIE_SIZE); + + if ((st->roschemes = calloc(ssize, sizeof(u_int8_t))) == NULL) { + state_value_reset(st); + return -1; + } + bcopy(schemes, st->roschemes, ssize); + st->roschemesize = ssize; + + if (pick_attrib(st, &(st->oSPIoattrib), + &(st->oSPIoattribsize)) == -1) { + state_value_reset(st); + return -1; + } + + st->lifetime = exchange_timeout + time(NULL); + + /* Now put the filled state object in the chain */ + state_insert(st); + } + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_value_response(st, packet_buffer, &packet_size) == -1) + return -1; + + send_packet(); + + /* Compute the shared secret now */ + compute_shared_secret(st, &(st->shared), &(st->sharedsize)); +#ifdef DEBUG + { + int i = BUFFER_SIZE; + bin2hex(buffer, &i, st->shared, st->sharedsize); + printf("Shared secret is: 0x%s\n", buffer); + } +#endif + + st->retries = 0; + st->phase = VALUE_RESPONSE; + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_value_response.c b/sbin/ipsec/photurisd/handle_value_response.c new file mode 100644 index 00000000000..1fcf263bca8 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_value_response.c @@ -0,0 +1,156 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_value_response: + * receive a VALUE_RESPONSE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_value_response.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "scheme.h" +#include "packet.h" +#include "schedule.h" +#include "exchange.h" +#include "secrets.h" +#include "spi.h" +#include "errlog.h" +#ifdef DEBUG +#include "config.h" +#endif + +int +handle_value_response(u_char *packet, int size, char *address, + char *local_address) + +{ + struct value_response *header; + struct stateob *st; + u_int8_t *p; + u_int16_t i, asize; + + if (size < VALUE_RESPONSE_MIN) + return -1; /* packet too small */ + + header = (struct value_response *) packet; + + st = state_find_cookies(address, header->icookie, header->rcookie); + if (st == NULL) + return -1; /* Silently discard */ + + 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 */ + + /* Fill the state object */ + st->uSPIoattrib = calloc(i, 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; + +#ifdef DEBUG + { + int i = BUFFER_SIZE; + bin2hex(buffer, &i, VALUE_RESPONSE_VALUE(header), + varpre2octets(VALUE_RESPONSE_VALUE(header))); + printf("Got exchange value 0x%s\n", buffer); + } +#endif + + /* Set exchange value */ + st->texchangesize = varpre2octets(VALUE_RESPONSE_VALUE(header)); + 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); + + /* Compute the shared secret now */ + compute_shared_secret(st, &(st->shared), &(st->sharedsize)); +#ifdef DEBUG + { + int i = BUFFER_SIZE; + bin2hex(buffer, &i, st->shared, st->sharedsize); + printf("Shared secret is: 0x%s\n", buffer); + } +#endif + + /* Create SPI + choice of attributes */ + if (make_spi(st, local_address, st->oSPI, &(st->olifetime), + &(st->oSPIattrib), &(st->oSPIattribsize)) == -1) { + log_error(0, "make_spi() in handle_value_response()"); + return -1; + } + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_identity_request(st, packet_buffer, &packet_size) == -1) + return -1; + + packet_save(st, packet_buffer, packet_size); + + send_packet(); + + st->retries = 0; + st->phase = IDENTITY_REQUEST; + + schedule_remove(TIMEOUT, st->icookie); + schedule_insert(TIMEOUT, retrans_timeout, st->icookie, COOKIE_SIZE); + return 0; +} diff --git a/sbin/ipsec/photurisd/handle_verification_failure.c b/sbin/ipsec/photurisd/handle_verification_failure.c new file mode 100644 index 00000000000..d57e1eb0fe7 --- /dev/null +++ b/sbin/ipsec/photurisd/handle_verification_failure.c @@ -0,0 +1,74 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_verification_failure: + * receive a VERIFICATION_FAILURE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: handle_verification_failure.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" +#include "buffer.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" + +int +handle_verification_failure(u_char *packet, int size, char *address) +{ + struct error_message *header; + struct stateob *st; + + if (size != ERROR_MESSAGE_PACKET_SIZE) + return -1; /* packet too small/big */ + + header = (struct error_message *) packet; + + if ((st = state_find_cookies(address, header->icookie, + header->rcookie)) == NULL) { + log_error(0, "No state for VERIFICATION_FAILURE message from %s", + address); + return -1; + } + + log_error(0, "Received VERIFICATION_FAILURE from %s", address); + + return 0; +} diff --git a/sbin/ipsec/photurisd/identity.c b/sbin/ipsec/photurisd/identity.c new file mode 100644 index 00000000000..fdfc11d0431 --- /dev/null +++ b/sbin/ipsec/photurisd/identity.c @@ -0,0 +1,728 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * identity.c: + * handling identity choices and creation of the before mentioned. + */ + +#ifndef lint +static char rcsid[] = "$Id: identity.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#define _IDENTITY_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <sys/types.h> +#include <pwd.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <md5.h> +#include <gmp.h> +#include <sha1.h> +#include "config.h" +#include "photuris.h" +#include "state.h" +#include "attributes.h" +#include "modulus.h" +#include "exchange.h" +#include "identity.h" +#include "buffer.h" +#include "scheme.h" +#include "errlog.h" + +#ifdef NEED_STRSEP +#include "strsep.h" +#endif + +static struct identity *idob = NULL; + +int +init_identities(char *name, struct identity *root) +{ + FILE *fp; + char *p, *p2, *file = secret_file; + struct identity *tmp, **ob; + struct passwd *pwd; + struct stat sb; + int type; + + if (name != NULL) { + ob = (struct identity **)&root->object; + file = name; + } else + ob = &idob; + + if (lstat(file, &sb) == -1) { + log_error(1, "lstat() on %s in init_identities()", file); + return -1; + } + if (((sb.st_mode & S_IFMT) & ~S_IFREG)) { + log_error(0, "no regular file %s in init_identities()", file); + return -1; + } + fp = fopen(file, "r"); + if (fp == (FILE *) NULL) + { + log_error(1, "no hash secrets file %s", file); + return -1; + } + +#ifdef DEBUG + if (name == NULL) + printf("[Reading identities + secrets]\n"); +#endif + + while(fgets(buffer, BUFFER_SIZE,fp)) { + p=buffer; + while(isspace(*p)) /* Get rid of leading spaces */ + p++; + if(*p == '#') /* Ignore comments */ + continue; + + if (!strncmp(p, IDENT_LOCAL, strlen(IDENT_LOCAL))) { + type = ID_LOCAL; + p += strlen(IDENT_LOCAL); + } else if (!strncmp(p, IDENT_LOCALPAIR, strlen(IDENT_LOCALPAIR))) { + type = ID_LOCALPAIR; + p += strlen(IDENT_LOCALPAIR); + } else if (!strncmp(p, IDENT_REMOTE, strlen(IDENT_REMOTE))) { + type = ID_REMOTE; + p += strlen(IDENT_REMOTE); + } else if (!strncmp(p, IDENT_LOOKUP, strlen(IDENT_LOOKUP))) { + type = ID_LOOKUP; + p += strlen(IDENT_LOOKUP); + } else { + log_error(0, "Unkown tag %s in %s", p, file); + continue; + } + + if ((tmp = identity_new()) == NULL) { + log_error(0, "identity_new() in init_identities()"); + continue; + } + + p2 = p; + if (!isspace(*p2)) + continue; + + /* Tokens are braced with "token" */ + if((p=strsep(&p2, "\"\'")) == NULL || + (p=strsep(&p2, "\"\'")) == NULL) + continue; + + tmp->type = type; + tmp->tag = strdup(p); + tmp->root = root; + + switch(type) { + case ID_LOCAL: + case ID_REMOTE: + if (type == ID_REMOTE) { + /* Search for duplicates */ + if (identity_find(idob, tmp->tag, ID_REMOTE) != NULL) { + log_error(0, "Duplicate id \"%s\" found in %s", + tmp->tag, name != NULL ? name : "root"); + identity_value_reset(tmp); + continue; + } + } + /* Tokens are braced with "token" */ + if((p=strsep(&p2, "\"\'")) == NULL || + (p=strsep(&p2, "\"\'")) == NULL) { + identity_value_reset(tmp); + continue; + } + tmp->object = strdup(p); + break; + case ID_LOCALPAIR: + /* Tokens are braced with "token" */ + if((p=strsep(&p2, "\"\'")) == NULL || + (p=strsep(&p2, "\"\'")) == NULL) { + identity_value_reset(tmp); + continue; + } + tmp->pairid = strdup(p); + /* Tokens are braced with "token" */ + if((p=strsep(&p2, "\"\'")) == NULL || + (p=strsep(&p2, "\"\'")) == NULL) { + identity_value_reset(tmp); + continue; + } + tmp->object = strdup(p); + break; + case ID_LOOKUP: + if (name != NULL) { + log_error(0, "lookup in user file %s in init_identities()", + name); + continue; + } + while(isspace(*p2)) p2++; + + while(isspace(p2[strlen(p2)-1])) + p2[strlen(p2)-1] = 0; + + if ((pwd = getpwnam(p2)) == NULL) { + log_error(1, "getpwnam() in init_identities()"); + identity_value_reset(tmp); + continue; + } else { + char *dir = calloc(strlen(PHOTURIS_USER_SECRET)+ + strlen(pwd->pw_dir) + 2, + sizeof(char)); + + /* This is the user name */ + tmp->pairid = strdup(p2); + + if (dir == NULL) { + log_error(1, "calloc() in init_identities()"); + identity_value_reset(tmp); + continue; + } + sprintf(dir,"%s/%s", pwd->pw_dir, PHOTURIS_USER_SECRET); + if (init_identities(dir, (struct identity *)tmp) == -1) { + free(dir); + identity_value_reset(tmp); + continue; + } + + free(dir); + } + break; + } + identity_insert(ob, tmp); + } + fclose(fp); + + return 0; +} + +/* + * Get shared symmetric keys and identity, put the values in + * the state object. If a SPI User ident is given, we look up + * the matching remote secret. + */ + +int +get_secrets(struct stateob *st, int mode) +{ + u_int8_t local_ident[MAX_IDENT]; + u_int8_t local_secret[MAX_IDENT_SECRET]; + u_int8_t remote_secret[MAX_IDENT_SECRET]; + + struct identity *id, *root = idob; + + local_ident[0] = '\0'; + local_secret[0] = '\0'; + remote_secret[0] = '\0'; + + /* + * Remote secret first, if we find the remote secret in + * a user secret file, we restrict our local searches + * to that tree. + */ + + if(st->uSPIident != NULL && st->uSPIsecret == NULL && + (mode & ID_REMOTE)) { + int skip; + + if (st->uSPIident[0] == 255 && st->uSPIident[1] == 255) + skip = 8; + else if (st->uSPIident[0] == 255) + skip = 4; + else + skip = 2; + + id = identity_find(root, st->uSPIident+skip, ID_REMOTE); + if (id != NULL) { + strncpy(remote_secret, id->object, MAX_IDENT_SECRET-1); + remote_secret[MAX_IDENT_SECRET-1] = '\0'; + + if (id->root) + root = (struct identity *)id->root->object; + } + } + + if (st->user != NULL && + (id = identity_find(idob, st->user, ID_LOOKUP)) != NULL) { + /* User keying */ + id = identity_find((struct identity *)id->object, NULL, ID_LOCAL); + } else + id = NULL; + + if (id == NULL) { + /* Host keying */ + id = identity_find(root, NULL, ID_LOCAL); + } + + if (id != NULL && (mode & (ID_LOCAL|ID_LOCALPAIR))) { + /* Namespace: root->tag + user->tag */ + if (id->root) { + strncpy(local_ident, id->root->tag, MAX_IDENT-1); + local_ident[MAX_IDENT-1] = '\0'; + } + strncpy(local_ident+strlen(local_ident), id->tag, + MAX_IDENT-1-strlen(local_ident)); + local_ident[MAX_IDENT_SECRET-1] = '\0'; + + strncpy(local_secret, id->object, MAX_IDENT_SECRET-1); + local_secret[MAX_IDENT_SECRET-1] = '\0'; + } + if (st->uSPIident != NULL && st->oSPIident == NULL && + (mode & (ID_LOCAL|ID_LOCALPAIR))) { + int skip; + if (st->uSPIident[0] == 255 && st->uSPIident[1] == 255) + skip = 8; + else if (st->uSPIident[0] == 255) + skip = 4; + else + skip = 2; + + id = identity_find(root, st->uSPIident+skip, ID_LOCALPAIR); + if (id != NULL) { + local_ident[0] = '\0'; + /* Namespace: root->tag + user->tag */ + if (id->root) { + strncpy(local_ident, id->root->tag, MAX_IDENT-1); + local_ident[MAX_IDENT-1] = '\0'; + } + strncpy(local_ident+strlen(local_ident), id->pairid, + MAX_IDENT-1-strlen(local_ident)); + local_ident[MAX_IDENT-1] = '\0'; + + strncpy(local_secret, id->object, MAX_IDENT_SECRET-1); + local_secret[MAX_IDENT_SECRET-1] = '\0'; + } + } + + if((strlen(remote_secret) == 0 && (mode & ID_REMOTE)) || + (strlen(local_ident) == 0 && (mode & (ID_LOCAL|ID_LOCALPAIR))) ) { + log_error(0, "Can't find identities or secrets in get_secrets()"); + return -1; + } + + if(st->oSPIident == NULL && (mode & (ID_LOCAL|ID_LOCALPAIR))) { + st->oSPIident = calloc(2+strlen(local_ident)+1,sizeof(u_int8_t)); + if(st->oSPIident == NULL) + return -1; + strcpy(st->oSPIident+2,local_ident); + 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)); + if(st->oSPIsecret == NULL) + return -1; + strcpy(st->oSPIsecret,local_secret); + st->oSPIsecretsize = strlen(local_secret)+1; + } + if(st->uSPIident != NULL && st->uSPIsecret == NULL && + (mode & ID_REMOTE)) { + st->uSPIsecret = calloc(strlen(remote_secret)+1,sizeof(u_int8_t)); + if(st->uSPIsecret == NULL) + return -1; + strcpy(st->uSPIsecret,remote_secret); + st->uSPIsecretsize = strlen(remote_secret)+1; + } + return 0; +} + +int +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; + int mode = 0; + rsize = *size; + + /* XXX - we only have one identity choice at the moment. */ + tmp = 0; + while(attribsize>0 && !tmp) { + switch(*attributes) { + case AT_MD5_DP: + tmp = 1; + break; + default: + if(attribsize -(*(attributes+1)+2) > attribsize) { + attribsize=0; + break; + } + attribsize -= *(attributes+1)+2; + attributes += *(attributes+1)+2; + break; + } + } + + if(attribsize == 0) { + log_error(0, "No identity choice found in offered attributes " + "in choose_identity"); + return -1; + } + + if(rsize < *(attributes+1)+2) + return -1; + + asize = *(attributes+1)+2; + rsize -= asize; + bcopy(attributes, packet, asize); + + /* Now put identity in state object */ + if (st->oSPIidentchoice == NULL) { + if ((st->oSPIidentchoice = calloc(asize, sizeof(u_int8_t))) == NULL) + return -1; + bcopy(attributes, st->oSPIidentchoice, asize); + st->oSPIidentchoicesize = asize; + } + + packet += asize; + + /* Chooses identity and secrets for Owner and User */ + if (st->uSPIsecret == NULL && st->uSPIident != NULL) + mode |= ID_REMOTE; + if (st->oSPIsecret == NULL) + mode |= ID_LOCAL; + if(get_secrets(st, mode) == -1) + return -1; + + /* oSPIident is varpre already */ + tmp = 2+strlen(st->oSPIident+2)+1; + if(rsize < tmp) + return -1; + + bcopy(st->oSPIident, packet, tmp); + + *size = asize + tmp; + + return 0; +} + + +u_int16_t +get_identity_verification_size(struct stateob *st, u_int8_t *choice) +{ + switch(*choice) { + case AT_MD5_DP: + return (128/8)+2; + default: + log_error(0, "Unknown identity choice: %d\n", *choice); + return 0; + } +} + +int +create_identity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size) +{ + int hash_size; + switch(*(st->oSPIidentchoice)) { + case AT_MD5_DP: + hash_size = MD5idsign(st, buffer+2, packet, size); + break; + default: + log_error(0, "Unknown identity choice: %d\n", + *(st->oSPIidentchoice)); + return 0; + } + if(hash_size) { + /* Create varpre number from digest */ + buffer[0] = hash_size >> 5 & 0xFF; + buffer[1] = hash_size << 3 & 0xFF; + + if(st->oSPIidentver != NULL) + free(st->oSPIidentver); + + st->oSPIidentver = calloc(hash_size+2,sizeof(u_int8_t)); + if(st->oSPIidentver == NULL) { + log_error(1, "Not enough memory in create_identity_verification()", 0); + return 0; + } + + bcopy(buffer, st->oSPIidentver, hash_size+2); + st->oSPIidentversize = hash_size+2; + } + return hash_size+2; +} + +int +verify_identity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size) +{ + switch(*(st->uSPIidentchoice)) { + case AT_MD5_DP: + if (varpre2octets(buffer) != 18) + return 0; + return MD5idverify(st, buffer+2, packet, size); + default: + log_error(0, "Unknown identity choice %d in verify_identity_verification()", + *(st->uSPIidentchoice)); + return 0; + } +} + + +int +MD5idsign(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize) +{ + MD5_CTX ctx; + struct moduli_cache *mod; + struct identity_message *p; + + MD5Init(&ctx); + + MD5Update(&ctx, st->shared, st->sharedsize); + + MD5Update(&ctx, st->icookie, COOKIE_SIZE); + MD5Update(&ctx, st->rcookie, COOKIE_SIZE); + MD5Update(&ctx, st->roschemes, st->roschemesize); + + /* Our exchange value */ + mod = mod_find_modgen(st->modulus, st->generator); + MD5Update(&ctx, mod->exchangevalue, mod->exchangesize); + MD5Update(&ctx, st->oSPIoattrib, st->oSPIoattribsize); + MD5Update(&ctx, st->oSPIident, strlen(st->oSPIident)); + MD5Update(&ctx, st->oSPIsecret, st->oSPIsecretsize); + + /* Their exchange value */ + MD5Update(&ctx, st->texchange, st->texchangesize); + MD5Update(&ctx, st->uSPIoattrib, st->uSPIoattribsize); + + if(st->uSPIident != NULL) { + MD5Update(&ctx, st->uSPIident, strlen(st->uSPIident)); + MD5Update(&ctx, st->uSPIsecret, st->uSPIsecretsize); + } + + /* Hash type, lifetime + spi fields */ + p = (struct identity_message *)packet; + MD5Update(&ctx, (char *)&(p->type), IDENTITY_MESSAGE_MIN - 2*COOKIE_SIZE); + + /* Hash attribute choice, padding */ + 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; + + MD5Update(&ctx, packet, psize); + + /* Data fill */ + MD5Final(NULL, &ctx); + + /* And finally the trailing key */ + MD5Update(&ctx, st->shared, st->sharedsize); + + MD5Final(signature, &ctx); + + return MD5_SIZE; +} + +int +MD5idverify(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize) +{ + MD5_CTX ctx; + u_int8_t digest[16]; + struct moduli_cache *mod; + struct identity_message *p; + + p = (struct identity_message *)packet; + + MD5Init(&ctx); + + /* Our shared secret */ + MD5Update(&ctx, st->shared, st->sharedsize); + + MD5Update(&ctx, st->icookie, COOKIE_SIZE); + MD5Update(&ctx, st->rcookie, COOKIE_SIZE); + MD5Update(&ctx, st->roschemes, st->roschemesize); + + /* Their exchange value */ + MD5Update(&ctx, st->texchange, st->texchangesize); + MD5Update(&ctx, st->uSPIoattrib, st->uSPIoattribsize); + MD5Update(&ctx, st->uSPIident, strlen(st->uSPIident)); + MD5Update(&ctx, st->uSPIsecret, st->uSPIsecretsize); + + /* Our exchange value */ + mod = mod_find_modgen(st->modulus, st->generator); + MD5Update(&ctx, mod->exchangevalue, mod->exchangesize); + MD5Update(&ctx, st->oSPIoattrib, st->oSPIoattribsize); + + /* Determine if the sender knew our secret already */ + if(p->type != IDENTITY_REQUEST) { + MD5Update(&ctx, st->oSPIident, strlen(st->oSPIident)); + MD5Update(&ctx, st->oSPIsecret, st->oSPIsecretsize); + } + + /* Hash type, lifetime + spi fields */ + MD5Update(&ctx, (char *)&(p->type), IDENTITY_MESSAGE_MIN - 2*COOKIE_SIZE); + + 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; + MD5Update(&ctx, packet, psize); + + /* Data fill */ + MD5Final(NULL, &ctx); + + /* And finally the trailing key */ + MD5Update(&ctx, st->shared, st->sharedsize); + + MD5Final(digest, &ctx); + + return !bcmp(digest, signature, MD5_SIZE); +} + +int +identity_insert(struct identity **idob, struct identity *ob) +{ + struct identity *tmp; + + ob->next = NULL; + + if(*idob == NULL) { + *idob = ob; + return 1; + } + + tmp=*idob; + while(tmp->next!=NULL) + tmp = tmp->next; + + tmp->next = ob; + return 1; +} + +int +identity_unlink(struct identity **idob, struct identity *ob) +{ + struct identity *tmp; + if(*idob == ob) { + *idob = ob->next; + free(ob); + return 1; + } + + for(tmp=*idob; tmp!=NULL; tmp=tmp->next) { + if(tmp->next==ob) { + tmp->next=ob->next; + free(ob); + return 1; + } + } + return 0; +} + +struct identity * +identity_new(void) +{ + struct identity *p; + + if((p = calloc(1, sizeof(struct identity)))==NULL) + return NULL; + + return p; +} + +int +identity_value_reset(struct identity *ob) +{ + if (ob->tag != NULL) + free(ob->tag); + if (ob->pairid != NULL) + free(ob->pairid); + if (ob->object != NULL) + free(ob->object); + + return 1; +} + +/* + * find the state ob with matching address + */ + +struct identity * +identity_root(void) +{ + return idob; +} + +/* On ID_LOOKUP match pairid, on ID_LOCAL only match type */ + +struct identity * +identity_find(struct identity *idob, char *id, int type) +{ + struct identity *tmp = idob, *p; + while(tmp!=NULL) { + if(((type == ID_LOCAL && id == NULL) || + (type != ID_LOOKUP && !strcmp(id, tmp->tag)) || + (type == ID_LOOKUP && tmp->pairid != NULL && !strcmp(id, tmp->pairid))) && + type == tmp->type) + return tmp; + if (tmp->type == ID_LOOKUP && tmp->object != NULL) { + p = identity_find((struct identity *)tmp->object, id, type); + if (p != NULL) + return p; + } + tmp = tmp->next; + } + return NULL; +} + +void +identity_cleanup(struct identity **root) +{ + struct identity *p; + struct identity *tmp; + + if (root == NULL) + tmp = idob; + else + tmp = *root; + + while(tmp!=NULL) { + if (tmp->type == ID_LOOKUP) + identity_cleanup((struct identity **)&tmp->object); + p = tmp; + tmp = tmp->next; + identity_value_reset(p); + free(p); + } + + if (root != NULL) + *root = NULL; + else + idob = NULL; +} diff --git a/sbin/ipsec/photurisd/identity.h b/sbin/ipsec/photurisd/identity.h new file mode 100644 index 00000000000..0b6d3d69459 --- /dev/null +++ b/sbin/ipsec/photurisd/identity.h @@ -0,0 +1,97 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 */ +/* + * identity.h: + * identity for a security association + */ + +#ifndef _IDENTITY_H_ +#define _IDENTITY_H_ +#include "state.h" + +#undef EXTERN +#ifdef _IDENTITY_C_ +#define EXTERN + +char *secret_file = NULL; + +#else +#define EXTERN extern + +extern char *secret_file; +#endif + +#define ID_LOCAL 1 +#define ID_LOCALPAIR 2 +#define ID_REMOTE 4 +#define ID_LOOKUP 8 + +#define IDENT_LOCAL "identity local" +#define IDENT_LOCALPAIR "identity pair local" +#define IDENT_REMOTE "identity remote" +#define IDENT_LOOKUP "identity lookup" + +#define MAX_IDENT 120 +#define MAX_IDENT_SECRET 120 + +struct identity { + struct identity *next; + struct identity *root; + int type; + char *tag; + char *pairid; + void *object; +}; + +#define MD5_SIZE 16 +#define SHA1_SIZE 20 + +int init_identities(char *name, struct identity *ob); +int identity_insert(struct identity **idob, struct identity *ob); +int identity_unlink(struct identity **idob, struct identity *ob); +struct identity *identity_new(void); +struct identity *identity_root(void); +int identity_value_reset(struct identity *ob); +struct identity *identity_find(struct identity *ob, char *id, int type); +void identity_cleanup(struct identity **idob); + +int get_secrets(struct stateob *st, int mode); +int choose_identity(struct stateob *st, u_int8_t *packet, u_int16_t *size, + u_int8_t *attributes, u_int16_t attribsize); +u_int16_t get_identity_verification_size(struct stateob *st, u_int8_t *choice); +int create_identity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size); +int verify_identity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size); + +int MD5idsign(struct stateob *, u_int8_t *, u_int8_t *, u_int16_t); +int MD5idverify(struct stateob *, u_int8_t *, u_int8_t *, u_int16_t); +#endif diff --git a/sbin/ipsec/photurisd/kernel.c b/sbin/ipsec/photurisd/kernel.c new file mode 100644 index 00000000000..ac7955a87a2 --- /dev/null +++ b/sbin/ipsec/photurisd/kernel.c @@ -0,0 +1,460 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$Id: kernel.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/mbuf.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/route.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#include <netns/ns.h> +#include <netiso/iso.h> +#include <netccitt/x25.h> +#include <arpa/inet.h> +#include <netdb.h> + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <paths.h> +#define INET /* Needed for setting ipsec routes */ +#include <net/encap.h> +#include <netinet/ip_ipsp.h> +#include <netinet/ip_esp.h> +#include <netinet/ip_ah.h> + +#define _KERNEL_C_ +#include "state.h" +#include "attributes.h" +#include "buffer.h" +#include "spi.h" +#include "kernel.h" +#include "errlog.h" +#ifdef DEBUG +#include "config.h" +#endif + +static int sd; + +int +init_kernel(void) +{ + if ((sd = socket(AF_ENCAP, SOCK_RAW, AF_UNSPEC)) < 0) + crit_error(1, "socket() in init_kernel()"); + return 1; +} + +int +kernel_get_socket(void) +{ + return sd; +} + +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()"); + return 0; + } + return 1; +} + +int +kernel_xf_read(struct encap_msghdr *em, int msglen) +{ + if (read(sd, (char *)em, msglen) != msglen) { + log_error(1, "read() in kernel_xf_read()"); + return 0; + } + return 1; +} + +u_int32_t +kernel_reserve_spi(char *srcaddress) +{ + struct encap_msghdr *em; + + bzero(buffer, EMT_ENABLESPI_FLEN); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_RESERVESPI_FLEN; + em->em_version = PFENCAP_VERSION_1; + em->em_type = EMT_RESERVESPI; + + em->em_gen_spi = 0; + em->em_gen_dst.s_addr = inet_addr(srcaddress); + + if (!kernel_xf_set(em)) + return 0; + + if (!kernel_xf_read(em, EMT_RESERVESPI_FLEN)) + return 0; + + return em->em_gen_spi; +} +int +kernel_md5(char *srcaddress, char *dstaddress, u_int8_t *spi, u_int8_t *secret) +{ + struct encap_msghdr *em; + struct ah_old_xencap *xd; + int klen; + + klen = MD5_KEYLEN/8; + + bzero(buffer, EMT_SETSPI_FLEN + 4 + klen); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN + 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); + em->em_alg = XF_OLD_AH; + em->em_sproto = IPPROTO_AH; + + xd = (struct ah_old_xencap *)(em->em_dat); + + xd->amx_hash_algorithm = ALG_AUTH_MD5; + xd->amx_keylen = klen; + + bcopy(secret, xd->amx_key, klen); + + if (!kernel_xf_set(em)) + return -1; + + return MD5_KEYLEN/8; +} + +int +kernel_des(char *srcaddress, char *dstaddress, u_int8_t *spi, u_int8_t *secret) +{ + struct encap_msghdr *em; + struct esp_old_xencap *xd; + + bzero(buffer, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN + 4 + 8); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN + 4 + 8; + 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_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); + + if (!kernel_xf_set(em)) + return -1; + + return 8; +} + +/* Group an ESP SPI with an AH SPI */ + +int +kernel_group_spi(char *address, u_int8_t *spi) +{ + struct encap_msghdr *em; + in_addr_t addr; + u_int32_t SPI; + + SPI = (spi[0]<<24) + (spi[1]<<16) + (spi[2]<<8) + spi[3]; + addr = inet_addr(address); + + bzero(buffer, EMT_GRPSPIS_FLEN); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_GRPSPIS_FLEN; + em->em_version = PFENCAP_VERSION_1; + em->em_type = EMT_GRPSPIS; + + em->em_rel_spi = htonl(SPI); + em->em_rel_dst.s_addr = addr; + em->em_rel_sproto = IPPROTO_ESP; + em->em_rel_spi2 = htonl(SPI); + em->em_rel_dst2.s_addr = addr; + em->em_rel_sproto2 = IPPROTO_AH; + + if (!kernel_xf_set(em)) + return -1; + + return 1; +} + +int +kernel_enable_spi(char *isrc, char *ismask, char *idst, char *idmask, + char *address, u_int8_t *spi, int proto, int flags) +{ + struct encap_msghdr *em; + u_int32_t SPI; + + SPI = (spi[0]<<24) + (spi[1]<<16) + (spi[2]<<8) + spi[3]; + + bzero(buffer, EMT_ENABLESPI_FLEN); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_ENABLESPI_FLEN; + em->em_version = PFENCAP_VERSION_1; + em->em_type = EMT_ENABLESPI; + + em->em_ena_isrc.s_addr = inet_addr(isrc); + em->em_ena_ismask.s_addr = inet_addr(ismask); + em->em_ena_idst.s_addr = inet_addr(idst); + em->em_ena_idmask.s_addr = inet_addr(idmask); + + em->em_ena_dst.s_addr = inet_addr(address); + em->em_ena_spi = htonl(SPI); + em->em_ena_sproto = proto; + em->em_ena_flags = flags; + + if (!kernel_xf_set(em)) + return -1; + + return 1; +} + +int +kernel_disable_spi(char *isrc, char *ismask, char *idst, char *idmask, + char *address, u_int8_t *spi, int proto, int flags) +{ + struct encap_msghdr *em; + u_int32_t SPI; + + SPI = (spi[0]<<24) + (spi[1]<<16) + (spi[2]<<8) + spi[3]; + + bzero(buffer, EMT_DISABLESPI_FLEN); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_DISABLESPI_FLEN; + em->em_version = PFENCAP_VERSION_1; + em->em_type = EMT_DISABLESPI; + + em->em_ena_isrc.s_addr = inet_addr(isrc); + em->em_ena_ismask.s_addr = inet_addr(ismask); + em->em_ena_idst.s_addr = inet_addr(idst); + em->em_ena_idmask.s_addr = inet_addr(idmask); + + em->em_ena_dst.s_addr = inet_addr(address); + em->em_ena_spi = htonl(SPI); + em->em_ena_sproto = proto; + em->em_ena_flags = flags; + + if (!kernel_xf_set(em)) + return -1; + + return 1; +} + +int +kernel_delete_spi(char *address, u_int8_t *spi, int proto) +{ + struct encap_msghdr *em; + + bzero(buffer, EMT_DELSPI_FLEN); + + em = (struct encap_msghdr *)buffer; + + em->em_msglen = EMT_DELSPI_FLEN; + em->em_version = PFENCAP_VERSION_1; + em->em_type = EMT_DELSPI; + em->em_gen_spi = htonl((spi[0]<<24) + (spi[1]<<16) + + (spi[2]<<8) + spi[3]); + em->em_gen_dst.s_addr = inet_addr(address); + em->em_gen_sproto = proto; + + if (!kernel_xf_set(em)) + return -1; + + return 1; +} + +int +kernel_insert_spi(struct spiob *SPI) +{ + u_int8_t *spi; + u_int8_t *attributes; + u_int16_t attribsize; + u_int8_t *secrets; + int i, n, offset, proto = 0; + + spi = SPI->SPI; + attributes = SPI->attributes; + attribsize = SPI->attribsize; + secrets = SPI->sessionkey; + + for(n=0, i=0; n<attribsize; n += attributes[n+1] + 2) { + switch(attributes[n]) { + case AT_AH_ATTRIB: + case AT_ESP_ATTRIB: + break; + case AT_MD5_KDP: + offset = kernel_md5(SPI->local_address, SPI->owner ? + SPI->local_address : SPI->address, + spi, secrets); + if (offset == -1) + return -1; + secrets += offset; + i++; + if (!proto) + proto = IPPROTO_AH; + break; + case AT_DES_CBC: + offset = kernel_des(SPI->local_address, SPI->owner ? + SPI->local_address : SPI->address, + spi, secrets); + if (offset == -1) + 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; + } + } + + /* Group the SPIs for User */ + if (!SPI->owner && i > 1) { + if (kernel_group_spi(SPI->address, spi) == -1) + log_error(0, "kernel_group_spi() in kernel_insert_spi()"); + } + + if (!SPI->owner && !SPI->notify) { + if (kernel_enable_spi(SPI->local_address, "255.255.255.255", + SPI->address, "255.255.255.255", + SPI->address, spi, proto, + ENABLE_FLAG_REPLACE|ENABLE_FLAG_LOCAL) == -1) + log_error(0, "kernel_enable_spi() in kernel_insert_spi()"); + } + + /* Is this what people call perfect forward security ? */ + bzero(SPI->sessionkey, SPI->sessionkeysize); + free(SPI->sessionkey); + SPI->sessionkey = NULL; SPI->sessionkeysize = 0; + + return 1; +} + +int +kernel_unlink_spi(struct spiob *ospi) +{ + int n, proto = 0; + u_int32_t spi; + u_int8_t SPI[SPI_SIZE], *p; + + if (!ospi->owner) + p = ospi->address; + else + p = ospi->local_address; + + + spi = (ospi->SPI[0]<<24) + (ospi->SPI[1]<<16) + + (ospi->SPI[2]<<8) + ospi->SPI[3]; + + for(n=0; n<ospi->attribsize; n += ospi->attributes[n+1] + 2) { + SPI[0] = (spi >> 24) & 0xFF; + SPI[1] = (spi >> 16) & 0xFF; + SPI[2] = (spi >> 8) & 0xFF; + SPI[3] = spi & 0xFF; + switch(ospi->attributes[n]) { + case AT_AH_ATTRIB: + case AT_ESP_ATTRIB: + break; + case AT_MD5_KDP: + if (!proto) { + proto = IPPROTO_AH; + if (!ospi->owner && + kernel_disable_spi(ospi->local_address, "255.255.255.255", + ospi->address, "255.255.255.255", + 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->owner && + kernel_disable_spi(ospi->local_address, "255.255.255.255", + ospi->address, "255.255.255.255", + 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()"); + break; + default: + log_error(0, "Unknown attribute %d in kernel_unlink_spi()", + ospi->attributes[n]); + return -1; + } + } + + + return 1; +} diff --git a/sbin/ipsec/photurisd/kernel.h b/sbin/ipsec/photurisd/kernel.h new file mode 100644 index 00000000000..520da3cbae0 --- /dev/null +++ b/sbin/ipsec/photurisd/kernel.h @@ -0,0 +1,69 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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.1 1997/07/18 22:48:50 provos Exp $ */ +/* + * kernel.h: + * security paramter index creation. + */ + +#ifndef _KERNEL_H_ +#define _KERNEL_H_ + +#undef EXTERN +#ifdef _KERNEL_C_ +#define EXTERN + +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 kernel_md5(char *srcaddress, char *dstaddress, + u_int8_t *spi, u_int8_t *secret); +int kernel_group_spi(char *address, u_int8_t *spi); + +int kernel_enable_spi(char *isrc, char *ismask, char *idst, char *idmask, + char *address, u_int8_t *spi, int proto, int flags); +int kernel_disable_spi(char *isrc, char *ismask, char *idst, char *idmask, + char *address, u_int8_t *spi, int proto, int flags); +int kernel_delete_spi(char *address, u_int8_t *spi, int proto); + +#else +#define EXTERN extern +#endif + +EXTERN u_int32_t kernel_reserve_spi( char *srcaddress); + +EXTERN int kernel_insert_spi(struct spiob *SPI); +EXTERN int kernel_unlink_spi(struct spiob *ospi); +EXTERN int init_kernel(void); +EXTERN int kernel_get_socket(void); + +#endif /* _KERNEL_H */ diff --git a/sbin/ipsec/photurisd/modulus.c b/sbin/ipsec/photurisd/modulus.c new file mode 100644 index 00000000000..c0bbd91277d --- /dev/null +++ b/sbin/ipsec/photurisd/modulus.c @@ -0,0 +1,300 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * modulus.c: + * functions for handling moduli + */ + +#define _MODULUS_C_ + +#ifdef DEBUG +#include <stdio.h> +#endif + +#include <stdlib.h> +#include <time.h> +#include <gmp.h> +#include "config.h" +#include "modulus.h" +#include "errlog.h" + +static struct moduli_cache *modob = NULL; + +int +mod_insert(struct moduli_cache *ob) +{ + struct moduli_cache *tmp; + + ob->next = NULL; + + if(modob == NULL) { + modob = ob; + return 1; + } + + tmp=modob; + while(tmp->next!=NULL) + tmp = tmp->next; + + tmp->next = ob; + return 1; +} + +int +mod_unlink(struct moduli_cache *ob) +{ + struct moduli_cache *tmp; + if(modob == ob) { + modob = ob->next; + free(ob); + return 1; + } + + for(tmp=modob; tmp!=NULL; tmp=tmp->next) { + if(tmp->next==ob) { + tmp->next=ob->next; + free(ob); + return 1; + } + } + return 0; +} + +/* + * Check moduli for primality: + * check iter iterations, remain at max tm seconds here + * tm == 0, check all. + */ + +void +mod_check_prime(int iter, int tm) +{ + struct moduli_cache *p = modob, *tmp; + time_t now; + int flag; + +#ifdef DEBUG + char *hex; +#endif + + now = time(NULL); + while(p != NULL && (tm == 0 || (time(NULL) - now < tm))) { + if (p->iterations < MOD_PRIME_MAX && + (p->status == MOD_UNUSED || p->status == MOD_COMPUTING)) { +#ifdef DEBUG + hex = mpz_get_str(NULL, 16, p->modulus); + printf(" Checking 0x%s for primality: ", hex); + fflush(stdout); + free(hex); +#endif + flag = mpz_probab_prime_p(p->modulus, iter); + if (!flag) + log_error(0, "found a non prime in mod_check_prime()"); + + tmp = mod_find_modulus(p->modulus); + while(tmp != NULL) { + if (!flag) { + tmp->status = MOD_NOTPRIME; + tmp->lifetime = now + 2*MOD_TIMEOUT; + } else { + tmp->iterations += iter; + if (tmp->iterations >= MOD_PRIME_MAX) + tmp->status = MOD_PRIME; + else + tmp->status = MOD_COMPUTING; + } + tmp = mod_find_modulus_next(tmp, p->modulus); + } +#ifdef DEBUG + if (!flag) + printf("not prime\n"); + else if (p->iterations >= MOD_PRIME_MAX) + printf("probably prime.\n"); + else + printf("undecided.\n"); +#endif + } + + if (p->status == MOD_NOTPRIME && p->lifetime < now) { + struct moduli_cache *tmp; +#ifdef DEBUG + printf("Unlinking non prime modulus.\n"); +#endif + tmp = p; + p = p->next; + mod_value_reset(tmp); + mod_unlink(tmp); + } + p = p->next; + } +} + +struct moduli_cache * +mod_new_modgen(mpz_t m, mpz_t g) +{ + struct moduli_cache *p; + + if((p = calloc(1, sizeof(struct moduli_cache)))==NULL) + return NULL; + + mpz_init_set(p->modulus,m); + mpz_init_set(p->generator,g); + mpz_init(p->private_value); + + /* XXX - change lifetime later */ + p->lifetime = time(NULL) + MOD_TIMEOUT; + p->status = MOD_UNUSED; + + return p; +} + +struct moduli_cache * +mod_new_modulus(mpz_t m) +{ + struct moduli_cache *tmp; + + mpz_t generator; + mpz_init(generator); + tmp = mod_new_modgen(m, generator); + mpz_clear(generator); + + return tmp; +} + +int +mod_value_reset(struct moduli_cache *ob) +{ + mpz_clear(ob->private_value); + mpz_clear(ob->modulus); + mpz_clear(ob->generator); + + if (ob->exchangevalue != NULL) + free(ob->exchangevalue); + + return 1; +} + +/* Find a proper modulus and generator in the queue. + * 0 matches everything. + */ + +struct moduli_cache * +mod_find_modgen_next(struct moduli_cache *ob, mpz_t modulus, mpz_t generator) +{ + struct moduli_cache *tmp = ob; + + if (tmp == NULL) + tmp = modob; + else + tmp = tmp->next; + + while(tmp!=NULL) { + if((!mpz_cmp_ui(generator,0) || + !mpz_cmp(tmp->generator,generator)) && + (!mpz_cmp_ui(modulus,0) || !mpz_cmp(modulus,tmp->modulus))) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +struct moduli_cache * +mod_find_modgen(mpz_t modulus, mpz_t generator) +{ + return mod_find_modgen_next(NULL, modulus, generator); +} + +struct moduli_cache * +mod_find_generator_next(struct moduli_cache *ob, mpz_t generator) +{ + struct moduli_cache *tmp; + mpz_t modulus; + + mpz_init(modulus); /* Is set to zero by init */ + tmp = mod_find_modgen_next(ob, modulus, generator); + mpz_clear(modulus); + + return tmp; +} + +struct moduli_cache * +mod_find_generator(mpz_t generator) +{ + struct moduli_cache *tmp; + mpz_t modulus; + + mpz_init(modulus); /* Is set to zero by init */ + tmp = mod_find_modgen(modulus,generator); + mpz_clear(modulus); + + return tmp; +} + +struct moduli_cache * +mod_find_modulus_next(struct moduli_cache *ob, mpz_t modulus) +{ + struct moduli_cache *tmp; + mpz_t generator; + + mpz_init(generator); /* Is set to zero by init */ + tmp = mod_find_modgen_next(ob, modulus, generator); + mpz_clear(generator); + + return tmp; +} + +struct moduli_cache * +mod_find_modulus(mpz_t modulus) +{ + struct moduli_cache *tmp; + mpz_t generator; + + mpz_init(generator); /* Is set to zero by init */ + tmp = mod_find_modgen(modulus,generator); + mpz_clear(generator); + + return tmp; +} + + +void +mod_cleanup() +{ + struct moduli_cache *p; + struct moduli_cache *tmp = modob; + while(tmp!=NULL) { + p = tmp; + mod_value_reset(tmp); + tmp = tmp->next; + free(p); + } + modob = NULL; +} + diff --git a/sbin/ipsec/photurisd/modulus.h b/sbin/ipsec/photurisd/modulus.h new file mode 100644 index 00000000000..e79cedb2017 --- /dev/null +++ b/sbin/ipsec/photurisd/modulus.h @@ -0,0 +1,95 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: modulus.h,v 1.1 1997/07/18 22:48:49 provos Exp $ */ +/* + * modulus.h: + * modulus handling functions + */ + +#ifndef _MODULUS_H_ +#define _MODULUS_H_ + +#undef EXTERN + +#ifdef _MODULUS_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +#include "gmp.h" + +/* Possible values for the status field */ + +#define MOD_UNUSED 0 +#define MOD_COMPUTING 1 +#define MOD_PRIME 2 +#define MOD_NOTPRIME 3 + +#define MOD_PRIME_ITER 5 /* Do each cycle */ +#define MOD_PRIME_MAX 20 /* > => Is prime */ +#define MOD_PRIME_TIME 4 /* max time in mod_check_prime */ + +#define MOD_TIMEOUT 120 + +struct moduli_cache { + struct moduli_cache *next; /* Link to next member */ + mpz_t modulus; /* Modulus for computation */ + mpz_t generator; /* Used generator */ + mpz_t private_value; /* Our own private value */ + u_int8_t *exchangevalue; /* Our own exchange value */ + u_int16_t exchangesize; + int iterations; /* primality check iterations */ + int status; /* Status of the modulus */ + time_t lifetime; /* For modulus + exchange value */ +}; + +/* Prototypes */ +int mod_insert(struct moduli_cache *ob); +int mod_unlink(struct moduli_cache *ob); + +struct moduli_cache *mod_new_modgen(mpz_t m, mpz_t g); +struct moduli_cache *mod_new_modulus(mpz_t m); + +int mod_value_reset(struct moduli_cache *ob); + +struct moduli_cache *mod_find_modgen(mpz_t modulus, mpz_t generator); +struct moduli_cache *mod_find_modgen_next(struct moduli_cache *ob, mpz_t modulus, mpz_t generator); +struct moduli_cache *mod_find_modulus(mpz_t modulus); +struct moduli_cache *mod_find_generator(mpz_t generator); +struct moduli_cache *mod_find_modulus_next(struct moduli_cache *ob, mpz_t modulus); +struct moduli_cache *mod_find_generator_next(struct moduli_cache *ob, mpz_t generator); + +void mod_check_prime(int iter, int tm); + +void mod_cleanup(void); + + +#endif diff --git a/sbin/ipsec/photurisd/packet.c b/sbin/ipsec/photurisd/packet.c new file mode 100644 index 00000000000..4eb182d0ca4 --- /dev/null +++ b/sbin/ipsec/photurisd/packet.c @@ -0,0 +1,223 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * handle_packet.c: + * handle messages from other photuris daemons. + */ + +#ifndef lint +static char rcsid[] = "$Id: packet.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _PACKET_C_ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <arpa/inet.h> +#include "state.h" +#include "photuris.h" +#include "packets.h" +#include "errlog.h" +#include "buffer.h" +#include "config.h" +#include "packet.h" +#include "server.h" + +#define RECV_BUFFER_SIZE 8192 + +/* We have a serialised daemon */ +static struct sockaddr_in sin; + +int handle_packet(int sock, char *address) +{ + struct cookie_request *header; + static char recv_buffer[RECV_BUFFER_SIZE]; + int i, size; + + bzero(recv_buffer, RECV_BUFFER_SIZE); + + i = sizeof(struct sockaddr_in); + if ((size = recvfrom(sock, recv_buffer, RECV_BUFFER_SIZE, 0, + (struct sockaddr *) &sin, &i)) == -1) + crit_error(1, "recvfrom() in handle_packet()"); + + header = (struct cookie_request *)recv_buffer; +#ifdef DEBUG + i = BUFFER_SIZE; + bin2hex(buffer, &i, header->icookie, 16); + printf("%s: Received %d bytes from %s, type %d with icookie: 0x%s\n", + address, size, + inet_ntoa(sin.sin_addr), header->type, buffer); +#endif + + switch(header->type) { + case COOKIE_REQUEST: + if (handle_cookie_request(recv_buffer, size, + inet_ntoa(sin.sin_addr), + ntohs(sin.sin_port), + global_schemes, global_schemesize) + == -1) { + log_error(0, "handle_cookie_request() in handle_packet()"); + return -1; + } + break; + case COOKIE_RESPONSE: + if (handle_cookie_response(recv_buffer, size, + inet_ntoa(sin.sin_addr), + ntohs(sin.sin_port)) == -1) { + log_error(0, "handle_cookie_response() in handle_packet()"); + return -1; + } + break; + case VALUE_REQUEST: + if (handle_value_request(recv_buffer, size, + inet_ntoa(sin.sin_addr), + ntohs(sin.sin_port), + global_schemes, global_schemesize) + == -1) { + log_error(0, "handle_value_request() in handle_packet()"); + return -1; + } + break; + case VALUE_RESPONSE: + if (handle_value_response(recv_buffer, size, + inet_ntoa(sin.sin_addr), + address) == -1) { + log_error(0, "handle_value_response() in handle_packet()"); + return -1; + } + break; + case IDENTITY_REQUEST: + if (handle_identity_request(recv_buffer, size, + inet_ntoa(sin.sin_addr), + address) == -1) { + log_error(0, "handle_identity_request() in handle_packet()"); + return -1; + } + break; + case IDENTITY_RESPONSE: + if (handle_identity_response(recv_buffer, size, + inet_ntoa(sin.sin_addr), + address) == -1) { + log_error(0, "handle_identity_response() in handle_packet()"); + return -1; + } + break; + case SPI_UPDATE: + if (handle_spi_update(recv_buffer, size, + inet_ntoa(sin.sin_addr), + address) == -1) { + log_error(0, "handle_spi_update() in handle_packet()"); + return -1; + } + break; + case SPI_NEEDED: + if (handle_spi_needed(recv_buffer, size, + inet_ntoa(sin.sin_addr), + address) == -1) { + log_error(0, "handle_spi_needed() in handle_packet()"); + return -1; + } + break; + case BAD_COOKIE: + if (handle_bad_cookie(recv_buffer, size, + inet_ntoa(sin.sin_addr)) == -1) { + log_error(0, "handle_bad_cookie() in handle_packet()"); + return -1; + } + break; + case RESOURCE_LIMIT: + if (handle_resource_limit(recv_buffer, size, + inet_ntoa(sin.sin_addr)) == -1) { + log_error(0, "handle_resource_limit() in handle_packet()"); + return -1; + } + break; + case VERIFICATION_FAILURE: + if (handle_verification_failure(recv_buffer, size, + inet_ntoa(sin.sin_addr)) == -1) { + log_error(0, "handle_verification_failure() in handle_packet()"); + return -1; + } + break; + case MESSAGE_REJECT: + if (handle_message_reject(recv_buffer, size, + inet_ntoa(sin.sin_addr)) == -1) { + log_error(0, "handle_message_reject() in handle_packet()"); + return -1; + } + break; + default: + log_error(0, "Unknown packet type %d in handle_packet()", + header->type); + return 0; + } + + return 0; +} + +void +send_packet(void) +{ +#ifdef DEBUG + struct cookie_request *header = (struct cookie_request *)packet_buffer; + int i = BUFFER_SIZE; + bin2hex(buffer, &i, header->icookie, 16); + printf("Sending %d bytes to %s, type %d with icookie: 0x%s\n", + packet_size, inet_ntoa(sin.sin_addr), header->type, buffer); +#endif + /* We constructed a valid response packet here, send it off. */ + if (sendto(global_socket, packet_buffer, packet_size, 0, + (struct sockaddr *) &sin, sizeof(sin)) != packet_size) { + /* XXX Code to notify kernel of failure */ + log_error(1, "sendto() in handle_packet()"); + return; + } +} + +void +packet_save(struct stateob *st, u_int8_t *buffer, u_int16_t len) +{ + if (st->packet != NULL) + free(st->packet); + + if ((st->packet = calloc(len, sizeof(u_int8_t))) == NULL) { + st->packetlen = 0; + return; + } + + bcopy(buffer, st->packet, len); + st->packetlen = len; +} diff --git a/sbin/ipsec/photurisd/packet.h b/sbin/ipsec/photurisd/packet.h new file mode 100644 index 00000000000..389e9b54ddf --- /dev/null +++ b/sbin/ipsec/photurisd/packet.h @@ -0,0 +1,50 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 $ */ +/* + * packet.h: + * prototyped for receiving and anwsering packets + */ + +#ifndef _PACKET_H_ +#define _PACKET_H_ + +#undef EXTERN +#ifdef _PACKET_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN int handle_packet(int, char *); +EXTERN void send_packet(void); +EXTERN void packet_save(struct stateob *, u_int8_t *, u_int16_t); + +#endif /* _STATE_H */ diff --git a/sbin/ipsec/photurisd/packets.h b/sbin/ipsec/photurisd/packets.h new file mode 100644 index 00000000000..7d8ed7ee4f7 --- /dev/null +++ b/sbin/ipsec/photurisd/packets.h @@ -0,0 +1,149 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 $ */ +/* + * packets.h: + */ + +#ifndef _PACKETS_H_ +#define _PACKETS_H_ + +#define COOKIE_REQUEST 0 +#define COOKIE_RESPONSE 1 +#define VALUE_REQUEST 2 +#define VALUE_RESPONSE 3 +#define IDENTITY_REQUEST 4 +#define SECRET_RESPONSE 5 +#define SECRET_REQUEST 6 +#define IDENTITY_RESPONSE 7 +#define SPI_NEEDED 8 +#define SPI_UPDATE 9 +#define BAD_COOKIE 10 +#define RESOURCE_LIMIT 11 +#define VERIFICATION_FAILURE 12 +#define MESSAGE_REJECT 13 + +#define COOKIE_SIZE 16 +#define SPI_SIZE 4 + +struct cookie_request { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t counter; +}; + +#define COOKIE_REQUEST_PACKET_SIZE sizeof(struct cookie_request) + +struct cookie_response { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t counter; +}; + +#define COOKIE_RESPONSE_MIN sizeof(struct cookie_response) +#define COOKIE_RESPONSE_SCHEMES(p) (((u_int8_t *)(p))+COOKIE_RESPONSE_MIN) + +#define SCHEME_SIZE(p) (4 + ((u_int16_t)*((p)+2))*256 + (*((p)+3))) + +struct value_request { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t counter; + u_int8_t scheme[2]; +}; + +#define VALUE_REQUEST_MIN sizeof(struct value_request) +#define VALUE_REQUEST_VALUE(p) (((u_int8_t *)(p))+VALUE_REQUEST_MIN) + +struct value_response { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t reserved[3]; +}; + +#define VALUE_RESPONSE_MIN sizeof(struct value_response) +#define VALUE_RESPONSE_VALUE(p) (((u_int8_t *)(p))+VALUE_RESPONSE_MIN) + +struct identity_message { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t lifetime[3]; + u_int8_t SPI[SPI_SIZE]; +}; + +#define IDENTITY_MESSAGE_MIN sizeof(struct identity_message) +#define IDENTITY_MESSAGE_CHOICE(p) (((u_int8_t *)(p))+IDENTITY_MESSAGE_MIN) +#define IDENTITY_MESSAGE_IDENT(p) (IDENTITY_MESSAGE_CHOICE(p)+*((u_int8_t *)(p)+1)) + +struct spi_needed { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t reserved[7]; +}; + +#define SPI_NEEDED_MIN sizeof(struct spi_needed) +#define SPI_NEEDED_VERIFICATION(p) (((u_int8_t *)(p))+SPI_NEEDED_MIN) + +struct spi_update { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t lifetime[3]; + u_int8_t SPI[SPI_SIZE]; +}; + +#define SPI_UPDATE_MIN sizeof(struct spi_update) +#define SPI_UPDATE_VERIFICATION(p) (((u_int8_t *)(p))+SPI_UPDATE_MIN) + +struct error_message { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; +}; + +#define ERROR_MESSAGE_PACKET_SIZE sizeof(struct error_message) + +struct message_reject { + u_int8_t icookie[COOKIE_SIZE]; + u_int8_t rcookie[COOKIE_SIZE]; + u_int8_t type; + u_int8_t badtype; + u_int16_t offset; +}; + +#define MESSAGE_REJECT_PACKET_SIZE sizeof(struct message_reject) + +#endif /* _PACKETS_H_ */ diff --git a/sbin/ipsec/photurisd/photuris.h b/sbin/ipsec/photurisd/photuris.h new file mode 100644 index 00000000000..6e4f41e6344 --- /dev/null +++ b/sbin/ipsec/photurisd/photuris.h @@ -0,0 +1,108 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: photuris.h,v 1.1 1997/07/18 22:48:50 provos Exp $ */ +/* + * photuris.h: + * general header file + */ + +#ifndef _PHOTURIS_H_ +#define _PHOTURIS_H_ + +#include "state.h" + +#undef EXTERN +#ifdef _PHOTURIS_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +#define PHOTURIS_DIR "/etc/photuris" +#define PHOTURIS_FIFO "photuris.pipe" +#define PHOTURIS_STARTUP "photuris.startup" +#define PHOTURIS_CONFIG "photuris.conf" +#define PHOTURIS_SECRET "secrets.conf" +#define PHOTURIS_USER_SECRET ".photuris_secrets" +#define PHOTURIS_ATTRIB "attributes.conf" + +EXTERN char *config_file; +EXTERN char *attrib_file; +EXTERN u_int8_t *global_schemes; +EXTERN u_int16_t global_schemesize; +EXTERN int max_retries; +EXTERN int retrans_timeout; +EXTERN int exchange_timeout; +EXTERN int exchange_lifetime; +EXTERN int spi_lifetime; + +/* Infos about our interfaces */ +EXTERN char **addresses; +EXTERN int *sockets; +EXTERN int num_ifs; + + +/* Packet creation functions */ + +int photuris_cookie_request(struct stateob *, u_char *, int *); +int photuris_cookie_response(struct stateob *, u_char *, int *, u_int8_t *, + u_int8_t, u_int8_t *, u_int16_t, u_int8_t *, u_int16_t); +int photuris_value_request(struct stateob *, u_char *, int *); +int photuris_value_response(struct stateob *, u_char *, int *); +int photuris_identity_request(struct stateob *, u_char *, int *); +int photuris_identity_response(struct stateob *, u_char *, int *); +int photuris_spi_update(struct stateob *, u_char *, int *); +int photuris_spi_needed(struct stateob *, u_char *, int *, u_int8_t *, + u_int16_t); +int photuris_error_message(struct stateob *, u_char *, int *, char *, char *, + u_int8_t, u_int8_t); + +/* Packet handling functions */ + +int handle_cookie_request(u_char *, int, u_int8_t *, u_int16_t, u_int8_t *, u_int16_t); +int handle_cookie_response(u_char *, int , char *, int); +int handle_value_request(u_char *, int, char *, u_short, u_int8_t *, u_int16_t ); +int handle_value_response(u_char *, int , char *, char *); +int handle_identity_request(u_char *, int , char *, char *); +int handle_identity_response(u_char *, int, char *, char *); +int handle_spi_needed(u_char *, int , char *, char *); +int handle_spi_update(u_char *, int, char *, char *); +int handle_bad_cookie(u_char *, int, char *); +int handle_resource_limit(u_char *, int, char *); +int handle_verification_failure(u_char *, int, char *); +int handle_message_reject(u_char *, int, char *); + +#if defined(DEBUG) && !defined(IPSEC) +#define PHOTURIS_PORT 7468 +#else +#define PHOTURIS_PORT 468 +#endif + +#endif /* _PHOTURIS_H */ diff --git a/sbin/ipsec/photurisd/photuris_cookie_request.c b/sbin/ipsec/photurisd/photuris_cookie_request.c new file mode 100644 index 00000000000..ac1922e1ca7 --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_cookie_request.c @@ -0,0 +1,98 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_cookie_request: + * create a COOKIE_REQUEST packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_cookie_request.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> /* XXX - get header files right */ +#include <strings.h> +#include <time.h> +#include <sys/time.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" + +int +photuris_cookie_request(struct stateob *st, u_char *buffer, int *size) +{ + struct cookie_request *header; + struct stateob *prev_st, *old_st; + time_t timeout = 0; + + if (*size < COOKIE_REQUEST_PACKET_SIZE) + return -1; /* buffer not large enough */ + + header = (struct cookie_request *) buffer; + *size = COOKIE_REQUEST_PACKET_SIZE; /* fixed size */ + + st->counter = 0; + prev_st = state_find(st->address); + old_st = NULL; + while (prev_st != NULL) { + if (prev_st->lifetime >= timeout) { + timeout = prev_st->lifetime; + old_st = prev_st; + } + prev_st = prev_st->next; + } + + /* Check if we have an exchange going already */ + if (old_st != NULL && old_st != st && timeout > time(NULL)) { + if (old_st->initiator) { + bcopy(old_st->rcookie, st->rcookie, COOKIE_SIZE); + st->counter = old_st->counter; + } else { + bcopy(old_st->icookie, st->rcookie, COOKIE_SIZE); + st->counter = 0; + } + } + + cookie_generate(st, st->icookie, COOKIE_SIZE); + st->phase = COOKIE_REQUEST; + st->lifetime = exchange_timeout + time(NULL); + + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + header->counter = st->counter; /* set to zero or prev. */ + + header->type = COOKIE_REQUEST; + + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_cookie_response.c b/sbin/ipsec/photurisd/photuris_cookie_response.c new file mode 100644 index 00000000000..ca65553138e --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_cookie_response.c @@ -0,0 +1,93 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_cookie_response: + * create a COOKIE_RESPONSE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_cookie_response.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" + + +/* XXX - on value_request receive we need to set the responder schemes */ + +int +photuris_cookie_response(struct stateob *st, u_char *buffer, int *size, + u_int8_t *icookie, u_int8_t counter, + u_int8_t *address, u_int16_t port, + u_int8_t *schemes, u_int16_t ssize) +{ + struct cookie_response *header; + struct stateob tempst; + + if (*size < COOKIE_RESPONSE_MIN + ssize) + return -1; /* buffer not large enough */ + + header = (struct cookie_response *) buffer; + + /* Copy list of schemes */ + bcopy(schemes, COOKIE_RESPONSE_SCHEMES(header), ssize); + + /* XXX - There are no state information at this phase */ + bzero((char *)&tempst, sizeof(tempst)); /* Set up temp. state */ + tempst.initiator = 0; /* We are the Responder */ + bcopy(icookie, tempst.icookie, COOKIE_SIZE); + strncpy(tempst.address, address, 15); + tempst.port = port; + + bcopy(tempst.icookie, header->icookie, COOKIE_SIZE); + + if (st == NULL) + tempst.counter = counter + 1; + else + tempst.counter = st->counter + 1; + + if (tempst.counter == 0) + tempst.counter = 1; + + cookie_generate(&tempst, header->rcookie, COOKIE_SIZE); + + header->counter = tempst.counter; + + header->type = COOKIE_RESPONSE; + + *size = COOKIE_RESPONSE_MIN + ssize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_error_message.c b/sbin/ipsec/photurisd/photuris_error_message.c new file mode 100644 index 00000000000..dd83a0fcd60 --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_error_message.c @@ -0,0 +1,84 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_error_message: + * create a ERROR_MESSAGE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_error_message.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "cookie.h" + +int +photuris_error_message(struct stateob *st, u_char *buffer, int *size, + char *icookie, char *rcookie, u_int8_t counter, + u_int8_t error_type) +{ + struct error_message *header; + + if (*size < ERROR_MESSAGE_PACKET_SIZE + + (error_type == RESOURCE_LIMIT ? 1 : 0)) + return -1; /* buffer not large enough */ + + header = (struct error_message *) buffer; + *size = ERROR_MESSAGE_PACKET_SIZE + + (error_type == RESOURCE_LIMIT ? 1 : 0); + + bcopy(icookie, header->icookie, COOKIE_SIZE); + bcopy(rcookie, header->rcookie, COOKIE_SIZE); + + header->type = error_type; + + if (error_type == RESOURCE_LIMIT) { + int i; + buffer[ERROR_MESSAGE_PACKET_SIZE] = counter; + + for(i = 0; i<COOKIE_SIZE; i++) + if (rcookie[i] != 0) + break; + + if (i != COOKIE_SIZE || counter != 0) + return 0; + + if (st != NULL) + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + } + + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_identity_request.c b/sbin/ipsec/photurisd/photuris_identity_request.c new file mode 100644 index 00000000000..4a6296a02ef --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_identity_request.c @@ -0,0 +1,124 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_identity_request: + * create a IDENTITY_REQUEST packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_identity_request.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "identity.h" +#include "encrypt.h" + +int +photuris_identity_request(struct stateob *st, u_char *buffer, int *size) +{ + struct identity_message *header; + u_int16_t rsize, asize, tmp; + u_int8_t *p, *verifyp; + + rsize = *size; + if (rsize < IDENTITY_MESSAGE_MIN) + return -1; /* buffer not large enough */ + + asize = IDENTITY_MESSAGE_MIN; /* Actual size */ + rsize -= asize; /* Remaining size */ + + header = (struct identity_message *) buffer; + header->type = IDENTITY_REQUEST; + + /* Copy the cookies */ + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + header->lifetime[0] = (st->olifetime >> 16) & 0xFF; + header->lifetime[1] = (st->olifetime >> 8) & 0xFF; + header->lifetime[2] = st->olifetime & 0xFF; + bcopy(st->oSPI, header->SPI, SPI_SIZE ); + + /* Choose identity parameters (choice + value) */ + p = IDENTITY_MESSAGE_CHOICE(header); /* To Identity choice */ + tmp = rsize; /* Remaining size */ + + /* Choose and Copy choice */ + if (choose_identity(st, p, &tmp, st->uSPIoattrib, + st->uSPIoattribsize) == -1 ) + return -1; + + p += tmp; asize += tmp; rsize -= tmp; + + verifyp = p; + + /* Leave space for verification data */ + tmp = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)); + + if (rsize < tmp) + return -1; /* buffer not large enough */ + + /* Zero the buffer, so we can hash over it */ + bzero(verifyp, tmp); + + p += tmp; asize += tmp; rsize -= tmp; + + if (rsize < st->oSPIattribsize) + return -1; /* buffer not large enough */ + + /* Copy attributes and padding */ + bcopy(st->oSPIattrib, p, st->oSPIattribsize); + asize += st->oSPIattribsize; + rsize -= st->oSPIattribsize; + p += st->oSPIattribsize; + + tmp = rsize; + if(packet_create_padding(st, asize - IDENTITY_MESSAGE_MIN, + p, &tmp) == -1) + return -1; + + p += tmp; asize += tmp; rsize -= tmp; + + /* Create verification data */ + create_identity_verification(st, verifyp, (u_int8_t *)header, asize); + + /* Encrypt the packet after SPI if wished for */ + packet_encrypt(st, IDENTITY_MESSAGE_CHOICE(header), + asize - IDENTITY_MESSAGE_MIN); + + *size = asize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_identity_response.c b/sbin/ipsec/photurisd/photuris_identity_response.c new file mode 100644 index 00000000000..550fa0d25ec --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_identity_response.c @@ -0,0 +1,124 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_identity_response: + * create a IDENTITY_RESPONSE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_identity_response.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "identity.h" +#include "encrypt.h" + +int +photuris_identity_response(struct stateob *st, u_char *buffer, int *size) +{ + struct identity_message *header; + u_int16_t rsize, asize, tmp; + u_int8_t *p, *verifyp; + + rsize = *size; + if (rsize < IDENTITY_MESSAGE_MIN) + return -1; /* buffer not large enough */ + + asize = IDENTITY_MESSAGE_MIN; /* Actual size */ + rsize -= asize; /* Remaining size */ + + header = (struct identity_message *) buffer; + header->type = IDENTITY_RESPONSE; + + /* Copy the cookies */ + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + header->lifetime[0] = (st->olifetime >> 16) & 0xFF; + header->lifetime[1] = (st->olifetime >> 8) & 0xFF; + header->lifetime[2] = st->olifetime & 0xFF; + bcopy(st->oSPI, header->SPI, SPI_SIZE ); + + /* Choose identity parameters (choice + value) */ + p = IDENTITY_MESSAGE_CHOICE(header); /* To Identity choice */ + tmp = rsize; /* Remaining size */ + + /* Choose and Copy choice */ + if (choose_identity(st, p, &tmp, st->uSPIoattrib, + st->uSPIoattribsize) == -1 ) + return -1; + + p += tmp; asize += tmp; rsize -= tmp; + + verifyp = p; + + /* Leave space for verification data */ + tmp = get_identity_verification_size(st, IDENTITY_MESSAGE_CHOICE(header)); + + if (rsize < tmp) + return -1; /* buffer not large enough */ + + /* Zero the buffer, so we can hash over it */ + bzero(verifyp, tmp); + + p += tmp; asize += tmp; rsize -= tmp; + + if (rsize < st->oSPIattribsize) + return -1; /* buffer not large enough */ + + /* Copy attributes and padding */ + bcopy(st->oSPIattrib, p, st->oSPIattribsize); + asize += st->oSPIattribsize; + rsize -= st->oSPIattribsize; + p += st->oSPIattribsize; + + tmp = rsize; + if(packet_create_padding(st, asize - IDENTITY_MESSAGE_MIN, + p, &tmp) == -1) + return -1; + + p += tmp; asize += tmp; rsize -= tmp; + + /* Create verification data */ + create_identity_verification(st, verifyp, (u_int8_t *)header, asize); + + /* Encrypt the packet after SPI if wished for */ + packet_encrypt(st, IDENTITY_MESSAGE_CHOICE(header), + asize - IDENTITY_MESSAGE_MIN); + + *size = asize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_packet_encrypt.c b/sbin/ipsec/photurisd/photuris_packet_encrypt.c new file mode 100644 index 00000000000..f614cede679 --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_packet_encrypt.c @@ -0,0 +1,372 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_packet_encrypt: + * encrypts packets with the privacy choice. + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_packet_encrypt.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#define _ENCRYPT_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <des.h> +#include "config.h" +#include "packets.h" +#include "state.h" +#include "attributes.h" +#include "encrypt.h" +#include "secrets.h" +#include "errlog.h" +#ifdef DEBUG +#include "config.h" +#endif + +void +packet_mask(u_int8_t *packet, u_int16_t len, u_int8_t *key) +{ + int i; + for (i=0; i<len; i++) + packet[i] ^= key[i]; +} + +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) +{ + u_int8_t padlength, i; + + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: + padlength = (arc4random() & 0xf0) - (size%16); + if (padlength < 8) + padlength += 8; + break; + default: + padlength = (arc4random() & 0xf0) - (size%16); + if (padlength < 8) + padlength += 8; + break; + } + + if(*rsize < padlength) + return -1; + + /* Pad the rest of the payload */ + for(i=1;i<=padlength;i++) + padd[i-1] = i; + + *rsize = padlength; + + return 0; +} + +int +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; + + input = (des_cblock *)payload; + + /* No encryption needed */ + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: +#ifdef DEBUG + printf("[Packet encryption: None]\n"); +#endif + pkey = calloc(payloadlen,sizeof(u_int8_t)); + if(pkey == NULL) { + log_error(1, "Not enough memory for privacy secret"); + return -1; + } + if(compute_privacy_key(st, pkey, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + payloadlen*8, 0, 1) == -1) + return -1; +#ifdef DEBUG + { + int i; + char buffer[3000]; + i = 3000; + bin2hex(buffer, &i, pkey, payloadlen); + printf("Encrypt key: %s\n", buffer ); + } +#endif + packet_mask(payload, payloadlen, pkey); + return 0; + case DH_G_2_DES_MD5: + case DH_G_3_DES_MD5: + case DH_G_5_DES_MD5: +#ifdef DEBUG + printf("[Packet encryption: DES]\n"); +#endif + pkey = calloc(payloadlen + 16, sizeof(u_int8_t)); + if(pkey == NULL) { + log_error(1, "Not enough memory for privacy secret"); + return -1; + } + if(compute_privacy_key(st, pkey, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + payloadlen*8+128, 0, 1) == -1) + return -1; +#ifdef DEBUG + { + int i; + char buffer[3000]; + i = 3000; + bin2hex(buffer, &i, pkey, payloadlen+16); + 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); + + 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: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: +#ifdef DEBUG + printf("[Packet encryption: 3DES]\n"); +#endif + pkey = calloc(payloadlen+32, sizeof(u_int8_t)); + if(pkey == NULL) { + log_error(1, "Not enough memory for owner privacy secret"); + return -1; + } + if(compute_privacy_key(st, pkey, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + payloadlen*8+256, 0, 1) == -1) + return -1; +#ifdef DEBUG + { + int i; + char buffer[3000]; + i = 3000; + bin2hex(buffer, &i, pkey, payloadlen+32); + 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); + 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); + + des_set_key(&keys[0], key1); + des_set_key(&keys[1], key2); + des_set_key(&keys[2], key3); + + 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; + default: + log_error(0, "Unknown exchange scheme: %d\n", + *((u_int16_t *)st->scheme)); + return -1; + } + + free(pkey); + + return 0; +} + +int +packet_decrypt(struct stateob *st, u_int8_t *payload, u_int16_t *payloadlen) +{ + u_int8_t padlength, i; + des_cblock keys[4], *input; + des_key_schedule key1,key2,key3; + u_int8_t *pkey; + + input = (des_cblock *)payload; + + /* No encryption needed */ + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: +#ifdef DEBUG + printf("[Packet decryption: None]\n"); +#endif + pkey = calloc(*payloadlen, sizeof(u_int8_t)); + if(pkey == NULL) { + log_error(1, "Not enough memory for privacy secret"); + return -1; + } + if(compute_privacy_key(st, pkey, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + *payloadlen*8, 0, 0) == -1) + return -1; +#ifdef DEBUG + { + int i = 3000; + char buffer[3000]; + bin2hex(buffer, &i, pkey, *payloadlen); + printf("Decrypt key: %s\n", buffer ); + } +#endif + packet_mask(payload, *payloadlen, pkey); + return 0; + case DH_G_2_DES_MD5: + case DH_G_3_DES_MD5: + case DH_G_5_DES_MD5: +#ifdef DEBUG + printf("[Packet decryption: DES]\n"); +#endif + pkey = calloc(*payloadlen+16, sizeof(u_int8_t)); + if(pkey == NULL) { + log_error(1, "Not enough memory for privacy secret"); + return -1; + } + if(compute_privacy_key(st, pkey, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + *payloadlen*8+128, 0, 0) == -1) + return -1; +#ifdef DEBUG + { + int i = 3000; + char buffer[3000]; + bin2hex(buffer, &i, pkey, *payloadlen+ 16); + 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); + + packet_make_iv((u_int32_t *)&keys[1], (u_int32_t *)(payload - 8)); + + des_cbc_encrypt(input,input,*payloadlen, key1,&keys[1], DES_DECRYPT); + + packet_mask(payload, *payloadlen, pkey); + break; + case DH_G_2_3DES_SHA1: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: +#ifdef DEBUG + printf("[Packet decryption: 3DES]\n"); +#endif + pkey = calloc(*payloadlen + 32, sizeof(u_int8_t)); + if(pkey == NULL) { + log_error(1, "Not enough memory for privacy secret"); + return -1; + } + if(compute_privacy_key(st, pkey, + payload - 2*COOKIE_SIZE - 4 - SPI_SIZE, + *payloadlen*8+256, 0, 0) == -1) + return -1; +#ifdef DEBUG + { + int i = 3000; + char buffer[3000]; + bin2hex(buffer, &i, pkey, *payloadlen+32); + 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_odd_parity(&keys[1]); + bcopy(pkey+*payloadlen+16, &keys[2], 8); + des_set_odd_parity(&keys[2]); + bcopy(pkey+*payloadlen+24, &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); + + packet_mask(payload, *payloadlen, pkey); + break; + default: + log_error(0,"Unknown exchange scheme: %d\n", + *((u_int16_t *)st->scheme)); + return -1; + } + + padlength = *(payload+(*payloadlen)-1); + + /* Check the padding */ + + if(padlength > 255 || padlength < 8) + return -1; + + *payloadlen = *payloadlen - padlength; + + for(i=1;i<=padlength;i++) + if(payload[*payloadlen+i-1] != i) + return -1; + + return 0; +} + diff --git a/sbin/ipsec/photurisd/photuris_spi_needed.c b/sbin/ipsec/photurisd/photuris_spi_needed.c new file mode 100644 index 00000000000..1831390526c --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_spi_needed.c @@ -0,0 +1,106 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_spi_needed: + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_spi_needed.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "packets.h" +#include "state.h" +#include "validity.h" +#include "encrypt.h" + +int +photuris_spi_needed(struct stateob *st, u_char *buffer, int *size, + u_int8_t *attributes, u_int16_t attribsize) +{ + struct spi_needed *header; + u_int16_t rsize, asize, tmp; + u_int8_t *p; + + rsize = *size; + if (rsize < SPI_NEEDED_MIN) + return -1; /* buffer not large enough */ + + asize = SPI_NEEDED_MIN; /* Actual size */ + rsize -= asize; /* Remaining size */ + + header = (struct spi_needed *) buffer; + header->type = SPI_NEEDED; + + bzero(header->reserved, sizeof(header->reserved)); + + /* Copy the cookies */ + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + p = SPI_NEEDED_VERIFICATION(header); + + /* Leave space for verification data */ + tmp = get_validity_verification_size(st); + + if (rsize < tmp) + return -1; /* buffer not large enough */ + + p += tmp; asize += tmp; rsize -= tmp; + + if (rsize < attribsize) + return -1; /* buffer not large enough */ + + /* Copy attributes and padding */ + bcopy(attributes, p, attribsize); + asize += attribsize; + rsize -= attribsize; + p += attribsize; + + tmp = rsize; + if(packet_create_padding(st, asize - SPI_NEEDED_MIN, p, &tmp) == -1) + return -1; + + p += tmp; asize += tmp; rsize -= tmp; + + /* Create verification data */ + create_validity_verification(st,SPI_UPDATE_VERIFICATION(header), + (u_int8_t *)header,asize); + + /* Encrypt the packet after header if wished for */ + packet_encrypt(st, SPI_NEEDED_VERIFICATION(header), + asize - SPI_NEEDED_MIN); + + *size = asize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_spi_update.c b/sbin/ipsec/photurisd/photuris_spi_update.c new file mode 100644 index 00000000000..759ea014fdb --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_spi_update.c @@ -0,0 +1,112 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_spi_update: + * create a SPI_UPDATE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_spi_update.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "packets.h" +#include "state.h" +#include "validity.h" +#include "encrypt.h" + +/* XXX - the SPI needs to be put into a new state object */ + +int +photuris_spi_update(struct stateob *st, u_char *buffer, int *size) +{ + struct spi_update *header; + u_int16_t rsize, asize, tmp; + u_int8_t *p; + + rsize = *size; + if (rsize < SPI_UPDATE_MIN) + return -1; /* buffer not large enough */ + + asize = SPI_UPDATE_MIN; /* Actual size */ + rsize -= asize; /* Remaining size */ + + header = (struct spi_update *) buffer; + header->type = SPI_UPDATE; + + /* Copy the cookies */ + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + /* Copy SPI and life time */ + bcopy(st->oSPI, header->SPI, SPI_SIZE ); + header->lifetime[0] = (st->olifetime >> 16) & 0xFF; + header->lifetime[1] = (st->olifetime >> 8) & 0xFF; + header->lifetime[2] = st->olifetime & 0xFF; + + p = SPI_UPDATE_VERIFICATION(header); + + /* Leave space for verification data */ + tmp = get_validity_verification_size(st); + + if (rsize < tmp) + return -1; /* buffer not large enough */ + + p += tmp; asize += tmp; rsize -= tmp; + + if (rsize < st->oSPIattribsize) + return -1; /* buffer not large enough */ + + /* Copy attributes and padding */ + bcopy(st->oSPIattrib, p, st->oSPIattribsize); + asize += st->oSPIattribsize; + rsize -= st->oSPIattribsize; + p += st->oSPIattribsize; + + tmp = rsize; + if(packet_create_padding(st, asize - SPI_UPDATE_MIN, p, &tmp) == -1) + return -1; + + p += tmp; asize += tmp; rsize -= tmp; + + /* Create validity verification data */ + create_validity_verification(st,SPI_UPDATE_VERIFICATION(header), + (u_int8_t *)header,asize); + + /* Encrypt the packet after SPI if wished for */ + packet_encrypt(st, SPI_UPDATE_VERIFICATION(header), + asize - SPI_UPDATE_MIN); + + *size = asize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_value_request.c b/sbin/ipsec/photurisd/photuris_value_request.c new file mode 100644 index 00000000000..92eb6bc34fe --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_value_request.c @@ -0,0 +1,85 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_value_request: + * create a VALUE_REQUEST packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_value_request.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "exchange.h" + +int +photuris_value_request(struct stateob *st, u_char *buffer, int *size) + +{ + struct value_request *header; + u_int16_t rsize, asize, tmp; + + rsize = *size; + + if (rsize < VALUE_REQUEST_MIN + st->oSPIoattribsize) + return -1; /* buffer not large enough */ + + header = (struct value_request *)buffer; + + asize = VALUE_REQUEST_MIN + st->oSPIoattribsize; + rsize -= asize; + + /* Generate an exchangevalue if not done already */ + tmp = rsize; + if(exchange_value_generate(st, VALUE_REQUEST_VALUE(header), &tmp) == -1) + return -1; + + asize += tmp; + bcopy(st->oSPIoattrib, VALUE_REQUEST_VALUE(header)+tmp, + st->oSPIoattribsize); + + header = (struct value_request *) buffer; + header->type = VALUE_REQUEST; + + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + header->counter = st->counter; + bcopy(st->scheme, header->scheme, 2 ); /* Only scheme */ + + *size = asize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photuris_value_response.c b/sbin/ipsec/photurisd/photuris_value_response.c new file mode 100644 index 00000000000..78d20847915 --- /dev/null +++ b/sbin/ipsec/photurisd/photuris_value_response.c @@ -0,0 +1,84 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photuris_value_response: + * create a VALUE_RESPONSE packet; return -1 on failure, 0 on success + * + */ + +#ifndef lint +static char rcsid[] = "$Id: photuris_value_response.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "photuris.h" +#include "packets.h" +#include "state.h" +#include "exchange.h" + +int +photuris_value_response(struct stateob *st, u_char *buffer, int *size) + +{ + struct value_response *header; + u_int16_t asize, rsize, tmp; + + rsize = *size; + if (rsize < VALUE_RESPONSE_MIN + st->oSPIoattribsize) + return -1; /* buffer not large enough */ + + header = (struct value_response *)buffer; + + asize = VALUE_RESPONSE_MIN + st->oSPIoattribsize; + rsize -= asize; + + /* Generate an exchangevalue if not done already */ + tmp = rsize; + if(exchange_value_generate(st, VALUE_RESPONSE_VALUE(header), &tmp) == -1\ +) + return -1; + + asize += tmp; + bcopy(st->oSPIoattrib, VALUE_RESPONSE_VALUE(header)+tmp, + st->oSPIoattribsize); + + header = (struct value_response *) buffer; + header->type = VALUE_RESPONSE; + + bcopy(st->icookie, header->icookie, COOKIE_SIZE); + bcopy(st->rcookie, header->rcookie, COOKIE_SIZE); + + bzero(header->reserved, sizeof(header->reserved)); /* zero for now */ + + *size = asize; + return 0; +} diff --git a/sbin/ipsec/photurisd/photurisd.1 b/sbin/ipsec/photurisd/photurisd.1 new file mode 100644 index 00000000000..3ca4e6a160f --- /dev/null +++ b/sbin/ipsec/photurisd/photurisd.1 @@ -0,0 +1,219 @@ +.\" $OpenBSD: photurisd.1,v 1.1 1997/07/18 22:48:51 provos Exp $ +.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Niels Provos. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Manual page, using -mandoc macros +.\" +.Dd April 15, 1997 +.Dt PHOTURISD 1 +.Os OpenBSD 2.1 +.Sh NAME +.Nm photurisd +.Nd IPSec key management daemon +.Sh SYNOPSIS +.Nm photurisd +.Op Fl fi +.Op Fl d Ar directory +.Sh DESCRIPTION +The +.Nm photuris +daemon establisches security associations for encrypted +and/or authenticated network traffic. +.Pp +The daemon listens to a named pipe +.Pa photuris.pipe +for user requests and on a +.Nm PF_ENCAP +socket for kernel requests. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl f +The +.Fl f +option is used to obmit the primality check of the bootstrapped moduli. +.It Fl i +The +.Fl i +option can be used to ignore the +.Pa photuris.startup +file. Otherwise the exchanges in that file will be initiated +on startup. +.It Fl d +The +.Fl d +option specifies the directory in wich +.Nm photurisd +looks for its startup files. The default is +.Pa /etc/photuris/ +.El +.Pp +The file +.Pa photuris.conf +contains the moduli for the DH exchange and the actual exchange +schemes used to establish a shared secret. +.Pp +The file +.Pa attributes.conf +contains the attributes, i.e. different choices of encryption +and authenication, offered to the other peer. +.Pp +The file +.Pa secrets.conf +contains the party preconfigured symmetric secrets for the +identity exchange. User secrets files can be included. +.Pp +Finally the file +.Pa photuris.startup +contains parameters for exchanges which are created during +startup. +.Pp +.Sh EXAMPLE +The keywords +.Nm dst , +.Nm port , +.Nm options , +.Nm tsrc , +.Nm tdsr +and +.Nm user +are understood in the +.Pa photuris.startup +file. The values are as follow: +.Bl -tag -width options -offser indent +.It dst +The destination IP address with which the exchange is to be established. +.It port +The port number of the destination +.Nm photuris +daemon. +.It options +The options to be used in the exchange. Possible values are +.Nm enc +and +.Nm auth . +.It tsrc +The source address with netmask from which packets are accepted +for the tunnel to be created. +.It tdst +The destination address with netmask for which packets are +accepted for the tunnel being created. +.It user +The user name for whom the keying shall be done. Preconfigured +secrets are taken from the users secret file. +.El +.Pp +Exchanges are separated by newlines. +.Pp +Example: +.Pp + dst=134.100.106.2 port=468 options=auth +.Pp + tsrc=134.100.104.0/255.255.255.255 +.Pp + tdst=134.100.106.0/255.255.255.255 +.Pp +If the file +.Pa /etc/fbtab +exists, +.Nm login +changes the protection and ownership of certain devices specified in this +file. +.Pp +If the file +.Pa /var/log/failedlogin +exists, +.Nm login +will record failed login attempts in this file. +.Pp +Immediately after logging a user in, +.Nm login +displays the system copyright notice, the date and time the user last +logged in, the date and time of the last unsucessful login (if the file +.Pa /var/log/failedlogin +exists), the message of the day as well as other information. +If the file +.Dq Pa .hushlogin +exists in the user's home directory, all of these messages are suppressed. +This is to simplify logins for non-human users, such as +.Xr uucp 1 . +.Nm Login +then records an entry in the +.Xr wtmp 5 +and +.Xr utmp 5 +files and executes the user's command interpreter. +.Pp +Login enters information into the environment (see +.Xr environ 7 ) +specifying the user's home directory (HOME), command interpreter (SHELL), +search path (PATH), terminal type (TERM) and user name (both LOGNAME and +USER). +.Pp +The standard shells, +.Xr csh 1 +and +.Xr sh 1 , +do not fork before executing the +.Nm login +utility. +.Sh FILES +.Bl -tag -width /var/mail/userXXX -compact +.It Pa /etc/fbtab +changes device protections +.It Pa /etc/motd +message-of-the-day +.It Pa /etc/nologin +disallows logins +.It Pa /var/run/utmp +current logins +.It Pa /var/log/lastlog +last login account records +.It Pa /var/log/wtmp +login account records +.It Pa /var/log/failedlogin +failed login account records +.It Pa /var/mail/user +system mailboxes +.It Pa \&.hushlogin +makes login quieter +.El +.Sh SEE ALSO +.Xr chpass 1 , +.Xr passwd 1 , +.Xr rlogin 1 , +.Xr skey 1 , +.Xr getpass 3 , +.Xr utmp 5 , +.Xr environ 7, +.Xr fbtab 5 +.Sh HISTORY +A +.Nm login +appeared in +.At v6 . diff --git a/sbin/ipsec/photurisd/photurisd.c b/sbin/ipsec/photurisd/photurisd.c new file mode 100644 index 00000000000..744e2295f0b --- /dev/null +++ b/sbin/ipsec/photurisd/photurisd.c @@ -0,0 +1,172 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * photurisd.c: photuris daemon and stuff. + */ + +#ifndef lint +static char rcsid[] = "$Id: photurisd.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _PHOTURIS_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "config.h" +#include "photuris.h" +#include "server.h" +#include "buffer.h" +#include "cookie.h" +#include "identity.h" +#include "spi.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" +#ifdef IPSEC +#include "kernel.h" +#endif + +static int init_vars(void); +static void usage(void); + +static void +usage(void) +{ + FILE *f = stderr; + + fprintf(f, "usage: photurisd [-fi] [-d directory]\n"); + fprintf(f, "\t-f don't check primes on startup\n"); + fprintf(f, "\t-t ignore startup file %s\n", PHOTURIS_STARTUP); + fprintf(f, "\t-d specifies the startup dir\n"); + exit(1); +} + + +static int +init_vars(void) +{ + global_schemes = NULL; + global_schemesize = 0; + + config_file = NULL; + attrib_file = NULL; + + if ((config_file = calloc(1, sizeof(PHOTURIS_CONFIG))) == NULL) + crit_error(1, "no memory in init_vars()" ); + strcpy(config_file, PHOTURIS_CONFIG); + + if ((secret_file = calloc(1, sizeof(PHOTURIS_SECRET))) == NULL) + crit_error(1, "no memory in init_vars()" ); + strcpy(secret_file, PHOTURIS_SECRET); + + if ((attrib_file = calloc(1, sizeof(PHOTURIS_ATTRIB))) == NULL) + crit_error(1, "no memory in init_vars()"); + strcpy(attrib_file, PHOTURIS_ATTRIB); + + reset_secret(); + + max_retries = MAX_RETRIES; + retrans_timeout = RETRANS_TIMEOUT; + exchange_timeout = EXCHANGE_TIMEOUT; + exchange_lifetime = EXCHANGE_LIFETIME; + spi_lifetime = SPI_LIFETIME; + + return 1; +} + +void main(int argc, char **argv) +{ + int ch; + int primes = 1, ignore = 0; + char *dir = PHOTURIS_DIR; + + while ((ch = getopt(argc, argv, "fid:")) != -1) + switch((char)ch) { + case 'f': + primes = 0; + break; + case 'i': + ignore = 1; + break; + case 'd': + dir = optarg; + break; + case '?': + default: + usage(); + } + + if (chdir(dir) == -1) + crit_error(1, "chdir(\"%s\") in main()", dir); + + + argc -= optind; + argv += optind; + + init_vars(); + + init_times(); + + init_moduli(primes); + + init_schemes(); + + init_attributes(); + + if (init_identities(NULL,NULL) == -1) + exit(-1); + + init_schedule(); + +#ifdef IPSEC + init_kernel(); +#endif + + init_server(); + + /* Startup preconfigured exchanges */ + if( !ignore) + init_startup(); + +#ifndef DEBUG + init_signals(); + if (fork()) + exit(0); +#endif + + server(); + +} diff --git a/sbin/ipsec/photurisd/schedule.c b/sbin/ipsec/photurisd/schedule.c new file mode 100644 index 00000000000..bd81cd8c0d1 --- /dev/null +++ b/sbin/ipsec/photurisd/schedule.c @@ -0,0 +1,364 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Parts derived from code by Angelos D. Keromytis, kermit@forthnet.gr + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * schedule.c: + * SCHEDULE handling functions + */ + +#ifndef lint +static char rcsid[] = "$Id: schedule.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _SCHEDULE_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <arpa/inet.h> +#include "state.h" +#include "spi.h" +#include "photuris.h" +#include "buffer.h" +#include "schedule.h" +#include "secrets.h" +#include "errlog.h" +#include "cookie.h" +#include "modulus.h" +#ifdef IPSEC +#include "kernel.h" +#endif +#ifdef DEBUG +#include "config.h" +#endif + +static struct schedule *schedob = NULL; + +void +schedule_insert(int type, int off, u_int8_t *cookie, u_int16_t cookie_size) +{ + struct schedule *tmp; + +#ifdef DEBUG + { + if( cookie != NULL) { + int i = BUFFER_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); + } +#endif + + if ((tmp = calloc(1, sizeof(struct schedule))) == NULL) { + log_error(1, "calloc() in schedule_insert()"); + return; + } + + tmp->event = type; + tmp->offset = off; + tmp->tm = time(NULL) + off; + + if (cookie != NULL) { + tmp->cookie = calloc(cookie_size, sizeof(u_int8_t)); + if (tmp->cookie == NULL) { + log_error(1, "calloc() in schedule_insert()"); + free(tmp); + return; + } + bcopy(cookie, tmp->cookie, cookie_size); + tmp->cookie_size = cookie_size; + } + + tmp->next = NULL; + + if (schedob == NULL) + schedob = tmp; + else { + tmp->next = schedob; + schedob = tmp; + } +} + +int +schedule_next(void) +{ + struct schedule *tmp; + time_t tm; + + if (schedob == NULL) + return -1; + + tm = schedob->tm; + tmp = schedob->next; + while (tmp != NULL) { + if (tmp->tm < tm) + tm = tmp->tm; + tmp = tmp->next; + } + + if ((tm -= time(NULL)) < 0) + return 0; + + return((int) tm); +} + +int +schedule_offset(int type, u_int8_t *cookie) +{ + struct schedule *tmp = schedob; + while (tmp != NULL) { + if (tmp->event == type && + ((tmp->cookie == NULL && cookie == NULL) || + !bcmp(tmp->cookie, cookie, tmp->cookie_size))) + return tmp->offset; + tmp = tmp->next; + } + + return -1; +} + +void +schedule_remove(int type, u_int8_t *cookie) +{ + struct schedule *tmp, *otmp = NULL; + + tmp = schedob; + while (tmp != NULL) { + if (tmp->event == type && + ((tmp->cookie == NULL && cookie == NULL) || + !bcmp(tmp->cookie, cookie, tmp->cookie_size))) { + if (tmp == schedob) + schedob = tmp->next; + else + otmp->next = tmp->next; + + if (tmp->cookie != NULL) + free(tmp->cookie); + free(tmp); + return; + } + otmp = tmp; + tmp = tmp->next; + } +} + +void +schedule_process(int sock) +{ + struct schedule *tmp, *tmp2; + struct sockaddr_in sin; + struct stateob *st; + struct spiob *spi, *nspi; + time_t tm; + int remove; + + tm = time(NULL); + tmp = schedob; + while (tmp != NULL) { + if (tmp->tm > tm) { + tmp = tmp->next; + continue; + } + + remove = 0; + switch(tmp->event) { + case REKEY: +#ifdef DEBUG + printf("Resetting secrets\n"); +#endif + reset_secret(); + tmp->tm = time(NULL) + REKEY_TIMEOUT; + break; + case MODULUS: +#ifdef DEBUG + printf("Checking moduli\n"); +#endif + mod_check_prime(MOD_PRIME_ITER, MOD_PRIME_TIME); + tmp->tm = time(NULL) + MODULUS_TIMEOUT; + break; + case CLEANUP: +#ifdef DEBUG + printf("Cleaning up states\n"); +#endif + state_expire(); +#ifdef DEBUG + printf("Cleaning up SPI's\n"); +#endif + spi_expire(); + tmp->tm = time(NULL) + CLEANUP_TIMEOUT; + break; + case TIMEOUT: + st = state_find_cookies(NULL, tmp->cookie, NULL); + if (st == NULL || st->retries >= max_retries) { + remove = 1; + break; + } + + st->retries++; + + if (st->packet == NULL || st->packetlen == 0) { + log_error(0, "no packet in schedule_process()"); + remove = 1; + } + /* Only send the packet when no error occured */ + if (!remove) { + sin.sin_port = htons(st->port); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(st->address); + + if (sendto(sock, st->packet, st->packetlen, 0, + (struct sockaddr *) &sin, sizeof(sin)) + != st->packetlen) { + log_error(1, "sendto() in schedule_process()"); + remove = 1; + break; + } + +#ifdef DEBUG + printf("Resending packet type %d, length %d.\n", + st->phase, st->packetlen); +#endif + tmp->tm = tm + retrans_timeout; + } + break; + case UPDATE: +#ifdef DEBUG + { + int i = BUFFER_SIZE; + bin2hex(buffer, &i, tmp->cookie, SPI_SIZE); + printf("Upating SPI 0x%s\n", buffer); + } +#endif + remove = 1; + /* We are to create a new SPI */ + if ((spi = spi_find(NULL, tmp->cookie)) == NULL) { + log_error(0, "spi_find() in schedule_process()"); + break; + } + if ((st = state_find_cookies(spi->address, spi->icookie, NULL)) == NULL) { + log_error(0, "state_find_cookies() in schedule_process()"); + break; + } + + if (st->oSPIattrib != NULL) + free(st->oSPIattrib); + if ((st->oSPIattrib = calloc(spi->attribsize, sizeof(u_int8_t))) == NULL) { + log_error(1, "calloc() in schedule_process()"); + break; + } + st->oSPIattribsize = spi->attribsize; + bcopy(spi->attributes, st->oSPIattrib, st->oSPIattribsize); + + /* We can keep our old attributes, this is only an update */ + if (make_spi(st, spi->local_address, st->oSPI, &(st->olifetime), + &(st->oSPIattrib), &(st->oSPIattribsize)) == -1) { + log_error(0, "make_spi() in schedule_process()"); + break; + } + + packet_size = PACKET_BUFFER_SIZE; + if (photuris_spi_update(st, packet_buffer, &packet_size) == -1) { + log_error(0, "photuris_spi_update() in schedule_process()"); + break; + } + + /* Send the packet */ + sin.sin_port = htons(st->port); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(st->address); + + if (sendto(sock, packet_buffer, packet_size, 0, + (struct sockaddr *) &sin, sizeof(sin)) != packet_size) { + log_error(1, "sendto() in schedule_process()"); + break; + } + +#ifdef DEBUG + printf("Sending SPI UPDATE to %s.\n", st->address); +#endif + /* Insert Owner SPI */ + if ((nspi = spi_new(st->address, st->oSPI)) == NULL) { + log_error(1, "spi_new() in handle_spi_needed()"); + break; + } + if ((nspi->local_address = strdup(spi->local_address)) == NULL) { + log_error(1, "strdup() in handle_spi_needed()"); + spi_value_reset(nspi); + break; + } + bcopy(st->icookie, nspi->icookie, COOKIE_SIZE); + nspi->owner = 1; + nspi->attribsize = st->oSPIattribsize; + nspi->attributes = calloc(nspi->attribsize, sizeof(u_int8_t)); + if (nspi->attributes == NULL) { + log_error(1, "calloc() in handle_spi_needed()"); + spi_value_reset(nspi); + break; + } + bcopy(st->oSPIattrib, nspi->attributes, nspi->attribsize); + nspi->lifetime = time(NULL) + st->olifetime; + + make_session_keys(st, nspi); + + spi_insert(nspi); + schedule_insert(UPDATE, st->olifetime/2, nspi->SPI, SPI_SIZE); +#ifdef IPSEC + kernel_insert_spi(nspi); +#endif + break; + default: + remove = 1; + log_error(0, "Unknown event in schedule_process()"); + break; + } + + if (remove) { + tmp2 = tmp; + tmp = tmp->next; + schedule_remove(tmp2->event, tmp2->cookie); + } else + tmp = tmp->next; + } +} + +void +init_schedule(void) +{ + schedule_insert(REKEY, REKEY_TIMEOUT, NULL, 0); + schedule_insert(CLEANUP, CLEANUP_TIMEOUT, NULL, 0); + schedule_insert(MODULUS, MODULUS_TIMEOUT, NULL, 0); +} diff --git a/sbin/ipsec/photurisd/schedule.h b/sbin/ipsec/photurisd/schedule.h new file mode 100644 index 00000000000..cf3fb985719 --- /dev/null +++ b/sbin/ipsec/photurisd/schedule.h @@ -0,0 +1,81 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: schedule.h,v 1.1 1997/07/18 22:48:50 provos Exp $ */ +/* + * schedule.h: + * schedule events like retransmission and clean ups. + */ + +#ifndef _SCHEDULE_H_ +#define _SCHEDULE_H_ + +#include "state.h" +#include "packets.h" + +#undef EXTERN + +#ifdef _SCHEDULE_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +#define REKEY 0 +#define TIMEOUT 1 +#define CLEANUP 2 +#define MODULUS 3 +#define UPDATE 4 + +#define MAX_RETRIES 3 /* Resend a packet max. as often */ + +#define CLEANUP_TIMEOUT 60 +#define MODULUS_TIMEOUT 75 +#define RESPONDER_TIMEOUT 300 +#define RETRANS_TIMEOUT 10 +#define REKEY_TIMEOUT 360 + +struct schedule { + struct schedule *next; + time_t tm; + int offset; + int event; + u_int8_t *cookie; + u_int16_t cookie_size; +}; + +EXTERN void schedule_process(int sock); +EXTERN int schedule_next(void); +EXTERN int schedule_offset(int type, u_int8_t *cookie); +EXTERN void schedule_insert(int type, int off, u_int8_t *cookie, + u_int16_t cookie_size); +EXTERN void schedule_remove(int type, u_int8_t *cookie); +EXTERN void init_schedule(void); + +#endif /* _SCHEDULE_H */ diff --git a/sbin/ipsec/photurisd/scheme.c b/sbin/ipsec/photurisd/scheme.c new file mode 100644 index 00000000000..edb81c345cc --- /dev/null +++ b/sbin/ipsec/photurisd/scheme.c @@ -0,0 +1,191 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * scheme.c: + * SCHEME handling functions + */ + +#ifndef lint +static char rcsid[] = "$Id: scheme.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _SCHEME_C_ + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "attributes.h" +#include "buffer.h" +#include "scheme.h" +#include "errlog.h" + +u_int8_t * +scheme_get_gen(u_int8_t *scheme) +{ + int header; + switch(ntohs(*(u_int16_t *)scheme)) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_2_DES_MD5: + case DH_G_5_MD5: + case DH_G_3_DES_MD5: + case DH_G_2_3DES_SHA1: + case DH_G_5_DES_MD5: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: + return NULL; + case DH_G_VAR_MD5: + case DH_G_VAR_DES_MD5: + case DH_G_VAR_3DES_SHA1: + if (scheme[2] == 255 && scheme[3] == 255) + header = 8; + else if (scheme[2] == 255) + header = 4; + else + header = 2; + return scheme+2+header; + default: + log_error(0, "Unknown scheme in scheme_get_gen()"); + return NULL; + } +} + +u_int8_t * +scheme_get_mod(u_int8_t *scheme) +{ + int header; + switch(ntohs(*(u_int16_t *)scheme)) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_2_DES_MD5: + case DH_G_5_MD5: + case DH_G_3_DES_MD5: + case DH_G_2_3DES_SHA1: + case DH_G_5_DES_MD5: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: + return scheme+2; + break; + case DH_G_VAR_MD5: + case DH_G_VAR_DES_MD5: + case DH_G_VAR_3DES_SHA1: + if (scheme[2] == 255 && scheme[3] == 255) + header = 8; + else if (scheme[2] == 255) + header = 4; + else + header = 2; + if (varpre2octets(scheme+2) > 2) + return scheme+2+header+varpre2octets(scheme+2+header); + else + return scheme+2; + break; + default: + log_error(0, "Unknown scheme in scheme_get_mod()"); + return NULL; + } +} + +size_t +scheme_get_len(u_int8_t *scheme) +{ + return 2 + varpre2octets(scheme+2); +} + +u_int16_t +scheme_get_ref(u_int8_t *scheme) +{ + switch(ntohs(*(u_int16_t *)scheme)) { + case DH_G_2_MD5: + case DH_G_2_DES_MD5: + case DH_G_2_3DES_SHA1: + return DH_G_2_MD5; + case DH_G_3_MD5: + case DH_G_3_DES_MD5: + case DH_G_3_3DES_SHA1: + return DH_G_3_MD5; + case DH_G_5_MD5: + case DH_G_5_DES_MD5: + case DH_G_5_3DES_SHA1: + return DH_G_5_MD5; + case DH_G_VAR_MD5: + case DH_G_VAR_DES_MD5: + case DH_G_VAR_3DES_SHA1: + return DH_G_VAR_MD5; + default: + log_error(0, "Unknown scheme in scheme_get_ref()"); + return 0; + } +} + +size_t +varpre2octets(u_int8_t *varpre) +{ + int blocks, header; + size_t size; + mpz_t offset, a; + + mpz_init(offset); + mpz_init(a); + + /* XXX - only support a few octets at the moment */ + + if(*varpre == 255 && *(varpre+1) == 255) { + blocks = 6; + varpre += 2; + mpz_set_ui(offset, 16776960); + header = 8; + } else if (*varpre == 255) { + blocks = 3; + varpre++; + mpz_set_ui(offset, 65280); + header = 4; + } else { + header = 2; + blocks = 2; + } + + while(blocks--) { + mpz_mul_ui(a, a, 256); + mpz_add_ui(a, a, *varpre); + varpre++; + } + mpz_add(offset, offset, a); + mpz_cdiv_q_ui(offset, offset, 8); + size = mpz_get_ui(offset) + header; + mpz_clear(offset); + mpz_clear(a); + + return size; +} + diff --git a/sbin/ipsec/photurisd/scheme.h b/sbin/ipsec/photurisd/scheme.h new file mode 100644 index 00000000000..2c66a2a8a28 --- /dev/null +++ b/sbin/ipsec/photurisd/scheme.h @@ -0,0 +1,55 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: scheme.h,v 1.1 1997/07/18 22:48:50 provos Exp $ */ +/* + * scheme.h: + * security paramter index creation. + */ + +#ifndef _SCHEME_H_ +#define _SCHEME_H_ + +#include <sys/types.h> +#include "state.h" + +#undef EXTERN + +#ifdef _SCHEME_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN u_int8_t *scheme_get_mod(u_int8_t *scheme); +EXTERN u_int8_t *scheme_get_gen(u_int8_t *scheme); +EXTERN u_int16_t scheme_get_ref(u_int8_t *scheme); +EXTERN size_t scheme_get_len(u_int8_t *scheme); +EXTERN size_t varpre2octets(u_int8_t *varpre); +#endif /* _SCHEME_H */ diff --git a/sbin/ipsec/photurisd/secrets.h b/sbin/ipsec/photurisd/secrets.h new file mode 100644 index 00000000000..3063ab7b3e0 --- /dev/null +++ b/sbin/ipsec/photurisd/secrets.h @@ -0,0 +1,61 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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.1 1997/07/18 22:48:49 provos Exp $ */ +/* + * secrets.h: + * prototypes for compute_secrets.c + */ + +#ifndef _SECRETS_H_ +#define _SECRETS_H_ + +#include "state.h" +#include "spi.h" +#include "gmp.h" + +#undef EXTERN + +#ifdef _SECRETS_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN int compute_shared_secret(struct stateob *, u_int8_t **, u_int16_t *); +EXTERN int compute_session_key(struct stateob *st, u_int8_t *key, + u_int8_t *attribute, int owner, + u_int16_t *order); +EXTERN int get_session_key_length(u_int8_t *attribute); +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); +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 new file mode 100644 index 00000000000..fa88abaa90f --- /dev/null +++ b/sbin/ipsec/photurisd/server.c @@ -0,0 +1,290 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Parts derived from code by Angelos D. Keromytis, kermit@forthnet.gr + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * server.c: + * SERVER handling functions + */ + +#ifndef lint +static char rcsid[] = "$Id: server.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _SERVER_C_ +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <string.h> +#include <unistd.h> +#ifdef _AIX +#include <sys/select.h> +#endif +#include <errno.h> +#include "config.h" +#include "photuris.h" +#include "server.h" +#include "api.h" +#include "packet.h" +#include "schedule.h" +#include "errlog.h" +#include "buffer.h" +#ifdef IPSEC +#include "spi.h" +#include "kernel.h" +#endif + +int +init_server(void) +{ + struct sockaddr_in sin, *sin2; + struct protoent *proto; + struct stat sb; + int sock, d, i, ip, on = 1; + struct ifconf ifconf; + char buf[1024]; + +#ifndef PHOTURIS_PORT + struct servent *ser; + + if ((ser = getservbyname("photuris", "udp")) == (struct servent *) NULL) + crit_error(1, "getservbyname() in init_server()"); + + global_port = ser->s_port; +#else + global_port = PHOTURIS_PORT; +#endif + + + if ((proto = getprotobyname("udp")) == (struct protoent *) NULL) + crit_error(1, "getprotobyname() in init_server()"); + + if ((global_socket = socket(PF_INET, SOCK_DGRAM, proto->p_proto)) < 0) + crit_error(1, "socket() in init_server()"); + + setsockopt(global_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + sizeof(on)); + + /* get the local addresses */ + + ifconf.ifc_len = 1024; + ifconf.ifc_buf = buf; + bzero(buf, 1024); + + if (ioctl(global_socket, SIOCGIFCONF, &ifconf) == -1) + crit_error(1, "ioctl() in init_server()"); + + sin.sin_port = htons(global_port); + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_family = AF_INET; + + if (bind(global_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) + crit_error(1, "bind() in init_server()"); + + /* Save interfaces addresses here */ + addresses = (char **) calloc(1+1, sizeof(char *)); + if (addresses == (char **) NULL) + crit_error(1, "calloc() in init_server()"); + addresses[1] = (char *) NULL; + + sockets = (int *) calloc(1+1, sizeof(int)); + if (sockets == (int *) NULL) + crit_error(1, "calloc() in init_server()"); + sockets[1] = -1; + + if (lstat(PHOTURIS_FIFO, &sb) == -1) { + if (errno != ENOENT) + crit_error(1, "stat() in init_server()"); + if (mkfifo(PHOTURIS_FIFO, 0660) == -1) + crit_error(1, "mkfifo() in init_server()"); + } else if (!(sb.st_mode & S_IFIFO)) + log_error(0, "%s is not a FIFO in init_server()", PHOTURIS_FIFO); + + /* We listen on a named pipe */ + if ((sockets[0] = open(PHOTURIS_FIFO, O_RDONLY | O_NONBLOCK, 0)) == -1) + crit_error(1, "open() in init_server()"); + i = 1; /* One interface already */ + +#ifdef IPSEC + /* We also listen on PF_ENCAP for notify messages */ + addresses = (char **) realloc(addresses, + (i + 2) * sizeof(char *)); + if (addresses == (char **) NULL) + crit_error(1, "realloc() in init_server()"); + + addresses[i + 1] = (char *) NULL; + + sockets = (int *) realloc(sockets, (i + 2)* sizeof(int)); + if (sockets == (int *) NULL) + crit_error(1, "realloc() in init_server()"); + sockets[i] = kernel_get_socket(); + sockets[i+1] = -1; + + i++; /* Next interface */ +#endif + + for (ip = 0, d = 0; d < ifconf.ifc_len; d += IFNAMSIZ + +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(_AIX) + buf[IFNAMSIZ + d] +#else + sizeof(struct sockaddr) +#endif + , i++, ip++) { + sin2 = (struct sockaddr_in *) &buf[IFNAMSIZ + d]; + + if (sin2->sin_family != AF_INET) { + i--; ip--; + continue; + } + + addresses = (char **) realloc(addresses, + (i + 2) * sizeof(char *)); + if (addresses == (char **) NULL) + crit_error(1, "realloc() in init_server()"); + + addresses[i] = strdup(inet_ntoa(sin2->sin_addr)); + if (addresses[i] == (char *) NULL) + crit_error(1, "strdup() in init_server()"); + addresses[i + 1] = (char *) NULL; + + sockets = (int *) realloc(sockets, (i + 2)* sizeof(int)); + if (sockets == (int *) NULL) + crit_error(1, "realloc() in init_server()"); + sockets[i+1] = -1; + + if ((sock = socket(PF_INET, SOCK_DGRAM, proto->p_proto)) < 0) + crit_error(1, "socket() in init_server()"); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + sizeof(on)); + sockets[i] = sock; + +#ifdef DEBUG + printf("Local interface %s, address %s.\n", buf + d, + addresses[i]); +#endif + + bzero((void *)&sin, sizeof(sin)); + sin.sin_port = htons(global_port); + sin.sin_addr.s_addr = inet_addr(addresses[i]); + sin.sin_family = AF_INET; + + if (bind(sockets[i], (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) + crit_error(1, "bind() in init_server()"); + + } + + num_ifs = i; + +#ifdef DEBUG + printf("%d local interfaces supporting IP found.\n", ip); +#endif + + return 1; +} + +int +server(void) +{ + struct sockaddr_in sin; + struct timeval timeout; + fd_set readfds, normfds; + int i, d; + + setvbuf(stdout, (char *)NULL, _IOLBF, 0); + + FD_ZERO(&normfds); + + for (i=0; i<num_ifs; i++) + FD_SET(sockets[i], &normfds); + + while (1) { + bcopy(&normfds, &readfds, sizeof(normfds)); + + /* Timeout till next job */ + timeout.tv_usec = 0; + timeout.tv_sec = schedule_next(); + +#ifdef DEBUG + printf("Sleeping for %ld seconds\n", timeout.tv_sec); +#endif + + if (select(sockets[num_ifs-1]+1, + &readfds, (fd_set *) NULL, (fd_set *) NULL, + (timeout.tv_sec == -1 ? NULL : &timeout)) < 0) + if (errno == EINTR) + continue; + else + crit_error(1, "select() in server()"); + + for (i=0; i<num_ifs; i++) { + if (FD_ISSET(sockets[i], &readfds)) { + /* XXX - As long as we have no PF_KEY */ + if (addresses[i] == NULL) + process_api(sockets[i], global_socket); + else if (strcmp("127.0.0.1", inet_ntoa(sin.sin_addr))) { + d = sizeof(struct sockaddr_in); + if (recvfrom(sockets[i], +#ifdef BROKEN_RECVFROM + (char *) buffer, 1, +#else + (char *) NULL, 0, +#endif + MSG_PEEK, + (struct sockaddr *) &sin, &d) == -1) { + log_error(1, "recvfrom() in server()"); + return -1; + } + handle_packet(sockets[i], addresses[i]); + } else { + /* XXX - flush it. APUE */ + d = sizeof(struct sockaddr_in); + recvfrom(sockets[i], (char *)buffer, BUFFER_SIZE, 0, + (struct sockaddr *) &sin, &d); + } + } + } + + schedule_process(global_socket); + fflush(stdout); + fflush(stderr); + } + + /* We will never reach this place - it's called limbo */ + +} diff --git a/sbin/ipsec/photurisd/server.h b/sbin/ipsec/photurisd/server.h new file mode 100644 index 00000000000..708090a008d --- /dev/null +++ b/sbin/ipsec/photurisd/server.h @@ -0,0 +1,51 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: server.h,v 1.1 1997/07/18 22:48:50 provos Exp $ */ +/* + * server.h: + * handling interfaces and communication + */ + +#ifndef _SERVER_H_ +#define _SERVER_H_ + +#undef EXTERN +#ifdef _SERVER_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN int init_server(void); +EXTERN int server(void); +EXTERN int global_port; +EXTERN int global_socket; + +#endif /* _SERVER_H */ diff --git a/sbin/ipsec/photurisd/snprintf.c b/sbin/ipsec/photurisd/snprintf.c new file mode 100644 index 00000000000..1362100e560 --- /dev/null +++ b/sbin/ipsec/photurisd/snprintf.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: snprintf.c,v 1.1 1997/07/18 22:48:51 provos Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#if __STDC__ +snprintf(char *str, size_t n, char const *fmt, ...) +#else +snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + if ((int)n < 1) + return (EOF); +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n - 1; + ret = vfprintf(&f, fmt, ap); + *f._p = 0; + va_end(ap); + return (ret); +} diff --git a/sbin/ipsec/photurisd/snprintf.h b/sbin/ipsec/photurisd/snprintf.h new file mode 100644 index 00000000000..a7fd9179dcb --- /dev/null +++ b/sbin/ipsec/photurisd/snprintf.h @@ -0,0 +1,30 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +int snprintf(char *, size_t, char *, ...); diff --git a/sbin/ipsec/photurisd/spi.c b/sbin/ipsec/photurisd/spi.c new file mode 100644 index 00000000000..ae73182fbb2 --- /dev/null +++ b/sbin/ipsec/photurisd/spi.c @@ -0,0 +1,354 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * spi.c: + * SPI handling functions + */ + +#ifndef lint +static char rcsid[] = "$Id: spi.c,v 1.1 1997/07/18 22:48:49 provos Exp $"; +#endif + +#define _SPI_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "photuris.h" +#include "state.h" +#include "attributes.h" +#include "buffer.h" +#include "spi.h" +#include "schedule.h" +#include "errlog.h" +#ifdef IPSEC +#include "kernel.h" +#endif + + +static struct spiob *spiob = NULL; + +int +isinattrib(u_int8_t *attributes, u_int16_t attribsize, u_int8_t attribute) +{ + while(attribsize>0) { + if(*attributes==attribute) + return 1; + if(attribsize - (*(attributes+1)+2) > attribsize) + return 0; + + attribsize -= *(attributes+1)+2; + attributes += *(attributes+1)+2; + } + return 0; +} + +time_t +getspilifetime(struct stateob *st) +{ + /* XXX - destination depend lifetimes */ + return spi_lifetime; +} + +int +make_spi(struct stateob *st, char *local_address, + u_int8_t *SPI, time_t *lifetime, + u_int8_t **attributes, u_int16_t *attribsize) +{ + u_int32_t tmp = 0; + 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); + return -1; + } + *attribsize = count; + bcopy(buffer, *attributes, count); + } + + /* Just grab a random number, this should be uniq */ + for(i=0; i<SPI_SIZE; i++) { + if(i%4 == 0) +#ifdef IPSEC + tmp = kernel_reserve_spi(local_address); +#else + tmp = arc4random(); +#endif + SPI[i] = tmp & 0xFF; + tmp = tmp >> 8; + } + + *lifetime = getspilifetime(st) + (arc4random() & 0x1F); + + return 0; +} + + +int +spi_insert(struct spiob *ob) +{ + struct spiob *tmp; + + ob->next = NULL; + + if(spiob == NULL) { + spiob = ob; + return 1; + } + + tmp=spiob; + while(tmp->next!=NULL) + tmp = tmp->next; + + tmp->next = ob; + return 1; +} + +int +spi_unlink(struct spiob *ob) +{ + struct spiob *tmp; + if(spiob == ob) { + spiob = ob->next; + free(ob); + return 1; + } + + for(tmp=spiob; tmp!=NULL; tmp=tmp->next) { + if(tmp->next==ob) { + tmp->next=ob->next; + free(ob); + return 1; + } + } + return 0; +} + +struct spiob * +spi_new(char *address, u_int8_t *spi) +{ + struct spiob *p; + if (spi_find(address, spi) != NULL) + return NULL; + if ((p = calloc(1, sizeof(struct spiob))) == NULL) + return NULL; + + if ((p->address = strdup(address)) == NULL) { + free(p); + return NULL; + } + bcopy(spi, p->SPI, SPI_SIZE); + + return p; +} + +int +spi_value_reset(struct spiob *ob) +{ + if (ob->address != NULL) + free(ob->address); + if (ob->local_address != NULL) + free(ob->local_address); + if (ob->attributes != NULL) + free(ob->attributes); + if (ob->sessionkey != NULL) + free(ob->sessionkey); + + return 1; +} + + +struct spiob * +spi_find_attrib(char *address, u_int8_t *attrib, u_int16_t attribsize) +{ + struct spiob *tmp = spiob; + u_int16_t i; + + while(tmp!=NULL) { + if(!strcmp(address, tmp->address)) { + for(i=0;i<attribsize; i += attrib[i+1]+2) { + if (attrib[i] == AT_AH_ATTRIB || attrib[i] == AT_ESP_ATTRIB) + continue; + if (!isinattrib(tmp->attributes, tmp->attribsize, attrib[i])) + break; + } + if (i == attribsize) + return tmp; + } + tmp = tmp->next; + } + return NULL; +} + +/* + * find the spi ob with matching address + * Alas this is tweaked, for owner = 1 compare with local_address + * and for owner = 0 compare with address. + */ + +struct spiob * +spi_find(char *address, u_int8_t *spi) +{ + struct spiob *tmp = spiob; + while(tmp!=NULL) { + if ((address == NULL || (tmp->owner ? + !strcmp(address, tmp->local_address) : + !strcmp(address, tmp->address))) && + !bcmp(spi, tmp->SPI, SPI_SIZE)) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +struct spiob * +spi_root(void) +{ + return spiob; +} + +void +spi_cleanup() +{ + struct spiob *p; + struct spiob *tmp = spiob; + while(tmp!=NULL) { + p = tmp; + tmp = tmp->next; + spi_value_reset(p); + free(p); + } + spiob = NULL; +} + +void +spi_expire(void) +{ + struct spiob *tmp = spiob, *p; + time_t tm; + + tm = time(NULL); + while (tmp != NULL) { + if (tmp->lifetime == -1 || + tmp->lifetime + (tmp->owner ? CLEANUP_TIMEOUT : 0) > tm) { + tmp = tmp->next; + continue; + } +#ifdef DEBUG + { + int i = BUFFER_SIZE; + bin2hex(buffer, &i, tmp->SPI, 4); + printf("Expiring %s spi %s to %s\n", tmp->owner ? "Owner" : "User", + buffer, tmp->address); + } +#endif +#ifdef IPSEC + kernel_unlink_spi(tmp); +#endif + p = tmp; + tmp = tmp->next; + spi_value_reset(p); + spi_unlink(p); + } +} diff --git a/sbin/ipsec/photurisd/spi.h b/sbin/ipsec/photurisd/spi.h new file mode 100644 index 00000000000..03bfd05b992 --- /dev/null +++ b/sbin/ipsec/photurisd/spi.h @@ -0,0 +1,84 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* $Id: spi.h,v 1.1 1997/07/18 22:48:49 provos Exp $ */ +/* + * spi.h: + * security paramter index creation. + */ + +#ifndef _SPI_H_ +#define _SPI_H_ + +#include "state.h" + +#undef EXTERN + +#ifdef _SPI_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +#define SPI_LIFETIME 1800 /* 30 minutes default lifetime */ + +struct spiob { + struct spiob *next; /* Linked list */ + char *address; + char *local_address; + int owner; + int notify; /* Created due to kernel notify */ + u_int8_t SPI[SPI_SIZE]; /* SPI */ + u_int8_t icookie[COOKIE_SIZE]; /* Initator cookie */ + u_int8_t *attributes; /* SPI attributes */ + u_int16_t attribsize; + u_int8_t *sessionkey; /* to be delete after use */ + u_int16_t sessionkeysize; + time_t lifetime; /* Lifetime for the SPI */ +}; + +EXTERN int isinattrib(u_int8_t *attributes, u_int16_t attribsize, + u_int8_t attribute); +EXTERN time_t getspilifetime(struct stateob *st); +EXTERN int make_spi(struct stateob *st, char *local_address, + u_int8_t *SPI, time_t *lifetime, + u_int8_t **attributes, u_int16_t *attribsize); + +EXTERN int spi_insert(struct spiob *); +EXTERN int spi_unlink(struct spiob *); +EXTERN struct spiob *spi_new(char *, u_int8_t *); +EXTERN int spi_value_reset(struct spiob *); +EXTERN struct spiob *spi_find_attrib(char *address, + u_int8_t *attrib, u_int16_t attribsize); +EXTERN struct spiob *spi_find(char *, u_int8_t *); +EXTERN struct spiob *spi_root(void); +EXTERN void spi_cleanup(void); +EXTERN void spi_expire(void); + +#endif /* _SPI_H */ diff --git a/sbin/ipsec/photurisd/state.c b/sbin/ipsec/photurisd/state.c new file mode 100644 index 00000000000..9349337c334 --- /dev/null +++ b/sbin/ipsec/photurisd/state.c @@ -0,0 +1,243 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * state.c: + * functions for handling states + */ + +#define _STATE_C_ + +#ifdef DEBUG +#include <stdio.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include "photuris.h" +#include "state.h" +#include "schedule.h" +#include "errlog.h" + +static struct stateob *stateob = NULL; + +int +state_insert(struct stateob *ob) +{ + struct stateob *tmp; + + ob->next = NULL; + + if(stateob == NULL) { + stateob = ob; + return 1; + } + + tmp=stateob; + while(tmp->next!=NULL) + tmp = tmp->next; + + tmp->next = ob; + return 1; +} + +int +state_unlink(struct stateob *ob) +{ + struct stateob *tmp; + if(stateob == ob) { + stateob = ob->next; + free(ob); + return 1; + } + + for(tmp=stateob; tmp!=NULL; tmp=tmp->next) { + if(tmp->next==ob) { + tmp->next=ob->next; + free(ob); + return 1; + } + } + return 0; +} + +struct stateob * +state_new(void) +{ + struct stateob *p; + + if((p = calloc(1, sizeof(struct stateob)))==NULL) + return NULL; + + mpz_init(p->modulus); + mpz_init(p->generator); + + return p; +} + +int +state_value_reset(struct stateob *ob) +{ + mpz_clear(ob->modulus); + mpz_clear(ob->generator); + + if (ob->texchange != NULL) + free(ob->texchange); + + if (ob->roschemes != NULL) + free(ob->roschemes); + if (ob->scheme != NULL) + free(ob->scheme); + if (ob->shared != NULL) + free(ob->shared); + + if (ob->user != NULL) + free(ob->user); + + if (ob->oSPIident != NULL) + free(ob->oSPIident); + if (ob->oSPIattrib != NULL) + free(ob->oSPIattrib); + if (ob->oSPIoattrib != NULL) + free(ob->oSPIoattrib); + if (ob->oSPIsecret != NULL) + free(ob->oSPIsecret); + if (ob->oSPIidentver != NULL) + free(ob->oSPIidentver); + if (ob->oSPIidentchoice != NULL) + free(ob->oSPIidentchoice); + + if (ob->uSPIident != NULL) + free(ob->uSPIident); + if (ob->uSPIattrib != NULL) + free(ob->uSPIattrib); + if (ob->uSPIoattrib != NULL) + free(ob->uSPIoattrib); + if (ob->uSPIsecret != NULL) + free(ob->uSPIsecret); + if (ob->uSPIidentver != NULL) + free(ob->uSPIidentver); + if (ob->uSPIidentchoice != NULL) + free(ob->uSPIidentchoice); + + if (ob->packet != NULL) + free(ob->packet); + + return 1; +} + +/* + * find the state ob with matching address + */ + +struct stateob * +state_root(void) +{ + return stateob; +} + +struct stateob * +state_find(char *address) +{ + struct stateob *tmp = stateob; + while(tmp!=NULL) { + if(address == NULL || !strcmp(address, tmp->address)) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +struct stateob * +state_find_next(struct stateob *prev, char *address) +{ + struct stateob *tmp = prev->next; + while(tmp!=NULL) { + if(address == NULL || !strcmp(address, tmp->address)) + return tmp; + tmp = tmp->next; + } + return NULL; +} + + +struct stateob * +state_find_cookies(char *address, u_int8_t *icookie, u_int8_t *rcookie) +{ + struct stateob *tmp; + + tmp = state_find(address); + while(tmp!=NULL) { + if (!bcmp(tmp->icookie, icookie, COOKIE_SIZE) && + (rcookie == NULL || !bcmp(tmp->rcookie, rcookie, COOKIE_SIZE))) + return tmp; + tmp = state_find_next(tmp, address); + } + + return NULL; +} + +void +state_cleanup() +{ + struct stateob *p; + struct stateob *tmp = stateob; + while(tmp!=NULL) { + p = tmp; + tmp = tmp->next; + state_value_reset(p); + free(p); + } + stateob = NULL; +} + +void +state_expire(void) +{ + struct stateob *tmp = stateob, *p; + time_t tm; + + tm = time(NULL); + while (tmp != NULL) { + if (tmp->retries < max_retries && + (tmp->lifetime == -1 || tmp->lifetime > tm)) { + tmp = tmp->next; + continue; + } +#ifdef DEBUG + printf("Expiring state to %s in phase %d\n", + tmp->address, tmp->phase); +#endif + p = tmp; + tmp = tmp->next; + state_value_reset(p); + state_unlink(p); + } +} diff --git a/sbin/ipsec/photurisd/state.h b/sbin/ipsec/photurisd/state.h new file mode 100644 index 00000000000..61f6170537a --- /dev/null +++ b/sbin/ipsec/photurisd/state.h @@ -0,0 +1,139 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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.1 1997/07/18 22:48:49 provos Exp $ */ +/* + * state.h: + * state object + */ + +#ifndef _STATE_H_ +#define _STATE_H_ + +#include <netinet/in.h> +#include <gmp.h> +#include <time.h> +#include "userdefs.h" +#ifdef NEED_UTYPES +#include "utypes.h" +#endif + +#include "packets.h" + +/* Possible values of flags */ +#define IPSEC_OPT_ENC 0x001 /* Negotiate encryption */ +#define IPSEC_OPT_AUTH 0x002 /* Negotiate authentication */ +#define IPSEC_OPT_TUNNEL 0x004 /* Negotiate tunne mode */ +#define IPSEC_OPT_REPLAY 0x100 /* Encryption with replay protection */ +#define IPSEC_OPT_ENC_AUTH 0x200 /* Encryption with authentication */ +#define IPSEC_OPT_XOR 0x400 /* Encryption with XOR */ +#define IPSEC_OPT_COMPRESS 0x800 /* Encryption with COMPRESS */ + +struct stateob { + struct stateob *next; /* Linked list */ + + int initiator; /* Boolean */ + int phase; /* Actual phase in the exchange */ + + char *user; /* User name for which do the exchange */ + int flags; /* Possible flags for this exchange */ + in_addr_t isrc, ismask; /* Accept source for tunnel */ + in_addr_t idst, idmask; /* Accept destination for tunnel */ + + 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; /* */ + + u_int8_t *scheme; /* Selected exchange scheme, holds gen. */ + u_int16_t schemesize; /* Size including value ... */ + + u_int8_t *roschemes; /* Responder offered schemes */ + u_int16_t roschemesize; /* Responder offered schemes size */ + + u_int8_t oSPI[SPI_SIZE]; /* Owner SPI */ + u_int8_t *oSPIident; /* Owner SPI identification */ + u_int8_t *oSPIattrib; /* Owner SPI attributes */ + u_int16_t oSPIattribsize; + u_int8_t *oSPIoattrib; /* Owner SPI offered attributes */ + u_int16_t oSPIoattribsize; + u_int8_t *oSPIsecret; /* Owner SPI secret keys */ + u_int16_t oSPIsecretsize; + u_int8_t *oSPIidentver; /* Owner SPI Identity Verification */ + u_int16_t oSPIidentversize; + u_int8_t *oSPIidentchoice; /* Owner SPI Identity Choice */ + u_int16_t oSPIidentchoicesize; + time_t olifetime; /* Owner SPI lifetime */ + + u_int8_t uSPI[SPI_SIZE]; /* User SPI */ + u_int8_t *uSPIident; /* User SPI identification */ + u_int8_t *uSPIattrib; /* User SPI attributes */ + u_int16_t uSPIattribsize; + u_int8_t *uSPIoattrib; /* User SPI offered attributes */ + u_int16_t uSPIoattribsize; + u_int8_t *uSPIsecret; /* User SPI secret keys */ + u_int16_t uSPIsecretsize; + u_int8_t *uSPIidentver; /* User SPI Identity Verification */ + u_int16_t uSPIidentversize; + u_int8_t *uSPIidentchoice; /* User SPI Identity Choice */ + u_int16_t uSPIidentchoicesize; + time_t ulifetime; /* User SPI lifetime */ + + mpz_t modulus; /* Modulus for look up in cache */ + mpz_t generator; /* Generator for look up in cache */ + u_int8_t *texchange; /* Their exchange value */ + u_int16_t texchangesize; + u_int8_t *shared; /* Shared secret */ + u_int16_t sharedsize; + + int retries; /* Number of retransmits */ + u_int8_t *packet; /* Buffer for retransmits */ + u_int16_t packetlen; + time_t lifetime; /* Lifetime for the exchange */ +}; + +/* Prototypes */ +int state_insert(struct stateob *); +int state_unlink(struct stateob *); +struct stateob *state_new(void); +int state_value_reset(struct stateob *); +struct stateob *state_root(void); +struct stateob *state_find(char *); +struct stateob *state_find_next(struct stateob *, char *); +struct stateob *state_find_cookies(char *, u_int8_t *, u_int8_t *); +void state_cleanup(void); +void state_expire(void); + +#define EXCHANGE_TIMEOUT 60 +#define EXCHANGE_LIFETIME 1800 + +#endif diff --git a/sbin/ipsec/photurisd/strsep.c b/sbin/ipsec/photurisd/strsep.c new file mode 100644 index 00000000000..7867f0a25fa --- /dev/null +++ b/sbin/ipsec/photurisd/strsep.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strsep.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <string.h> + +/* + * Get next token from string *stringp, where tokens are nonempty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strtoken returns NULL. + */ +char * +strsep(stringp, delim) + register char **stringp; + register const char *delim; +{ + register char *s; + register const char *spanp; + register int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/sbin/ipsec/photurisd/strsep.h b/sbin/ipsec/photurisd/strsep.h new file mode 100644 index 00000000000..128fc0b5947 --- /dev/null +++ b/sbin/ipsec/photurisd/strsep.h @@ -0,0 +1,30 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +char *strsep(char **stringp, char *delim); diff --git a/sbin/ipsec/photurisd/userdefs.h b/sbin/ipsec/photurisd/userdefs.h new file mode 100644 index 00000000000..253db82333e --- /dev/null +++ b/sbin/ipsec/photurisd/userdefs.h @@ -0,0 +1,65 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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: userdefs.h,v 1.1 1997/07/18 22:48:49 provos Exp $ */ +/* + * userdefs.h: + * handling userdefs + */ + +#ifndef _USERDEFS_H_ +#define _USERDEFS_H_ + +/* #define MACHINE_ENDIAN */ + +/* #define ENDIAN */ + +/* #define LITTLE_ENDIAN */ + +/* #define SYS_MACHINE */ + +/* #define NEED_UTYPES */ + +/* #define NEED_IN_ADDR */ + +/* #define NEED_STRSEP */ + +/* #define IPSEC */ + +#ifdef _AIX +#define NEED_UTYPES +#define __P(x) x +#define SYS_MACHINE +#define SYS_LTYPES +#define NEED_STRSEP +#define NEED_SNPRINTF +#endif + +#endif /* _USERDEFS_H_ */ + diff --git a/sbin/ipsec/photurisd/utypes.h b/sbin/ipsec/photurisd/utypes.h new file mode 100644 index 00000000000..a4fe219d0bf --- /dev/null +++ b/sbin/ipsec/photurisd/utypes.h @@ -0,0 +1,51 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _UTYPES_H_ +#define _UTYPES_H_ + +#ifdef SYS_LTYPES +#include <sys/ltypes.h> +#endif +#ifdef SYS_MACHINE +#include <sys/machine.h> +#endif + +#ifdef _AIX +typedef uint32 u_int32_t; +typedef uchar u_int8_t; +typedef ushort u_int16_t; +#else +typedef unsigned long u_int32_t; +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +#endif + +#endif /* _UTYPES_H_ */ + diff --git a/sbin/ipsec/photurisd/validity.c b/sbin/ipsec/photurisd/validity.c new file mode 100644 index 00000000000..d1b64268f0f --- /dev/null +++ b/sbin/ipsec/photurisd/validity.c @@ -0,0 +1,284 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * validity.c: + * validity verification + */ + +#ifndef lint +static char rcsid[] = "$Id: validity.c,v 1.1 1997/07/18 22:48:50 provos Exp $"; +#endif + +#define _VALIDITY_C_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <md5.h> +#include <sha1.h> +#include "config.h" +#include "scheme.h" +#include "exchange.h" +#include "errlog.h" +#include "state.h" +#include "attributes.h" +#include "validity.h" +#include "buffer.h" + +int MD5valsign(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize); +int MD5valverify(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize); +int SHA1valsign(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize); +int SHA1valverify(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize); + +u_int16_t +get_validity_verification_size(struct stateob *st) +{ + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: + case DH_G_2_DES_MD5: + case DH_G_3_DES_MD5: + case DH_G_5_DES_MD5: + return (128/8)+2; /* Two octets for varpre size */ + case DH_G_2_3DES_SHA1: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: + return (160/8)+2; + default: + log_error(0, "validitiy.c: Unknown exchange scheme: %d\n", + *((u_int16_t *)st->scheme)); + return 0; + } +} + +int +create_validity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size) +{ + int hash_size; + + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: + case DH_G_2_DES_MD5: + case DH_G_3_DES_MD5: + case DH_G_5_DES_MD5: + hash_size = MD5valsign(st, buffer+2, packet, size); + break; + case DH_G_2_3DES_SHA1: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: + hash_size = SHA1valsign(st, buffer+2, packet, size); + break; + default: + log_error(0, "validity.c: Unknown exchange scheme: %d\n", + *((u_int16_t *)st->scheme)); + return 0; + } + + if(hash_size) { + /* Create varpre number from digest */ + buffer[0] = (hash_size >> 5) & 0xFF; + buffer[1] = (hash_size << 3) & 0xFF; + } + + return size+2; +} + +int +verify_validity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size) +{ + switch(ntohs(*((u_int16_t *)st->scheme))) { + case DH_G_2_MD5: + case DH_G_3_MD5: + case DH_G_5_MD5: + case DH_G_2_DES_MD5: + case DH_G_3_DES_MD5: + case DH_G_5_DES_MD5: + if (varpre2octets(buffer) != 18) + return 0; + return MD5valverify(st, buffer+2, packet, size); + case DH_G_2_3DES_SHA1: + case DH_G_3_3DES_SHA1: + case DH_G_5_3DES_SHA1: + if (varpre2octets(buffer) != 22) + return 0; + return SHA1valverify(st, buffer+2, packet, size); + default: + log_error(0, "validity.c: Unknown exchange scheme: %d\n", + *((u_int16_t *)st->scheme)); + return 0; + } +} + + +int +MD5valsign(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize) +{ + MD5_CTX ctx; + + MD5Init(&ctx); + + MD5Update(&ctx, st->shared, st->sharedsize); + + MD5Update(&ctx, st->icookie, COOKIE_SIZE); + MD5Update(&ctx, st->rcookie, COOKIE_SIZE); + + MD5Update(&ctx, st->oSPIidentver, st->oSPIidentversize); + MD5Update(&ctx, st->uSPIidentver, st->uSPIidentversize); + + packet += 2*COOKIE_SIZE; psize -= 2*COOKIE_SIZE; + MD5Update(&ctx, packet, 4 + SPI_SIZE); + + packet += 4 + SPI_SIZE + 18; psize -= 4 + SPI_SIZE + 18; + MD5Update(&ctx, packet, psize); + + /* Data fill */ + MD5Final(NULL, &ctx); + + MD5Update(&ctx, st->shared, st->sharedsize); + MD5Final(signature, &ctx); + + return MD5_SIZE; +} + +/* We assume that the verification field is zeroed */ + +int +MD5valverify(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize) +{ + MD5_CTX ctx; + u_int8_t digest[MD5_SIZE]; + + + MD5Init(&ctx); + + MD5Update(&ctx, st->shared, st->sharedsize); + + MD5Update(&ctx, st->icookie, COOKIE_SIZE); + MD5Update(&ctx, st->rcookie, COOKIE_SIZE); + + + MD5Update(&ctx, st->uSPIidentver, st->uSPIidentversize); + MD5Update(&ctx, st->oSPIidentver, st->oSPIidentversize); + + packet += 2*COOKIE_SIZE; psize -= 2*COOKIE_SIZE; + MD5Update(&ctx, packet, 4 + SPI_SIZE); + + packet += 4 + SPI_SIZE + 18; psize -= 4 + SPI_SIZE + 18; + MD5Update(&ctx, packet, psize); + + /* Data fill */ + MD5Final(NULL, &ctx); + + MD5Update(&ctx, st->shared, st->sharedsize); + MD5Final(digest, &ctx); + + return !bcmp(digest,signature,MD5_SIZE); +} + +int +SHA1valsign(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize) +{ + SHA1_CTX ctx; + + SHA1Init(&ctx); + + SHA1Update(&ctx, st->shared, st->sharedsize); + + SHA1Update(&ctx, st->icookie, COOKIE_SIZE); + SHA1Update(&ctx, st->rcookie, COOKIE_SIZE); + + SHA1Update(&ctx, st->oSPIidentver, st->oSPIidentversize); + SHA1Update(&ctx, st->uSPIidentver, st->uSPIidentversize); + + packet += 2*COOKIE_SIZE; psize -= 2*COOKIE_SIZE; + SHA1Update(&ctx, packet, 4 + SPI_SIZE); + + packet += 4 + SPI_SIZE + 22; psize -= 4 + SPI_SIZE + 22; + SHA1Update(&ctx, packet, psize); + + /* Data fill */ + SHA1Final(NULL, &ctx); + + SHA1Update(&ctx, st->shared, st->sharedsize); + SHA1Final(signature, &ctx); + + return SHA1_SIZE; +} + +/* We assume that the verification field is zeroed */ + +int +SHA1valverify(struct stateob *st, u_int8_t *signature, + u_int8_t *packet, u_int16_t psize) +{ + SHA1_CTX ctx; + u_int8_t digest[SHA1_SIZE]; + + + SHA1Init(&ctx); + + SHA1Update(&ctx, st->shared, st->sharedsize); + + SHA1Update(&ctx, st->icookie, COOKIE_SIZE); + SHA1Update(&ctx, st->rcookie, COOKIE_SIZE); + + SHA1Update(&ctx, st->uSPIidentver, st->uSPIidentversize); + SHA1Update(&ctx, st->oSPIidentver, st->oSPIidentversize); + + packet += 2*COOKIE_SIZE; psize -= 2*COOKIE_SIZE; + SHA1Update(&ctx, packet, 4 + SPI_SIZE); + + packet += 4 + SPI_SIZE + 22; psize -= 4 + SPI_SIZE + 22; + SHA1Update(&ctx, packet, psize); + + /* Data fill */ + SHA1Final(NULL, &ctx); + + SHA1Update(&ctx, st->shared, st->sharedsize); + SHA1Final(digest, &ctx); + + return !bcmp(digest,signature,SHA1_SIZE); +} diff --git a/sbin/ipsec/photurisd/validity.h b/sbin/ipsec/photurisd/validity.h new file mode 100644 index 00000000000..c51136ff2a0 --- /dev/null +++ b/sbin/ipsec/photurisd/validity.h @@ -0,0 +1,61 @@ +/* + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 */ +/* + * validity.h: + * validity for a security association + */ + +#ifndef _VALIDITY_H_ +#define _VALIDITY_H_ +#include "state.h" + +#undef EXTERN + +#ifdef _VALIDITY_C_ +#define EXTERN +#else +#define EXTERN extern +#endif + +#ifndef MD5_SIZE +#define MD5_SIZE 16 +#endif +#ifndef SHA1_SIZE +#define SHA1_SIZE 20 +#endif + +EXTERN u_int16_t get_validity_verification_size(struct stateob *st); +EXTERN int create_validity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size); +EXTERN int verify_validity_verification(struct stateob *st, u_int8_t *buffer, + u_int8_t *packet, u_int16_t size); + +#endif |