summaryrefslogtreecommitdiff
path: root/sbin/ipsec
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>1997-07-18 22:48:52 +0000
committerNiels Provos <provos@cvs.openbsd.org>1997-07-18 22:48:52 +0000
commita182901164f2df77714485fcf4f81b0cdcb0e0b5 (patch)
tree080dc3e1b75e07f244a3f6c7a710c0e9e2782602 /sbin/ipsec
parentabe3a6221fda054003729a6f7d6d61dbb31e77b0 (diff)
initial import of the photuris keymanagement daemon
Diffstat (limited to 'sbin/ipsec')
-rw-r--r--sbin/ipsec/photurisd/INSTALL31
-rw-r--r--sbin/ipsec/photurisd/Makefile23
-rw-r--r--sbin/ipsec/photurisd/README18
-rw-r--r--sbin/ipsec/photurisd/README.howtouse76
-rw-r--r--sbin/ipsec/photurisd/api.c168
-rw-r--r--sbin/ipsec/photurisd/api.h60
-rw-r--r--sbin/ipsec/photurisd/attributes.c155
-rw-r--r--sbin/ipsec/photurisd/attributes.h85
-rw-r--r--sbin/ipsec/photurisd/buffer.c46
-rw-r--r--sbin/ipsec/photurisd/buffer.h48
-rw-r--r--sbin/ipsec/photurisd/compute_secrets.c370
-rw-r--r--sbin/ipsec/photurisd/config.c815
-rw-r--r--sbin/ipsec/photurisd/config.h116
-rw-r--r--sbin/ipsec/photurisd/cookie.c99
-rw-r--r--sbin/ipsec/photurisd/cookie.h55
-rw-r--r--sbin/ipsec/photurisd/encrypt.h58
-rw-r--r--sbin/ipsec/photurisd/errlog.c166
-rw-r--r--sbin/ipsec/photurisd/errlog.h67
-rw-r--r--sbin/ipsec/photurisd/exchange.c369
-rw-r--r--sbin/ipsec/photurisd/exchange.h56
-rw-r--r--sbin/ipsec/photurisd/handle_bad_cookie.c117
-rw-r--r--sbin/ipsec/photurisd/handle_cookie_request.c121
-rw-r--r--sbin/ipsec/photurisd/handle_cookie_response.c145
-rw-r--r--sbin/ipsec/photurisd/handle_identity_request.c323
-rw-r--r--sbin/ipsec/photurisd/handle_identity_response.c292
-rw-r--r--sbin/ipsec/photurisd/handle_message_reject.c75
-rw-r--r--sbin/ipsec/photurisd/handle_resource_limit.c98
-rw-r--r--sbin/ipsec/photurisd/handle_spi_needed.c208
-rw-r--r--sbin/ipsec/photurisd/handle_spi_update.c195
-rw-r--r--sbin/ipsec/photurisd/handle_value_request.c248
-rw-r--r--sbin/ipsec/photurisd/handle_value_response.c156
-rw-r--r--sbin/ipsec/photurisd/handle_verification_failure.c74
-rw-r--r--sbin/ipsec/photurisd/identity.c728
-rw-r--r--sbin/ipsec/photurisd/identity.h97
-rw-r--r--sbin/ipsec/photurisd/kernel.c460
-rw-r--r--sbin/ipsec/photurisd/kernel.h69
-rw-r--r--sbin/ipsec/photurisd/modulus.c300
-rw-r--r--sbin/ipsec/photurisd/modulus.h95
-rw-r--r--sbin/ipsec/photurisd/packet.c223
-rw-r--r--sbin/ipsec/photurisd/packet.h50
-rw-r--r--sbin/ipsec/photurisd/packets.h149
-rw-r--r--sbin/ipsec/photurisd/photuris.h108
-rw-r--r--sbin/ipsec/photurisd/photuris_cookie_request.c98
-rw-r--r--sbin/ipsec/photurisd/photuris_cookie_response.c93
-rw-r--r--sbin/ipsec/photurisd/photuris_error_message.c84
-rw-r--r--sbin/ipsec/photurisd/photuris_identity_request.c124
-rw-r--r--sbin/ipsec/photurisd/photuris_identity_response.c124
-rw-r--r--sbin/ipsec/photurisd/photuris_packet_encrypt.c372
-rw-r--r--sbin/ipsec/photurisd/photuris_spi_needed.c106
-rw-r--r--sbin/ipsec/photurisd/photuris_spi_update.c112
-rw-r--r--sbin/ipsec/photurisd/photuris_value_request.c85
-rw-r--r--sbin/ipsec/photurisd/photuris_value_response.c84
-rw-r--r--sbin/ipsec/photurisd/photurisd.1219
-rw-r--r--sbin/ipsec/photurisd/photurisd.c172
-rw-r--r--sbin/ipsec/photurisd/schedule.c364
-rw-r--r--sbin/ipsec/photurisd/schedule.h81
-rw-r--r--sbin/ipsec/photurisd/scheme.c191
-rw-r--r--sbin/ipsec/photurisd/scheme.h55
-rw-r--r--sbin/ipsec/photurisd/secrets.h61
-rw-r--r--sbin/ipsec/photurisd/server.c290
-rw-r--r--sbin/ipsec/photurisd/server.h51
-rw-r--r--sbin/ipsec/photurisd/snprintf.c76
-rw-r--r--sbin/ipsec/photurisd/snprintf.h30
-rw-r--r--sbin/ipsec/photurisd/spi.c354
-rw-r--r--sbin/ipsec/photurisd/spi.h84
-rw-r--r--sbin/ipsec/photurisd/state.c243
-rw-r--r--sbin/ipsec/photurisd/state.h139
-rw-r--r--sbin/ipsec/photurisd/strsep.c78
-rw-r--r--sbin/ipsec/photurisd/strsep.h30
-rw-r--r--sbin/ipsec/photurisd/userdefs.h65
-rw-r--r--sbin/ipsec/photurisd/utypes.h51
-rw-r--r--sbin/ipsec/photurisd/validity.c284
-rw-r--r--sbin/ipsec/photurisd/validity.h61
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