diff -BbruN freeswan-1.91.orig/INSTALL.pkix freeswan-1.91/INSTALL.pkix
--- freeswan-1.91.orig/INSTALL.pkix	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/INSTALL.pkix	Mon Jul  2 21:54:12 2001
@@ -0,0 +1,47 @@
+Documentation on how to use the PKIX extension for IPSec can be found under
+'doc/pkix'. Within that directory, you will also find working examples I 
+have preserved to test the various connection modes I have successfully
+connection with FreeSWAN. There are also some scripts you might (will?)
+find useful.
+
+Requirements:
+OpenLDAP 1.2 or better
+OpenSSL 0.9.5a with Shared Libraries compiled.
+
+
+  If you have to compile OpenSSL 0.9.5a yourself, here's how you should 
+compile it. Don't forget to add '/usr/local/ssl/lib' (or whatever your SSL 
+path is going to be) to '/etc/ld.so.conf'. This following script will let 
+you create '.so' shared library files. Of course, Run it as Root.:
+-------------------------------------------------------
+./config
+make
+if [ ! -d shlib_dir ]; 
+then 
+  mkdir shlib_dir 
+else 
+  rm -f shlib_dir/*
+fi
+cd shlib_dir
+ar -x ../libcrypto.a && gcc -shared ./*.o -Wl,-soname \
+  -Wl,libcrypto.so -o ./libcrypto.so.0.9.5a && rm *.o
+ar -x ../libssl.a && gcc -shared ./*.o -Wl,-soname \
+  -Wl,libssl.so -o ./libssl.so.0.9.5a && rm *.o
+cp libssl.so.0.9.5a /usr/local/ssl/lib
+cp libcrypto.so.0.9.5a /usr/local/ssl/lib
+cd ..
+make install
+ldconfig
+-------------------------------------------------------
+
+NOTE: I don't think freeswan-pkix will compile against OpenSSL 0.9.6. There
+has been many major changes in the OpenSSL project.
+
+Don't forget to edit the root Makefile for OPENSSLROOT and LDAPROOT if their
+include paths are non-standard (ie: not under /usr/include/).
+
+
+Otherwise, just follow FreeSWAN's own INSTALL file normally.
+
+-- Luc Lanthier
+luc.lanthier@rebel.com
diff -BbruN freeswan-1.91.orig/Makefile freeswan-1.91/Makefile
--- freeswan-1.91.orig/Makefile	Wed May 30 02:18:44 2001
+++ freeswan-1.91/Makefile	Mon Jul  2 20:27:12 2001
@@ -13,21 +13,41 @@
 #
 # RCSID $Id: Makefile,v 1.128 2001/05/30 06:18:44 henry Exp $
 
-# install pathnames; DESTDIR can be used to supply a prefix to them all
-# PUBDIR is where the "ipsec" command goes; beware, many things define PATH
-# settings which are assumed to include it (or at least, to include *some*
-# copy of the "ipsec" command).
-PUBDIR=$(DESTDIR)/usr/local/sbin
-# PRIVDIR is where commands get put, REALPRIVDIR is where they think they
-# will be run from in the end (currently only used by utils/ipsec)
+
+# change this to 0 if you don't want OPENSSL support turned on
+# it will turn off all pkix support also
+# check the paths for the OPENSSLROOT and LDAPROOT
+export USEOPENSSL=1
+ifeq "$(USEOPENSSL)" "1"
+export OPENSSLROOT=/usr/local/ssl
+export OPENSSLINCLS=-I$(OPENSSLROOT)/include
+export OPENSSLLIBS=-L$(OPENSSLROOT)/lib -lcrypto
+
+export LDAPROOT=/usr/local
+export LDAPINCS=-I$(LDAPROOT)/include
+endif
+
+# PREFIX controls where everything gets installed to.  This is intended
+# only for use by RPM, which installs everything into a temporary root
+# prior to creating the package.
+export PREFIX ?= /
+
+# public and private command directories
+# Beware, many things define PATH settings which are assumed to include
+# PUBDIR (or at least, to include *some* copy of the "ipsec" command).
+PUBDIR=$(PREFIX)/usr/local/sbin
+
+# PRIVDIR is where things get put, FINALPRIVDIR is where they think they
+# will be put (currently only used by utils/ipsec)
+PRIVDIR=/usr/local/lib/ipsec
+FINALPRIVDIR=/usr/local/lib/ipsec
 REALPRIVDIR=/usr/local/lib/ipsec
-PRIVDIR=$(DESTDIR)$(REALPRIVDIR)
 # where manpages go
-MANTREE=$(DESTDIR)/usr/local/man
+MANTREE=/usr/local/man
 # all relevant manpage subdirectories
 MANPLACES=man3 man5 man8
 # where configuration files go
-CONFDIR=$(DESTDIR)/etc
+CONFDIR=$(PREFIX)/etc
 # RCDIR is where boot/shutdown scripts go (first RCDIRS that exists gets it);
 # REALRCDIR is where they think they will ultimately be (for utils/Makefile)
 RCDIRS=/etc/rc.d/init.d /etc/rc.d /etc/init.d /sbin/init.d
@@ -38,7 +58,7 @@
 RCDIR=$(DESTDIR)$(REALRCDIR)
 
 # kernel location, and location of kernel patches in the distribution
-KERNELSRC=/usr/src/linux
+KERNELSRC?=/usr/src/linux
 DIRIN22=$(KERNELSRC)/net/netlink
 FILIN24=$(KERNELSRC)/net/khttpd/main.c
 KERNELREL=$(shell { test -f $(FILIN24) && echo 2.3; } || { test -d $(DIRIN22) && echo 2.2; } )
@@ -48,10 +68,12 @@
 # note, some of the patches know the last part of this path
 KERNELKLIPS=$(KERNELSRC)/net/ipsec
 
+
+
 # kernel make name:  zImage for 2.0.xx, bzImage for 2.2.xx and later, and
-# boot elsewhere (what ever happened to standards?)
+# different foolishness on the Alpha (what ever happened to standards?)
 B=$(shell test -d $(DIRIN22) && echo b)
-KERNEL=$(shell if expr " `uname -m`" : ' i.86' >/dev/null ; then echo $(B)zImage ; else echo boot ; fi)
+KERNEL=$(shell if test " `uname -m`" = " alpha" ; then echo boot ; else echo $(B)zImage ; fi)
 
 # pass pathnames etc. down
 SETTINGS=BINDIR=$(PRIVDIR) PUBDIR=$(PUBDIR) PRIVDIR=$(PRIVDIR) \
@@ -89,13 +111,29 @@
 	ln -s `pwd`/libdes/asm/*.pl $(KERNELKLIPS)/libdes/asm
 	ln -s `pwd`/libdes/asm/perlasm $(KERNELKLIPS)/libdes/asm
 	ln -s `pwd`/zlib/Makefile $(KERNELKLIPS)/zlib
-	ln -s `pwd`/zlib/*.[chS] $(KERNELKLIPS)/zlib
+
+kcopy:
+	rm -rf $(KERNELKLIPS)
+	mkdir -p $(KERNELKLIPS)/libdes/asm
+	mkdir -p $(KERNELKLIPS)/libfreeswan
+	mkdir -p $(KERNELKLIPS)/zlib
+	cp -R --verbose `pwd`/klips/net/ipsec/Makefile $(KERNELKLIPS)
+	cp -R --verbose `pwd`/klips/net/ipsec/Config.in $(KERNELKLIPS)
+	cp -R --verbose `pwd`/klips/net/ipsec/defconfig $(KERNELKLIPS)
+	cp -R --verbose `pwd`/klips/net/ipsec/*.[ch] $(KERNELKLIPS)
+	cp -R --verbose `pwd`/lib/Makefile.kernel $(KERNELKLIPS)/libfreeswan/Makefile
+	cp -R --verbose `pwd`/lib/*.[ch] $(KERNELKLIPS)/libfreeswan
+	cp -R --verbose `pwd`/libdes/Makefile $(KERNELKLIPS)/libdes
+	cp -R --verbose `pwd`/libdes/*.[ch] $(KERNELKLIPS)/libdes
+	cp -R --verbose `pwd`/libdes/asm/*.pl $(KERNELKLIPS)/libdes/asm
+	cp -R --verbose `pwd`/libdes/asm/perlasm $(KERNELKLIPS)/libdes/asm
+	cp -R --verbose `pwd`/zlib/Makefile $(KERNELKLIPS)/zlib
+	cp -R --verbose `pwd`/zlib/*.[chS] $(KERNELKLIPS)/zlib
 
 PATCHER=utils/patcher
 patches:
-	echo "===============" >>out.kpatch
-	echo "`date` `cd $(KERNELSRC) ; pwd`" >>out.kpatch
-	$(MAKE) _patches$(KERNELREL) $(SETTINGS) >>out.kpatch
+	rm -f out.kpatch
+	$(MAKE) _patches$(KERNELREL) $(SETTINGS) >out.kpatch
 
 # Linux-2.0.x version
 _patches:
@@ -122,14 +160,13 @@
 	@$(PATCHER) -v $(KERNELSRC) drivers/isdn/isdn_net.c
 
 # Linux-2.2.x version
-PATCHES24=klips/patches2.3
 _patches2.2:
 	@$(PATCHER) -v $(KERNELSRC) Documentation/Configure.help \
 		'CONFIG_IPSEC' $(PATCHES)/Documentation.Configure.help
 	@$(PATCHER) -v $(KERNELSRC) include/linux/in.h \
 		'IPPROTO_ESP' $(PATCHES)/include.linux.in.h
 	@$(PATCHER) -v $(KERNELSRC) net/Config.in \
-		'CONFIG_IPSEC' $(PATCHES24)/net.Config.in
+		'CONFIG_IPSEC' $(PATCHES)/net.Config.in
 	@$(PATCHER) -v $(KERNELSRC) net/Makefile \
 		'CONFIG_IPSEC' $(PATCHES)/net.Makefile
 	@$(PATCHER) -v $(KERNELSRC) net/ipv4/af_inet.c \
@@ -212,8 +249,8 @@
 	cd utils ; $(MAKE) $(SETTINGS)
 
 install:
-	mkdir -p $(PRIVDIR) $(PUBDIR)
-	for m in $(MANPLACES) ; do mkdir -p $(MANTREE)/$$m ; done
+	mkdir -p $(PREFIX)/$(PRIVDIR) $(PREFIX)/$(PUBDIR)
+	for m in $(MANPLACES) ; do mkdir -p $(PREFIX)/$(MANTREE)/$$m ; done
 	cd lib ; $(MAKE) install $(SETTINGS)
 	cd klips/utils ; $(MAKE) install $(SETTINGS)
 	cd pluto ; $(MAKE) install $(SETTINGS)
@@ -224,11 +261,7 @@
 	cd klips/utils ; $(MAKE) clean $(SETTINGS)
 	cd pluto ; $(MAKE) clean $(SETTINGS)
 	cd utils ; $(MAKE) clean $(SETTINGS)
-	rm -f out.kbuild out.kinstall
-
-# out.kpatch contents are usually worth retaining
-spotless:	clean
-	rm -f out.kpatch
+	rm -f out.kbuild out.kinstall out.kpatch
 
 
 
@@ -239,10 +272,6 @@
 oldgo:	precheck insert ocf confcheck programs install kernel
 menugo:	precheck insert mcf confcheck programs install kernel
 xgo:	precheck insert xcf confcheck programs install kernel
-omod:	precheck insert pcf confcheck programs install module
-oldmod:	precheck insert ocf confcheck programs install module
-menumod:	precheck insert mcf confcheck programs install module
-xmod:	precheck insert xcf confcheck programs install module
 
 # preliminaries
 precheck:
@@ -291,15 +320,6 @@
 	fi
 	utils/errcheck out.kbuild
 
-# module-only building, with error checks
-module:
-	rm -f out.kbuild out.kinstall
-	egrep -q '^CONFIG_MODULES=y' $(KCFILE)
-	egrep -q '^CONFIG_IPSEC=m' $(KCFILE)
-	( cd $(KERNELSRC) ; \
-		$(MAKE) modules 2>&1 ) | tee out.kbuild
-	utils/errcheck out.kbuild
-
 # kernel install, with error checks
 kinstall:
 	rm -f out.kinstall
@@ -311,15 +331,6 @@
 	fi
 	utils/errcheck out.kinstall
 
-# module-only install, with error checks
-minstall:
-	rm -f out.kinstall
-	egrep -q '^CONFIG_MODULES=y' $(KCFILE)
-	egrep -q '^CONFIG_IPSEC=m' $(KCFILE)
-	( cd $(KERNELSRC) ; \
-		$(MAKE) modules_install 2>&1 ) | tee out.kinstall
-	utils/errcheck out.kinstall
-
 
 
 # backup of (almost) everything an install touches
@@ -357,3 +368,9 @@
 	ctags `find lib pluto klips/utils klips/net/ipsec -name '*.[ch]'`
 
 dummy:
+
+patchclean:
+	find $(KERNELSRC) -name '*.preipsec' -exec rm {} \;
+	find $(KERNELSRC) -name '*.wipsec' -exec rm {} \;
+	find $(KERNELSRC) -name '*.ipsecmd5' -exec rm {} \;
+
diff -BbruN freeswan-1.91.orig/README.pkix freeswan-1.91/README.pkix
--- freeswan-1.91.orig/README.pkix	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/README.pkix	Tue Jul  3 03:15:54 2001
@@ -0,0 +1,4 @@
+This program is released under the GPL with the additional exemption
+that compiling, linking and/or using OpenSSL is allowed.
+
+-- Luc Lanthier
diff -BbruN freeswan-1.91.orig/doc/pkix/CA-regenerate-flatfile.sh freeswan-1.91/doc/pkix/CA-regenerate-flatfile.sh
--- freeswan-1.91.orig/doc/pkix/CA-regenerate-flatfile.sh	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/CA-regenerate-flatfile.sh	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,20 @@
+#!/bin/sh
+if [ -d /var/lib/ssl ]; then
+  cd /var/lib/ssl
+elif [ -d /usr/lib/ssl ]; then
+  cd /usr/lib/ssl
+elif [ -d /usr/local/lib/ssl ]; then
+  cd /usr/local/lib/ssl
+elif [ -d /usr/share/ssl ]; then
+  cd /usr/share/ssl
+else
+  echo "ERROR: Cannot determine location of ssl directory."
+  exit 1
+fi
+
+for ii in certs/*.pem cacert.pem crl.pem;
+do
+  cat $ii | \
+  perl -e '$printme = 0; while (<>) { if (/---BEGIN/) {$printme = 1;}; if ($printme) {print STDOUT $_;} }; print STDOUT "\n";' \
+  >> flatfile.txt
+done
diff -BbruN freeswan-1.91.orig/doc/pkix/README.certificates freeswan-1.91/doc/pkix/README.certificates
--- freeswan-1.91.orig/doc/pkix/README.certificates	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/README.certificates	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,452 @@
+	     Readme for certificate setup under FreeS/WAN
+
+			     Neil Dunbar
+			  5th November, 1999
+
+The certificate patches are (almost) always against the most recent
+snapshots available from
+ftp://ftp.xs4all.nl/~freeswan/snapshot.tar.gz. The patches are
+available from ftp://hplose.hpl.hp.com/pub/nd/pluto-openssl.tar.gz.
+
+The patches count on your having OpenSSL-0.9.3 or above installed on
+your system. Check out http://www.openssl.org for details on how to
+get OpenSSL. NB: the patches will *not* work on OpenSSL-0.9.2 or
+below.
+
+1. Applying the patches
+
+To apply the patches, cd to the build directory for the snapshot,
+which is generally freeswan-snap1999MonthDayb, and untar the
+pluto-openssl.tar.gz.
+
+Then type 'patch -p0 < pluto.diff', followed by 'patch -p0 <
+utils.diff'.
+
+2. Building and Installing FreeS/WAN
+
+Go to the pluto directory in the snapshot source directory, and edit
+the Makefile. Find the line OPENSSLROOT=.... and change the value of
+that variable to be the location of where you have installed the
+includes and libraries for OpenSSL. By default this is set to
+/usr/local/ssl.
+
+After that, build the system as per the FreeS/WAN installation notes.
+
+Installation, similarly, is no different to the normal method.
+
+3. Configuring FreeS/WAN
+
+In order to allow Pluto to use digital signatures, rather than
+preshared secrets to generate key material for IPsec, there are
+several options within the connection section of the file
+/etc/ipsec.conf which need to be set.
+
+For examples, we assume the host to host connection as follows
+
+	      west === westhop ...... easthop ==== east
+
+3.1 certfile
+
+The certfile setting should be set to the full path name of the file
+which contains the certificate whose private key will be used to
+perform the digital signatures. This file must be set in order for
+pluto to send the certificate to the other side, if requested. The
+certificate can  be in PEM or DER format.
+
+Example : /etc/ipsec/west.certificate.pem
+
+3.2 keyfile
+
+This setting should be set to the full path name to the file which
+contains the key which will be used to perform the digital
+signature.
+
+The key file can be stored in several formats, but at the moment, only
+unencrypted private keys can be used. If you use an encrypted one, the
+key load will fail, and signature/public key modes will cease to be
+available.
+
+The key files can be stored in DER or PEM format, using the OpenSSL
+private key format, which is specific to OpenSSL. Alternatively, the
+key can be stored in PKCS-8 format, which is system independent. The
+problem is that, for the moment, the OpenSSL key generation
+applications only store keys in OpenSSL format. To convert a key file
+into PKCS-8 form, use the following command (assuming that the file
+key.pem stores the OpenSSL private key in PEM format).
+
+openssl -nocrypt -topk8 -in key.pem -inform PEM -outform DER \
+	-out key.pk8
+
+(If the original key is in DER format, change '-inform PEM' to
+'-inform DER'. Similarly, if you want a PEM PKCS-8 file, change
+'-outform DER' to '-outform PEM).
+
+The key can be either an RSA or DSA key. Note that if an RSA key is
+loaded, DSS signature modes will not be offered (or accepted) from the
+other side. Similarly, a DSA key will prevent RSA modes from being
+selected.
+
+Example : /etc/ipsec/west.key.pk8
+
+3.3 peerfile
+
+This option is obsolete. It used to specify the path to certificates
+used to start public key authentication mode. This function has been
+subsumed by the certpath option.
+
+Do not use peerfile any more.
+
+3.4 certpath
+
+This gives a comma separated list of maps (see README.xmap) which can
+be used to look up certificates and/or CRLs by specifying their
+subject names, issuer names and such like.
+
+At the moment, the XMAP types are file, dir, db, ldap.
+
+Example : ldap:/etc/ldap.conf:ldap_ipsec,dir:/etc/ipsec
+
+(The first item specifies an LDAP directory lookup, whose details are
+specified in the file /etc/ldap.conf, and the identifier of which LDAP
+lookup to use within that file is 'ldap_ipsec'. The second specifies a
+local directory called /etc/ipsec, which should have files and
+symbolic links which index the relevant certificates in the
+directory).
+
+For the format of ldap files, and certificate directories, read the
+file README.xmap.
+
+3.5 certopts
+
+This setting is a comma separated list which gives a set of switches
+which control the behaviour of the public key encryption/signatures
+within pluto.
+
+To set an option in the list, one simply includes its name.
+
+To clear an option in the list, one includes its name, with a '!'
+symbol before the name.
+
+Example : !send,!pkcs7,!pk,strict,dss-sha,dss-alt
+
+The example means: turn ON the options 'strict', 'dss-sha' and
+'dss-alt', but turn OFF the options 'send', 'pkcs7' and 'pk'.
+
+The options are as follows
+
+3.5.1 'send'
+
+Set this option if you want your side of the connection to send its
+certificate to the other side as part of the main mode
+negotiations. This certificate must be in the set of certificates
+which the other side is expecting on this connection.
+
+3.5.2 'pkcs7'
+
+***NOT IMPLEMENTED YET***
+
+When sending a certificate, if this option is set, a PKCS7 encoding
+for the certificate will be chosen. If not set, a standard DER
+encoding of the X.509 certificate will be used.
+
+3.5.3 'pk'
+
+When choosing between digital signature and public key encryption
+ISAKMP methods, this option forces pluto to select public key
+encryption. If not set, pluto will choose digital signature methods.
+
+Note that this option used to be called 'rsa', but this name makes
+little sense, since both RSA and El Gamal encryption methods are
+selected by this option.
+
+3.5.3 'rev'
+
+If using public key encryption for Phase 1 negotiations, this option
+makes pluto prefer to use the revised mode method, rather than the
+standard public key mode. Revised public key mode uses fewer public
+key encryptions and transmits fewer bytes in the protocol (since
+public key ciphertexts are much larger than their symmetric key
+counterparts). Probably not a bad idea to use this one all the time if
+you want ID protection.
+
+3.5.4 'strict'
+
+This option forces verification to be very strict on the acceptability
+of certificates from the peer. If 'strict' mode is on, the following
+conditions must apply to the peer's certificate --
+
+1. For every signing certificate in the chain up to the root CA
+   certificate a valid CRL *must* be present. If a CRL is not
+   available, or the CRL is not valid (badly signed, expired, etc),
+   the verification of the certificate will fail.
+
+2. The name on the certificate must bear some relation to the name of
+   the peer, as given in the ISAKMP ID field. Assuming that the name
+   of the peer is an IPv4 address, which is the only supported one,
+   then the Common Name on the subject of the certificate must start
+   with the fully qualified domain name of the peer. Failing that, the
+   subjectAltName extension must contain an entry of type IP, which is
+   equal to the IP address given as the peer's name, or it must
+   contain an entry of type DNS, which must be equal to the name of
+   the resoved FQDN of the IP address given as the peer's name. If any
+   of these conditions are met, the certificate will be accepted. If
+   none of these conditions succeed, the verification will fail.
+
+If strict mode is not set, and these conditions fail, then debugging
+warnings will be logged, but verification will succeed. Be warned that
+this makes the setup less secure than would strict mode.
+
+3.5.5 'dss-sha'
+
+RFC2409 stipulates that the DSS signature method requires the output
+of a SHA1 hash to sign and send to the other side. It does not say
+whether this hash is a keyed one (eg HMAC) or unkeyed (ie plain SHA1).
+
+A subsequent document, draft-ietf-ipsec-ike-01.txt, given a formula
+for the plain SHA1 output. However, as Tero Kivinen of SSH has pointed
+out, most implementations of IKE use the standard HMAC method.
+
+This option forces pluto to use the plain SHA1 method outlined in the
+draft document. Clearing this option forces the HMAC method to be
+used.
+
+3.5.6 'dss-alt'
+
+RFC2409 stipulates that the encoding of a DSS signature should be 'r
+followed by s'. It does not say what format this should take. ANSI
+document X9.30 states that DSS output should be the DER encoding of
+the ASN.1 construct -
+
+ SEQUENCE {
+  r INTEGER;
+  s INTEGER;
+ };
+
+This puts some wrapper bytes around the 160 bit integers r and s, so
+that the signature is some 45-48 bytes long (depending on leading
+zeros within the integers).
+
+draft-ietf-ipsec-ike-01.txt states that the signature should be a
+single 320 bit string, with r occupying the first 160 bits and s
+occupying the next 160, without wrappers, such that all signatures are
+exactly 40 bytes long.
+
+By using the 'dss-alt' option, pluto is forced into the draft document
+mode of operation. By clearing it, the X9.30 implementation is used.
+
+4. Creating the certificates
+
+This section summarises the far more useful guide within the OpenSSL
+documentation, but should serve to generate the certificates and keys
+required for a connection. The document assumes that OpenSSL has been
+compiled and installed in /usr/local/ssl. Furthermore, it assumes that
+that configuration file for OpenSSL is stored in
+/usr/local/ssl/lib/openssl.cnf. If this is not the case, all 'openssl
+<command>' entries should be replaced by 'openssl <command> -config
+/path/to/openssl.cnf'.
+
+I am heavily indebted to Peter Onion of BT Labs for his efforts to
+debug and clarify this documentation. Peter: Your efforts are much
+appreciated.
+
+NB: This isn't the "correct" way to generate certs/CRLs. It's just my
+own recipe (largely from memory - it's been a while!) for doing
+so. It's not efficient, and you really should read the OpenSSL docs
+for better guidance.
+
+4.1 Edit openssl.cnf
+
+Ensure that the following settings for the CA_default section are more
+or less as follows -
+
+dir             = /usr/local/ssl
+certs           = $dir/certs
+crl_dir         = $dir/crl
+database        = $dir/index.txt
+new_certs_dir   = $dir/newcerts
+ 
+certificate     = $dir/cacert.pem
+serial          = $dir/serial
+crl             = $dir/crl.pem
+private_key     = $dir/private/cakey.pem
+RANDFILE        = $dir/private/.rand
+
+Fill in the default fields (country, organization, etc) as seems right
+for your setup.
+
+Create a file ca.ext containing the following -
+
+-----------------------------------
+# Extensions for a typical CA - PKIX recommendation.
+ 
+subjectKeyIdentifier=hash
+ 
+authorityKeyIdentifier=keyid:always,issuer:always
+basicConstraints = CA:true 
+keyUsage = cRLSign, keyCertSign
+nsCertType = sslCA, emailCA
+subjectAltName=email:copy
+----------------------------------
+
+4.2 Make the CA certificate
+
+Go to the directory /usr/local/ssl
+
+Generate your CA cert by the usual method
+
+openssl req -new -newkey rsa:1024 \
+  -keyout /usr/local/ssl/private/cakey.pem \
+  -out careq.pem
+
+Now sign the CA cert, citing the extensions for [v3_ca]
+
+openssl x509 -CAcreateserial -signkey private/cakey.pem -req \
+  -in careq.pem -out cacert.pem -days 2000 -extfile ca.ext
+
+This creates the self signed certificate which can be used to sign
+further certificates. Ensure that this cacert.pem file is made widely
+available to all hosts which will communicate via IPsec.
+
+4.3 Make an empty certificate database
+
+Execute the following commands, whilst in the directory /usr/local/ssl
+
+touch index.txt
+
+echo "01" > serial
+
+This creates the database, and starts issued certificates with the
+serial number starting at 1.
+
+4.4 Generate a CRL
+
+Use the command
+
+openssl ca -gencrl -out crl.pem
+
+to generate an (initially empty) CRL.  You should always have a
+current CRL, even if nothing has been revoked, since that proves
+*actively* that no certificates have been cancelled. Without a CRL,
+you are forced into the assumption that no certificates have been
+revoked.
+
+The CRL is placed in /usr/local/ssl/crl.pem. Distribute this file to
+all hosts holding the cacert.pem file. (Or, if you have an LDAP
+directory handy, publish the CRL there, so that all hosts can contact
+it).
+
+4.5 Generate the host certificate requests.
+
+On each host, generate a key and certificate request with the
+following command (I'll assume that ipsec certificates are in the
+directory /etc/ipsec, which must exist beforehand).
+
+I'll assume that the host is called foo, and lives in .mydomain.com,
+and has IP address aa.bb.cc.dd.
+
+openssl req -new -newkey rsa:1024 \
+  -nodes -keyout /etc/ipsec/foo.key -out foo.req.pem
+
+Fill in the fields for the subject name, and ensure that the common
+name section is set to 'foo.mydomain.com IPsec certificate #1', or
+some such thing - either way, it should start with foo.mydomain.com.
+
+See section 3.2 (keyfile) on converting private key files to the
+standard PKCS-8 format (which pluto can also understand). If you do
+this, you can delete the original private key file 'foo.key', once you
+have a PKCS-8 equivalent of it.
+
+Change the file permissions on foo.key to be 400 - Owner read only,
+and change to owner to be root.
+
+Transport the file foo.req.pem to the host which will sign certificate
+requests. This should be done via some secure method of
+transmission. In an ideal setup, your CA host shouldn't be connected
+to any network at all - but that's a site specific decision)
+
+4.6 Sign the certificate requests.
+
+On the CA host, edit the openssl.cnf file such that there is a section
+[svr_cert] at the bottom of the file with the following contents. 
+
+[ svr_cert ]
+basicConstraints=CA:FALSE
+nsCertType = server
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+nsComment = $ENV::NSCOMMENT
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+subjectAltName=email:copy,DNS:$ENV::HOSTFQDN,IP:$ENV::HOSTIP
+issuerAltName=issuer:copy       
+
+If this is not already done, alter the x509_extensions in the
+[CA_default] section such that it looks like -
+
+x509_extensions = $ENV::EXTENSION
+
+Now sign the request with the wrapper script 'signIPSEC', which
+is produced below. The script was written by Peter Onion.
+
+-----------------8<-------CUT HERE------8<----------------------------
+#! /bin/bash
+
+# Simple wrapper for "openssl ca" that sets environment to pass in
+# values for the svr_cert extension
+# P.J.Onion  23/9/1999
+
+if test $# -ne 3 ; then
+        echo "Usage: signIPSEC hostname ipaddress reqfile"
+        exit 1
+fi
+
+
+HOSTFQDN=$1
+HOSTIP=$2
+NSCOMMENT="IPsec Certificate for $1"
+EXTENSION=svr_cert
+
+export HOSTFQDN HOSTIP NSCOMMENT EXTENSION
+# Change /usr/local/ssl to be the directory in which OpenSSL
+# is installed.
+
+/usr/local/ssl/bin/openssl ca -in $3
+
+-----------8<----------CUT TO HERE --------8<-------------------------
+
+
+In the case above, you would do
+
+signIPSEC foo.mydomain.com 192.168.1.5 foo.req
+
+(assuming that foo.mydomain.com has the IP address 192.168.1.5, and
+that foo.req contains the PEM certificate request).
+
+Check the details that it prints, and commit the new certificate to
+the database. The new certificate will be in the directory
+/usr/local/ssl/newcerts. Tranport this file back to the requesting
+host and place it in the file /etc/ipsec/foo.pem. You can delete the
+file foo.req.pem now.
+
+Once the certificate has been delivered, move the file from newcerts
+into certs and run the command
+
+c_rehash /usr/local/ssl/certs
+
+to create the hashed directory.
+
+4.7 Renewing a certificate
+
+When you want to replace a certificate stored in file foo.pem, issue
+the command
+
+openssl ca -revoke foo.pem
+
+This changes the database to reflect the fact that the certificate has
+been cancelled, but does not update the CRL. Do that with the
+instructions in section 4.4. Make sure that the new CRL is propagated
+to all participating hosts.
+
+Now create the key/request/certificate as per sections 4.5 onwards.
+
+   ******************* End of document ********************
+
diff -BbruN freeswan-1.91.orig/doc/pkix/README.certopts freeswan-1.91/doc/pkix/README.certopts
--- freeswan-1.91.orig/doc/pkix/README.certopts	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/README.certopts	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,22 @@
+The current options available within this PKIX package are:
+
+send 	-> If using RSASIG or RPKE, send your certificate to the peer.
+	   This option is usually optional.
+
+pk	-> Use PKE authentication
+
+pk,rev	-> Use RPKE authentication
+
+strict	-> Strict authenticate. There _must_ be a CRL available, and it
+	   must be valid.
+
+I recommend always sending the optional certificate to the peer, as well 
+as using "strict" at all times to make sure the connection is truly 
+fully authenticated.
+	certopts=send,strict,pk,rev
+
+For more information on these certopts options, please refer to Neil Dunbar's
+README.certificates document.
+
+-- Luc Lanthier
+luc.lanthier@rebel.com 
diff -BbruN freeswan-1.91.orig/doc/pkix/README.xmap freeswan-1.91/doc/pkix/README.xmap
--- freeswan-1.91.orig/doc/pkix/README.xmap	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/README.xmap	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,398 @@
+			     README.xmap
+
+			     Neil Dunbar
+			  21st October, 1999
+
+1. Introduction
+
+As of the October release of the pluto-openssl patches, the
+certificate paths parameter has been replaced by a list of
+XMAPs. XMAPs are an abstraction of a dictionary lookup, which are
+designed to look up public key information. This includes X.509
+certificates, X.509 certificate revocation lists, and, in theory,
+simple public key values (NB: raw public keys are not supported yet).
+
+An XMAP is similar to the X509_LOOKUP system employed within OpenSSL
+to specify file and directory lookup. Indeed, XMAP has two mechanisms
+for lookup via file and directory, as well as others.
+
+The specification for an XMAP consists of a text string of the format
+<type>:<details>. The type denotes the sort of search which the XMAP
+library will carry out, and the details give appropriate parameter
+information so that the search can execute. As an example, a file XMAP
+on the file /etc/ipsec/certs.txt would have the form
+"file:/etc/ipsec/certs.txt".
+
+2. XMAP lookup
+
+(Programmer stuff - ignore if not interested)
+
+A lookup is a search which is identified by three parameters: the type
+of the thing being looked for, the search identifier and a search
+parameter (which is governed by the search identifier).
+
+The result of the search is a list (actually an OpenSSL STACK) of type
+X509_OBJECT (all of which fit the search criteria specified, sorted to
+be age order [most recent first, oldest last]. The type X509_OBJECT is
+defined in the OpenSSL header file x509_vfy.h. Note: this is NOT the
+same as the file X509_OBJECTS defined in x509.h. The C type
+declaration is reproduced here.
+
+typedef struct x509_object_st {
+   /* one of the above types */
+   int type;
+   union  {
+     char *ptr;
+     X509 *x509;
+     X509_CRL *crl;
+     EVP_PKEY *pkey;
+   } data; 
+} X509_OBJECT;
+
+Thus, if an X.509 certificate is stored in such an object, the type
+field will be set to X509_LU_X509, and <object>.data.x509 holds a
+pointer to the actual certificate data.
+
+Thus, to iterate through all certificates returned in a search, a C
+program fragment would look like the following.
+
+XMAP *xmap;
+int i;
+STACK_OF(X509_OBJECT) *sk;
+X509_OBJECT *obj;
+X509 *x;
+ :
+ :
+sk = XMAP_lookup(xmap, X509_LU_X509, <search id>, <search parameter>);
+for (i=0; i<sk_X509_OBJECT_num(sk); i++) {
+    obj = sk_X509_OBJECT_value(sk, i);
+    x = obj->data.x509;
+
+    /* Operations on the certificate 'x' */
+} 
+
+3. XMAP Search types
+
+The various search types are detailed in the following sections. The
+list of items are sorted (if possible) in date descending order, ie
+the most recent object is first in the return list, and the oldest
+object comes last. All duplicates are removed from the return list.
+
+3.1 "subject" (returns X.509 cert)
+
+The search looks for a certificate whose name is the the same as the
+X.509 name given in the parameter to the search.
+
+3.2 "issuer" (returns X.509 CRL)
+
+The search looks for a certificate revocation list (CRL) whose issuer
+is the same as the X.509 given as a search parameter.
+
+3.3 "uid" (returns X.509 cert)
+
+The search looks for the certificates which are listed as belonging to
+the user whose ID is given by the null terminated character string
+given as the search parameter.
+
+3.4 "dns" (returns X.509 cert)
+
+The search returns a list of the certificates which are listed as
+belonging to the fully qualified domain name (FQDN) as given in the
+search parameter, which is a null terminated character string.
+
+NB: Any certificate MUST have a subjectAltName which includes a DNS
+entry which is the same as the search string. This requirement is in
+addition to any indexing which is required for the individual XMAP
+search type.
+
+3.5 "ip" (returns X.509 cert)
+
+The search returns a list of the certificates which are listed as
+belonging to the IPv4 address given as a search parameter. The search
+parameter is a 4 octet string, which gives the IP address in network
+order; for example the ip address 15.144.59.30 would have the search
+parameter (in hex) 0F903B1E.
+
+As with DNS indexed certificates, the certificates must contain a
+subjectAltName with the correct IP entry within it.
+
+3.6 "ca" (returns X.509 cert)
+
+This search returns all CA certificates indexed in the list. A CA
+certificate is one which has a basicConstraints extension with the CA
+flag set to true. Also the CA has the subjectName and issuerName set
+to be the same.
+
+There is no search parameter for this search. It should be set to NULL
+in the XMAP_lookup() call.
+
+4. XMAP Types
+
+There are currently four types of XMAP: File, Directory, Berkeley DB
+and LDAP. Respectively, their type specifiers are "file", "dir", "db"
+and "ldap". Each subsection will detail the exact representation and
+expectations of the XMAP.
+
+4.1 File
+
+Type Specifier: "file"
+Syntax: file:<file name>
+
+This implements a simple flat file structure for lookups. The file can
+contain as many certificates in PEM format as desired. In order to
+index them, certain fields should be prepended to the certificates.
+
+For example a file might look like this.
+
+-----BEGIN CERTIFICATE-----
+MIIEHzCCAwegAwIBAgIBADANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMCR0Ix
+HQ0Qb72dPlXYO20xtdMR9fX92PfSQSgAulNITYzusd8KE6yvJ8+HEbUuwXLHXZh4
+  :
+  :
+  :
+pk/Bv8iFUiZhH8EAr6SvF0AkpULi46bVcoQlr36Ax59uQ8OcJeNmljKYdbrN5uFL
+62In
+-----END CERTIFICATE-----
+
+uid: nd
+-----BEGIN CERTIFICATE-----
+MIIETDCCA7WgAwIBAgIQE9hfeRmSr51Wzgvm4B19JjANBgkqhkiG9w0BAQQFADCB
+njEPMA0GA1UEChMGaHAuY29tMRowGAYDVQQLExFJVCBJbmZyYXN0cnVjdHVyZTEL
+  :
+  :
+  :
+6pZk+pEpZ5S55lFP1QspTsBVbrBgsEuGFyGpHTo9sIEaQYxfRGNEvW+ZaEPU1HKo
+YVkAahuv5T21GdvouWdelA6l6uWMK/hfsQo9PdpBLDaUrwH5lkDuXcNk+LHZvVDt
+-----END CERTIFICATE-----                                       
+
+-----BEGIN X509 CRL-----
+MIICLTCCARUwDQYJKoZIhvcNAQEEBQAwgacxCzAJBgNVBAYTAkdCMR4wHAYDVQQI
+ExVTb3V0aCBHbG91Y2VzdGVyc2hpcmUxEDAOBgNVBAcTB0JyaXN0b2wxJTAjBgNV
+  :
+  :
+  :
+++lOGcX1WTtZ2dnV6Lb5r5xQ3IGavf2TKnu1/nCyAKFlF34+j7/+fIxT4iQiEDjk
+Z8Q76UEWVRMw7Tk63aAf0Yf5qaI1Tpd+SKhSTgc4arJH
+-----END X509 CRL-----
+
+ip: 15.144.59.30
+dns: pinky.hpl.hp.com
+-----BEGIN CERTIFICATE-----
+MIIHgTCCBmmgAwIBAgIBCjANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMCR0Ix
+HjAcBgNVBAgTFVNvdXRoIEdsb3VjZXN0ZXJzaGlyZTEQMA4GA1UEBxMHQnJpc3Rv
+  :
+  :
+  :
+KkW/kYOxRrmg9KGnSVOolD1ueLYg9D4CtY30r1JGE/wixmIvQEP8JEv+X6Cr4Wiu
+VfENrF8=
+-----END CERTIFICATE-----
+
+This example indexes the fourth certificate as belonging to the IP
+address 15.144.59.30, as well as the DNS name "pinky.hpl.hp.com". The
+second certificate belongs to the user ID "nd".
+
+The file also contains a CRL embedded within it.
+
+Note: indexed searches in files are done by simple linear search. It's
+not an efficient means for searching serious amounts of data - use the
+other types for anything other than trivial data.
+
+
+4.2 Directory
+
+Type Specifier: "dir"
+Syntax: dir:<path to directory>
+
+The directory type is a derivation of the hashed directory used in the
+OpenSSL applications. The certificates are stored within a single
+level directory. Each certificate (or CRL) is stored in exactly one
+file in the directory. These files can be in either DER or PEM format,
+unlike the flat file above. To index the files for subject and issuer
+searches, you need to make a symbolic link from a hashed
+representation of the X.509 name of the certificate subject name (or
+CRL issuer name).
+
+To do this, you should execute the command -
+
+[for certificate files -- all on one line]
+
+ln -s certificate.pem
+  `openssl x509 -noout -hash -in certificate.pem`.cert.0
+
+NB: The .0 on the end is an arbitrary extension to the link name in
+case there might be a hash clash in the directory. You can call it
+anythin you like, but the ".cert" extension MUST be present -- unlike
+standard OpenSSL hash directories.
+
+[ for CRL files ]
+ln -s crl.pem
+  `openssl crl -noout -hash -in certificate.pem`.crl.0
+
+Again, the .0 is a differentiating extension, but the ".crl" is
+mandatory for marking out certificates.
+
+To index other attributes, you should make links which have the
+following appearance -
+
+uid-<user ID>.cert.0 [ denotes a user file ]
+dns-<fully qualified domain name>.cert.0 [ a DNS indexed cert ]
+ip-<IPv4 dotted form address>.cert.0 [ an IP indexed cert ]
+
+For example, assume that file pinky.pem held the certificate for DNS
+pinky.hpl.hp.com and/or IP address 15.144.59.30, the links would look
+like -
+
+dns-pinky.hpl.hp.com.cert.0  )__________\. pinky.pem
+ip-15.144.59.30.cert.0       )          /
+
+CA certificates don't need to be indexed. CA searches are performed by
+loading every certificate file in the directory and checking for a CA
+certificate, so it's failrly slow for this type of search.
+
+What Directories *are* good for is converting into a Berkeley DB file
+database - which is the fastest of all searches.
+
+-- ADDENDUM -- 20001016, Luc Lanthier
+
+I've created a short and ugly shell script 'rehashcertdir' which will 
+do this work for you. Usage:
+
+  ipsec rehashcertdir <directory>
+
+
+
+3.3 - Berkeley DB searches
+
+Type Specifier: "db"
+Syntax: db:<path to db file>
+
+Assuming you have a Berkeley DB 1.85 library available on your system,
+you can index the certificates/CRLs in a DB hash file, which provides
+the fastest lookup of any of the methods.
+
+The internal details of the DB file are maintained in a separate file
+(README.XMAP.DB -- to be written -- nd). To make a DB file, you should
+create a directory as in the above section, then run the utility
+command "dir2hash" as follows, assuming that the directory to be
+hashed is called "my_dir" and the output DB file should be called
+certs.db :-
+
+  ipsec dir2hash -o dbhash.db my_dir
+
+Note: You don't have to make the hashed, DNS or IP links as in the
+directory above (they are automatically figured out by the dir2hash
+program from the subjectNames and subjectAltNames of the
+certificates/CRLs). You DO have to index the uid entries manually,
+since the certificates don't necessarily have the means of
+indentifying which users they belong to.
+
+Note that IPsec knows nothing of uid's and doesn;t use them yet, so a
+perfectly valid IPsec DB file can be mafe by putting all the
+certificates into a directory without any links at all, then running
+dir2hash on the directory.
+
+However, this still creates a single file which must be copied to all
+hosts participating in the IPsec process. Therefore, this mechanism
+will not scale past a few, easily managed hosts. For scalability you
+should use LDAP.
+
+3.4 - LDAP searches
+
+Type Specifier: "ldap"
+Syntax: ldap:<LDAP config file>:<LDAP identifier>
+
+Assuming that you have at least one LDAP server available on your
+network, you can make a config file (which is NOT the same as
+ipsec.conf) to specify how to search for entries in one or more LDAP
+servers. A single ldap configuration file can hold search details for
+many ldap servers. Each server specification must be identified by a
+unique ldap ID. This ID can be any alphanumeric string. If the LDAP
+identifier is omitted, then the first specification in the file will
+be used by default.
+
+The entries in the configuration file can be of the following form:
+
+<ID>_host_name: <FQDN of the LDAP server host. Default: localhost>
+
+<ID>_port: <port number on the server. Default: 389>
+
+<ID>_base: <base search string for server. Default: NONE>
+
+<ID>_timeout: <timeout for searches, in seconds: Default: 10>
+
+<ID>_bindDN: <DN to bind to the LDAP server as: Default: "">
+
+<ID>_bindPW: <Password for the bind DN: Default: "">
+
+Note that you MUST supply a base search string: the software cannot
+guess a reasonable default. Also, the bind DN and password is the only
+supported authentication mechanism. PLEASE don't put the LDAP server
+on a host which needs to reached via IPsec. If you're relying on it to
+serve all certificates, the LDAP connection won't work (since the
+IPsec connection might not be up yet).
+
+For each search type, you must specify the filter string and
+attributes which should be searched for from the LDAP directory.
+
+The filter string specification has the form
+
+<ID>_filter:<search index>:<return type>: <LDAP search filter>
+
+where <search index> is either "uid", "subject", "issuer", "dns" or
+"ip" as above, and <return type> is either "cert" (for X.509
+certificates) or "crl" for CRL searches. Either the <search index> or
+<return type> can be set to "*", which is a wildcard, meaning any
+index or any return type.
+
+Similarly, the attribute specification looks like:
+
+<ID>_attributes:<search index>:<return type>: <list of attributes>
+
+The <search string> and <return type> are as above, with the list of
+attributes a comma separated list of attributes.
+
+For an example, let us use the following file
+
+ldapnd_host_name = ldap.hpl.hp.com
+ldapnd_base = o=Hewlett-Packard Laboratories, c=GB
+ldapnd_filter:uid = (uid=%s)
+
+ldapnd_attributes:*:crl = certificaterevocationlist, certificaterevocationlist;binary
+
+ldapnd_filter:*:crl = (&(objectclass=certificationAuthority)(cn=%s))
+
+ldapnd_filter:ca = (objectclass=certificationauthority)
+
+ldapnd_filter:dns = (&(objectclass=hostRecord)(dNSRecord=%s))
+ldapnd_attributes:dns = servercertificate, servercertificate;binary
+
+ldapnd_filter:ip = (&(objectclass=hostRecord)(ipv4Address=%s))   
+ldapnd_attributes:ip = servercertificate, servercertificate;binary
+
+This stipulates an anonymous bind search of the LDAP server on
+ldap.hpl.hp.com port 389 (the default), whose base for searches is
+"o=Hewlett-Packard Laboratories,c=GB".
+
+For DNS searches, the filter used will be
+
+"(&(objectClass=hostRecord)(dNSRecord=%s))"
+
+where "%s" will be replaced by the DNS name being searched for. In the
+case of a search for pinky.hpl.hp.com, the search string will be -
+
+"(&(objectClass=hostRecord)(dNSRecord=pinky.hpl.hp.com))"
+
+For IP address searches, the filter used will be
+
+"(&(objectclass=hostRecord)(ipv4Address=%s))"
+
+Again, searching for the host with IP address 15.144.59.30, the host
+search filter will be -
+
+"(&(objectclass=hostRecord)(ipv4Address=15.144.59.30))"
+
+In both DNS and IP searches, the search will return the attributes
+"serverCertificate" and "serverCertificate;binary".
+
+Note that the return type is missing from many of the
+specifications. Return types default to "cert".
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/arm-devel.key freeswan-1.91/doc/pkix/examples/arm-devel.key
--- freeswan-1.91.orig/doc/pkix/examples/arm-devel.key	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/arm-devel.key	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQCoqQwsIfybAtb0mMfD3NGNMZH7ckGrCehSm741ddjw9rW6igzZ
+AptaqQ2Y5raPl0XrF+MQI8SQkfTtzP92/ZU9eqbEWbBFRfYLqckMd21eU9GHDVl5
+UPmUwWSOXuE4lK58f2heEFE975yf9CsIvOuas33FsiuYtO5UEmzapAVAnQIDAQAB
+AoGAXUzWvPs4IBAcFUcHCyR2j6LiXLTB+voKGNirCivdDL+NnFmN7eZxRl/Kc9D9
+IMXQGdMm+uCudkMnuPz0PUDeczQST46jiTlG5vkQdj3zpmz/x73t5I4E8vFSX6A4
+gKREFeGxSCEm0THNusBKk1Q+huHUDKw4mFh85MTopy32McECQQDVWcc3BMlDICG2
+6bFc3+1ieeVIKoD2GnJR7b/GU57umLFyDmSFwOkTTt7VWp3jV/81Oy+xBe3cC8Fm
+mFC/e45VAkEAymA9ke8XFduafs2Q+nsbfx4QI+f8lAd51pBR4A4J+W50JLO1/WqC
+PwOXwVPRCPyzHiY9B8L9KPrFKSwVedihKQJBAKnGCl/+wAVZcVqztf649pbRdyGp
+KPwt6WDGtz+j1Sn6eeHQEC/bZd2Geo3+0PtTT/NVCMtuc2wSMrFobYEiWg0CQQCl
+lf9qw5049jlAHYTNXiNObFO6fVuN51wKcoV7dSE2JOkFCsISuq4dTxxBRApadyE7
+vv/atPGdMSpXGMntq5GZAkEA1PJ0w4WSC3sW3guq4WzDLWqmbK2pOvC40ATZR67y
+lYC1okanKDsRam0remPY7xWZ8WACJx5KOIvYgXhX+dNXPg==
+-----END RSA PRIVATE KEY-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/arm-devel.pem freeswan-1.91/doc/pkix/examples/arm-devel.pem
--- freeswan-1.91.orig/doc/pkix/examples/arm-devel.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/arm-devel.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/arm-devel.req.pem freeswan-1.91/doc/pkix/examples/arm-devel.req.pem
--- freeswan-1.91.orig/doc/pkix/examples/arm-devel.req.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/arm-devel.req.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIB4DCCAUkCAQAwgZ8xCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w
+DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29m
+dEVuZzEgMB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkC
+m1qpDZjmto+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ
++ZTBZI5e4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGg
+ADANBgkqhkiG9w0BAQQFAAOBgQCNEgKfb3Qwtk7rgHcLiUCcXA4w4XFyHxRA8GEO
+N/sJVOFq6mV2wVHEmhYalMQTXs3KXNucppQ3ZtHhiLCxzuHSe1Cs6q3iBXPaOPsY
+L6I2gJ/wQ49E11HYtMSzDjcAbxV3zWWd42Xk8mNNrhT2r1h+g30DQEgFjXkXhbpt
+1R+0uA==
+-----END CERTIFICATE REQUEST-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/db-pk-rw.conf freeswan-1.91/doc/pkix/examples/db-pk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/db-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/db-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/db-pk.conf freeswan-1.91/doc/pkix/examples/db-pk.conf
--- freeswan-1.91.orig/doc/pkix/examples/db-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/db-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/db-rpk-rw.conf freeswan-1.91/doc/pkix/examples/db-rpk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/db-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/db-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/db-rpk.conf freeswan-1.91/doc/pkix/examples/db-rpk.conf
--- freeswan-1.91.orig/doc/pkix/examples/db-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/db-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/db-rsasig-rw.conf freeswan-1.91/doc/pkix/examples/db-rsasig-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/db-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/db-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/db-rsasig.conf freeswan-1.91/doc/pkix/examples/db-rsasig.conf
--- freeswan-1.91.orig/doc/pkix/examples/db-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/db-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/60601ae4.cert.0 freeswan-1.91/doc/pkix/examples/dir/60601ae4.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/60601ae4.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/60601ae4.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/arm-devel.pem freeswan-1.91/doc/pkix/examples/dir/arm-devel.pem
--- freeswan-1.91.orig/doc/pkix/examples/dir/arm-devel.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/arm-devel.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/arm1.pem freeswan-1.91/doc/pkix/examples/dir/arm1.pem
--- freeswan-1.91.orig/doc/pkix/examples/dir/arm1.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/arm1.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/b2dc4b6f.cert.0 freeswan-1.91/doc/pkix/examples/dir/b2dc4b6f.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/b2dc4b6f.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/b2dc4b6f.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/cacert.pem freeswan-1.91/doc/pkix/examples/dir/cacert.pem
--- freeswan-1.91.orig/doc/pkix/examples/dir/cacert.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/cacert.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID2jCCA0OgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MTk0NTAyWhcNMDYwODA3MTk0NTAyWjCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANWu/vkaR1M1bvP2Y80Dv105n3VHmOqZcyy9fnbaXXc92nKbBMib
+bsuUdfWdjOuC34BjfNuC9DU3rP8jZNBg+qeyAie6G7Q1R3atroqYvaFFhEbU1OnZ
+vBigB39dOIjfFiHbeqNCqlxLlrMJwkBJtkLdiktuf6Rqp+nnX6ymxz1BAgMBAAGj
+ggE4MIIBNDAdBgNVHQ4EFgQUejh16bmUq7YAxTaB6qVgPvr+5OEwgcEGA1UdIwSB
+uTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYTAkNB
+MRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJl
+YmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRldmVs
+MSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMAwGA1Ud
+EwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAhBgNVHREE
+GjAYgRZsdWMubGFudGhpZXJAcmViZWwuY29tMA0GCSqGSIb3DQEBBAUAA4GBAHzh
+QeKz7deGehWh7KtZ1tNNu1gWxeW4fwjHUT/xkoepd0XclIIRoKH+2h6w5QG3p2Up
+9TLxWlS8SB0tR0FiVu1WD658vOZjDTqqL9EVdEgSCrWX26KaMhNLrYzT3nzqq9VR
+QYqYZDAD3Z345UweqfCJBgxrim03x++bsEq9tP4Y
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/crl.pem freeswan-1.91/doc/pkix/examples/dir/crl.pem
--- freeswan-1.91.orig/doc/pkix/examples/dir/crl.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/crl.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,10 @@
+-----BEGIN X509 CRL-----
+MIIBWjCBxDANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20XDTAxMDIxNDE5NDUzN1oXDTAx
+MDMxNjE5NDUzN1owDQYJKoZIhvcNAQEEBQADgYEAcM3oRcSVw2rf7AQbcX0WqsEh
+YEHnMUNur13Wd2ai7b6KSKxHj+O/WWSupH3IDPL1TEKwdWLG9+MtbhKhBh8WNzQh
+7Nl/NzTgdCh0xDBoJDGG7zN7WDNQ1WGbaAkjDUJm6ty92zlpFkF4Gg2B1dl8WwYK
+LSSaMtj6/VV4CuhzFMg=
+-----END X509 CRL-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0 freeswan-1.91/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0 freeswan-1.91/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/eb7e7e69.cert.0 freeswan-1.91/doc/pkix/examples/dir/eb7e7e69.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/eb7e7e69.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/eb7e7e69.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID2jCCA0OgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MTk0NTAyWhcNMDYwODA3MTk0NTAyWjCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANWu/vkaR1M1bvP2Y80Dv105n3VHmOqZcyy9fnbaXXc92nKbBMib
+bsuUdfWdjOuC34BjfNuC9DU3rP8jZNBg+qeyAie6G7Q1R3atroqYvaFFhEbU1OnZ
+vBigB39dOIjfFiHbeqNCqlxLlrMJwkBJtkLdiktuf6Rqp+nnX6ymxz1BAgMBAAGj
+ggE4MIIBNDAdBgNVHQ4EFgQUejh16bmUq7YAxTaB6qVgPvr+5OEwgcEGA1UdIwSB
+uTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYTAkNB
+MRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJl
+YmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRldmVs
+MSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMAwGA1Ud
+EwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAhBgNVHREE
+GjAYgRZsdWMubGFudGhpZXJAcmViZWwuY29tMA0GCSqGSIb3DQEBBAUAA4GBAHzh
+QeKz7deGehWh7KtZ1tNNu1gWxeW4fwjHUT/xkoepd0XclIIRoKH+2h6w5QG3p2Up
+9TLxWlS8SB0tR0FiVu1WD658vOZjDTqqL9EVdEgSCrWX26KaMhNLrYzT3nzqq9VR
+QYqYZDAD3Z345UweqfCJBgxrim03x++bsEq9tP4Y
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/eb7e7e69.crl.0 freeswan-1.91/doc/pkix/examples/dir/eb7e7e69.crl.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/eb7e7e69.crl.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/eb7e7e69.crl.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,10 @@
+-----BEGIN X509 CRL-----
+MIIBWjCBxDANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20XDTAxMDIxNDE5NDUzN1oXDTAx
+MDMxNjE5NDUzN1owDQYJKoZIhvcNAQEEBQADgYEAcM3oRcSVw2rf7AQbcX0WqsEh
+YEHnMUNur13Wd2ai7b6KSKxHj+O/WWSupH3IDPL1TEKwdWLG9+MtbhKhBh8WNzQh
+7Nl/NzTgdCh0xDBoJDGG7zN7WDNQ1WGbaAkjDUJm6ty92zlpFkF4Gg2B1dl8WwYK
+LSSaMtj6/VV4CuhzFMg=
+-----END X509 CRL-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/ip-10.1.49.124.cert.0 freeswan-1.91/doc/pkix/examples/dir/ip-10.1.49.124.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/ip-10.1.49.124.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/ip-10.1.49.124.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir/ip-10.8.49.122.cert.0 freeswan-1.91/doc/pkix/examples/dir/ip-10.8.49.122.cert.0
--- freeswan-1.91.orig/doc/pkix/examples/dir/ip-10.8.49.122.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir/ip-10.8.49.122.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir-pk-rw.conf freeswan-1.91/doc/pkix/examples/dir-pk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/dir-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir-pk.conf freeswan-1.91/doc/pkix/examples/dir-pk.conf
--- freeswan-1.91.orig/doc/pkix/examples/dir-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir-rpk-rw.conf freeswan-1.91/doc/pkix/examples/dir-rpk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/dir-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir-rpk.conf freeswan-1.91/doc/pkix/examples/dir-rpk.conf
--- freeswan-1.91.orig/doc/pkix/examples/dir-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir-rsasig-rw.conf freeswan-1.91/doc/pkix/examples/dir-rsasig-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/dir-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/dir-rsasig.conf freeswan-1.91/doc/pkix/examples/dir-rsasig.conf
--- freeswan-1.91.orig/doc/pkix/examples/dir-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/dir-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ff-pk-rw.conf freeswan-1.91/doc/pkix/examples/ff-pk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/ff-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ff-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ff-pk.conf freeswan-1.91/doc/pkix/examples/ff-pk.conf
--- freeswan-1.91.orig/doc/pkix/examples/ff-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ff-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ff-rpk-rw.conf freeswan-1.91/doc/pkix/examples/ff-rpk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/ff-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ff-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ff-rpk.conf freeswan-1.91/doc/pkix/examples/ff-rpk.conf
--- freeswan-1.91.orig/doc/pkix/examples/ff-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ff-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ff-rsasig-rw.conf freeswan-1.91/doc/pkix/examples/ff-rsasig-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/ff-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ff-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ff-rsasig.conf freeswan-1.91/doc/pkix/examples/ff-rsasig.conf
--- freeswan-1.91.orig/doc/pkix/examples/ff-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ff-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/flatfile.txt freeswan-1.91/doc/pkix/examples/flatfile.txt
--- freeswan-1.91.orig/doc/pkix/examples/flatfile.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/flatfile.txt	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,92 @@
+ip: 10.8.49.122
+dns: arm-devel.netwinder.org
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
+
+ip: 10.1.49.124
+dns: arm1.netwinder.org
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIID2jCCA0OgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MTk0NTAyWhcNMDYwODA3MTk0NTAyWjCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANWu/vkaR1M1bvP2Y80Dv105n3VHmOqZcyy9fnbaXXc92nKbBMib
+bsuUdfWdjOuC34BjfNuC9DU3rP8jZNBg+qeyAie6G7Q1R3atroqYvaFFhEbU1OnZ
+vBigB39dOIjfFiHbeqNCqlxLlrMJwkBJtkLdiktuf6Rqp+nnX6ymxz1BAgMBAAGj
+ggE4MIIBNDAdBgNVHQ4EFgQUejh16bmUq7YAxTaB6qVgPvr+5OEwgcEGA1UdIwSB
+uTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYTAkNB
+MRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJl
+YmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRldmVs
+MSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMAwGA1Ud
+EwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAhBgNVHREE
+GjAYgRZsdWMubGFudGhpZXJAcmViZWwuY29tMA0GCSqGSIb3DQEBBAUAA4GBAHzh
+QeKz7deGehWh7KtZ1tNNu1gWxeW4fwjHUT/xkoepd0XclIIRoKH+2h6w5QG3p2Up
+9TLxWlS8SB0tR0FiVu1WD658vOZjDTqqL9EVdEgSCrWX26KaMhNLrYzT3nzqq9VR
+QYqYZDAD3Z345UweqfCJBgxrim03x++bsEq9tP4Y
+-----END CERTIFICATE-----
+
+-----BEGIN X509 CRL-----
+MIIBWjCBxDANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20XDTAxMDIxNDE5NDUzN1oXDTAx
+MDMxNjE5NDUzN1owDQYJKoZIhvcNAQEEBQADgYEAcM3oRcSVw2rf7AQbcX0WqsEh
+YEHnMUNur13Wd2ai7b6KSKxHj+O/WWSupH3IDPL1TEKwdWLG9+MtbhKhBh8WNzQh
+7Nl/NzTgdCh0xDBoJDGG7zN7WDNQ1WGbaAkjDUJm6ty92zlpFkF4Gg2B1dl8WwYK
+LSSaMtj6/VV4CuhzFMg=
+-----END X509 CRL-----
+
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ipsec.conf freeswan-1.91/doc/pkix/examples/ipsec.conf
--- freeswan-1.91.orig/doc/pkix/examples/ipsec.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ipsec.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,60 @@
+# /etc/ipsec.conf - FreeS/WAN IPSEC configuration file
+
+# More elaborate and more varied sample configurations can be found
+# in doc/examples.
+
+# basic configuration
+config setup
+	# THIS SETTING MUST BE CORRECT or almost nothing will work;
+	# %defaultroute is okay for most simple cases.
+	interfaces=%defaultroute
+	# Debug-logging controls:  "none" for (almost) none, "all" for lots.
+	klipsdebug=none
+	#plutodebug=all
+	#plutodebug=crypt
+	plutodebug=none
+	# Use auto= parameters in conn descriptions to control startup actions.
+	plutoload=%search
+	plutostart=%search
+
+# defaults for subsequent connection descriptions
+conn %default
+	# How persistent to be in (re)keying negotiations (0 means very).
+	keyingtries=3
+	# Authentication by RSA signature keys
+	authby=rsasig
+
+#Standard connection types.
+#include /etc/ipsec/psk.conf
+#include /etc/ipsec/rsasig.conf
+#include /etc/ipsec/rsasig-rw.conf
+#
+# PKIX ########
+# LDAP lookups
+#include /etc/ipsec/ldap-rsasig.conf
+#include /etc/ipsec/ldap-rsasig-rw.conf
+#include /etc/ipsec/ldap-pk.conf
+include /etc/ipsec/ldap-pk-rw.conf
+#include /etc/ipsec/ldap-rpk.conf
+#include /etc/ipsec/ldap-rpk-rw.conf
+# dir lookups
+#include /etc/ipsec/dir-rsasig.conf
+#include /etc/ipsec/dir-rsasig-rw.conf
+#include /etc/ipsec/dir-pk.conf
+#include /etc/ipsec/dir-pk-rw.conf
+#include /etc/ipsec/dir-rpk.conf
+#include /etc/ipsec/dir-rpk-rw.conf
+# db lookups
+#include /etc/ipsec/db-rsasig.conf
+#include /etc/ipsec/db-rsasig-rw.conf
+#include /etc/ipsec/db-pk.conf
+#include /etc/ipsec/db-pk-rw.conf
+#include /etc/ipsec/db-rpk.conf
+#include /etc/ipsec/db-rpk-rw.conf
+# flatfile lookups
+#include /etc/ipsec/ff-rsasig.conf
+#include /etc/ipsec/ff-rsasig-rw.conf
+#include /etc/ipsec/ff-pk.conf
+#include /etc/ipsec/ff-pk-rw.conf
+#include /etc/ipsec/ff-rpk.conf
+#include /etc/ipsec/ff-rpk-rw.conf
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap-pk-rw.conf freeswan-1.91/doc/pkix/examples/ldap-pk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/ldap-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap-pk.conf freeswan-1.91/doc/pkix/examples/ldap-pk.conf
--- freeswan-1.91.orig/doc/pkix/examples/ldap-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap-rpk-rw.conf freeswan-1.91/doc/pkix/examples/ldap-rpk-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/ldap-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap-rpk.conf freeswan-1.91/doc/pkix/examples/ldap-rpk.conf
--- freeswan-1.91.orig/doc/pkix/examples/ldap-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap-rsasig-rw.conf freeswan-1.91/doc/pkix/examples/ldap-rsasig-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/ldap-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap-rsasig.conf freeswan-1.91/doc/pkix/examples/ldap-rsasig.conf
--- freeswan-1.91.orig/doc/pkix/examples/ldap-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/ldap.cnf freeswan-1.91/doc/pkix/examples/ldap.cnf
--- freeswan-1.91.orig/doc/pkix/examples/ldap.cnf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/ldap.cnf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,20 @@
+ldapdevel_host_name = 10.8.49.122
+ldapdevel_base = dc=netwinder,dc=org
+ldapdevel_filter:uid = (uid=%s)
+
+ldapdevel_attributes:*:crl = certificaterevocationlist, certificaterevocationlist;binary
+ldapdevel_filter:*:crl = (&(objectclass=certificationAuthority)(cn=CA))
+
+ldapdevel_filter:ca = (objectclass=certificationauthority)
+
+ldapdevel_filter:dns = (&(objectclass=hostRecord)(dNSRecord=%s))
+ldapdevel_attributes:dns = servercertificate, servercertificate;binary
+
+ldapdevel_filter:ip = (&(objectclass=hostRecord)(ipv4Address=%s))
+ldapdevel_attributes:ip = servercertificate, servercertificate;binary
+
+ldapdevel_filter:subject = (&(objectclass=hostRecord)(subject=%s))
+ldapdevel_attributes:subject = servercertificate, servercertificate;binary
+
+ldapdevel_filter:issuer = (&(objectclass=hostRecord)(issuer=%s))
+ldapdevel_attributes:issuer = servercertificate, servercertificate;binary
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/privkey.pem freeswan-1.91/doc/pkix/examples/privkey.pem
--- freeswan-1.91.orig/doc/pkix/examples/privkey.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/privkey.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQCoqQwsIfybAtb0mMfD3NGNMZH7ckGrCehSm741ddjw9rW6igzZ
+AptaqQ2Y5raPl0XrF+MQI8SQkfTtzP92/ZU9eqbEWbBFRfYLqckMd21eU9GHDVl5
+UPmUwWSOXuE4lK58f2heEFE975yf9CsIvOuas33FsiuYtO5UEmzapAVAnQIDAQAB
+AoGAXUzWvPs4IBAcFUcHCyR2j6LiXLTB+voKGNirCivdDL+NnFmN7eZxRl/Kc9D9
+IMXQGdMm+uCudkMnuPz0PUDeczQST46jiTlG5vkQdj3zpmz/x73t5I4E8vFSX6A4
+gKREFeGxSCEm0THNusBKk1Q+huHUDKw4mFh85MTopy32McECQQDVWcc3BMlDICG2
+6bFc3+1ieeVIKoD2GnJR7b/GU57umLFyDmSFwOkTTt7VWp3jV/81Oy+xBe3cC8Fm
+mFC/e45VAkEAymA9ke8XFduafs2Q+nsbfx4QI+f8lAd51pBR4A4J+W50JLO1/WqC
+PwOXwVPRCPyzHiY9B8L9KPrFKSwVedihKQJBAKnGCl/+wAVZcVqztf649pbRdyGp
+KPwt6WDGtz+j1Sn6eeHQEC/bZd2Geo3+0PtTT/NVCMtuc2wSMrFobYEiWg0CQQCl
+lf9qw5049jlAHYTNXiNObFO6fVuN51wKcoV7dSE2JOkFCsISuq4dTxxBRApadyE7
+vv/atPGdMSpXGMntq5GZAkEA1PJ0w4WSC3sW3guq4WzDLWqmbK2pOvC40ATZR67y
+lYC1okanKDsRam0remPY7xWZ8WACJx5KOIvYgXhX+dNXPg==
+-----END RSA PRIVATE KEY-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/psk.conf freeswan-1.91/doc/pkix/examples/psk.conf
--- freeswan-1.91.orig/doc/pkix/examples/psk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/psk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,9 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=psk
+	auto=add
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/pubcert.pem freeswan-1.91/doc/pkix/examples/pubcert.pem
--- freeswan-1.91.orig/doc/pkix/examples/pubcert.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/pubcert.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/rsasig-rw.conf freeswan-1.91/doc/pkix/examples/rsasig-rw.conf
--- freeswan-1.91.orig/doc/pkix/examples/rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,12 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	leftrsasigkey=0x010383adc0c40d031b8b51445074a015b6f6575221df37a23c597acafa7b588eccaeac2a705ca95c7062b7808849728a9083daf7e8f73335ecfdbfe18dda96b4c6b9c47cc695d1d9c20a92ce652cb0cd8b71af87cfb84d4ef5e02f13ef2233da2c98e5147b9092a5ef9f2789defb0b45d47570c1662bf8f159ae8e82107850184055
+	leftid="@arm1.netwinder.org"
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	rightrsasigkey=0x0103e39df4e5d9cdfb1bd781cc516b99053af9d39f97230e663ecdf77cb14764fcd7aadb274b2da2eaa6c8b7f3764e1b87a5ae5d9f7cafdad01dd95518da017794fcf7c86f435f7b7ce45429414d9c099ebb91d8a3f54514be78f9b801b02608e8299a5d19a3a4fa5510d0d318b692c649dc3b37287153852a9ac81891d140a38a0d
+	rightid="@arm-devel.netwinder.org"
+	authby=rsasig
+	auto=add
diff -BbruN freeswan-1.91.orig/doc/pkix/examples/rsasig.conf freeswan-1.91/doc/pkix/examples/rsasig.conf
--- freeswan-1.91.orig/doc/pkix/examples/rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/examples/rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,13 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	leftrsasigkey=0x010383adc0c40d031b8b51445074a015b6f6575221df37a23c597acafa7b588eccaeac2a705ca95c7062b7808849728a9083daf7e8f73335ecfdbfe18dda96b4c6b9c47cc695d1d9c20a92ce652cb0cd8b71af87cfb84d4ef5e02f13ef2233da2c98e5147b9092a5ef9f2789defb0b45d47570c1662bf8f159ae8e82107850184055
+	leftid="@arm1.netwinder.org"
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	rightrsasigkey=0x0103e39df4e5d9cdfb1bd781cc516b99053af9d39f97230e663ecdf77cb14764fcd7aadb274b2da2eaa6c8b7f3764e1b87a5ae5d9f7cafdad01dd95518da017794fcf7c86f435f7b7ce45429414d9c099ebb91d8a3f54514be78f9b801b02608e8299a5d19a3a4fa5510d0d318b692c649dc3b37287153852a9ac81891d140a38a0d
+	rightid="@arm-devel.netwinder.org"
+	authby=rsasig
+	auto=add
diff -BbruN freeswan-1.91.orig/doc/pkix/ldap-ca.quickstart freeswan-1.91/doc/pkix/ldap-ca.quickstart
--- freeswan-1.91.orig/doc/pkix/ldap-ca.quickstart	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/ldap-ca.quickstart	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,340 @@
+
+Quick commands and files based on how I set up my own LDAP CA.
+-- Luc Lanthier, 20001004
+-- revised: 20010301
+
+A more complete explanation can be found in the README.xmap file written
+by the original freeswan-pkix patch author, Neil Dunbar.
+
+Building and LDAP server is nothing simple. Easiest is installing the base 
+package or compiling it yourself. But after that, it's editing, creating, or
+modifying many configuration files or scripts.
+
+Here's a list of some of the config files or scripts you will encounter 
+in this document:
+  LDIF.sh
+  LDIF
+  slapd.oc-x509.conf
+  slapd.at-x509.conf
+  slapd.conf
+  regen-ldap_ca.sh
+  ldap.cnf
+  ipsec.conf
+  /etc/ipsec/*
+  /etc/rc.d/rc.local
+
+
+Your best bet is to following the LDAP documentation and use this document as
+a source of information, with examples.
+
+
+
+1A- Building openldap software:
+-----------------------------------------------------------------
+# The following containing version numbers is just an example.
+# If you compile from source, you can expect the config files to
+# be found in /usr/local/etc/openldap
+cd /usr/src
+tar xfvz openldap-stable-20000704.tgz 
+cd openldap-1.2.11
+./configure --enable-shared --with-gnu-ld --enable-ldapd 
+make depend
+make
+cd tests
+make
+cd ..
+make install
+
+1B- Installing openldap software from RPMs:
+-----------------------------------------------------------------
+Make sure the following are installed. Version numbers are merely a 
+suggestion.
+  openldap-1.2.9-6_nw1.armv4l.rpm
+  openldap-devel-1.2.9-6_nw1.armv4l.rpm
+The config files should be found under "/etc/openldap".
+
+
+
+2: Creating LDIF files:
+-----------------------------------------------------------------
+A LDIF file contains the information to add to the LDAP directory
+database in a simplified manner.
+
+Use your favorite editor and create an LDIF file that contains:
+            dn: dc=<MY-DOMAIN>, dc=<COM> 
+            objectclass: dcObject 
+            objectclass: organization 
+            o: <MY ORGANIZATION> 
+            dc: <MY-DOMAIN> 
+
+            dn: cn=Manager, dc=<MY-DOMAIN>, dc=<COM> 
+            objectclass: organizationalRole 
+            cn: Manager
+
+Now, you may run ldapadd(1) to insert these entries into your directory.
+            ldapadd -D "cn=Manager, dc=<MY-DOMAIN>, dc=<COM>" -W -f example.ldif
+
+
+Now we're ready to verify the added entries are in your directory. You 
+can use any LDAP client to do this, but our example uses the 
+ldapsearch(1) tool. Remember to replace dc=example,dc=com with the correct 
+values for your site:
+            ldapsearch -b 'dc=example,dc=com' '(objectclass=*)'
+
+-----------------------------------------------------------------
+
+
+3- How I created my own LDIF file
+-----------------------------------------------------------------
+Try to keep track of which certificate belongs to which host while
+creating the CA. The CA will only store the certificates in a 
+simplified naming format.
+ie: /usr/share/ssl/certs/01.pem
+
+If you forget, query the certificate, and look at the CN part of the 
+subject line. If created correctly, the CommonName will contain 
+the hostname.
+
+=========================
+[root@arm-devel ipsec]# openssl x509 -in /usr/share/ssl/certs/01.pem \
+	-noout -subject
+subject=/C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+=========================
+
+To save me time, I created a shell script much like the following to speed up
+the generation of LDIF files.
+----------- LDIF.sh:
+#!/usr/bin/bash
+
+function openssl_out ()
+{
+  openssl x509 -in $1 -inform PEM -outform DER | \
+    ldif -b servercertificate 
+  openssl x509 -in $1 -noout -subject | \
+    sed -e 's/^subject=/subject: /'
+  openssl x509 -in $1 -noout -issuer | \
+    sed -e 's/^issuer=/issuer: /'
+}
+
+###### First, create entries for manager and CA.
+cat <<EOM
+dn: dc=netwinder, dc=org
+objectclass: dcObject 
+objectclass: organization 
+o: Rebel.com
+dc: SoftEng
+
+dn: cn=Manager, dc=netwinder, dc=org
+objectclass: organizationalRole 
+cn: Manager
+
+dn: cn=CA, dc=netwinder, dc=org
+cn: CA
+objectclass: certificationAuthority
+EOM
+
+# the crl and the certs HAVE to be in DER format.
+openssl crl -in /var/lib/ssl/crl.pem -inform PEM -outform DER | \
+	ldif -b certificationrevocationlist 
+openssl x509 -in /var/lib/ssl/cacert.pem -inform PEM -outform DER | \
+	ldif -b cACertificate 
+echo
+############################
+## Good! Now that the entry for the CA's done, let's create an entry for it,
+## as a host. (hostRecord)
+############################
+
+cat <<EOM
+dn: cn=phoenix, dc=netwinder, dc=org
+cn: phoenix
+objectclass: hostRecord
+ipv4Address: 10.8.49.100
+EOM
+openssl_out /var/lib/ssl/cacert.pem
+echo "dNSRecord: phoenix.netwinder.org"
+echo
+
+###########################################
+## now we create entries for the hosts.
+###########################################
+cat <<EOM
+dn: cn=sticky, dc=netwinder, dc=org
+cn: sticky
+objectclass: hostRecord
+ipv4Address: 10.1.49.233
+EOM
+openssl_out /var/lib/ssl/certs/01.pem
+echo "dNSRecord: sticky.netwinder.org"
+echo
+####################################
+
+cat <<EOM
+dn: cn=x86rack1, dc=netwinder, dc=org
+cn: x86rack1
+objectclass: hostRecord
+ipv4Address: 10.8.49.101
+EOM
+
+openssl_out /var/lib/ssl/certs/08.pem
+echo "dNSRecord: x86rack1.netwinder.org"
+echo
+#######################
+# etc..
+-----------------------------------------------------------------
+
+
+
+4- Additional files to set up:
+Use your better judgement and be aware of paths, domains, etc.
+
+----------- Create: /usr/local/etc/openldap/slapd.oc-x509.conf 
+==========================================
+objectclass hostRecord
+	requires
+		objectClass
+	allows
+		dNSRecord,
+		ipv4Address,
+		servercertificate,
+		subject
+==========================================
+
+------------ Create: /usr/local/etc/openldap/slapd.at-x509.conf 
+==========================================
+attribute	servercertificate			bin
+==========================================
+
+------------ Edit: /usr/local/etc/openldap/slapd.conf 
+==========================================
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include		/usr/local/etc/openldap/slapd.at.conf
+include		/usr/local/etc/openldap/slapd.oc.conf
+schemacheck	off
+#referral	ldap://root.openldap.org/
+
+pidfile		/usr/local/var/slapd.pid
+argsfile	/usr/local/var/slapd.args
+
+#################
+# x509
+include		/usr/local/etc/openldap/slapd.at-x509.conf
+include		/usr/local/etc/openldap/slapd.oc-x509.conf
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+database	ldbm
+suffix		"dc=netwinder, dc=org"
+#suffix		"o=My Organization Name, c=US"
+rootdn		"cn=Manager, dc=netwinder, dc=org"
+#rootdn		"cn=Manager, o=My Organization Name, c=US"
+# cleartext passwords, especially for the rootdn, should
+# be avoid.  See slapd.conf(5) for details.
+rootpw		ipsecsecret
+# database directory
+# this directory MUST exist prior to running slapd AND
+# should only be accessable by the slapd/tools  Mode 700 recommended.
+#directory	/usr/local/var/openldap-ldbm
+directory	/var/lib/ssl/ldap-ldbm
+
+index default pres,eq
+index objectClass,uid
+index cn,sn eq,sub,approx
+==========================================
+-----------------------------------------------------------------
+
+
+
+5- How I regen'd my ldap DB:
+-----------------------------------------------------------------
+I created a shell script which stops the LDAP daemon, deletes the 
+LDAP dir, and recreates it from scratch reusing my LDIF.sh script.
+You can manage your LDAP dir any which way you want, but that's just
+how I decided to attack this problem.
+Make the file executable and place it in a reachable path.. maybe 
+'/usr/local/bin'?
+Don't forget to doublecheck filepaths and domains used in the file.
+It's just a template.
+-- regen-ldap_ca.sh ---------------------------------------------
+#!/bin/sh
+cd /usr/share/ssl/
+mkdir -p ldap-ldbm
+killall slapd
+rm -f ldap-ldbm/*
+LDIF.sh > LDIF
+ldif2ldbm -i LDIF
+slapd -s 1
+-----------------------------------------------------------------
+
+
+6- How I access the ldap DB from freeswan, the config files:
+-----------------------------------------------------------------
+The following file is used by FreeSWAN's pkix ldap lookup. 
+"ldapnd" in the front of each name is the name of the server the lookup
+is done on. If you wish to access 2 or more different ldap servers, just 
+copy the entire section a second time, while using the new header name.
+Keep in mind to change the domain and server hostname IP address.
+-- /etc/ipsec/ldap.cnf ------------------------------------------
+ldapnd_host_name = 10.8.49.100
+ldapnd_base = dc=netwinder,dc=org
+ldapnd_filter:uid = (uid=%s)
+
+ldapnd_attributes:*:crl = certificaterevocationlist, certificaterevocationlist;binary
+ldapnd_filter:*:crl = (&(objectclass=certificationAuthority)(cn=CA))
+
+ldapnd_filter:ca = (objectclass=certificationauthority)
+
+ldapnd_filter:dns = (&(objectclass=hostRecord)(dNSRecord=%s))
+ldapnd_attributes:dns = servercertificate, servercertificate;binary
+
+ldapnd_filter:ip = (&(objectclass=hostRecord)(ipv4Address=%s))
+ldapnd_attributes:ip = servercertificate, servercertificate;binary
+
+ldapnd_filter:subject = (&(objectclass=hostRecord)(subject=%s))
+ldapnd_attributes:subject = servercertificate, servercertificate;binary
+
+ldapnd_filter:issuer = (&(objectclass=hostRecord)(issuer=%s))
+ldapnd_attributes:issuer = servercertificate, servercertificate;binary
+-----------------------------------------------------------------
+
+The following is an example config entry for freeswan to use. You
+can either enter these settings in '/etc/ipsec.conf', or create
+a separate file with these settings to use. '/etc/ipsec.conf' can load
+separate files with 'include <path_and_filename>' commands.
+-- freeswan config ----------------------------------------------
+conn test_host-host
+	left=10.1.49.233
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.firewall
+	right=10.8.49.101
+	rightupdown=/usr/lib/ipsec/updown.firewall
+	rightnexthop=10.8.54.1
+	auto=add
+	authby=cert
+	# certfile: full path to private key
+	certfile=/etc/ipsec/pubcert.pem
+	# keyfile: full path to public key in unencrypted format
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapnd
+	certopts=send,pk,rev
+	#The certificate are found using IKE's ID_DER_ASN1_DN ID payload
+	#You can provide the info by running:
+	#  ipsec fswcert -d a -l /etc/ipsec/[hostleft].pem
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=x86eng/CN=Luc Lanthier/Email=firesoul@netwinder.org
+	leftid=@~308182310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D310F300D060355040B1306783836656E67311530130603550403130C4C7563204C616E74686965723125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
+	#  ipsec fswcert -d a -l /etc/ipsec/[hostright].pem
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SE/CN=Luc Lanthier/Email=firesoul@pet.notbsd.org
+	rightid=@~307F310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D310B3009060355040B13025345311530130603550403130C4C7563204C616E74686965723126302406092A864886F70D010901161766697265736F756C407065742E6E6F746273642E6F7267
+-----------------------------------------------------------------
+
+The certificate are found using IKE's ID_DER_ASN1_DN ID payload
+You can provide the info by running on each respective host:
+-----------------------------------------------------------------
+ipsec fswcert -d a -l /etc/ipsec/[hostleft].pem
+ipsec fswcert -d a -r /etc/ipsec/[hostright].pem
+
+
diff -BbruN freeswan-1.91.orig/doc/pkix/openssl-ca.quickstart freeswan-1.91/doc/pkix/openssl-ca.quickstart
--- freeswan-1.91.orig/doc/pkix/openssl-ca.quickstart	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/openssl-ca.quickstart	Mon Jun 18 16:35:38 2001
@@ -0,0 +1,268 @@
+This document is much like a quickstart, but in an even shorter form.
+These are the steps I took to create an opensourced CA capable of signing 
+certificates.
+
+How I set up a CA on RedHat 6.2 and used it:
+
+
+1- install openssl on the CA. 
+If the openssl package is already installed, then ignore this 
+section. Please note: requires 0.9.5a. I doubt FreeSWAN will
+run with openssl 0.9.6.
+----------------------------------------------------------------
+cd /usr/src/redhat/SRPMS
+scp root@10.8.49.101:/usr/src/redhat/SRPMS/openssl*.src.rpm .
+rpm --rebuild openssl-0.9.5a-1.src.rpm
+cd ../RPMS/i386/
+rpm -i openssl-*
+
+
+2- Setting up the openssl CA.
+The openssl RPM already create a /var/lib/ssl directory. If you installed
+openssl from source, look for it in either /usr/ssl, /usr/local/ssl,
+or even /usr/share/ssl.
+----------------------------------------------------------------
+cd /var/lib/ssl
+# Note! Newer redhat openssl RPMs created the dir in /usr/share/ssl
+
+# will simplify finding global conf files.
+ln -s /etc etc 
+
+# see README.certificates, section 4.1, for instructions
+# on the creation/addition of openssl.cnf 
+# Note! Since Redhat redid its openssl packages, openssl.cnf is present.
+# Use it instead.
+vi /etc/openssl.cnf
+
+# see README.certificates, section 4.1, for instructions
+# on the CA extensions to define in ca.ext
+vi ca.ext 
+
+openssl req -new -newkey rsa:1024 -keyout \
+	private/cakey.pem -out careq.pem
+# Please enter in a password to be able to use the CA's signing cert once 
+# it is generated. Only that password will unlock it for use.
+# Data may be asked of you to enter.
+# ____________________________________________________________________
+# --- Country Name (2 letter code) [AU]:
+# --- State or Province Name (full name) [Some-State]:
+# --- Locality Name (eg, city) []:
+# **important** The OrgName must match on ALL certs which will be signed
+# by this self-signed cert.
+#   --- Organization Name (eg, company) [Internet Widgits Pty Ltd]:
+# --- Organizational Unit Name (eg, section) []:
+# **Note** Try to use the machine's FQDN as common name. Not your own
+# name. :
+#   --- Common Name (eg, your name or your server's hostname) []:
+# --- Email Address []:
+# ____________________________________________________________________
+#
+# Unimportant:
+# Please enter the following 'extra' attributes
+# to be sent with your certificate request
+# A challenge password []:
+# An optional company name []:
+
+# sign our own CA certificate.
+openssl x509 -CAcreateserial -signkey private/cakey.pem -req \
+	-in careq.pem -out cacert.pem -days 2000 -extfile ca.ext
+
+touch index.txt
+echo "01" > serial
+openssl ca -gencrl -out crl.pem; # distribute/make available to all hosts.
+
+
+3- adding cacert.pem and crl.pem to hosts (OPTIONAL)
+Unless you are using LDAP lookup, you will have to make the certificate
+available on all the client hosts. Of course, make sure the destination 
+directory exists.
+----------------------------------------------------------------
+scp crl.pem 10.1.49.233:/etc/ipsec
+scp cacert.pem 10.1.49.233:/etc/ipsec
+scp crl.pem 10.8.49.101:/etc/ipsec
+scp cacert.pem 10.8.49.101:/etc/ipsec
+
+
+4- Each client host -- generate certificate requests.
+The CA's signing certificate is ready. Now we can create the client
+certificates. 
+NOTE: a CA can also be its own client if a separate certificate
+is generated. Both the cacert.pem and the host certificates must be
+made available as standard host certificates, as if they were 2 separate
+hosts.
+----------------------------------------------------------------
+mkdir -p /etc/ipsec
+cd /etc/ipsec
+
+# Make sure the info entered for the "CommonName" for each client 
+#   is DIFFERENT, usually containing the hostname.
+# Make sure the "OrgName" used is the same as the one used 
+#   for cacert.pem's creation.
+# Make sure you don't create this certificate with a password.
+#  This certificate must be available for use without user intervention.
+#  (that includes password entry)
+openssl req -new -newkey rsa:1024 -nodes -keyout \
+	`hostname`.key -out `hostname`.req.pem
+############################
+# OR DSA: (still unsupported. left note in to remember how to do it)
+# openssl dsaparam 1024 -out dsa_params.txt
+# chmod 400 dsa_params.txt
+#openssl req -new -newkey dsa:dsa_params.txt -nodes -keyout \
+#        /etc/ipsec/`hostname`.key -out /etc/ipsec/`hostname`.req.pem
+#remember that all parties must use DSA
+############################
+
+# how about a generic name on each host for ease?
+ln -fs `hostname`.key privkey.pem
+ln -fs `hostname`.pem pubcert.pem; # will be created soon.
+
+# protect the private key.
+chmod 400 `hostname`.key
+
+
+
+5- Signing certificates on the CA host
+Signing the certificates is a necessary step in the pkix CA setup,
+but first, you must give your CA the ability.
+You may find the signIPSEC script handy.
+----------------------------------------------------------------
+###########################
+# Create/Undate the following ONCE.
+# Once again, note the paths may be wrong.
+vi /etc/openssl.cnf; # (see README.certificates section 4.6)
+
+# Either create signIPSEC, or copy it from the current directory.
+#   to /usr/local/bin on the CA host.
+vi /usr/local/bin/signIPSEC; # (see README.certificates section 4.6)
+
+chmod 700 /usr/local/bin/signIPSEC
+# use: signIPSEC foo.mydomain.com 192.168.1.5 foo.req
+
+# Once again, CD to the correct path.
+cd /var/lib/ssl/
+mkdir -p newcerts
+
+# The following steps can be reused over and over, for each host to add
+#
+# 1- copy over the unsigned public cert from the host.
+scp root@10.1.49.233:/etc/ipsec/*.req.pem .
+#
+# 2- sign it with the correct values.
+signIPSEC sticky.netwinder.org 10.1.49.233 sticky.req.pem
+#
+# 3- copy the newly signed certificate to the host.
+scp newcerts/`cat serial.old`.pem root@10.1.49.233:/etc/ipsec/sticky.pem
+#
+# 4- rehash the current database of certificates handled by the CA.
+mv newcerts/* certs/
+c_rehash certs
+
+
+
+6- CA host: prepping flat file for client hosts
+Here's a short script for quick generations of text flatfiles needed
+by the various clients. LDAP lookup is prefered, but flatfile is available
+for testing or simplicity.
+The script is available as "CA-regenerate-flatfile.sh".
+----------------------------------------------------------------
+#!/bin/sh -x
+
+if [ -d /var/lib/ssl ]; then
+  cd /var/lib/ssl
+elif [ -d /usr/lib/ssl ]; then
+  cd /usr/lib/ssl
+elif [ -d /usr/local/lib/ssl ]; then
+  cd /usr/local/lib/ssl
+elif [ -d /usr/share/ssl ]; then
+  cd /usr/share/ssl
+else
+  echo "ERROR: Cannot determine location of ssl directory."
+  exit 1
+fi
+
+cat /dev/null > flatfile.txt
+
+for ii in certs/*.pem cacert.pem crl.pem;
+do
+  if [ "`basename $ii`" != "crl.pem" ] && [ "`basename $ii`" != "cacert.pem" ];
+  then
+    perl -e "open(IN, \"openssl x509 -in $ii -noout -text \|\"); \
+      @IN = <IN>; \
+      foreach (@IN) { \
+        if (/IP Address:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/) { \
+          print \"ip: \$1\\n\"; \
+        } \
+        if (/DNS:([^, ]*).*$/) { \
+          print \"dns: \$1\\n\"; \
+        } \
+      };" >> flatfile.txt
+  fi
+  cat $ii | \
+  perl -e '$printme = 0; while (<>) { if (/---BEGIN/) {$printme = 1;}; if ($printme) {print STDOUT $_;} }; print STDOUT "\n";' \
+  >> flatfile.txt
+done
+----------------------------------------------------------------
+
+# the flatfile is created. Send to Client hosts.
+scp flatfile.txt root@10.1.49.233:/etc/ipsec
+scp flatfile.txt root@10.8.49.101:/etc/ipsec
+
+
+
+7- revoking a certificate
+Sometimes it becomes necessary to revoke a certificate. 
+----------------------------------------------------------------
+# First, find out which certificate has to be revoked. If properly
+# generated, the CommonName (CN) will be the certificate's owner 
+# hostname. Replace "WANTED_HOSTNAME" by the hostname to look for.
+cd /var/lib/ssl/
+(
+for certs in certs/*.pem; do 
+  echo -n "$certs: " 
+  openssl x509 -in $certs -noout -subject
+done
+) | grep WANTED_HOSTNAME
+
+# Example output:
+# 02.pem: subject=/C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+
+# next, proceed to revoke the certificate.
+# once again, double-check the paths.
+openssl ca -revoke /var/lib/ssl/certs/02.pem 
+openssl ca -gencrl -out /var/lib/ssl/crl.pem
+
+# If we're using LDAP, the new crl.pem will be used automatically.
+# Otherwise, it has to be copied to each one of the client hosts.
+scp crl.pem root@10.1.49.233:/etc/ipsec
+scp crl.pem root@10.8.49.101:/etc/ipsec
+
+
+8- converting to and from PKCS#7 enveloped certificates
+
+  From PKCS7 in PEM format to certificates:
+    openssl pkcs7 -in x86rack1.pk7 -print_certs -inform PEM
+  From PKCS7 in DER format to certificates:
+    openssl pkcs7 -in x86rack1.pk7 -print_certs -inform DER
+
+  From certificate (with available CRL) to DER PKCS7:
+    openssl crl2pkcs7 -in dir/crl.pem -certfile x86rack1.pem -outform DER \
+      -out x86rack1.pk7
+  From certificate (no crl) to DER PKCS7:
+    openssl crl2pkcs7 -nocrl -certfile x86rack1.pem -outform DER \
+      -out x86rack1.pk7
+
+Sending with CRL gives an idea what your CA is from the other end's 
+perspective. Using that info, cross referencing can occur and a
+connection be established despite being registered on different CAs.
+
+
+9- converting to and from PKCS#12 "bag"s.
+
+  Extracting private key from PKCS12 in DER format:
+    openssl pkcs12 -in x86rack1.p12 -nocerts -out x86rack1.key
+  Extracting public certificate(s) from PKCS12 in DER format:
+    openssl pkcs12 -in x86rack1.p12 -nokeys -out x86rack1.pem
+
+  Creating a PKCS12 file:
+    openssl pkcs12 -export -in x86rack1.pem -inkey x86rack1.key  \
+      -des3 -name "my pkcs12" -out x86rack1.p12
diff -BbruN freeswan-1.91.orig/doc/pkix/signIPSEC freeswan-1.91/doc/pkix/signIPSEC
--- freeswan-1.91.orig/doc/pkix/signIPSEC	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/doc/pkix/signIPSEC	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Simple wrapper for "openssl ca" that sets environment to pass in
+# values for the svr_cert extension
+# P.J.Onion  23/9/1999
+# updated by: Luc Lanthier   20010214
+if [ -d /var/lib/ssl ]; then
+  SSLDIR="/var/lib/ssl";
+elif [ -d /usr/lib/ssl ]; then
+  SSLDIR="/usr/lib/ssl";
+elif [ -d /usr/local/lib/ssl ]; then
+  SSLDIR="/usr/local/lib/ssl";
+elif [ -d /usr/share/ssl ]; then
+  SSLDIR="/usr/share/ssl";
+else
+  echo "ERROR: Cannot determine location of ssl directory."
+  exit 1
+fi
+
+
+if test $# -ne 3 ; then
+        echo "Usage: $0 hostname ipaddress reqfile"
+        exit 1
+fi
+
+
+HOSTFQDN=$1
+HOSTIP=$2
+NSCOMMENT="IPsec Certificate for $1"
+EXTENSION=svr_cert
+
+export HOSTFQDN HOSTIP NSCOMMENT EXTENSION
+if (which openssl &> /dev/null) ; then
+  openssl ca -in $3
+else
+  echo "ERROR: Cannot locate/execute openssl binary."
+  exit 1
+fi
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/Config.in freeswan-1.91/klips/net/ipsec/Config.in
--- freeswan-1.91.orig/klips/net/ipsec/Config.in	Thu Jun 14 15:35:07 2001
+++ freeswan-1.91/klips/net/ipsec/Config.in	Mon Jul  2 20:30:27 2001
@@ -27,6 +27,7 @@
 bool '   IPSEC: Encapsulating Security Payload' CONFIG_IPSEC_ESP
 if [ "$CONFIG_IPSEC_ESP" = "y" ]; then
   bool '      3DES encryption algorithm' CONFIG_IPSEC_ENC_3DES
+  bool '      DES encryption algorithm' CONFIG_IPSEC_ENC_DES
 fi
 
 bool '   IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/Makefile freeswan-1.91/klips/net/ipsec/Makefile
--- freeswan-1.91.orig/klips/net/ipsec/Makefile	Thu Jun 14 15:35:07 2001
+++ freeswan-1.91/klips/net/ipsec/Makefile	Mon Jul  2 20:31:23 2001
@@ -57,6 +57,7 @@
 EXTRA_CFLAGS += -Wbad-function-cast 
 
 obj-$(CONFIG_IPSEC_ENC_3DES) += libdes/libdes.a
+obj-$(CONFIG_IPSEC_ENC_DES) += libdes/libdes.a
 obj-$(CONFIG_IPSEC_AUTH_HMAC_MD5) += ipsec_md5c.o
 obj-$(CONFIG_IPSEC_AUTH_HMAC_SHA1) += ipsec_sha1.o
 obj-$(CONFIG_IPSEC_IPCOMP) += ipcomp.o zlib/zlib.a
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/defconfig freeswan-1.91/klips/net/ipsec/defconfig
--- freeswan-1.91.orig/klips/net/ipsec/defconfig	Thu Nov 30 12:26:56 2000
+++ freeswan-1.91/klips/net/ipsec/defconfig	Mon Jul  2 20:31:39 2001
@@ -43,6 +43,7 @@
 
 # Encryption algorithm(s):
 CONFIG_IPSEC_ENC_3DES=y
+CONFIG_IPSEC_ENC_DES=y
 
 # IP Compression: new, probably still has minor bugs.
 CONFIG_IPSEC_IPCOMP=y
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/ipsec_esp.h freeswan-1.91/klips/net/ipsec/ipsec_esp.h
--- freeswan-1.91.orig/klips/net/ipsec/ipsec_esp.h	Thu Jun 14 15:35:08 2001
+++ freeswan-1.91/klips/net/ipsec/ipsec_esp.h	Mon Jul  2 20:37:04 2001
@@ -40,6 +40,27 @@
 #define DB_ES_OH	0x0400
 #define DB_ES_REPLAY	0x0800
 
+struct espdesold_xdata
+{
+       int     edx_ivlen;              /* 4 or 8 */
+       union
+       {
+               __u8    Iv[8];          /* that's enough space */
+               __u32   Ivl[2];
+               __u64   Ivq;
+       }Iu;
+#define edx_iv Iu.Iv
+#define edx_ivl Iu.Ivl
+#define edx_ivq Iu.Ivq
+       union
+       {
+               __u8 Rk[8];
+               __u32 Eks[16][2];
+       }Xu;
+#define edx_rk Xu.Rk
+#define edx_eks        Xu.Eks
+};
+
 struct espblkrply_edata
 {
 	__u16	eme_klen;		/* encryption key length */
@@ -64,6 +85,19 @@
 };
 
 #ifdef __KERNEL__
+struct espdesmd5_xdata
+{
+       __u8    edmx_flags;             /* same as before */
+       __u8    edmx_ooowin;            /* out-of-order window size */
+       __u16   edmx_ivlen;             /* IV length */
+       __u32   edmx_bitmap;            /* this&next should be 4 bytes each */
+       __u32   edmx_lastseq;           /* in host order */
+       __u32   edmx_eks[16][2];        /* the key schedule */
+       __u32   edmx_iv[2];             /* constant IV */
+       MD5_CTX edmx_ictx;              /* derived from HMAC_key */
+       MD5_CTX edmx_octx;              /* ditto */
+};
+
 struct esp3desmd5_xdata
 {
 	__u8	edmx_flags;		/* same as before */
@@ -89,6 +123,19 @@
 	MD5_CTX edmx_octx;		/* ditto */
 };
 
+struct espdessha1_xdata
+{
+       __u8    edmx_flags;             /* same as before */
+       __u8    edmx_ooowin;            /* out-of-order window size */
+       __u16   edmx_ivlen;             /* IV length */
+       __u32   edmx_bitmap;            /* this&next should be 4 bytes each */
+       __u32   edmx_lastseq;           /* in host order */
+       __u32   edmx_eks[16][2];        /* the key schedule */
+       __u32   edmx_iv[2];             /* constant IV */
+       SHA1_CTX edmx_ictx;             /* derived from HMAC_key */
+       SHA1_CTX edmx_octx;             /* ditto */
+};
+
 struct esp3dessha1_xdata
 {
 	__u8	edmx_flags;		/* same as before */
@@ -112,6 +159,17 @@
 	__u32	edmx_lastseq;		/* in host order */
 	SHA1_CTX edmx_ictx;		/* derived from HMAC_key */
 	SHA1_CTX edmx_octx;		/* ditto */
+};
+
+struct espdes_xdata
+{
+       __u8    edmx_flags;             /* same as before */
+       __u8    edmx_ooowin;            /* out-of-order window size */
+       __u16   edmx_ivlen;             /* IV length */
+       __u32   edmx_bitmap;            /* this&next should be 4 bytes each */
+       __u32   edmx_lastseq;           /* in host order */
+       __u32   edmx_eks[16][2];        /* the key schedule */
+       __u32   edmx_iv[2];             /* constant IV */
 };
 
 struct esp3des_xdata
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/ipsec_rcv.c freeswan-1.91/klips/net/ipsec/ipsec_rcv.c
--- freeswan-1.91.orig/klips/net/ipsec/ipsec_rcv.c	Wed Jun 13 16:58:40 2001
+++ freeswan-1.91/klips/net/ipsec/ipsec_rcv.c	Mon Jul  2 20:42:15 2001
@@ -77,6 +77,7 @@
 int sysctl_ipsec_inbound_policy_check = 1;
 
 #ifdef CONFIG_IPSEC_ESP
+extern void des_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, int);
 extern void des_ede3_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, caddr_t, caddr_t, int);
 #endif /* !CONFIG_IPSEC_ESP */
 #if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
@@ -1026,6 +1027,7 @@
 #ifdef CONFIG_IPSEC_ESP
 		case IPPROTO_ESP:
 			switch(tdbp->tdb_encalg) {
+			case ESP_DES:
 			case ESP_3DES:
 				iv[0] = *((__u32 *)(espp->esp_iv)    );
 				iv[1] = *((__u32 *)(espp->esp_iv) + 1);
@@ -1043,6 +1045,23 @@
 			ilen -= esphlen;
 			
 			switch(tdbp->tdb_encalg) {
+                       case ESP_DES:
+                               if ((ilen) % 8) {
+                                       tdbp->tdb_encsize_errs += 1;
+                                       spin_unlock(&tdb_lock);
+                                       printk("klips_error:ipsec_rcv: "
+                                              "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",
+                                              ilen,
+                                              ipaddr_txt);
+                                       if(stats) {
+                                               stats->rx_errors++;
+                                       }
+                                       goto rcvleave;
+                               }
+                               des_cbc_encrypt(idat, idat, ilen,
+                                                    tdbp->tdb_key_e,
+                                                    (caddr_t)iv, 0);
+                               break;
 			case ESP_3DES:
 				if ((ilen) % 8) {
 					tdbp->tdb_encsize_errs += 1;
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/ipsec_tunnel.c freeswan-1.91/klips/net/ipsec/ipsec_tunnel.c
--- freeswan-1.91.orig/klips/net/ipsec/ipsec_tunnel.c	Thu Jun 14 15:35:10 2001
+++ freeswan-1.91/klips/net/ipsec/ipsec_tunnel.c	Mon Jul  2 20:48:51 2001
@@ -103,6 +103,7 @@
 #ifdef MSS_HACK
 #include <net/tcp.h>		/* TCP options */
 #endif	/* MSS_HACK */
+extern void des_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, int);
 extern void des_ede3_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, caddr_t, caddr_t, int);
 static __u32 zeroes[64];
 
@@ -1065,6 +1066,11 @@
 #ifdef CONFIG_IPSEC_ESP
 			case IPPROTO_ESP:
 				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+					headroom += sizeof(struct esp);
+					break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 					headroom += sizeof(struct esp);
@@ -1350,6 +1356,11 @@
 #ifdef CONFIG_IPSEC_ESP
 			case IPPROTO_ESP:
 				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+					headroom += sizeof(struct esp);
+					break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 					headroom += sizeof(struct esp);
@@ -1447,6 +1458,16 @@
 				espp->esp_rpl = htonl(++(tdbp->tdb_replaywin_lastseq));
 				
 				switch(tdbp->tdb_encalg) {
+#if defined(CONFIG_IPSEC_ENC_DES)
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+#endif /* CONFIG_IPSEC_ENC_DES */
+					iv[0] = *((__u32*)&(espp->esp_iv)    ) =
+						((__u32*)(tdbp->tdb_iv))[0];
+					iv[1] = *((__u32*)&(espp->esp_iv) + 1) =
+						((__u32*)(tdbp->tdb_iv))[1];
+					break;
+#endif /* defined(CONFIG_IPSEC_ENC_DES) */
 #if defined(CONFIG_IPSEC_ENC_3DES)
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
@@ -1478,6 +1499,13 @@
 				iph->protocol = IPPROTO_ESP;
 				
 				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+					des_cbc_encrypt(idat, idat, ilen,
+							     (caddr_t)tdbp->tdb_key_e,
+							     (caddr_t)iv, 1);
+					break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 					des_ede3_cbc_encrypt(idat, idat, ilen,
@@ -1494,6 +1522,17 @@
 				}
 				
 				switch(tdbp->tdb_encalg) {
+#if defined(CONFIG_IPSEC_ENC_DES)
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+#endif /* CONFIG_IPSEC_ENC_DES */
+					/* XXX update IV with the last 8 octets of the encryption */
+					((__u32*)(tdbp->tdb_iv))[0] =
+						((__u32 *)(idat))[(ilen >> 2) - 2];
+					((__u32*)(tdbp->tdb_iv))[1] =
+						((__u32 *)(idat))[(ilen >> 2) - 1];
+					break;
+#endif /* defined(CONFIG_IPSEC_ENC_DES) */
 #if defined(CONFIG_IPSEC_ENC_3DES)
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/ipsec_xform.c freeswan-1.91/klips/net/ipsec/ipsec_xform.c
--- freeswan-1.91.orig/klips/net/ipsec/ipsec_xform.c	Thu Jun 14 15:35:11 2001
+++ freeswan-1.91/klips/net/ipsec/ipsec_xform.c	Tue Jul  3 01:24:29 2001
@@ -69,6 +69,9 @@
 { XF_IP4,		0,		"IPv4_Encapsulation"},
 { XF_AHHMACMD5,		XFT_AUTH,	"HMAC_MD5_Authentication"},
 { XF_AHHMACSHA1,	XFT_AUTH,	"HMAC_SHA-1_Authentication"},
+{ XF_ESPDES,           XFT_CONF,       "DES_Encryption"},
+{ XF_ESPDESMD596,      XFT_CONF,       "DES-MD5-96_Encryption"},
+{ XF_ESPDESSHA196,     XFT_CONF,       "DES-SHA1-96_Encryption"},
 { XF_ESP3DES,		XFT_CONF,	"3DES_Encryption"},
 { XF_ESP3DESMD596,	XFT_CONF,	"3DES-MD5-96_Encryption"},
 { XF_ESP3DESSHA196,	XFT_CONF,	"3DES-SHA1-96_Encryption"},
@@ -313,9 +316,9 @@
 	struct xformsw *xsp;
 	int error = 0;
         int i;
-#if defined(CONFIG_IPSEC_ENC_3DES)
+#if defined(CONFIG_IPSEC_ENC_DES) || if defined(CONFIG_IPSEC_ENC_3DES)
         int error;
-#endif /* CONFIG_IPSEC_ENC_3DES */
+#endif /* CONFIG_IPSEC_ENC_{3,}DES */
 
         char sa[SATOA_BUF];
         size_t sa_len;
@@ -568,6 +571,16 @@
 #endif /* CONFIG_IPSEC_AH */
 
 #ifdef CONFIG_IPSEC_ESP
+#ifdef CONFIG_IPSEC_ENC_DES
+                       case XF_ESPDES:
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+                       case XF_ESPDESMD596:
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+                       case XF_ESPDESSHA196:
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+#endif /* CONFIG_IPSEC_ENC_DES */
+
 #ifdef CONFIG_IPSEC_ENC_3DES
 			case XF_ESP3DES:
 #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
@@ -607,6 +620,10 @@
 				case XF_ESP3DES:
 				case XF_ESP3DESMD596:
 				case XF_ESP3DESSHA196:
+				case XF_ESPDES:
+				case XF_ESPDESMD596:
+				case XF_ESPDESSHA196:
+
 					if((tdbp->tdb_iv = (caddr_t)
 					   kmalloc((tdbp->tdb_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) {
 						SENDERR(ENOMEM);
@@ -618,6 +635,44 @@
 				}
 
 				switch(alg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+                               case XF_ESPDES:
+                               case XF_ESPDESMD596:
+                               case XF_ESPDESSHA196:
+                                       tdbp->tdb_encalg = ESP_DES;
+                               
+                                       if (ed->eme_klen != EMT_ESPDES_KEY_SZ) {
+                                               KLIPS_PRINT(debug_esp,
+                                                           "klips_debug:tdb_init: "
+                                                           "incorrect encryption key size: %d -- must be %d octets (bytes)\n",
+                                                           ed->eme_klen, EMT_ESPDES_KEY_SZ);
+                                               SENDERR(EINVAL);
+                                       }
+
+                                       tdbp->tdb_key_bits_e = ed->eme_klen;
+
+                                       if((tdbp->tdb_key_e = (caddr_t)
+                                          kmalloc((tdbp->tdb_key_e_size = sizeof(struct des_eks)),
+                                                  GFP_ATOMIC)) == NULL) {
+                                               SENDERR(ENOMEM);
+                                       }
+
+                                               error = des_set_key((caddr_t)(ed->eme_key),
+                                                                   (caddr_t)&((struct des_eks*)(tdbp->tdb_key_e)));
+                                               if (error == -1)
+                                                       printk("klips_debug:tdb_init: "
+                                                              "parity error in des key\n");
+                                               else if (error == -2)
+                                                       printk("klips_debug:tdb_init: "
+                                                              "illegal weak des key\n");
+                                               if (error) {
+                                                       memset(tdbp->tdb_key_e, 0, sizeof(struct des_eks));
+                                                       kfree(tdbp->tdb_key_e);
+                                                       SENDERR(EINVAL);
+                                               }
+
+                                       break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case XF_ESP3DES:
 				case XF_ESP3DESMD596:
@@ -672,6 +727,7 @@
 
 				switch(alg) {
 #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				case XF_ESPDESMD596:
 				case XF_ESP3DESMD596:
 				case XF_ESPNULLMD596:
 				{
@@ -748,6 +804,7 @@
 #ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
 				case XF_ESPNULLSHA196:
 				case XF_ESP3DESSHA196:
+				case XF_ESPDESSHA196:
 				{
 					SHA1_CTX *ictx;
 					SHA1_CTX *octx;
@@ -816,6 +873,7 @@
 					break;
 				}
 #endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+				case XF_ESPDES:
 				case XF_ESP3DES:
 					tdbp->tdb_authalg = AH_NONE;
 					break;
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/ipsec_xform.h freeswan-1.91/klips/net/ipsec/ipsec_xform.h
--- freeswan-1.91.orig/klips/net/ipsec/ipsec_xform.h	Thu Jun 14 15:35:11 2001
+++ freeswan-1.91/klips/net/ipsec/ipsec_xform.h	Mon Jul  2 20:58:42 2001
@@ -22,16 +22,22 @@
 #define XF_IP4			1	/* IPv4 inside IPv4 */
 #define XF_AHMD5		2	/* AH MD5 */
 #define XF_AHSHA		3	/* AH SHA */
+#define XF_ESPDESOLD		4       /* old ESP DES-CBC */
 #define XF_ESP3DES		5	/* ESP DES3-CBC */
 #define XF_AHHMACMD5		6	/* AH-HMAC-MD5 with opt replay prot */
 #define XF_AHHMACSHA1		7	/* AH-HMAC-SHA1 with opt replay prot */
+#define XF_ESPDESMD5           8       /* DES, HMAC-MD-5, 128-bits of authentication */
 #define XF_ESP3DESMD5		9	/* triple DES, HMAC-MD-5, 128-bits of authentication */
 #define	XF_ESP3DESMD596		10	/* triple DES, HMAC-MD-5, 96-bits of authentication */
+#define XF_ESPDESMD596          11      /* DES, HMAC-MD-5, 96-bits of authentication */
 #define	XF_ESPNULLMD596		12	/* NULL, HMAC-MD-5 with 96-bits of authentication */
 #define	XF_ESPNULLSHA196	13	/* NULL, HMAC-SHA-1 with 96-bits of authentication */
 #define	XF_ESP3DESSHA196	14	/* triple DES, HMAC-SHA-1, 96-bits of authentication */
-#define XF_IP6			15	/* IPv6 inside IPv6 */
-#define XF_COMPDEFLATE		16	/* IPCOMP deflate */
+#define XF_ESPDESSHA196         15      /* DES, HMAC-SHA-1, 96-bits of authentication */
+#define XF_ESPDES               16      /* ESP DES */
+
+#define XF_IP6			17	/* IPv6 inside IPv6 */
+#define XF_COMPDEFLATE		18	/* IPCOMP deflate */
 
 #define XF_CLR			126	/* Clear SA table */
 #define XF_DEL			127	/* Delete SA */
@@ -44,16 +50,20 @@
 #define AH_NONE                  0
 #define AH_MD5                   2
 #define AH_SHA                   3
+#define AH_DES                   3
 
 /* IPsec ESP transform values */
 
 #define ESP_NONE		 0
+#define ESP_DES_IV64             1
+#define ESP_DES                  2
 #define ESP_3DES                 3
 #define ESP_RC5                  4
 #define ESP_IDEA                 5
 #define ESP_CAST                 6
 #define ESP_BLOWFISH             7
 #define ESP_3IDEA                8
+#define ESP_DES_IV32             9
 #define ESP_RC4                 10
 #define ESP_NULL                11
 
@@ -179,6 +189,7 @@
 		((x)->tdb_encalg == SADB_X_CALG_DEFLATE ? \
 		 "_DEFLATE" : "_UNKNOWN_comp") : \
 	(x)->tdb_encalg == ESP_NONE ? "" : \
+	(x)->tdb_encalg == ESP_DES ? "_DES" : \
 	(x)->tdb_encalg == ESP_3DES ? "_3DES" : \
 	"_UNKNOWN_encr", \
 	(x)->tdb_authalg == AH_NONE ? "" : \
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/pfkey_v2_parser.c freeswan-1.91/klips/net/ipsec/pfkey_v2_parser.c
--- freeswan-1.91.orig/klips/net/ipsec/pfkey_v2_parser.c	Fri Jun 15 00:57:02 2001
+++ freeswan-1.91/klips/net/ipsec/pfkey_v2_parser.c	Mon Jul  2 21:03:21 2001
@@ -1049,10 +1049,13 @@
 		unsigned int aks, eks;
 		
 		switch(tdbp->tdb_encalg) {
+# ifdef CONFIG_IPSEC_ENC_DES
+		case ESP_DES:
+# endif /* CONFIG_IPSEC_ENC_DES */
 # ifdef CONFIG_IPSEC_ENC_3DES
 		case ESP_3DES:
 # endif /* CONFIG_IPSEC_ENC_3DES */
-# if defined(CONFIG_IPSEC_ENC_3DES)
+# if defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES)
 			if((tdbp->tdb_iv = (caddr_t)
 			    kmalloc((tdbp->tdb_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) {
 				SENDERR(ENOMEM);
@@ -1060,7 +1063,7 @@
 			get_random_bytes((void *)tdbp->tdb_iv, EMT_ESPDES_IV_SZ);
 			tdbp->tdb_iv_bits = tdbp->tdb_iv_size * 8;
 			break;
-# endif /* defined(CONFIG_IPSEC_ENC_3DES) */
+# endif /* defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES) */
 		case ESP_NONE:
 			break;
 		default:
@@ -1072,6 +1075,52 @@
 		}
 		
 		switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+               case ESP_DES:
+                       if(tdbp->tdb_key_bits_e != (EMT_ESPDES_KEY_SZ * 8)) {
+                               KLIPS_PRINT(debug_pfkey,
+                                           "klips_debug:pfkey_tdb_init: "
+                                           "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+                                           tdbp->tdb_key_bits_e, EMT_ESPDES_KEY_SZ * 8);
+                               SENDERR(EINVAL);
+                       }
+                       
+                       /* save encryption key pointer */
+                       ekp = tdbp->tdb_key_e;
+                       eks = tdbp->tdb_key_e_size;
+                       
+                       if((tdbp->tdb_key_e = (caddr_t)
+                           kmalloc(sizeof(struct des_eks), GFP_ATOMIC)) == NULL) {
+                               tdbp->tdb_key_e = ekp;
+                               SENDERR(ENOMEM);
+                       }
+                       tdbp->tdb_key_e_size = sizeof(struct des_eks);
+
+#if 0 /* we don't really want to print these unless there are really big problems */
+                       KLIPS_PRINT(debug_pfkey,
+                                   "klips_debug:pfkey_tdb_init: des key 1 is 0x%08lx%08lx\n",
+                                   ntohl(*((__u32 *)ed->eme_key)),
+                                   ntohl(*((__u32 *)ed->eme_key + 1)));
+#endif
+                       error = des_set_key((caddr_t)ekp, 
+                                           (caddr_t)(tdbp->tdb_key_e));
+                       if (error == -1)
+                                       printk("klips_debug:pfkey_tdb_init: "
+                                              "parity error in des key\n");
+                               else if (error == -2)
+                                       printk("klips_debug:pfkey_tdb_init: "
+                                              "illegal weak des key\n");
+                               if (error) {
+                                       memset(ekp, 0, eks);
+                                       kfree(ekp);
+                                       SENDERR(EINVAL);
+                               }
+
+                       /* paranoid */
+                       memset(ekp, 0, eks);
+                       kfree(ekp);
+                       break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 # ifdef CONFIG_IPSEC_ENC_3DES
 		case ESP_3DES:
 			if(tdbp->tdb_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) {
@@ -3247,6 +3296,14 @@
 		/* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */
 		/* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */
 		/* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */
+               { SADB_AALG_MD5HMAC,  SADB_EALG_DESCBC, SADB_SAFLAGS_PFS,
+                 128, 128, 56, 56,
+                 0, 0, 0, 0, 0,
+                 57600, 86400, 57600, 86400 },
+               { SADB_AALG_SHA1HMAC, SADB_EALG_DESCBC, SADB_SAFLAGS_PFS,
+                 160, 160, 56, 56,
+                 0, 0, 0, 0, 0,
+                 57600, 86400, 57600, 86400 },
 		{ SADB_AALG_MD5HMAC,  SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS,
 		  128, 128, 168, 168,
 		  0, 0, 0, 0, 0,
diff -BbruN freeswan-1.91.orig/klips/net/ipsec/version.c freeswan-1.91/klips/net/ipsec/version.c
--- freeswan-1.91.orig/klips/net/ipsec/version.c	Wed May 30 09:02:20 2001
+++ freeswan-1.91/klips/net/ipsec/version.c	Tue Jul  3 04:03:17 2001
@@ -1,2 +1,2 @@
 /* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
-static const char freeswan_version[] = "1.91";
+static const char freeswan_version[] = "FreeSWAN-1.91-pkix1";
diff -BbruN freeswan-1.91.orig/klips/utils/Makefile freeswan-1.91/klips/utils/Makefile
--- freeswan-1.91.orig/klips/utils/Makefile	Thu Jun 14 15:35:13 2001
+++ freeswan-1.91/klips/utils/Makefile	Mon Jul  2 21:05:30 2001
@@ -31,8 +31,8 @@
 CFLAGS+= -Wbad-function-cast 
 
 ALL=spi eroute spigrp tncfg klipsdebug
-BINDIR=/usr/local/lib/ipsec
-MANTREE=/usr/local/man
+BINDIR=/usr/lib/ipsec
+MANTREE=/usr/man
 MANDIR8=$(MANTREE)/man8
 MANDIR5=$(MANTREE)/man5
 FREESWANLIB=../../lib/libfreeswan.a
@@ -41,11 +41,11 @@
 all: $(ALL)
 
 install: $(ALL)
-	$(INSTALL) $(ALL) $(BINDIR)
+	$(INSTALL) $(ALL) $(PREFIX)/$(BINDIR)
 	for f in $(addsuffix .8, $(ALL)) ; do \
-		$(INSTALL) $$f $(MANDIR8)/ipsec_$$f || exit 1 ; done
+		$(INSTALL) $$f $(PREFIX)/$(MANDIR8)/ipsec_$$f || exit 1 ; done
 	for f in $(addsuffix .5, $(ALL) version pf_key) ; do \
-		$(INSTALL) $$f $(MANDIR5)/ipsec_$$f || exit 1 ; done
+		$(INSTALL) $$f $(PREFIX)/$(MANDIR5)/ipsec_$$f || exit 1 ; done
 
 spi: spi.o
 	$(CC) $(DFLAGS) -o $@ $? $(FREESWANLIB)
diff -BbruN freeswan-1.91.orig/klips/utils/version.c freeswan-1.91/klips/utils/version.c
--- freeswan-1.91.orig/klips/utils/version.c	Wed May 30 09:02:20 2001
+++ freeswan-1.91/klips/utils/version.c	Mon Jul  2 21:06:39 2001
@@ -1,2 +1,2 @@
 /* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
-static const char freeswan_version[] = "1.91";
+static const char freeswan_version[] = "FreeSWAN-1.91-pkix1";
diff -BbruN freeswan-1.91.orig/lib/Makefile freeswan-1.91/lib/Makefile
--- freeswan-1.91.orig/lib/Makefile	Wed Oct 25 19:58:57 2000
+++ freeswan-1.91/lib/Makefile	Mon Jul  2 21:51:03 2001
@@ -60,8 +60,8 @@
 	mkdir -p $(MANDIR)
 	for f in $(MANS) ; \
 	do \
-		$(INSTALL) $$f $(MANDIR)/ipsec_$$f || exit 1 ; \
-		../utils/manlink $(MANDIR) ipsec_$$f ; \
+		$(INSTALL) $$f $(PREFIX)/$(MANDIR)/ipsec_$$f || exit 1 ; \
+		../utils/manlink $(PREFIX)/$(MANDIR) ipsec_$$f ; \
 	done
 
 $(LIB):	$(OBJS)
diff -BbruN freeswan-1.91.orig/libdes/Makefile freeswan-1.91/libdes/Makefile
--- freeswan-1.91.orig/libdes/Makefile	Tue Oct 10 22:12:45 2000
+++ freeswan-1.91/libdes/Makefile	Mon Jul  2 21:53:03 2001
@@ -59,10 +59,10 @@
 #DES_ENC=asm/dx86-sol.o	asm/yx86-sol.o	# solaris format x86 
 #DES_ENC=asm/dx86bsdi.o	asm/yx86basi.o	# bsdi format x86 
 
-LIBDIR=/usr/local/lib
-BINDIR=/usr/local/bin
-INCDIR=/usr/local/include
-MANDIR=/usr/local/man
+LIBDIR=/usr/lib
+BINDIR=/usr/bin
+INCDIR=/usr/include
+MANDIR=/usr/man
 MAN1=1
 MAN3=3
 SHELL=/bin/sh
diff -BbruN freeswan-1.91.orig/pluto/Makefile freeswan-1.91/pluto/Makefile
--- freeswan-1.91.orig/pluto/Makefile	Sat Jun 16 15:36:40 2001
+++ freeswan-1.91/pluto/Makefile	Tue Jul  3 01:52:08 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: Makefile,v 1.79 2001/06/16 19:36:40 dhr Exp $
+# RCSID $Id: Makefile,v 1.76 2001/03/13 09:22:01 dhr Exp $
 
 SHELL = /bin/sh
 
@@ -31,17 +31,32 @@
 FREESWANLIB=$(FREESWANLIBDIR)/libfreeswan.a
 LIBDESLITE=$(FREESWANLIBDIR)/libdes.a
 
+ifeq "$(USEOPENSSL)" "1"
+OPENSSLDEFS=-DOPENSSL
+
+OPENSSLOBJS=openssl.o xmap.o xmap_file.o xmap_dir.o xmap_db.o xmap_ldap.o \
+	x_sobj.o
+
+LDAPLIBS=-L$(LDAPROOT)/lib -lldap -llber -Wl,-rpath $(LDAPROOT)/lib
+LDAPDEFS=-DHAVE_LDAP
+
+DBROOT=/usr
+DBINCS=-I$(DBROOT)/include
+DBLIBS=-L$(DBROOT)/lib -ldb
+DBDEFS=-DHAVE_DB -DHAVE_DB185
+endif # USEOPENSSL = 1
+
 KLIPSD=../klips/net/ipsec
 
 INSTALL=install
 
 # -O on Linux makes gcc coredump when compiling sha1.c
 # -Wundef is nice but RHL5.2 compiler doesn't support it
-CFLAGS = -g -Wall -W -Wmissing-prototypes -Wpointer-arith -Wbad-function-cast \
-	-Wcast-qual -Wmissing-declarations -Wwrite-strings -Wstrict-prototypes
+CFLAGS = -g -Wall -Wmissing-prototypes -Wpointer-arith -Wbad-function-cast \
+	-Wcast-qual -Wmissing-declarations -Wwrite-strings
 
 # where to find klips headers and FreeS/WAN headers
-HDRDIRS = -I$(KLIPSD) $(FREESWANINCLS)
+HDRDIRS = -I$(KLIPSD) $(FREESWANINCLS) $(OPENSSLINCLS) $(LDAPINCS) $(DBINCS)
 
 # On non-LINUX systems, these one of these may be needed (see endian.h)
 # BYTE_ORDER = -DBIG_ENDIAN=4321 -DLITTLE_ENDIAN=1234 -DBYTE_ORDER=BIG_ENDIAN
@@ -76,22 +91,31 @@
 
 CPPFLAGS = $(HDRDIRS) $(BYTE_ORDER) \
 	-DPLUTO -DKLIPS -DDODGE_DH_MISSING_ZERO_BUG \
-	-DDEBUG -DGCC_LINT
+	-DDEBUG -DGCC_LINT $(OPENSSLDEFS) $(LDAPDEFS) $(DBDEFS)
 
 ALLFLAGS = $(CPPFLAGS) $(CFLAGS)
 
 # libefence is a free memory allocation debugger
 # Solaris 2 needs -lsocket -lnsl
-LIBSPLUTO = -lgmp -lresolv # -lefence
+LIBSPLUTO = -lgmp -lresolv $(OPENSSLLIBS) $(LDAPLIBS) $(DBLIBS)  # -lefence
 
 LDFLAGS =
 
 # Solaris needs -lsocket -lnsl
 LIBSWHACK =
 
+LIBSD2H   = $(OPENSSLLIBS) $(DBLIBS)
+
 BINNAMEPLUTO = pluto
 BINNAMEWHACK = whack
 
+# Comment this out if you don't have Berkeley DB available, which,
+# if you're running Linux is a bit strange...
+#ifeq ($(USEOPENSSL),1)
+ifeq "$(USEOPENSSL)" "1"
+BINNAMED2H   = dir2hash
+endif
+
 RM = /bin/rm
 RMFLAGS = -f
 
@@ -105,7 +129,7 @@
 
 DISTGCRYPT = \
 	gcryptfix.c gcryptfix.h \
-	dsa.c dsa.h \
+        g10_dsa.c g10_dsa.h \
 	elgamal.c elgamal.h \
 	primegen.c \
 	smallprime.c
@@ -142,23 +166,30 @@
 
 # start of support for DSS/DSA.  Not currently used.
 # OBJSGCRYPT =  gcryptfix.o dsa.o elgamal.o primegen.o smallprime.o
-OBJSGCRYPT =
+OBJSGCRYPT = gcryptfix.o g10_dsa.o elgamal.o primegen.o smallprime.o
 
 OBJSPLUTO = connections.o constants.o cookie.o crypto.o defs.o log.o \
 	state.o main.o server.o timer.o id.o ipsec_doi.o kernel.o \
 	kernel_comm.o demux.o packet.o preshared.o dnskey.o rnd.o spdb.o \
-	sha1.o md5.o $(OBJSGCRYPT) $(LIBDESLITE) $(FREESWANLIB)
+	sha1.o md5.o $(OBJSGCRYPT) $(LIBDESLITE) $(FREESWANLIB) \
+	$(OPENSSLOBJS) $(LIBGMP)
 
 OBJSWHACK = whack.o $(FREESWANLIB)
 
-all: $(BINNAMEPLUTO) $(BINNAMEWHACK)
+#ifeq ($(USEOPENSSL),1)
+ifeq "$(USEOPENSSL)" "1"
+OBJSD2H = dir2hash.o
+endif
+
+all: $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINNAMED2H)
 
 install: all
-	$(INSTALL) $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINDIR)
-	$(INSTALL) pluto.8 $(PMANDIR)/ipsec_pluto.8
-	../utils/manlink $(PMANDIR) ipsec_pluto.8
-	$(INSTALL) ipsec.secrets.5 $(FMANDIR)
-	../utils/manlink $(FMANDIR) ipsec.secrets.5
+	$(INSTALL) $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINNAMED2H) \
+		$(PREFIX)/$(BINDIR)
+	$(INSTALL) pluto.8 $(PREFIX)/$(PMANDIR)/ipsec_pluto.8
+	../utils/manlink $(PREFIX)/$(PMANDIR) ipsec_pluto.8
+	$(INSTALL) ipsec.secrets.5 $(PREFIX)/$(FMANDIR)
+	../utils/manlink $(PREFIX)/$(FMANDIR) ipsec.secrets.5
 
 $(BINNAMEPLUTO): $(OBJSPLUTO)
 	$(CC) -o $(BINNAMEPLUTO) $(LDFLAGS) $(OBJSPLUTO) $(LIBSPLUTO)
@@ -166,6 +197,9 @@
 $(BINNAMEWHACK): $(OBJSWHACK)
 	$(CC) -o $(BINNAMEWHACK) $(OBJSWHACK) $(LIBSWHACK)
 
+$(BINNAMED2H): $(OBJSD2H)
+	$(CC) -o $(BINNAMED2H) $(OBJSD2H) $(LIBSD2H)
+
 distlist:
 	@echo $(DIST)
 
@@ -185,8 +219,10 @@
 realclean: clean
 
 clean:
-	$(RM) $(RMFLAGS) $(OBJSPLUTO) *.core core *~ a.out ktrace.out
-	$(RM) $(RMFLAGS) $(BINNAMEPLUTO) $(OBJSWHACK) $(BINNAMEWHACK)
+	$(RM) $(RMFLAGS) $(OBJSPLUTO) $(OBJSD2H) \
+		*.core core *~ a.out ktrace.out
+	$(RM) $(RMFLAGS) $(BINNAMEPLUTO) $(OBJSWHACK) $(BINNAMEWHACK) \
+		$(BINNAMED2H)
 
 .c.o:
 	$(CC) $(COPTS) $(ALLFLAGS) -c $<
@@ -221,9 +258,6 @@
 defs.o: defs.c
 demux.o: demux.c
 dnskey.o: dnskey.c
-dsa.o: dsa.c
-elgamal.o: elgamal.c
-gcryptfix.o: gcryptfix.c
 id.o: id.c
 ipsec_doi.o: ipsec_doi.c
 kernel.o: kernel.c
@@ -233,11 +267,9 @@
 md5.o: md5.c
 packet.o: packet.c
 preshared.o: preshared.c
-primegen.o: primegen.c
 rnd.o: rnd.c
 server.o: server.c
 sha1.o: sha1.c
-smallprime.o: smallprime.c
 spdb.o: spdb.c
 state.o: state.c
 timer.o: timer.c
@@ -302,23 +334,6 @@
 dnskey.o: dnskey.h
 dnskey.o: packet.h
 dnskey.o: timer.h
-dsa.o: constants.h
-dsa.o: defs.h
-dsa.o: log.h
-dsa.o: rnd.h
-dsa.o: gcryptfix.h
-dsa.o: dsa.h
-elgamal.o: constants.h
-elgamal.o: defs.h
-elgamal.o: log.h
-elgamal.o: rnd.h
-elgamal.o: gcryptfix.h
-elgamal.o: elgamal.h
-gcryptfix.o: constants.h
-gcryptfix.o: defs.h
-gcryptfix.o: log.h
-gcryptfix.o: rnd.h
-gcryptfix.o: gcryptfix.h
 id.o: constants.h
 id.o: defs.h
 id.o: id.h
@@ -351,7 +366,6 @@
 kernel.o: id.h
 kernel.o: connections.h
 kernel.o: state.h
-kernel.o: timer.h
 kernel.o: kernel.h
 kernel.o: log.h
 kernel.o: server.h
@@ -410,11 +424,6 @@
 preshared.o: dnskey.h
 preshared.o: log.h
 preshared.o: whack.h
-primegen.o: constants.h
-primegen.o: defs.h
-primegen.o: log.h
-primegen.o: rnd.h
-primegen.o: gcryptfix.h
 rnd.o: sha1.h
 rnd.o: constants.h
 rnd.o: defs.h
@@ -436,9 +445,6 @@
 server.o: whack.h
 sha1.o: sha1.h
 sha1.o: endian.h
-smallprime.o: constants.h
-smallprime.o: defs.h
-smallprime.o: gcryptfix.h
 spdb.o: constants.h
 spdb.o: defs.h
 spdb.o: id.h
@@ -474,7 +480,6 @@
 timer.o: packet.h
 timer.o: demux.h
 timer.o: ipsec_doi.h
-timer.o: kernel.h
 timer.o: server.h
 timer.o: log.h
 timer.o: rnd.h
diff -BbruN freeswan-1.91.orig/pluto/connections.c freeswan-1.91/pluto/connections.c
--- freeswan-1.91.orig/pluto/connections.c	Fri Jun 15 17:30:44 2001
+++ freeswan-1.91/pluto/connections.c	Tue Jul  3 01:56:45 2001
@@ -43,6 +43,10 @@
 #include "dnskey.h"	/* needs preshared.h */
 #include "whack.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#include "xmap.h"
+#endif
 static void flush_pending_by_connection(struct connection *c);	/* forward */
 
 static struct connection *connections = NULL;
@@ -280,6 +284,20 @@
     }
     release_connection(c);	/* won't delete c */
 
+#ifdef OPENSSL
+    if (c->cert != NULL) X509_free((X509 *)(c->cert));
+    if (c->key != NULL) EVP_PKEY_free((EVP_PKEY *)(c->key));
+    if (c->lu != NULL) sk_XMAP_pop_free(c->lu, XMAP_free);
+    {
+      int i;
+
+      for (i=0; i<MAX_OTHER; i++)
+       if (c->other[i].cert != NULL) {
+         X509_free((X509 *)(c->other[i].cert));
+        }
+    }
+#endif
+
     /* find and delete c from connections list */
     list_rm(struct connection, ac_next, c, connections);
     cur_connection = old_cur_connection;
@@ -540,12 +558,61 @@
 static void
 unshare_connection_strings(struct connection *c)
 {
+#ifdef OPENSSL
+    void *tempcert, *tempkey;
+    STACK_OF(XMAP) *templu;
+#endif
     c->name = clone_str(c->name, "connection name");
 
     unshare_id_content(&c->this.id);
     c->this.updown = clone_str(c->this.updown, "updown");
     unshare_id_content(&c->that.id);
     c->that.updown = clone_str(c->that.updown, "updown");
+
+#ifdef OPENSSL
+    {
+      int i;
+
+      for (i=0; i<MAX_OTHER; i++)
+        if (c->other[i].cert) {
+          tempcert = c->other[i].cert;
+          c->other[i].cert = X509_dup(tempcert);
+        }
+    }
+
+
+    if (c->cert) {
+      tempcert = c->cert;
+      c->cert = X509_dup(tempcert);
+    }
+/* ******** HOW to use EVP_PKEY *************
+ * #define RSAPrivateKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey,
+ *                (char *(*)())d2i_RSAPrivateKey,(char *)rsa)
+ * /usr/include/openssl/evp.h:621:RSA *  EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+ *
+ * DEFS:
+ * /usr/include/openssl/evp.h:637:EVP_PKEY *  d2i_PrivateKey(int type,
+ *               EVP_PKEY **a, unsigned char **pp,
+ * /usr/include/openssl/evp.h:641:int  i2d_PrivateKey(EVP_PKEY *a,
+ *               unsigned char **pp);
+ * X509 dup macro:
+ * #define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \
+ *                 (char *(*)())d2i_X509,(char *)x509)
+ * NEW MACRO:
+ * #define EVP_PKEY_dup(pkey) \
+ *   (EVP_PKEY *)ASN1_dup((int (*)())i2d_PrivateKey, \
+ *   (char *(*)())d2i_AutoPrivateKey,(char *)pkey)
+ */
+
+    if (c->key) {
+      tempkey = c->key;
+      c->key = EVP_PKEY_dup(tempkey);
+    }
+    if (c->lu) {
+      templu = c->lu;
+      c->lu = clone_sk_XMAP(templu);
+    }
+#endif
 }
 
 static void
@@ -615,7 +682,11 @@
 
 	    for (; c != NULL; c = c->hp_next)
 	    {
+#ifndef OPENSSL
 		if ((c->policy ^ wm->policy) & (POLICY_PSK | POLICY_RSASIG))
+#else
+		if ((c->policy ^ wm->policy) & (POLICY_PSK | POLICY_OPENSSL))
+#endif
 		{
 		    loglog(RC_CLASH
 			, "authentication method disagrees with \"%s\", which is also for an unspecified peer"
@@ -631,6 +702,8 @@
 void
 add_connection(const struct whack_message *wm)
 {
+    bool success = TRUE;
+
     if (con_by_name(wm->name, FALSE) != NULL)
     {
 	loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
@@ -655,6 +728,15 @@
 	c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
 	c->sa_keying_tries = wm->sa_keying_tries;
 
+	c->block_cypher = wm->block_cypher;
+
+#ifdef OPENSSL
+	c->this.id.key_id.len = 0;
+	c->that.id.key_id.len = 0;
+	c->this.id.der_asn1_dn.len = 0;
+	c->that.id.der_asn1_dn.len = 0;
+#endif
+
 	c->addr_family = wm->addr_family;
 	c->tunnel_addr_family = wm->tunnel_addr_family;
 
@@ -673,6 +755,43 @@
 	    c->that = t;
 	}
 
+#ifdef OPENSSL
+	{
+	    int i;
+
+	    for(i=0; i<MAX_OTHER; i++) {
+	      c->other[i].cert = NULL;
+	      c->other[i].type = 0;
+	    }
+	}
+	c->cert_options = parse_options(wm->whack_certopts);
+
+	/* c->cert_options can tell us if we have to deal with
+	 * X509 certs from now on. See function "use_openssl"
+	 */
+	if (c->cert_options != 0) {
+	  load_cert_and_key(wm->whack_certfile, wm->whack_keyfile,
+	    (X509 **)&(c->cert), (EVP_PKEY **)&(c->key), c->name);
+
+	  if ((c->cert == NULL) || (c->key == NULL)) {
+	    success = FALSE;
+	  }
+
+#if 0 /* to be removed? */
+	  /* ID_DER_ASN1_DN cannot be done with path=db or path=dir */
+	  if (! check_idtype_and_path(c, wm->whack_certpath)) {
+	    success = FALSE;
+	  }
+#endif
+
+          if (! make_lookups((STACK_OF(XMAP) **)(&(c->lu)),
+            wm->whack_certpath) ) {
+            success = FALSE;
+          }
+          strncpy(c->path, wm->whack_certpath, PATH_NAME_LIMIT);
+	}
+#endif
+
 	/* set internal fields */
 	c->ac_next = connections;
 	connections = c;
@@ -697,7 +816,8 @@
 
 	possibly_some_oppo = TRUE;	/* could be more careful about this */
 
-	/* log all about this connection */
+	/* log all about this connection, if successful */
+	if (success) {
 	log("added connection description \"%s\"", c->name);
 	DBG(DBG_CONTROL,
 	    char lhs[SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF];
@@ -730,6 +850,15 @@
 		, (unsigned long) c->sa_keying_tries
 		, bitnamesof(sa_policy_bit_names, c->policy));
 	);
+	} else {
+	  loglog(RC_LOG_SERIOUS,
+	    "Adding connection description \"%s\" failed.",
+	    c->name);
+	  loglog(RC_LOG_SERIOUS,
+	    "Deleting connection description \"%s\".",
+	    c->name);
+	  delete_connection(c);
+	}
     }
 }
 
@@ -1057,6 +1186,17 @@
 	{
 	    /* what should we do on failure? */
 	    (void) assign_hold(c, our_client, peer_client);
+
+	    switch (c->routing){
+	    case RT_UNROUTED:
+	        c->routing = RT_UNROUTED_HOLD;
+	        break;
+	    case RT_ROUTED_PROSPECTIVE:
+	        c->routing = RT_ROUTED_HOLD;
+	        break;
+	    default:
+	        passert(FALSE);
+	    }
 	}
 	ipsecdoi_initiate(whackfd, c, c->policy, 1);
 	whackfd = NULL_FD;	/* protect from close */
@@ -1425,7 +1565,13 @@
 	break;
 
     case OAKLEY_RSA_SIG:
+#ifndef OPENSSL
 	auth_policy = POLICY_RSASIG;
+#else
+   case OAKLEY_RSA_ENC:
+   case OAKLEY_RSA_ENC_REV:
+	auth_policy = POLICY_OPENSSL;
+#endif
 	if (initiator)
 	{
 	    /* at this point, we've committed to our RSA private key:
@@ -1436,7 +1582,14 @@
 		return NULL;	/* cannot determine my RSA private key! */
 	}
 	break;
-
+#ifdef OPENSSL
+    case OAKLEY_DSS_SIG:
+    case OAKLEY_ELGAMAL_ENC:
+    case OAKLEY_ELGAMAL_ENC_REV:
+	auth_policy = POLICY_OPENSSL;
+	/* Not implemented yet */
+	break;
+#endif
     default:
 	passert(FALSE);
     }
@@ -1461,6 +1614,27 @@
 	{
 	    bool exact = same_id(peer_id, &d->that.id);	/* exact peer ID match? */
 
+#ifdef OPENSSL
+           /* fetch d's other cert, when applicable. */
+             if (auth_policy == POLICY_OPENSSL) {
+               bool r;
+               switch(auth) {
+                 case OAKLEY_RSA_SIG:
+                 case OAKLEY_RSA_ENC:
+                 case OAKLEY_RSA_ENC_REV:
+                   r = have_othercert(d, EVP_PKEY_RSA);
+                   break;
+
+                  case OAKLEY_DSS_SIG:
+                 case OAKLEY_ELGAMAL_ENC:
+                 case OAKLEY_ELGAMAL_ENC_REV:
+                   r = have_othercert(d, EVP_PKEY_DSA);
+                   break;
+               default:
+                   passert(FALSE);
+               } /* END switch */
+             }
+#endif
 	    /* check if peer_id matches, exactly or after instantiation */
 	    if (!exact && !(rw && d->that.id.kind == ID_NONE))
 		continue;
@@ -1492,6 +1666,10 @@
 		break;
 
 	    case OAKLEY_RSA_SIG:
+#ifdef OPENSSL
+           case OAKLEY_RSA_ENC:
+           case OAKLEY_RSA_ENC_REV:
+#endif
 		/* We must at least be able to find our private key.
 		 * If we initiated, it must match the one we
 		 * used in the SIG_I payload that we sent previously.
diff -BbruN freeswan-1.91.orig/pluto/connections.h freeswan-1.91/pluto/connections.h
--- freeswan-1.91.orig/pluto/connections.h	Mon May 28 15:18:17 2001
+++ freeswan-1.91/pluto/connections.h	Tue Jul  3 01:56:59 2001
@@ -14,6 +14,10 @@
  * RCSID $Id: connections.h,v 1.54 2001/05/28 19:18:17 dhr Exp $
  */
 
+#ifdef OPENSSL
+#include "openssl_defs.h"
+#endif
+
 /* There are two kinds of connections:
  * - ISAKMP connections, between hosts (for IKE communication)
  * - IPsec connections, between clients (for secure IP communication)
@@ -87,6 +91,13 @@
  * is a stat that uses it.
  */
 
+#ifdef OPENSSL
+struct other_st {
+  u_int32_t type; /* type of certificate in 'cert': EVP_PKEY_RSA or EVP_PKEY_DSA */
+  void *cert;
+};
+#endif
+
 struct end {
     struct id id;
     ip_address
@@ -101,6 +112,20 @@
 
 struct connection {
     char *name;
+#ifdef OPENSSL
+    /* The declaration of these as void is truly horrific - they 
+     * should be X509 and EVP_PKEY pointers. Unfortunately, if this
+     * is declared, the MD5 header files from OpenSSL conflict with those
+     * in the KLIPS source. Hence we cast these pointers to the right
+     * type at the time of use. It's disgusting, but I can't think of
+     * another way -- ND 
+     */
+    void *cert, *key, *lu;
+    struct other_st other[MAX_OTHER];
+    u_char path[PATH_NAME_LIMIT];
+    u_int32_t cert_options;
+#endif
+    lset_t block_cypher;
     lset_t policy;
     time_t sa_ike_life_seconds;
     time_t sa_ipsec_life_seconds;
diff -BbruN freeswan-1.91.orig/pluto/constants.c freeswan-1.91/pluto/constants.c
--- freeswan-1.91.orig/pluto/constants.c	Tue May 29 14:39:56 2001
+++ freeswan-1.91/pluto/constants.c	Tue Jul  3 02:02:30 2001
@@ -311,13 +312,38 @@
 enum_names ident_names =
     { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL };
 
+#ifdef OPENSSL
+/* Certificate type values */
+static const char *const cert_name[] = {
+       "CERT_TYPE_NONE",
+       "CERT_TYPE_PKCS7",
+       "CERT_TYPE_PGP",
+       "CERT_TYPE_DNSKEY",
+       "CERT_TYPE_X509_SIG",
+       "CERT_TYPE_X509_KEX",
+       "CERT_TYPE_KERBEROS",
+       "CERT_TYPE_CRL",
+       "CERT_TYPE_ARL",
+       "CERT_TYPE_SPKI",
+       "CERT_TYPE_X509_ATTR",
+    };
+
+enum_names cert_names =
+    { CERT_TYPE_NONE, CERT_TYPE_X509_ATTR, cert_name, NULL };
+#endif
+
+
 /* Goal BITs for establishing an SA
  * Note: we drop the POLICY_ prefix so that logs are more concise.
  */
 
 const char *const sa_policy_bit_names[] = {
 	"PSK",
+#ifndef OPENSSL
 	"RSASIG",
+#else
+	"OPENSSL",
+#endif
 	"ENCRYPT",
 	"AUTHENTICATE",
 	"COMPRESS",
@@ -770,6 +796,26 @@
     return p;
 }
 
+void init_constants(void)
+{
+    err_t ugh;
+
+    ugh = anyaddr(AF_INET, &ipv4_any);
+    passert(ugh == NULL);
+    ugh = anyaddr(AF_INET, &ipv6_any);
+    passert(ugh == NULL);
+
+    ugh = rangetosubnet(&ipv4_any, &ipv4_any, &ipv4_wildcard);
+    passert(ugh == NULL);
+    ugh = rangetosubnet(&ipv6_any, &ipv6_any, &ipv6_wildcard);
+    passert(ugh == NULL);
+
+    ugh = initsubnet(&ipv4_any, 0, '0', &ipv4_all);
+    passert(ugh == NULL);
+    ugh = initsubnet(&ipv6_any, 0, '0', &ipv6_all);
+    passert(ugh == NULL);
+}
+
 /* construct a string to name the bits on in a set
  * Result may be in STATIC buffer!
  */
@@ -864,24 +910,4 @@
 	p = buf;
     }
     return p;
-}
-
-void init_constants(void)
-{
-    err_t ugh;
-
-    ugh = anyaddr(AF_INET, &ipv4_any);
-    passert(ugh == NULL);
-    ugh = anyaddr(AF_INET, &ipv6_any);
-    passert(ugh == NULL);
-
-    ugh = rangetosubnet(&ipv4_any, &ipv4_any, &ipv4_wildcard);
-    passert(ugh == NULL);
-    ugh = rangetosubnet(&ipv6_any, &ipv6_any, &ipv6_wildcard);
-    passert(ugh == NULL);
-
-    ugh = initsubnet(&ipv4_any, 0, '0', &ipv4_all);
-    passert(ugh == NULL);
-    ugh = initsubnet(&ipv6_any, 0, '0', &ipv6_all);
-    passert(ugh == NULL);
 }
diff -BbruN freeswan-1.91.orig/pluto/constants.h freeswan-1.91/pluto/constants.h
--- freeswan-1.91.orig/pluto/constants.h	Tue May 29 14:39:56 2001
+++ freeswan-1.91/pluto/constants.h	Tue Jul  3 02:02:31 2001
@@ -509,6 +509,30 @@
 #define ID_DER_ASN1_GN              10
 #define ID_KEY_ID                   11
 
+#ifdef OPENSSL
+#define CERT_OPTION_SEND           0x01
+#define CERT_OPTION_PKCS7          0x02
+#define CERT_OPTION_PK             0x04
+#define CERT_OPTION_REV            0x08
+#define CERT_OPTION_STRICT         0x10
+#define CERT_OPTION_DSS_SHA        0x20
+#define CERT_OPTION_DSS_ALT        0x40
+
+extern enum_names cert_names;
+
+#define CERT_TYPE_NONE              0
+#define CERT_TYPE_PKCS7             1
+#define CERT_TYPE_PGP               2
+#define CERT_TYPE_DNSKEY            3
+#define CERT_TYPE_X509_SIG          4
+#define CERT_TYPE_X509_KEX          5
+#define CERT_TYPE_KERBEROS          6
+#define CERT_TYPE_CRL               7
+#define CERT_TYPE_ARL               8
+#define CERT_TYPE_SPKI              9
+#define CERT_TYPE_X509_ATTR        10
+#endif
+
 /* Policies for establishing an SA
  *
  * These are used to specify attributes (eg. encryption) and techniques
@@ -519,10 +543,18 @@
 
 /* ISAKMP auth techniques */
 #define POLICY_PSK           LELEM(0)
+#ifndef OPENSSL
 #define POLICY_RSASIG        LELEM(1)
+#else
+#define POLICY_OPENSSL        LELEM(1)
+#endif
 
 #define POLICY_ISAKMP_SHIFT	0	/* log2(POLICY_PSK) */
+#ifndef OPENSSL
 #define POLICY_ID_AUTH_MASK	LRANGES(POLICY_PSK, POLICY_RSASIG)
+#else
+#define POLICY_ID_AUTH_MASK    LRANGES(POLICY_PSK, POLICY_OPENSSL)
+#endif
 #define POLICY_ISAKMP_MASK	POLICY_ID_AUTH_MASK	/* all so far */
 
 /* Quick Mode (IPSEC) attributes */
@@ -625,6 +657,12 @@
 
 #define SA_LIFE_DURATION_K_DEFAULT  0xFFFFFFFFlu
 
+/* DES support */
+#define ALL_BLOCK_CYPHER 1
+#define DES_BLOCK_CYPHER 2
+#define DES3_BLOCK_CYPHER 3
+#define FORCE_ENCRYPT_CYPHER_DEFAULT ALL_BLOCK_CYPHER
+
 /* Encapsulation Mode attribute */
 
 extern enum_names enc_mode_names;
diff -BbruN freeswan-1.91.orig/pluto/crypto.h freeswan-1.91/pluto/crypto.h
--- freeswan-1.91.orig/pluto/crypto.h	Sun Dec 12 19:40:50 1999
+++ freeswan-1.91/pluto/crypto.h	Tue Jul  3 02:04:35 2001
@@ -56,7 +56,11 @@
 /* unification of cryptographic hashing mechanisms */
 
 union hash_ctx {
+#ifndef OPENSSL
 	MD5_CTX ctx_md5;
+#else
+	PLUTO_MD5_CTX ctx_md5;
+#endif
 	SHA1_CTX ctx_sha1;
     };
 
diff -BbruN freeswan-1.91.orig/pluto/defs.c freeswan-1.91/pluto/defs.c
--- freeswan-1.91.orig/pluto/defs.c	Tue Mar 13 04:22:03 2001
+++ freeswan-1.91/pluto/defs.c	Tue Jul  3 02:05:03 2001
@@ -24,6 +24,8 @@
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
+#include "id.h"
+#include "connections.h" /* needs id.h */
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
 const chunk_t empty_chunk = { NULL, 0 };
diff -BbruN freeswan-1.91.orig/pluto/defs.h freeswan-1.91/pluto/defs.h
--- freeswan-1.91.orig/pluto/defs.h	Tue May  8 01:37:21 2001
+++ freeswan-1.91/pluto/defs.h	Tue Jul  3 02:05:03 2001
@@ -59,6 +59,19 @@
 #define pfreeany(p) { if ((p) != NULL) pfree(p); }
 #define replace(p, q) { pfreeany(p); (p) = (q); }
 
+#ifdef OPENSSL
+#include <des.h>
+
+typedef union _keysched_u {
+  struct _des3_ks { des_key_schedule ks[3]; } des3_ks;
+  des_key_schedule des_ks;
+
+#ifdef NOTYET
+  /* Other ciphers, eg CAST, RC5, etc... */
+#endif
+
+} keysched;
+#endif
 
 /* chunk is a simple pointer-and-size abstraction */
 
@@ -108,3 +121,31 @@
 
 /* pad_up(n, m) is the amount to add to n to make it a multiple of m */
 #define pad_up(n, m) (((m) - 1) - (((n) + (m) - 1) % (m)))
+
+/* writemem_short adds support to write to unaligned memory (arm). */
+#ifdef __arm__
+#define writemem_u_int16_t(addr, offset, n) do {\
+  u_int16_t temp16 = htons((n)); \
+  (addr)[(offset)] = temp16 & 0xff; \
+  (addr)[(offset)+1] = temp16 >> 8; \
+} while (0)
+#else
+#define writemem_u_int16_t(addr, offset, n) do {\
+  *((u_int16_t *)(&((addr)[(offset)]))) = htons((n)); \
+} while (0)
+#endif
+
+/* readmem_short adds support to read from unaligned memory (arm). */
+#ifdef __arm__
+#define readmem_u_int16_t(addr, offset, var) do {\
+  u_int16_t temp16 = 0; \
+  temp16 += *((u_int8_t *)(&((addr)[(offset)]))) << 8; \
+  temp16 += *((u_int8_t *)(&((addr)[(offset)+1]))); \
+  (var) = temp16; \
+} while (0)
+#else
+#define readmem_u_int16_t(addr, offset, var) do {\
+  u_int16_t temp16 = ntohs(*((u_int16_t *)(&((addr)[(offset)])))); \
+  (var) = temp16; \
+} while (0)
+#endif
diff -BbruN freeswan-1.91.orig/pluto/demux.c freeswan-1.91/pluto/demux.c
--- freeswan-1.91.orig/pluto/demux.c	Sat Jun 16 12:31:40 2001
+++ freeswan-1.91/pluto/demux.c	Tue Jul  3 02:09:48 2001
@@ -139,6 +139,10 @@
 #include "whack.h"	/* requires connections.h */
 #include "server.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#endif
+
 /* This file does basic header checking and demux of
  * incoming packets.
  */
@@ -242,11 +246,19 @@
 
     { STATE_MAIN_R1, SMF_PKE_AUTH
     , P(KE) | P(ID) | P(NONCE), P(VID) | P(HASH), PT(KE)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inI2_outR2_pk },
+#endif
 
     { STATE_MAIN_R1, SMF_RPKE_AUTH
     , P(NONCE) | P(KE) | P(ID), P(VID) | P(HASH) | P(CERT), PT(NONCE)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inI2_outR2_rpk },
+#endif
 
     /* for states from here on, output message must be encrypted */
 
@@ -264,11 +276,20 @@
 
     { STATE_MAIN_I2, SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
     , P(KE) | P(ID) | P(NONCE), P(VID), PT(HASH)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inR2_outI3_pk /* ??? not yet implemented */ },
+#endif
 
-    { STATE_MAIN_I2, SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
-    ,  P(NONCE) | P(KE) | P(ID), P(VID), PT(HASH)
+    { STATE_MAIN_I2, SMF_RPKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
+/*   ,  P(NONCE) | P(KE) | P(ID), P(VID), PT(HASH) */
+    ,  P(NONCE) | P(KE) | P(ID), P(VID) | P(CERT), PT(HASH)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inR2_outI3_rpk /* ??? not yet implemented */ },
+#endif
 
     /* for states from here on, input message must be encrypted */
 
@@ -283,11 +304,19 @@
 
     { STATE_MAIN_R2, SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(ID) | P(SIG), P(VID) | P(CERT), PT(ID)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, main_inI3_outR3 },
+#else
+    , EVENT_SA_REPLACE, main_inI3_outR3_whichds},
+#endif
 
     { STATE_MAIN_R2, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(HASH), P(VID), PT(HASH)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_SA_REPLACE, main_inI3_outR3_pk},
+#endif
 
     /* STATE_MAIN_I3: R3 --> done
      * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done
@@ -301,11 +330,20 @@
 
     { STATE_MAIN_I3, SMF_DS_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(ID) | P(SIG), P(VID) | P(CERT), PT(NONE)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, main_inR3 },
+#else
+    , EVENT_SA_REPLACE, main_inR3_whichds },
+#endif
 
     { STATE_MAIN_I3, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(HASH), P(VID), PT(NONE)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_SA_REPLACE, main_inR3_pk },
+#endif
+
 
     /* STATE_MAIN_R3: can only get here due to packet loss */
     { STATE_MAIN_R3, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE, LEMPTY, LEMPTY
@@ -1245,6 +1283,9 @@
 	    {
 		lset_t s = LELEM(np);
 
+                loglog(RC_LOG_SERIOUS, "parsing: (%s)",
+                   enum_show(&payload_names, np));
+
 		if (0 == (s & (needed | smc->opt_payloads
 		| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D))))
 		{
@@ -1257,6 +1298,267 @@
 		needed &= ~s;
 	    }
 
+#ifdef OPENSSL
+            {
+              /* This code really shouldn't be here - it should be in */
+              /* the ipsec_doi code section with all the other protocol */
+              /* spec. Unfortunately, the "syntax checking" of the payload */
+              /* is done here, and the "semantic checking" of the payload */
+              /* is over in ipsec_doi. Since the fields of the ID payload */
+              /* are encrypted, and the ipsec_doi code checks those fields */
+              /* before processing the ID payload, we must ensure that the */
+              /* payload is decrypted and stored in the identification */
+              /* structure *before* the main mode routines process it. So */
+              /* the code is here. */
+ 
+              if ((IS_PHASE1(md.from_state)) && (md.st)) {
+                if ((md.st->st_oakley.auth == OAKLEY_RSA_ENC) || 
+                    (md.st->st_oakley.auth == OAKLEY_ELGAMAL_ENC)) {
+                  if ((sd == &isakmp_identification_desc) ||
+                      (sd == &isakmp_nonce_desc)) {
+                    /* We need to decrypt this packet */
+                    char cpl[65], ppl[65];
+                    u_int16_t paylen;
+                    chunk_t ch;
+ 
+                    /* see macro in defs.h */
+                    readmem_u_int16_t(md.message_pbs.cur, 2, paylen);
+
+                    clonetochunk(ch, &(md.message_pbs.cur[4]), paylen-4, 
+                      "Ciphertext payload");
+ 
+                    /* Make a copy chunk of the payload after the generic */
+                    /* header, which should be the ciphertext of */
+                    /* the ID payload */
+                    if (sd == &isakmp_identification_desc) {
+                      snprintf(cpl, sizeof(cpl)-1, "ID payload (ciphertext): ");
+                      snprintf(ppl, sizeof(ppl)-1, "ID payload (plaintext): ");
+                    } else if (sd == &isakmp_nonce_desc) {
+                      snprintf(cpl, sizeof(cpl)-1,
+                               "Nonce payload (ciphertext): ");
+                      snprintf(ppl, sizeof(ppl)-1,
+                               "Nonce payload (plaintext): ");
+                    } else {
+                      snprintf(cpl, sizeof(cpl)-1,
+                               "Unknown payload (ciphertext): ");
+                      snprintf(ppl, sizeof(ppl)-1,
+                               "Unknown payload (plaintext): ");
+                    }
+ 
+                    if (!valid_ciphertext_length(paylen - 4, md.st->st_connection)) {
+                      log("Ciphertext length not a multiple of key modulus length for %s", cpl );
+                      free_md(&md);
+                      return;
+                    }
+
+                    DBG(DBG_RAW,
+                    DBG_dump_chunk(cpl, ch);
+                    );
+
+                    if (! privkey_decrypt_chunk( &ch, md.st )) {
+                      log("Ciphertext for %s could not be decrypted.", cpl );
+                      free_md(&md);
+                      return;
+                    }
+
+                    if ((ch.len == 0) || (ch.len > paylen)) {
+                      /* Error - the decryption has failed */
+                      log("Decryption failure - malformed payload in packet");
+                      free_md(&md);
+                      return;
+                    }
+
+                    DBG(DBG_RAW,
+                    DBG_dump_chunk(ppl, ch);
+                    );
+
+/*  ** a nice data dumper **
+ * {
+ * 	int *ptr = (int *) md.message_pbs.cur;
+ * 	int length = md.message_pbs.roof -  md.message_pbs.cur;
+ * 	int i;
+ * 	DBG_log("before memcopy: ---------------------- length %d", length);
+ * 	for (i=0; i<length/4; i+=4) {
+ * 		DBG_log("%4d: %08x %08x %08x %08x ", i*4, ntohl(ptr[0]), 
+ * 			ntohl(ptr[1]), ntohl(ptr[2]), ntohl(ptr[3]));
+ * 		ptr += 4;
+ * 	}
+ * }
+ */
+
+                    /* Now restructure the message_pbs block, so that the */ 
+                    /* plaintext is now stored in the ID/nonce payload space */
+                    /* Adjust the length first */
+                    /* see macro in defs.h */
+                    writemem_u_int16_t(md.message_pbs.cur, 2, (ch.len + 4));
+
+                    /* Now copy the plaintext */
+                    memcpy(&(md.message_pbs.cur[4]), ch.ptr, ch.len);
+                    /* Clear the source plaintext */
+                    memset(ch.ptr, 0, ch.len);
+
+                    /* Shift down all subsequent payloads */
+                    memmove(&(md.message_pbs.cur[ch.len+4]),
+                            &(md.message_pbs.cur[paylen]),
+                            md.message_pbs.roof - &(md.message_pbs.cur[paylen]));
+
+                    /* Adjust the size of root downwards */
+                    md.message_pbs.roof -= paylen - ch.len - 4;
+                    freeanychunk(ch);
+
+                  }
+                } else if ((md.st->st_oakley.auth == OAKLEY_RSA_ENC_REV) ||
+			   (md.st->st_oakley.auth == OAKLEY_ELGAMAL_ENC_REV)) {
+                  if ((sd == &isakmp_identification_desc) ||
+                      (sd == &isakmp_nonce_desc) ||
+                      (sd == &isakmp_keyex_desc) ||
+                      (sd == &isakmp_ipsec_certificate_desc)) {
+                    if (sd == &isakmp_nonce_desc) {
+                      /* Nonce is public key encrypted */
+                      u_int16_t paylen;
+                      chunk_t ch;
+ 
+                      /* see macro in defs.h */
+                      readmem_u_int16_t(md.message_pbs.cur, 2, paylen);
+
+                      clonetochunk(ch, &(md.message_pbs.cur[4]), paylen-4, 
+                        "Ciphertext payload");
+
+                      if (!valid_ciphertext_length(paylen - 4, 
+                        md.st->st_connection)) {
+                        log("Ciphertext length not a multiple of key modulus length for nonce" );
+                        free_md(&md);
+                        return;
+                      }
+
+                      DBG(DBG_PARSING | DBG_CRYPT, 
+                      DBG_dump_chunk("Nonce payload (ciphertext)", ch);
+                      );
+
+                      if (! privkey_decrypt_chunk( &ch, md.st )) {
+                        log("Ciphertext for %s could not be decrypted.",
+                          "Nonce payload (ciphertext)");
+                        free_md(&md);
+                        return;
+                      }
+
+                      if ((ch.len == 0) || (ch.len > paylen)) {
+                        /* Error - the decryption has failed */
+                        log("Decryption failure - malformed payload in packet");
+                        free_md(&md);
+                        return;
+                      }
+                      DBG(DBG_PARSING | DBG_CRYPT, 
+                      DBG_dump_chunk("Nonce payload (plaintext)", ch);
+                      );
+
+		      if ((md.st->st_state == STATE_MAIN_I1) ||
+			  (md.st->st_state == STATE_MAIN_I2) ||
+			  (md.st->st_state == STATE_MAIN_I3) ||
+			  (md.st->st_state == STATE_MAIN_I4)) {
+			if (derive_symmetric_key(md.st, ch,
+						 md.st->st_rcookie,
+						 COOKIE_SIZE,
+						 &md.st->st_ks_r,
+						 &md.st->st_ne_r) < 0) {
+			  log("Unable to derive symmetric key");
+			  free(&md);
+			  return;
+			}
+			memset(&md.st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
+			DBG(DBG_PARSING,
+			DBG_dump_chunk("Received Ke_r:", md.st->st_ne_r);
+			);
+		      } else {
+			if (derive_symmetric_key(md.st, ch,
+						 md.st->st_icookie,
+						 COOKIE_SIZE,
+						 &md.st->st_ks_i,
+						 &md.st->st_ne_i) < 0) {
+			  log("Unable to derive symmetric key");
+			  free(&md);
+			  return;
+			}
+			memset(&md.st->st_ne_i_iv, 0, MAX_DIGEST_LEN);
+			DBG(DBG_PARSING,
+			DBG_dump_chunk("Received Ke_i:", md.st->st_ne_i);
+			);
+		      }
+
+                      /* Now restructure the message_pbs block, so that the */
+                      /* plaintext is now stored in the payload space */
+                      /* Adjust the length first */
+                      /* see macro in defs.h */ 
+                      writemem_u_int16_t(md.message_pbs.cur, 2, (ch.len + 4));
+
+                      /* Now copy the plaintext */
+                      memcpy(&(md.message_pbs.cur[4]), ch.ptr, ch.len);
+                      /* Clear the source plaintext */
+                      memset(ch.ptr, 0, ch.len);
+                      /* Shift down all subsequent payloads */
+                      memmove(&(md.message_pbs.cur[ch.len+4]),
+                              &(md.message_pbs.cur[paylen]),
+                              md.message_pbs.roof - &(md.message_pbs.cur[paylen]));
+		      /* Adjust the size of roof downwards */
+                      md.message_pbs.roof -= paylen - ch.len - 4;
+
+		      /* Discard the plaintext chunk */
+		      memset(ch.ptr, 0, ch.len);
+		      freeanychunk(ch);
+		    } else {
+                      u_int16_t paylen;
+                      chunk_t ch, pch;
+ 
+                      /* see macro in defs.h */
+                      readmem_u_int16_t(md.message_pbs.cur, 2, paylen);
+
+                      DBG(DBG_CRYPT, 
+		      DBG_log("Encrypted payload length = %d", paylen);
+                      );
+                      clonetochunk(ch, &(md.message_pbs.cur[4]), paylen-4, "Ciphertext payload");
+		      setchunk(pch, NULL, 0);
+		      if ((md.st->st_state == STATE_MAIN_I1) ||
+			  (md.st->st_state == STATE_MAIN_I2) ||
+			  (md.st->st_state == STATE_MAIN_I3) ||
+			  (md.st->st_state == STATE_MAIN_I4)) {
+			if (! decrypt_payload(md.st, &md.st->st_ks_r,
+					      md.st->st_ne_r_iv,
+					      ch, &pch) ) {
+			  log("Unable to decrypt responder payload");
+			  free(&md);
+			  return;
+			}
+		      } else {
+			if (!decrypt_payload(md.st, &md.st->st_ks_i,
+					     md.st->st_ne_i_iv,
+					     ch, &pch) ) {
+			  log("Unable to decrypt initiator payload");
+			  free(&md);
+			  return;
+			}
+		      }
+                      /* see macro in defs.h */ 
+                      writemem_u_int16_t(md.message_pbs.cur, 2, (pch.len + 4));
+
+                      /* Now copy the plaintext */
+                      memcpy(&(md.message_pbs.cur[4]), pch.ptr, pch.len);
+                      /* Shift down all subsequent payloads */
+                      memmove(&(md.message_pbs.cur[pch.len+4]),
+                              &(md.message_pbs.cur[paylen]),
+                              md.message_pbs.roof - &(md.message_pbs.cur[paylen]));
+		      /* Adjust the size of roof downwards */
+                      md.message_pbs.roof -= paylen - pch.len - 4;
+
+		      freeanychunk(ch);
+		      memset(pch.ptr, 0, pch.len);
+		      freeanychunk(pch);
+		    }
+		  } /* Otherwise, let everything else pass */
+		} /* end if (revised PK mode ) */
+	      } /* end if Phase 1 */
+	    } /* end OPENSSL handling */
+#endif /* OPENSSL */
+                                                                             
 	    if (!in_struct(&pd->payload, sd, &md.message_pbs, &pd->pbs))
 	    {
 		loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
@@ -1666,3 +1968,294 @@
     }
     free_md(&md);
 }
+
+#ifdef OPENSSL
+int
+derive_symmetric_key( struct state *st, const chunk_t nonce,
+		      const u_char *seedptr, const size_t seedlen,
+		      keysched *ks,
+		      chunk_t *key )
+{
+  struct hmac_ctx ctx;
+  chunk_t k, kk, kchain;
+  chunk_t ne;
+  char nestr[8];
+  int needed_len;
+
+  DBG(DBG_PARSING, 
+	  DBG_dump_chunk("Deriving symmetric key from: ", nonce);
+	  DBG_dump("Initial Cookie:", seedptr, seedlen);
+	);
+  switch(st->st_oakley.encrypt) {
+    /* We really shouldn't deal with DES, */
+    /* uncomment this if you must have it */
+  case OAKLEY_DES_CBC:
+    needed_len = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    needed_len = IDEA_CBC_KEY_LEN;
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    needed_len = BLOWFISH_CBC_KEY_LEN;
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    needed_len = RC5_CBC_KEY_LEN;
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    needed_len = DES_CBC_BLOCK_SIZE * 3;
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    needed_len = CAST_CBC_KEY_LEN;
+    break;
+#endif
+  default:
+    log("Unknown block cipher ID for symmetric cipher");
+    return -1;
+  }
+
+  /* Generate initial decryption key material */
+  /* key = prf(Nonce-X, Cookie-X); X={I,R} */
+  ne.ptr = NULL;
+  hmac_init_chunk(&ctx, st->st_oakley.hasher, nonce);
+  hmac_update(&ctx, seedptr, seedlen);
+  hmac_final_chunk(ne, nestr, &ctx);
+  clonetochunk(*key, ne.ptr, ne.len, "Initial key material");
+
+  if (key->len < needed_len) {
+    freeanychunk(*key);
+    kchain.ptr = alloc_bytes(1, "initial zero octet");
+    kchain.len = 1;
+    memset(kchain.ptr, 0, kchain.len);
+    while (key->len < needed_len) {
+      kk.ptr = NULL;
+      hmac_init_chunk(&ctx, st->st_oakley.hasher, ne);
+      hmac_update_chunk(&ctx, kchain);
+      hmac_final_chunk(kk, "extra key material", &ctx);
+      clonereplacechunk(kchain, kk.ptr, kk.len, "chain key material");
+      /* Now append kk to key */
+      if (! key->ptr ) {
+	clonetochunk(*key, kk.ptr, kk.len, "initial extra key material");
+      } else {
+	k.ptr = alloc_bytes(key->len + kk.len, "appended key material");
+	k.len = key->len + kk.len;
+	memcpy(k.ptr, key->ptr, key->len);
+	memcpy(&(k.ptr[key->len]), kk.ptr, kk.len);
+	freeanychunk(*key);
+	key->len = k.len;
+	key->ptr = k.ptr;
+      }
+      freeanychunk(kk);
+    }
+    freeanychunk(kchain);
+  }
+
+  switch(st->st_oakley.encrypt) {
+    /* We really shouldn't deal with DES, */
+    /* uncomment this if you must have it */
+  case OAKLEY_DES_CBC:
+    (void)des_set_key((des_cblock *)key->ptr, ks->des_ks);
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    (void)des_set_key((des_cblock *)key->ptr + 0, ks->des3_ks.ks[0]);
+    (void)des_set_key((des_cblock *)key->ptr + 1, ks->des3_ks.ks[1]);
+    (void)des_set_key((des_cblock *)key->ptr + 2, ks->des3_ks.ks[2]);
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  return 0;
+}
+
+bool
+encrypt_payload( struct state *st, keysched *ks, u_char *iv,
+		 chunk_t inp, chunk_t *out )
+{
+  chunk_t temp;
+  int blocklen;
+  u_char pv;
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  /* Pad the input up to a block size multiple */
+  if (inp.len % blocklen == 0) { /* Add a full block for padding */
+    pv = (u_char)blocklen;
+    temp.len = inp.len + (size_t)pv;
+  } else {
+    pv = (u_char)(blocklen - 1  - ((inp.len + blocklen - 1) % blocklen));
+    temp.len = inp.len + (size_t)pv;
+  }
+
+  temp.ptr = alloc_bytes(temp.len, "padded plaintext");
+  memset(temp.ptr, 0, temp.len);
+  clonetochunk(*out, temp.ptr, temp.len, "ciphertext");
+  memcpy(temp.ptr, inp.ptr, inp.len);
+  temp.ptr[temp.len-1] = pv;
+  
+  DBG(DBG_PARSING | DBG_CRYPT,
+	  DBG_dump_chunk("Plaintext:", temp);
+	  DBG_dump("Old IV: ", iv, blocklen);
+	);
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    des_ncbc_encrypt((des_cblock *)temp.ptr, (des_cblock *)out->ptr,
+		     temp.len, ks->des_ks, (des_cblock *)iv, TRUE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    des_ede3_cbc_encrypt((des_cblock *)temp.ptr, (des_cblock *)out->ptr,
+			 temp.len,
+			 ks->des3_ks.ks[0],
+			 ks->des3_ks.ks[1],
+			 ks->des3_ks.ks[2],
+			 (des_cblock *)iv, TRUE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  DBG(DBG_PARSING | DBG_CRYPT,
+	DBG_dump_chunk("Ciphertext: ", *out);
+	DBG_dump("New IV: ", iv, blocklen);
+	);
+  freeanychunk(temp);
+  return TRUE;
+}
+
+bool
+decrypt_payload( struct state *st, keysched *ks, u_char *iv,
+		 chunk_t inp, chunk_t *out )
+{
+  chunk_t temp;
+  int blocklen;
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  if (inp.len % blocklen != 0) {
+    log("Ciphertext is not a multiple of block length");
+    return FALSE;
+  }
+
+  DBG(DBG_PARSING | DBG_CRYPT,
+	DBG_dump_chunk("Ciphertext: ", inp);
+	DBG_dump("Old IV: ", iv, blocklen);
+	);
+
+  temp.ptr = alloc_bytes(inp.len, "temporary plaintext");
+  temp.len = inp.len;
+  memset(temp.ptr, 0, temp.len);
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    des_ncbc_encrypt((des_cblock *)inp.ptr, (des_cblock *)temp.ptr,
+		     inp.len, ks->des_ks, (des_cblock *)iv, FALSE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    des_ede3_cbc_encrypt((des_cblock *)inp.ptr, (des_cblock *)temp.ptr,
+			 inp.len,
+			 ks->des3_ks.ks[0],
+			 ks->des3_ks.ks[1],
+			 ks->des3_ks.ks[2],
+			 (des_cblock *)iv, FALSE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  /* Strip padding from plaintext */
+  if ((temp.ptr[temp.len-1] < (u_char)1) ||
+      (temp.ptr[temp.len-1] > (u_char)blocklen) ||
+      (temp.ptr[temp.len-1] > temp.len)) {
+    /* Impossible padding value */
+    log("Impossible plaintext padding value: %d", temp.ptr[temp.len-1]);
+    memset(temp.ptr, 0, temp.len);
+    freeanychunk(temp);
+    return FALSE;
+  }
+
+  out->len = temp.len - (size_t)(temp.ptr[temp.len-1]);
+  out->ptr = alloc_bytes(inp.len, "plaintext");
+  memcpy(out->ptr, temp.ptr, out->len);
+
+  DBG(DBG_PARSING | DBG_CRYPT,
+	DBG_dump_chunk("Plaintext: ", *out);
+	DBG_dump("New IV: ", iv, blocklen);
+	);
+
+  memset(temp.ptr, 0, temp.len);
+  freeanychunk(temp);
+  return TRUE;
+}
+
+#endif
diff -BbruN freeswan-1.91.orig/pluto/demux.h freeswan-1.91/pluto/demux.h
--- freeswan-1.91.orig/pluto/demux.h	Fri May  4 22:51:38 2001
+++ freeswan-1.91/pluto/demux.h	Tue Jul  3 03:17:07 2001
@@ -77,3 +77,15 @@
 } stf_status;
 
 typedef stf_status state_transition_fn(struct msg_digest *md);
+
+#ifdef OPENSSL
+extern int derive_symmetric_key( struct state *st, const chunk_t nonce,
+				 const u_char *seedptr,
+				 const size_t seedlen,
+				 keysched *ks,
+				 chunk_t *key );
+extern bool encrypt_payload( struct state *st, keysched *ks, u_char *iv,
+			   chunk_t inp, chunk_t *out );
+extern bool decrypt_payload( struct state *st, keysched *ks, u_char *iv,
+			     chunk_t inp, chunk_t *out );
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/dir2hash.c freeswan-1.91/pluto/dir2hash.c
--- freeswan-1.91.orig/pluto/dir2hash.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/dir2hash.c	Tue Jul  3 02:10:21 2001
@@ -0,0 +1,1071 @@
+/*
+ * Convert an XMAP hash directory to a Berkeley DB hash file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <ctype.h>
+
+#ifdef HAVE_DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include <openssl/pem.h>
+#include <openssl/bio.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#define VERSION_SIZE 4
+static unsigned char version_data[] = { '\00', '\00', '\00', '\01' };
+
+#define TAGLEN 4
+
+#define UID_PREFIX "uid-"
+
+#define X509_TYPE 0
+#define X509_CRL_TYPE 1
+
+typedef struct _cert_st {
+  u_int8_t type;
+  union _inf {
+    X509 *x;
+    X509_CRL *c;
+  } info;
+  unsigned char *d;
+  size_t dlen;
+  unsigned char digest[SHA_DIGEST_LENGTH];
+  struct _cert_st *next;
+} CERT;
+
+typedef struct _xname_list_st {
+  unsigned char digest[SHA_DIGEST_LENGTH];
+  struct _xname_list_st *next;
+} XNAME_LIST;
+
+typedef struct _xname_st {
+  unsigned char *d;
+  size_t dlen;
+  int lcount;
+  XNAME_LIST *list;
+  struct _xname_st *next;
+} XNAME;
+
+static const char *hashout = "certhash.db";
+
+void *nalloc( size_t s );
+void dump( unsigned char *p, size_t l, const char *name );
+void free_xname_list_node( XNAME_LIST *node );
+void free_xname_node( XNAME *node );
+void free_xnames( XNAME **nl );
+XNAME *alloc_xname_node( const unsigned char *n, const size_t s );
+int add_unique_xname( XNAME **nl, X509_NAME *name,
+		      const unsigned char *digest );
+int add_unique_xname( XNAME **nl, X509_NAME *name,
+		      const unsigned char *digest );
+void add_unique_dns(XNAME **nl, X509 *x, const unsigned char *digest );
+void add_unique_ip(XNAME **nl, X509 *x, const unsigned char *digest );
+int isCA( X509 *x );
+void free_cert_node( CERT *c );
+int add_unique_xinf( CERT **cl, XNAME **xl,
+		     XNAME **cal, XNAME **dnl, XNAME **ipl,
+		     unsigned int type, void *x );
+void putcerts(DB *db, int start, int end, char *argv[],
+	      CERT **cl, XNAME **xl, XNAME **cal, XNAME **dnl, XNAME **ipl);
+void free_cert_list( CERT **cl );
+void putcrls(DB *db, int start, int end, char *argv[], CERT **cl, XNAME **xl);
+int add_unique_uid(XNAME **ul, X509 *x, const char *uid);
+void putuids(DB *db, int start, int end, char *argv[], XNAME **ul);
+
+void *
+nalloc( size_t s )
+{
+  void *t = malloc(s);
+
+  if (!t) {
+    fprintf(stderr, "cannot allocate %d bytes\n", s);
+    exit(-1);
+  }
+  return t;
+}
+
+void
+dump( unsigned char *p, size_t l, const char *name )
+{
+  int i;
+
+  printf("%s: (length %d)\n", name, l);
+  for(i=0; i<l; i++) {
+    printf("%02X", p[i]);
+    if (i < l-1) putchar((i % 16 == 15) ? '\n' : ':');
+  }
+  printf("\n");
+}
+
+void
+free_xname_list_node( XNAME_LIST *node )
+{
+  free(node);
+}
+
+void
+free_xname_node( XNAME *node )
+{
+  XNAME_LIST *xl, *p;
+
+  if (node->d) free(node->d);
+  for(xl=node->list; xl;) {
+    p = xl->next;
+    free_xname_list_node(xl);
+    xl = p;
+  }
+  free(node);
+}
+
+void
+free_xnames( XNAME **nl )
+{
+  XNAME *l, *p;
+
+  if (!nl) return;
+  for(l = *nl; l; ) {
+    p = l->next;
+    free_xname_node(l);
+    l = p;
+  }
+  *nl = NULL;
+}
+
+XNAME *
+alloc_xname_node( const unsigned char *n, const size_t s )
+{
+  /* Create an empty list for name store in n */
+  XNAME *ret;
+
+  ret = nalloc(sizeof(XNAME));
+  ret->lcount = 0;
+  ret->list = NULL;
+  ret->dlen = s;
+  ret->d = nalloc(s);
+  memcpy(ret->d, n, s);
+  ret->next = NULL;
+
+  return ret;
+}
+
+int
+add_unique_xname( XNAME **nl, X509_NAME *name,
+		  const unsigned char *digest )
+{
+  unsigned char *d, *dum;
+  size_t dlen;
+  XNAME *p;
+  int found, res = 1;
+
+  /* Create DER form of name */
+
+  if (name == NULL) {
+    dlen = 1;
+    d = nalloc(dlen);
+    d[0] = '\0';
+  } else {
+    dlen = i2d_X509_NAME(name, NULL);
+    d = nalloc(dlen); dum = d;
+    i2d_X509_NAME(name, &dum);
+  }
+
+  /* Search nl for name */
+  for (p=*nl, found = 0; ((!found) && (p));
+       (!found) ? p=p->next : p)
+    if ((dlen == p->dlen) && (memcmp(d, p->d, dlen) == 0)) found = 1;
+
+  if (found) {
+    XNAME_LIST *pp;
+
+    /* add digest to list of names if not already there */
+    for(pp = p->list, found = 0; ((!found) && (pp));
+	(!found) ? pp=pp->next : pp)
+      if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+    
+    if (!found) {
+      XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+      n->next = p->list;
+      memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+      p->list = n;
+      p->lcount++;
+    } else
+      res = 0;
+  } else {
+    p = alloc_xname_node(d, dlen);
+    p->list = nalloc(sizeof(XNAME_LIST));
+    p->list->next = NULL;
+    memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+    p->lcount = 1;
+    p->next = *nl;
+    *nl = p;
+  }
+  free(d);
+  return res;
+}
+
+void
+add_unique_dns(XNAME **nl, X509 *x, const unsigned char *digest )
+{
+  unsigned char *d;
+  size_t dlen;
+  XNAME *p;
+  int found, res = 1;
+  int i, loc;
+  u_char *pp;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  X509_EXTENSION *ext;
+  GENERAL_NAME *gn;
+
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) < 0) return;
+  if ((ext = X509_get_ext(x, loc)) == NULL) return;
+  pp = ext->value->data;
+  d2i_GENERAL_NAMES(&nsk, &pp, ext->value->length);
+  if (!nsk) return;
+  for(i=0; i<sk_GENERAL_NAME_num(nsk); i++) {
+    gn = sk_GENERAL_NAME_value(nsk, i);
+
+    if (gn->type == GEN_DNS) {
+      dlen = gn->d.ia5->length;
+      d = nalloc(dlen);
+      memcpy(d, gn->d.ia5->data, dlen);
+
+      for (p=*nl, found = 0; ((!found) && (p));
+	   (!found) ? p=p->next : p)
+	if ((dlen == p->dlen) && (memcmp(d, p->d, dlen) == 0)) found = 1;
+
+      if (found) {
+	XNAME_LIST *pp;
+	
+	/* add digest to list of names if not already there */
+	for(pp = p->list, found = 0; ((!found) && (pp));
+	    (!found) ? pp=pp->next : pp)
+	  if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+	
+	if (!found) {
+	  XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+	  n->next = p->list;
+	  memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+	  p->list = n;
+	  p->lcount++;
+	} else
+	  res = 0;
+      } else {
+	p = alloc_xname_node(d, dlen);
+	p->list = nalloc(sizeof(XNAME_LIST));
+	p->list->next = NULL;
+	memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+	p->lcount = 1;
+	p->next = *nl;
+	*nl = p;
+      }
+      free(d);
+    }
+  }
+  sk_GENERAL_NAME_free(nsk);
+}
+
+void
+add_unique_ip(XNAME **nl, X509 *x, const unsigned char *digest )
+{
+  unsigned char *d;
+  size_t dlen;
+  XNAME *p;
+  int found, res = 1;
+  int i, loc;
+  u_char *pp;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  X509_EXTENSION *ext;
+  GENERAL_NAME *gn;
+
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) < 0) return;
+  if ((ext = X509_get_ext(x, loc)) == NULL) return;
+  pp = ext->value->data;
+  d2i_GENERAL_NAMES(&nsk, &pp, ext->value->length);
+  if (!nsk) return;
+  for(i=0; i<sk_GENERAL_NAME_num(nsk); i++) {
+    gn = sk_GENERAL_NAME_value(nsk, i);
+
+    if (gn->type == GEN_IPADD) {
+      dlen = gn->d.ip->length;
+      d = nalloc(dlen);
+      memcpy(d, gn->d.ip->data, dlen);
+
+      for (p=*nl, found = 0; ((!found) && (p));
+	   (!found) ? p=p->next : p)
+	if ((dlen == p->dlen) && (memcmp(d, p->d, dlen) == 0)) found = 1;
+
+      if (found) {
+	XNAME_LIST *pp;
+	
+	/* add digest to list of names if not already there */
+	for(pp = p->list, found = 0; ((!found) && (pp));
+	    (!found) ? pp=pp->next : pp)
+	  if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+	
+	if (!found) {
+	  XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+	  n->next = p->list;
+	  memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+	  p->list = n;
+	  p->lcount++;
+	} else
+	  res = 0;
+      } else {
+	p = alloc_xname_node(d, dlen);
+	p->list = nalloc(sizeof(XNAME_LIST));
+	p->list->next = NULL;
+	memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+	p->lcount = 1;
+	p->next = *nl;
+	*nl = p;
+      }
+      free(d);
+    }
+  }
+  sk_GENERAL_NAME_free(nsk);
+}
+
+int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+void
+free_cert_node( CERT *c )
+{
+  if (c->d) free(c->d);
+  c->d = NULL;
+  switch(c->type) {
+    case X509_TYPE: if (c->info.x) X509_free(c->info.x); break;
+    case X509_CRL_TYPE: if (c->info.c) X509_CRL_free(c->info.c); break;
+  }
+  c->info.x = NULL;
+  memset(c->digest, 0, SHA_DIGEST_LENGTH);
+  c->next = NULL;
+  free(c);
+}
+
+int
+add_unique_xinf( CERT **cl, XNAME **xl,
+		 XNAME **cal, XNAME **dnl, XNAME **ipl,
+		 unsigned int type, void *x )
+{
+  int f;
+  CERT *p, *node;
+  unsigned char *dum;
+
+  if (!cl) return 0;
+
+  node = nalloc(sizeof(CERT));
+  node->next = NULL;
+  node->type = type;
+  switch(type) {
+  case X509_TYPE:
+    node->info.x = (X509 *)x;
+    node->dlen = i2d_X509((X509 *)x, NULL);
+    node->d = nalloc(node->dlen);
+    dum = node->d;
+    i2d_X509( (X509 *)x, &dum );
+    break;
+  case X509_CRL_TYPE:
+    node->info.c = (X509_CRL *)x;
+    node->dlen = i2d_X509_CRL((X509_CRL *)x, NULL);
+    node->d = nalloc(node->dlen);
+    dum = node->d;
+    i2d_X509_CRL( (X509_CRL *)x, &dum );
+    break;
+  default:
+    fprintf(stderr, "Unknown info type: %d\n", type);
+    free(node);
+    return 0;
+  }
+
+  SHA1(node->d, node->dlen, node->digest);
+
+  for(p=*cl, f=0; (!f) && (p); p=p->next)
+    if (memcmp(p->digest, node->digest, SHA_DIGEST_LENGTH) == 0) f=1;
+    /* found a duplicate */
+
+  if (!f) {
+    /* insert at head of list */
+    node->next = *cl;
+    *cl = node;
+    switch(type) {
+    case X509_TYPE:
+      add_unique_xname(xl, X509_get_subject_name((X509 *)x), node->digest);
+      if (isCA(x)) add_unique_xname(cal, NULL, node->digest);
+      add_unique_dns(dnl, (X509 *)x, node->digest);
+      add_unique_ip(ipl, (X509 *)x, node->digest);
+      break;
+    case X509_CRL_TYPE:
+      add_unique_xname(xl, X509_CRL_get_issuer((X509_CRL *)x), node->digest);
+      break;
+    }
+    return 1;
+  } else
+    return 0;
+}
+
+void
+free_cert_list( CERT **cl )
+{
+  CERT *c;
+
+  if (!cl) return;
+
+  for(c=*cl; c;) {
+    CERT *p = c->next;
+
+    free_cert_node(c);
+    c = p;
+  }
+  *cl = NULL;
+}
+
+static char dirname[PATH_MAX+1];
+static int
+select_files(const struct dirent *de)
+{
+  struct stat st;
+  char path[PATH_MAX+1];
+
+  snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
+  if (lstat(path, &st) == 0) {
+    if (S_ISREG(st.st_mode))
+      return 1;
+    else
+      return 0;
+  } else {
+    perror("stat");
+    return 0;
+  }
+}
+
+static int
+select_uid_files(const struct dirent *de)
+{
+  struct stat st;
+  char path[PATH_MAX+1];
+
+  if (strncasecmp(UID_PREFIX, de->d_name, strlen(UID_PREFIX)) != 0) return 0;
+  snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
+  if (lstat(path, &st) == 0) {
+    if ((S_ISREG(st.st_mode)) || (S_ISLNK(st.st_mode)))
+      return 1;
+    else
+      return 0;
+  } else {
+    perror("stat");
+    return 0;
+  }
+}
+
+void
+putcerts(DB *db, int start, int end, char *argv[],
+	 CERT **cl, XNAME **xl, XNAME **cal, XNAME **dnl, XNAME **ipl)
+{
+  int i, j, n;
+  struct dirent **namelist = NULL;
+  char path[PATH_MAX+1];
+
+  for(i=start; i<end; i++) {
+    printf("Dumping certs from directory \"%s\"\n", argv[i]);
+    snprintf(dirname, sizeof(dirname)-1, "%s", argv[i]);
+    if ((n = scandir(argv[i], &namelist, select_files, alphasort)) >= 0) {
+      for(j=0; j<n; j++) {
+	BIO *b;
+
+	printf("File: %s\n", namelist[j]->d_name);
+	snprintf(path, sizeof(path), "%s/%s", argv[i], namelist[j]->d_name);
+	if ((b = BIO_new_file(path, "r")) != NULL) {
+	  X509 *x;
+
+	  if (!(x = PEM_read_bio_X509(b, NULL, NULL, NULL))) {
+	    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	    x = d2i_X509_bio(b, NULL);
+	  }
+	  if ((x) && (!add_unique_xinf(cl, xl, cal, dnl, ipl, X509_TYPE, x)))
+	    X509_free(x);
+	  BIO_free(b);
+	}
+      }
+      free(namelist);
+    } else
+      perror("scandir");
+  }
+}
+
+void
+putcrls(DB *db, int start, int end, char *argv[], CERT **cl, XNAME **xl)
+{
+  int i, j, n;
+  struct dirent **namelist = NULL;
+  char path[PATH_MAX+1];
+
+  for(i=start; i<end; i++) {
+    printf("Dumping CRLs from directory \"%s\"\n", argv[i]);
+    snprintf(dirname, sizeof(dirname)-1, "%s", argv[i]);
+    if ((n = scandir(argv[i], &namelist, select_files, alphasort)) >= 0) {
+      for(j=0; j<n; j++) {
+	BIO *b;
+
+	printf("File: %s\n", namelist[j]->d_name);
+	snprintf(path, sizeof(path), "%s/%s", argv[i], namelist[j]->d_name);
+	if ((b = BIO_new_file(path, "r")) != NULL) {
+	  X509_CRL *c;
+
+	  if (!(c = PEM_read_bio_X509_CRL(b, NULL, NULL, NULL))) {
+	    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	    c = d2i_X509_CRL_bio(b, NULL);
+	  }
+	  if ((c) &&
+	      (!add_unique_xinf(cl, xl, NULL, NULL, NULL,X509_CRL_TYPE, c)))
+	    X509_CRL_free(c);
+
+	  BIO_free(b);
+	}
+      }
+      free(namelist);
+    } else
+      perror("scandir");
+  }
+}
+
+int
+add_unique_uid(XNAME **ul, X509 *x, const char *uid)
+{
+  int found;
+  XNAME *p;
+  unsigned char digest[SHA_DIGEST_LENGTH], *d, *dum;
+  size_t dlen;
+
+  if (!x || !ul) return 0;
+
+  dlen = i2d_X509(x, NULL);
+  d = nalloc(dlen);
+  dum = d;
+  i2d_X509( x, &dum );
+
+  SHA1(d, dlen, digest);
+  free(d);
+
+  printf("Adding user id \"%s\"\n", uid);
+  for(found=0, p=*ul; ((!found) && (p)); 
+      (!found) ? p=p->next : p)
+    if ((strlen(uid) == p->dlen) && (memcmp(p->d, uid, p->dlen) == 0))
+      found = 1;
+
+  if (found) {
+    XNAME_LIST *pp;
+    
+    for(pp = p->list, found = 0; ((!found) && (pp));
+	pp=(!found) ? pp->next : pp)
+      if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+    
+    if (!found) {
+      XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+      n->next = p->list;
+      memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+      p->list = n;
+      p->lcount++;
+    } else
+      return 0;
+  } else {
+    p = alloc_xname_node(uid, strlen(uid));
+    p->list = nalloc(sizeof(XNAME_LIST));
+    p->list->next = NULL;
+    memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+    p->lcount = 1;
+    p->next = *ul;
+    *ul = p;
+    return 1;
+  }
+  return 0;
+}
+
+static int
+isuidchar( char c )
+{
+  if (isalnum(c)) return 1;
+  if (c == '_') return 1;
+  return 0;
+}
+
+void
+putuids(DB *db, int start, int end, char *argv[], XNAME **ul)
+{
+  int i, j, n;
+  struct dirent **namelist = NULL;
+  char path[PATH_MAX+1];
+
+  for(i=start; i<end; i++) {
+    printf("Dumping uids from directory \"%s\"\n", argv[i]);
+    snprintf(dirname, sizeof(dirname)-1, "%s", argv[i]);
+    if ((n = scandir(argv[i], &namelist, select_uid_files, alphasort)) >= 0) {
+      for(j=0; j<n; j++) {
+	BIO *b;
+	char *n, *nn;
+
+	printf("File: %s\n", namelist[j]->d_name);
+	snprintf(path, sizeof(path), "%s/%s", argv[i], namelist[j]->d_name);
+	if ((b = BIO_new_file(path, "r")) != NULL) {
+	  X509 *x;
+
+	  if (!(x = PEM_read_bio_X509(b, NULL, NULL, NULL))) {
+	    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	    x = d2i_X509_bio(b, NULL);
+	  }
+
+	  n = nn = strdup(&(namelist[j]->d_name[strlen(UID_PREFIX)]));
+	  while ((*nn) && (isuidchar(*nn))) nn++;
+	  *nn = '\0';
+	  if ((x) && (!add_unique_uid(ul, x, n))) X509_free(x);
+
+	  BIO_free(b);
+	}
+      }
+      free(namelist);
+    } else
+      perror("scandir");
+  }
+}
+
+int
+main( int argc, char *argv[] )
+{
+  int c;
+  DB *db;
+  CERT *clist = NULL, *crlist = NULL;
+  XNAME *xlist = NULL, *nlist = NULL, *xcrlist = NULL, *calist = NULL;
+  XNAME *dnlist = NULL, *iplist = NULL;
+
+  while(1) {
+    int option_index = 0;
+    static struct option long_options[] = {
+      { "output", 1, 0, 0 },
+      { 0, 0, 0, 0 }
+    };
+
+    c = getopt_long(argc, argv, "o:",
+		    long_options, &option_index);
+    if (c == -1) break;
+
+    switch(c) {
+    case 0:
+      if (strcasecmp(long_options[option_index].name, "output") == 0)
+	hashout = optarg;
+      break;
+    case 'o':
+      hashout = optarg;
+      break;
+    case '?':
+      break;
+    default:
+      printf("?? getopt returned character code 0%o ??\n", c);
+    }
+  }
+
+  X509V3_add_standard_extensions();
+
+  if ((db = dbopen(hashout, O_CREAT | O_TRUNC | O_RDWR, 0644, DB_HASH, NULL)) == NULL) {
+    perror("dbopen");
+  } else {
+    DBT k, v;
+    CERT *c;
+    XNAME *x;
+    unsigned char *kk, *vv;
+
+    memset(&k, 0, sizeof(DBT));
+    memset(&v, 0, sizeof(DBT));
+    k.data = strdup("\xFF\xFF\xFF\xFFversion");
+    k.size = strlen("version") + TAGLEN;
+    v.data = version_data;
+    v.size = VERSION_SIZE;
+
+    if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+    db->sync(db, 0);
+    free(k.data);
+
+    putcerts(db, optind, argc, argv,
+	     &clist, &xlist,
+	     &calist, &dnlist, &iplist);
+    putcrls(db, optind, argc, argv, &crlist, &xcrlist);
+    putuids(db, optind, argc, argv, &nlist);
+
+    for(c=clist; c; c=c->next) {
+      k.size = SHA_DIGEST_LENGTH+TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = c->dlen;
+      v.data = nalloc(v.size);
+
+      kk = k.data;
+      vv = v.data;
+      memset(kk, 0, TAGLEN);
+      memcpy(&kk[TAGLEN], c->digest, SHA_DIGEST_LENGTH);
+      memcpy(vv, c->d, c->dlen);
+
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_cert_list(&clist);
+
+    for(x=xlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\01';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) < 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&xlist);
+
+    for(x=calist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\05';
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&calist);
+
+    for(x=dnlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\06';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&dnlist);
+
+    for(x=iplist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\07';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&iplist);
+
+    for(c=crlist; c; c=c->next) {
+      k.size = SHA_DIGEST_LENGTH+TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = c->dlen;
+      v.data = nalloc(v.size);
+
+      kk = k.data;
+      vv = v.data;
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\04';
+      memcpy(&kk[TAGLEN], c->digest, SHA_DIGEST_LENGTH);
+      memcpy(vv, c->d, c->dlen);
+
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_cert_list(&crlist);
+
+    for(x=xcrlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\02';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&xcrlist);
+
+    for(x=nlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\03';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&nlist);
+    db->close(db);
+  }
+
+  printf("Dumping keys from DB file\n");
+  if ((db = dbopen(hashout, 0, 0, DB_HASH, NULL)) == NULL) {
+    perror("db_open");
+  } else {
+    DBT k, v;
+    int i;
+
+    memset(&k, 0, sizeof(k));
+    memset(&v, 0, sizeof(v));
+    while (db->seq(db, &k, &v, R_NEXT) == 0) {
+      if (k.size < TAGLEN)
+	fprintf(stderr, "Error: key value too short\n");
+      else {
+	unsigned char *kk = k.data, *vv = v.data, *p;
+	u_int32_t c1, c2;
+	X509_NAME *xn;
+	
+	switch(kk[TAGLEN-1]) {
+	case 0:
+	  printf("X509 Certificate\n");
+	  dump(&kk[TAGLEN], k.size-TAGLEN, "SHA-DIGEST");
+	  printf("Data Length %d\n", v.size);
+	  break;
+	case 1:
+	  printf("X509 Subject Name\n");
+	  p = &kk[TAGLEN];
+	  if ((xn = d2i_X509_NAME(NULL, &p, k.size-TAGLEN)) != NULL) {
+	    char buf[256];
+	    
+	    X509_NAME_oneline(xn, buf, sizeof(buf));
+	    printf("%s:\n", buf);
+	    X509_NAME_free(xn);
+	    memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	    c2 = ntohl(c1);
+	    if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	      fprintf(stderr, "X509 name length error\n");
+	    } else {
+	      for(i=0; i<c2; i++)
+		dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		      SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	    }
+	    printf("\n");
+	  }
+	  break;
+	case 0x02:
+	  printf("X509 CRL Issuer Name\n");
+	  p = &kk[TAGLEN];
+	  if ((xn = d2i_X509_NAME(NULL, &p, k.size-TAGLEN)) != NULL) {
+	    char buf[256];
+	    
+	    X509_NAME_oneline(xn, buf, sizeof(buf));
+	    printf("%s:\n", buf);
+	    X509_NAME_free(xn);
+	    memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	    c2 = ntohl(c1);
+	    if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	      fprintf(stderr, "X509 name length error\n");
+	    } else {
+	      for(i=0; i<c2; i++)
+		dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		      SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	    }
+	    printf("\n");
+	  }
+	  break;
+	case 0x03:
+	  printf("UID: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%c", isprint(kk[i]) ? kk[i] : '?');
+	  printf("\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0x04:
+	  printf("X509 Certificate Revocation List\n");
+	  dump(&kk[TAGLEN], k.size-TAGLEN, "SHA-DIGEST");
+	  printf("Data Length %d\n", v.size);
+	  break;
+	case 0x05:
+	  printf("CA Certificate:\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0x06:
+	  printf("DNS: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%c", isprint(kk[i]) ? kk[i] : '?');
+	  printf("\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0x07:
+	  printf("IPv4: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%d.", kk[i]);
+	  printf("\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0xFF:
+	  printf("Metainfo: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%c", isprint(kk[i]) ? kk[i] : '?');
+	  printf(":- ");
+	  dump(v.data, v.size, "Value");
+	  printf("\n");
+	  break;
+	default:
+	  fprintf(stderr, "Error in type field: %02X\n", kk[TAGLEN-1]);
+	  break;
+	}
+      }
+    }
+    db->close(db);
+  }
+  printf("Done\n");
+
+  X509V3_EXT_cleanup();
+  return 0;
+}
+
+
diff -BbruN freeswan-1.91.orig/pluto/dsa.c freeswan-1.91/pluto/dsa.c
--- freeswan-1.91.orig/pluto/dsa.c	Mon Nov  1 16:52:39 1999
+++ freeswan-1.91/pluto/dsa.c	Wed Dec 31 19:00:00 1969
@@ -1,476 +0,0 @@
-/* dsa.c  -  DSA signature scheme
- *	Copyright (C) 1998 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef PLUTO
-#include <gmp.h>
-#include <freeswan.h>
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "rnd.h"
-#include "gcryptfix.h"
-#else /*! PLUTO */
-/* #include <config.h> */
-#endif /* !PLUTO */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef PLUTO
-/* #include <assert.h> */
-/* #include "util.h" */
-/* #include "mpi.h" */
-/* #include "cipher.h" */
-#endif
-
-#include "dsa.h"
-
-typedef struct {
-    MPI p;	    /* prime */
-    MPI q;	    /* group order */
-    MPI g;	    /* group generator */
-    MPI y;	    /* g^x mod p */
-} DSA_public_key;
-
-
-typedef struct {
-    MPI p;	    /* prime */
-    MPI q;	    /* group order */
-    MPI g;	    /* group generator */
-    MPI y;	    /* g^x mod p */
-    MPI x;	    /* secret exponent */
-} DSA_secret_key;
-
-
-static MPI gen_k( MPI q );
-static void test_keys( DSA_secret_key *sk, unsigned qbits );
-static int  check_secret_key( DSA_secret_key *sk );
-static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
-static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
-static int  verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
-
-static void
-progress( int c )
-{
-    fputc( c, stderr );
-}
-
-
-/****************
- * Generate a random secret exponent k less than q
- */
-static MPI
-gen_k( MPI q )
-{
-    MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
-    unsigned int nbits = mpi_get_nbits(q);
-    unsigned int nbytes = (nbits+7)/8;
-    char *rndbuf = NULL;
-
-    if( DBG_CIPHER )
-	log_debug("choosing a random k ");
-    for(;;) {
-	if( DBG_CIPHER )
-	    progress('.');
-
-	if( !rndbuf || nbits < 32 ) {
-	    m_free(rndbuf);
-	    rndbuf = get_random_bits( nbits, 1, 1 );
-	}
-	else { /* change only some of the higher bits */
-	    /* we could imporove this by directly requesting more memory
-	     * at the first call to get_random_bits() and use this the here
-	     * maybe it is easier to do this directly in random.c */
-	    char *pp = get_random_bits( 32, 1, 1 );
-	    memcpy( rndbuf,pp, 4 );
-	    m_free(pp);
-	}
-	mpi_set_buffer( k, rndbuf, nbytes, 0 );
-	if( mpi_test_bit( k, nbits-1 ) )
-	    mpi_set_highbit( k, nbits-1 );
-	else {
-	    mpi_set_highbit( k, nbits-1 );
-	    mpi_clear_bit( k, nbits-1 );
-	}
-
-	if( !(mpi_cmp( k, q ) < 0) ) {	/* check: k < q */
-	    if( DBG_CIPHER )
-		progress('+');
-	    continue; /* no  */
-	}
-	if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
-	    if( DBG_CIPHER )
-		progress('-');
-	    continue; /* no */
-	}
-	break;	/* okay */
-    }
-    m_free(rndbuf);
-    if( DBG_CIPHER )
-	progress('\n');
-
-    return k;
-}
-
-
-static void
-test_keys( DSA_secret_key *sk, unsigned qbits )
-{
-    DSA_public_key pk;
-    MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
-    MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
-    MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
-
-    pk.p = sk->p;
-    pk.q = sk->q;
-    pk.g = sk->g;
-    pk.y = sk->y;
-    /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
-    {	char *p = get_random_bits( qbits, 0, 0 );
-	mpi_set_buffer( test, p, (qbits+7)/8, 0 );
-	m_free(p);
-    }
-
-    sign( out1_a, out1_b, test, sk );
-    if( !verify( out1_a, out1_b, test, &pk ) )
-	log_fatal("DSA:: sign, verify failed\n");
-
-    mpi_free( test );
-    mpi_free( out1_a );
-    mpi_free( out1_b );
-}
-
-
-
-/****************
- * Generate a DSA key pair with a key of size NBITS
- * Returns: 2 structures filled with all needed values
- *	    and an array with the n-1 factors of (p-1)
- */
-static void
-generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
-{
-    MPI p;    /* the prime */
-    MPI q;    /* the 160 bit prime factor */
-    MPI g;    /* the generator */
-    MPI y;    /* g^x mod p */
-    MPI x;    /* the secret exponent */
-    MPI h, e;  /* helper */
-    unsigned qbits;
-    byte *rndbuf;
-
-    assert( nbits >= 512 && nbits <= 1024 );
-
-    qbits = 160;
-    p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
-    /* get q out of factors */
-    q = mpi_copy((*ret_factors)[0]);
-    if( mpi_get_nbits(q) != qbits )
-	BUG();
-
-    /* find a generator g (h and e are helpers)*/
-    /* e = (p-1)/q */
-    e = mpi_alloc( mpi_get_nlimbs(p) );
-    mpi_sub_ui( e, p, 1 );
-    mpi_fdiv_q( e, e, q );
-    g = mpi_alloc( mpi_get_nlimbs(p) );
-    h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
-    do {
-	mpi_add_ui( h, h, 1 );
-	/* g = h^e mod p */
-	mpi_powm( g, h, e, p );
-    } while( !mpi_cmp_ui( g, 1 ) );  /* continue until g != 1 */
-
-    /* select a random number which has these properties:
-     *	 0 < x < q-1
-     * This must be a very good random number because this
-     * is the secret part. */
-    if( DBG_CIPHER )
-	log_debug("choosing a random x ");
-    assert( qbits >= 160 );
-    x = mpi_alloc_secure( mpi_get_nlimbs(q) );
-    mpi_sub_ui( h, q, 1 );  /* put q-1 into h */
-    rndbuf = NULL;
-    do {
-	if( DBG_CIPHER )
-	    progress('.');
-	if( !rndbuf )
-	    rndbuf = get_random_bits( qbits, 2, 1 );
-	else { /* change only some of the higher bits (= 2 bytes)*/
-	    char *r = get_random_bits( 16, 2, 1 );
-	    memcpy(rndbuf, r, 16/8 );
-	    m_free(r);
-	}
-	mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
-	mpi_clear_highbit( x, qbits+1 );
-    } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
-    m_free(rndbuf);
-    mpi_free( e );
-    mpi_free( h );
-
-    /* y = g^x mod p */
-    y = mpi_alloc( mpi_get_nlimbs(p) );
-    mpi_powm( y, g, x, p );
-
-    if( DBG_CIPHER ) {
-	progress('\n');
-	log_mpidump("dsa  p= ", p );
-	log_mpidump("dsa  q= ", q );
-	log_mpidump("dsa  g= ", g );
-	log_mpidump("dsa  y= ", y );
-	log_mpidump("dsa  x= ", x );
-    }
-
-    /* copy the stuff to the key structures */
-    sk->p = p;
-    sk->q = q;
-    sk->g = g;
-    sk->y = y;
-    sk->x = x;
-
-    /* now we can test our keys (this should never fail!) */
-    test_keys( sk, qbits );
-}
-
-
-
-/****************
- * Test whether the secret key is valid.
- * Returns: if this is a valid key.
- */
-static int
-check_secret_key( DSA_secret_key *sk )
-{
-    int rc;
-    MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
-
-    mpi_powm( y, sk->g, sk->x, sk->p );
-    rc = !mpi_cmp( y, sk->y );
-    mpi_free( y );
-    return rc;
-}
-
-
-
-/****************
- * Make a DSA signature from HASH and put it into r and s.
- */
-
-static void
-sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
-{
-    MPI k;
-    MPI kinv;
-    MPI tmp;
-
-    /* select a random k with 0 < k < q */
-    k = gen_k( skey->q );
-
-    /* r = (a^k mod p) mod q */
-    mpi_powm( r, skey->g, k, skey->p );
-    mpi_fdiv_r( r, r, skey->q );
-
-    /* kinv = k^(-1) mod q */
-    kinv = mpi_alloc( mpi_get_nlimbs(k) );
-    mpi_invm(kinv, k, skey->q );
-
-    /* s = (kinv * ( hash + x * r)) mod q */
-    tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
-    mpi_mul( tmp, skey->x, r );
-    mpi_add( tmp, tmp, hash );
-    mpi_mulm( s , kinv, tmp, skey->q );
-
-    mpi_free(k);
-    mpi_free(kinv);
-    mpi_free(tmp);
-}
-
-
-/****************
- * Returns true if the signature composed from R and S is valid.
- */
-static int
-verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
-{
-    int rc;
-    MPI w, u1, u2, v;
-    MPI base[3];
-    MPI exp[3];
-
-
-    if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
-	return 0; /* assertion	0 < r < q  failed */
-    if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
-	return 0; /* assertion	0 < s < q  failed */
-
-    w  = mpi_alloc( mpi_get_nlimbs(pkey->q) );
-    u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
-    u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
-    v  = mpi_alloc( mpi_get_nlimbs(pkey->p) );
-
-    /* w = s^(-1) mod q */
-    mpi_invm( w, s, pkey->q );
-
-    /* u1 = (hash * w) mod q */
-    mpi_mulm( u1, hash, w, pkey->q );
-
-    /* u2 = r * w mod q  */
-    mpi_mulm( u2, r, w, pkey->q );
-
-    /* v =  g^u1 * y^u2 mod p mod q */
-    base[0] = pkey->g; exp[0] = u1;
-    base[1] = pkey->y; exp[1] = u2;
-    base[2] = NULL;    exp[2] = NULL;
-    mpi_mulpowm( v, base, exp, pkey->p );
-    mpi_fdiv_r( v, v, pkey->q );
-
-    rc = !mpi_cmp( v, r );
-
-    mpi_free(w);
-    mpi_free(u1);
-    mpi_free(u2);
-    mpi_free(v);
-    return rc;
-}
-
-
-/*********************************************
- **************  interface  ******************
- *********************************************/
-
-int
-dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
-{
-    DSA_secret_key sk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-
-    generate( &sk, nbits, retfactors );
-    skey[0] = sk.p;
-    skey[1] = sk.q;
-    skey[2] = sk.g;
-    skey[3] = sk.y;
-    skey[4] = sk.x;
-    return 0;
-}
-
-
-int
-dsa_check_secret_key( int algo, MPI *skey )
-{
-    DSA_secret_key sk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-    if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
-	return G10ERR_BAD_MPI;
-
-    sk.p = skey[0];
-    sk.q = skey[1];
-    sk.g = skey[2];
-    sk.y = skey[3];
-    sk.x = skey[4];
-    if( !check_secret_key( &sk ) )
-	return G10ERR_BAD_SECKEY;
-
-    return 0;
-}
-
-
-
-int
-dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
-{
-    DSA_secret_key sk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-    if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
-	return G10ERR_BAD_MPI;
-
-    sk.p = skey[0];
-    sk.q = skey[1];
-    sk.g = skey[2];
-    sk.y = skey[3];
-    sk.x = skey[4];
-    resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
-    resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
-    sign( resarr[0], resarr[1], data, &sk );
-    return 0;
-}
-
-int
-dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
-		    int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED)
-{
-    DSA_public_key pk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-    if( !data[0] || !data[1] || !hash
-	|| !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
-	return G10ERR_BAD_MPI;
-
-    pk.p = pkey[0];
-    pk.q = pkey[1];
-    pk.g = pkey[2];
-    pk.y = pkey[3];
-    if( !verify( data[0], data[1], hash, &pk ) )
-	return G10ERR_BAD_SIGN;
-    return 0;
-}
-
-
-
-unsigned
-dsa_get_nbits( int algo, MPI *pkey )
-{
-    if( algo != PUBKEY_ALGO_DSA )
-	return 0;
-    return mpi_get_nbits( pkey[0] );
-}
-
-
-/****************
- * Return some information about the algorithm.  We need algo here to
- * distinguish different flavors of the algorithm.
- * Returns: A pointer to string describing the algorithm or NULL if
- *	    the ALGO is invalid.
- * Usage: Bit 0 set : allows signing
- *	      1 set : allows encryption
- */
-const char *
-dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
-							 int *use )
-{
-    *npkey = 4;
-    *nskey = 5;
-    *nenc = 0;
-    *nsig = 2;
-
-    switch( algo ) {
-      case PUBKEY_ALGO_DSA:   *use = PUBKEY_USAGE_SIG; return "DSA";
-      default: *use = 0; return NULL;
-    }
-}
-
-
diff -BbruN freeswan-1.91.orig/pluto/dsa.h freeswan-1.91/pluto/dsa.h
--- freeswan-1.91.orig/pluto/dsa.h	Mon Nov  1 16:48:08 1999
+++ freeswan-1.91/pluto/dsa.h	Wed Dec 31 19:00:00 1969
@@ -1,32 +0,0 @@
-/* dsa.h  -  DSA signature scheme
- *	Copyright (C) 1998 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-#ifndef G10_DSA_H
-#define G10_DSA_H
-
-int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
-int dsa_check_secret_key( int algo, MPI *skey );
-int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
-int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
-		    int (*cmp)(void *, MPI), void *opaquev );
-unsigned dsa_get_nbits( int algo, MPI *pkey );
-const char *dsa_get_info( int algo, int *npkey, int *nskey,
-				    int *nenc, int *nsig, int *use );
-
-#endif /*G10_DSA_H*/
diff -BbruN freeswan-1.91.orig/pluto/g10_dsa.c freeswan-1.91/pluto/g10_dsa.c
--- freeswan-1.91.orig/pluto/g10_dsa.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/g10_dsa.c	Tue Jul  3 02:11:16 2001
@@ -0,0 +1,476 @@
+/* g10_dsa.c  -  DSA signature scheme
+ *	Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef PLUTO
+#include <gmp.h>
+#include <freeswan.h>
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "rnd.h"
+#include "gcryptfix.h"
+#else /*! PLUTO */
+/* #include <config.h> */
+#endif /* !PLUTO */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef PLUTO
+/* #include <assert.h> */
+/* #include "util.h" */
+/* #include "mpi.h" */
+/* #include "cipher.h" */
+#endif
+
+#include "g10_dsa.h"
+
+typedef struct {
+    MPI p;	    /* prime */
+    MPI q;	    /* group order */
+    MPI g;	    /* group generator */
+    MPI y;	    /* g^x mod p */
+} DSA_public_key;
+
+
+typedef struct {
+    MPI p;	    /* prime */
+    MPI q;	    /* group order */
+    MPI g;	    /* group generator */
+    MPI y;	    /* g^x mod p */
+    MPI x;	    /* secret exponent */
+} DSA_secret_key;
+
+
+static MPI gen_k( MPI q );
+static void test_keys( DSA_secret_key *sk, unsigned qbits );
+static int  check_secret_key( DSA_secret_key *sk );
+static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
+static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
+static int  verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
+
+static void
+progress( int c )
+{
+    fputc( c, stderr );
+}
+
+
+/****************
+ * Generate a random secret exponent k less than q
+ */
+static MPI
+gen_k( MPI q )
+{
+    MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
+    unsigned int nbits = mpi_get_nbits(q);
+    unsigned int nbytes = (nbits+7)/8;
+    char *rndbuf = NULL;
+
+    if( DBG_CIPHER )
+	log_debug("choosing a random k ");
+    for(;;) {
+	if( DBG_CIPHER )
+	    progress('.');
+
+	if( !rndbuf || nbits < 32 ) {
+	    m_free(rndbuf);
+	    rndbuf = get_random_bits( nbits, 1, 1 );
+	}
+	else { /* change only some of the higher bits */
+	    /* we could imporove this by directly requesting more memory
+	     * at the first call to get_random_bits() and use this the here
+	     * maybe it is easier to do this directly in random.c */
+	    char *pp = get_random_bits( 32, 1, 1 );
+	    memcpy( rndbuf,pp, 4 );
+	    m_free(pp);
+	}
+	mpi_set_buffer( k, rndbuf, nbytes, 0 );
+	if( mpi_test_bit( k, nbits-1 ) )
+	    mpi_set_highbit( k, nbits-1 );
+	else {
+	    mpi_set_highbit( k, nbits-1 );
+	    mpi_clear_bit( k, nbits-1 );
+	}
+
+	if( !(mpi_cmp( k, q ) < 0) ) {	/* check: k < q */
+	    if( DBG_CIPHER )
+		progress('+');
+	    continue; /* no  */
+	}
+	if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
+	    if( DBG_CIPHER )
+		progress('-');
+	    continue; /* no */
+	}
+	break;	/* okay */
+    }
+    m_free(rndbuf);
+    if( DBG_CIPHER )
+	progress('\n');
+
+    return k;
+}
+
+
+static void
+test_keys( DSA_secret_key *sk, unsigned qbits )
+{
+    DSA_public_key pk;
+    MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
+    MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
+    MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
+
+    pk.p = sk->p;
+    pk.q = sk->q;
+    pk.g = sk->g;
+    pk.y = sk->y;
+    /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
+    {	char *p = get_random_bits( qbits, 0, 0 );
+	mpi_set_buffer( test, p, (qbits+7)/8, 0 );
+	m_free(p);
+    }
+
+    sign( out1_a, out1_b, test, sk );
+    if( !verify( out1_a, out1_b, test, &pk ) )
+	log_fatal("DSA:: sign, verify failed\n");
+
+    mpi_free( test );
+    mpi_free( out1_a );
+    mpi_free( out1_b );
+}
+
+
+
+/****************
+ * Generate a DSA key pair with a key of size NBITS
+ * Returns: 2 structures filled with all needed values
+ *	    and an array with the n-1 factors of (p-1)
+ */
+static void
+generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
+{
+    MPI p;    /* the prime */
+    MPI q;    /* the 160 bit prime factor */
+    MPI g;    /* the generator */
+    MPI y;    /* g^x mod p */
+    MPI x;    /* the secret exponent */
+    MPI h, e;  /* helper */
+    unsigned qbits;
+    byte *rndbuf;
+
+    assert( nbits >= 512 && nbits <= 1024 );
+
+    qbits = 160;
+    p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
+    /* get q out of factors */
+    q = mpi_copy((*ret_factors)[0]);
+    if( mpi_get_nbits(q) != qbits )
+	BUG();
+
+    /* find a generator g (h and e are helpers)*/
+    /* e = (p-1)/q */
+    e = mpi_alloc( mpi_get_nlimbs(p) );
+    mpi_sub_ui( e, p, 1 );
+    mpi_fdiv_q( e, e, q );
+    g = mpi_alloc( mpi_get_nlimbs(p) );
+    h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
+    do {
+	mpi_add_ui( h, h, 1 );
+	/* g = h^e mod p */
+	mpi_powm( g, h, e, p );
+    } while( !mpi_cmp_ui( g, 1 ) );  /* continue until g != 1 */
+
+    /* select a random number which has these properties:
+     *	 0 < x < q-1
+     * This must be a very good random number because this
+     * is the secret part. */
+    if( DBG_CIPHER )
+	log_debug("choosing a random x ");
+    assert( qbits >= 160 );
+    x = mpi_alloc_secure( mpi_get_nlimbs(q) );
+    mpi_sub_ui( h, q, 1 );  /* put q-1 into h */
+    rndbuf = NULL;
+    do {
+	if( DBG_CIPHER )
+	    progress('.');
+	if( !rndbuf )
+	    rndbuf = get_random_bits( qbits, 2, 1 );
+	else { /* change only some of the higher bits (= 2 bytes)*/
+	    char *r = get_random_bits( 16, 2, 1 );
+	    memcpy(rndbuf, r, 16/8 );
+	    m_free(r);
+	}
+	mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
+	mpi_clear_highbit( x, qbits+1 );
+    } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
+    m_free(rndbuf);
+    mpi_free( e );
+    mpi_free( h );
+
+    /* y = g^x mod p */
+    y = mpi_alloc( mpi_get_nlimbs(p) );
+    mpi_powm( y, g, x, p );
+
+    if( DBG_CIPHER ) {
+	progress('\n');
+	log_mpidump("dsa  p= ", p );
+	log_mpidump("dsa  q= ", q );
+	log_mpidump("dsa  g= ", g );
+	log_mpidump("dsa  y= ", y );
+	log_mpidump("dsa  x= ", x );
+    }
+
+    /* copy the stuff to the key structures */
+    sk->p = p;
+    sk->q = q;
+    sk->g = g;
+    sk->y = y;
+    sk->x = x;
+
+    /* now we can test our keys (this should never fail!) */
+    test_keys( sk, qbits );
+}
+
+
+
+/****************
+ * Test whether the secret key is valid.
+ * Returns: if this is a valid key.
+ */
+static int
+check_secret_key( DSA_secret_key *sk )
+{
+    int rc;
+    MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
+
+    mpi_powm( y, sk->g, sk->x, sk->p );
+    rc = !mpi_cmp( y, sk->y );
+    mpi_free( y );
+    return rc;
+}
+
+
+
+/****************
+ * Make a DSA signature from HASH and put it into r and s.
+ */
+
+static void
+sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
+{
+    MPI k;
+    MPI kinv;
+    MPI tmp;
+
+    /* select a random k with 0 < k < q */
+    k = gen_k( skey->q );
+
+    /* r = (a^k mod p) mod q */
+    mpi_powm( r, skey->g, k, skey->p );
+    mpi_fdiv_r( r, r, skey->q );
+
+    /* kinv = k^(-1) mod q */
+    kinv = mpi_alloc( mpi_get_nlimbs(k) );
+    mpi_invm(kinv, k, skey->q );
+
+    /* s = (kinv * ( hash + x * r)) mod q */
+    tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
+    mpi_mul( tmp, skey->x, r );
+    mpi_add( tmp, tmp, hash );
+    mpi_mulm( s , kinv, tmp, skey->q );
+
+    mpi_free(k);
+    mpi_free(kinv);
+    mpi_free(tmp);
+}
+
+
+/****************
+ * Returns true if the signature composed from R and S is valid.
+ */
+static int
+verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
+{
+    int rc;
+    MPI w, u1, u2, v;
+    MPI base[3];
+    MPI exp[3];
+
+
+    if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
+	return 0; /* assertion	0 < r < q  failed */
+    if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
+	return 0; /* assertion	0 < s < q  failed */
+
+    w  = mpi_alloc( mpi_get_nlimbs(pkey->q) );
+    u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
+    u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
+    v  = mpi_alloc( mpi_get_nlimbs(pkey->p) );
+
+    /* w = s^(-1) mod q */
+    mpi_invm( w, s, pkey->q );
+
+    /* u1 = (hash * w) mod q */
+    mpi_mulm( u1, hash, w, pkey->q );
+
+    /* u2 = r * w mod q  */
+    mpi_mulm( u2, r, w, pkey->q );
+
+    /* v =  g^u1 * y^u2 mod p mod q */
+    base[0] = pkey->g; exp[0] = u1;
+    base[1] = pkey->y; exp[1] = u2;
+    base[2] = NULL;    exp[2] = NULL;
+    mpi_mulpowm( v, base, exp, pkey->p );
+    mpi_fdiv_r( v, v, pkey->q );
+
+    rc = !mpi_cmp( v, r );
+
+    mpi_free(w);
+    mpi_free(u1);
+    mpi_free(u2);
+    mpi_free(v);
+    return rc;
+}
+
+
+/*********************************************
+ **************  interface  ******************
+ *********************************************/
+
+int
+dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+{
+    DSA_secret_key sk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+
+    generate( &sk, nbits, retfactors );
+    skey[0] = sk.p;
+    skey[1] = sk.q;
+    skey[2] = sk.g;
+    skey[3] = sk.y;
+    skey[4] = sk.x;
+    return 0;
+}
+
+
+int
+dsa_check_secret_key( int algo, MPI *skey )
+{
+    DSA_secret_key sk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+    if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
+	return G10ERR_BAD_MPI;
+
+    sk.p = skey[0];
+    sk.q = skey[1];
+    sk.g = skey[2];
+    sk.y = skey[3];
+    sk.x = skey[4];
+    if( !check_secret_key( &sk ) )
+	return G10ERR_BAD_SECKEY;
+
+    return 0;
+}
+
+
+
+int
+dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
+{
+    DSA_secret_key sk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+    if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
+	return G10ERR_BAD_MPI;
+
+    sk.p = skey[0];
+    sk.q = skey[1];
+    sk.g = skey[2];
+    sk.y = skey[3];
+    sk.x = skey[4];
+    resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
+    resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
+    sign( resarr[0], resarr[1], data, &sk );
+    return 0;
+}
+
+int
+dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
+		    int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED)
+{
+    DSA_public_key pk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+    if( !data[0] || !data[1] || !hash
+	|| !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
+	return G10ERR_BAD_MPI;
+
+    pk.p = pkey[0];
+    pk.q = pkey[1];
+    pk.g = pkey[2];
+    pk.y = pkey[3];
+    if( !verify( data[0], data[1], hash, &pk ) )
+	return G10ERR_BAD_SIGN;
+    return 0;
+}
+
+
+
+unsigned
+dsa_get_nbits( int algo, MPI *pkey )
+{
+    if( algo != PUBKEY_ALGO_DSA )
+	return 0;
+    return mpi_get_nbits( pkey[0] );
+}
+
+
+/****************
+ * Return some information about the algorithm.  We need algo here to
+ * distinguish different flavors of the algorithm.
+ * Returns: A pointer to string describing the algorithm or NULL if
+ *	    the ALGO is invalid.
+ * Usage: Bit 0 set : allows signing
+ *	      1 set : allows encryption
+ */
+const char *
+dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
+							 int *use )
+{
+    *npkey = 4;
+    *nskey = 5;
+    *nenc = 0;
+    *nsig = 2;
+
+    switch( algo ) {
+      case PUBKEY_ALGO_DSA:   *use = PUBKEY_USAGE_SIG; return "DSA";
+      default: *use = 0; return NULL;
+    }
+}
+
+
diff -BbruN freeswan-1.91.orig/pluto/g10_dsa.h freeswan-1.91/pluto/g10_dsa.h
--- freeswan-1.91.orig/pluto/g10_dsa.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/g10_dsa.h	Tue Jul  3 02:11:16 2001
@@ -0,0 +1,32 @@
+/* dsa.h  -  DSA signature scheme
+ *	Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef G10_DSA_H
+#define G10_DSA_H
+
+int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
+int dsa_check_secret_key( int algo, MPI *skey );
+int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
+int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
+		    int (*cmp)(void *, MPI), void *opaquev );
+unsigned dsa_get_nbits( int algo, MPI *pkey );
+const char *dsa_get_info( int algo, int *npkey, int *nskey,
+				    int *nenc, int *nsig, int *use );
+
+#endif /*G10_DSA_H*/
diff -BbruN freeswan-1.91.orig/pluto/id.c freeswan-1.91/pluto/id.c
--- freeswan-1.91.orig/pluto/id.c	Thu Apr 12 19:34:14 2001
+++ freeswan-1.91/pluto/id.c	Tue Jul  3 02:11:54 2001
@@ -21,11 +21,16 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#ifdef OPENSSL
+#include <openssl/x509.h>	/* needed by DER handling */
+#endif
+
 #include <freeswan.h>
 
 #include "constants.h"
 #include "defs.h"
 #include "id.h"
+#include "log.h"
 #include "connections.h"	/* needs id.h */
 #include "packet.h"
 
@@ -38,9 +43,13 @@
 atoid(char *src, struct id *id)
 {
     err_t ugh = NULL;
+#ifdef OPENSSL
+    char *nptr, *kptr;
+    char s[4];
+    u_int i;
+#endif
 
     *id = empty_id;
-
     if (strchr(src, '@') == NULL)
     {
 	/* !!! this test is not sufficient for distinguishing address families.
@@ -56,11 +65,70 @@
     {
 	if (*src == '@')
 	{
+#ifdef OPENSSL
+          /* if there is a second specifier (#) on the line
+           * we interprete this as ID_KEY_ID
+           */
+          if (*(src+1) == '#')
+          {
+            id->key_id.ptr = NULL;
+
+            id->kind = ID_KEY_ID;
+            id->name.ptr = src+2;
+            id->key_id.ptr = alloc_bytes(strlen(id->name.ptr)/2, "keyid-ptr");
+            id->key_id.len = strlen(id->name.ptr)/2;
+            nptr = id->name.ptr;
+            kptr = id->key_id.ptr;
+
+            for (i=0; i<  strlen(id->name.ptr)/2; i++, kptr++)
+            {
+              snprintf(s, 3, "%s", nptr);
+              *kptr = strtol(s, NULL, 16);
+              nptr+=2;
+            }
+            DBG(DBG_PARSING,
+            DBG_dump("Key-ID: ", id->key_id.ptr, id->key_id.len);
+            );
+          }
+          else if (*(src+1) == '~')
+          {
+            /* if there is a second specifier (~) on the line
+             * we interprete this as
+             *   ID_DER_ASN1_DN -> Distinguished Name
+             * in ASN1 (Subject-Field in X.509)
+             */
+            id->kind = ID_DER_ASN1_DN;
+            id->name.ptr = src+2;
+            id->der_asn1_dn.ptr = alloc_bytes(strlen(id->name.ptr)/2, "der_asn1_dn-ptr");
+            id->der_asn1_dn.len = strlen(id->name.ptr)/2;
+            nptr = id->name.ptr;
+            kptr = id->der_asn1_dn.ptr;
+
+            for (i=0; i<  strlen(id->name.ptr)/2; i++, kptr++)
+            {
+              snprintf(s, 3, "%s", nptr);
+              *kptr = strtol(s, NULL, 16);
+              nptr+=2;
+            }
+
+            DBG(DBG_PARSING,
+            DBG_dump("DER ASN1 DN: ", id->der_asn1_dn.ptr,
+              id->der_asn1_dn.len);
+            );
+
+            /* Check DN */
+            ugh = check_der_asn1_dn(id);
+
+          }
+          else
+          {
 	    id->kind = ID_FQDN;
 	    id->name.ptr = src+1;	/* discard @ */
 	}
+	}
 	else
 	{
+#endif /* OPENSSL */
 	    /* We leave in @, as per DOI 4.6.2.4
 	     * (but DNS wants . instead).
 	     */
@@ -109,8 +177,17 @@
 	n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
 	break;
     case ID_USER_FQDN:
-	n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
+       break;
+#ifdef OPENSSL
+    case ID_KEY_ID:
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->key_id.len, id->key_id.ptr);
+       break;
+    case ID_DER_ASN1_DN:
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->der_asn1_dn.len,
+       id->der_asn1_dn.ptr);
 	break;
+#endif
     default:
 	n = snprintf(dst, dstlen, "unknown id kind %d", id->kind);
 	break;
@@ -139,8 +216,20 @@
     {
     case ID_FQDN:
     case ID_USER_FQDN:
-	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
+#ifdef OPENSSL
+    case ID_KEY_ID:
+#endif
+	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, 
+		"keep id name");
+	break;
+#ifdef OPENSSL
+    case ID_DER_ASN1_DN:
+	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, 
+		"keep id name");
+	id->der_asn1_dn.ptr = clone_bytes(id->der_asn1_dn.ptr, 
+		id->der_asn1_dn.len, "keep der_asn1_dn id");
 	break;
+#endif
     case ID_NONE:
     case ID_IPV4_ADDR:
     case ID_IPV6_ADDR:
@@ -150,6 +239,14 @@
     }
 }
 
+/* free a heap struct id */
+void
+free_id(struct id *id)
+{
+    free_id_content(id);
+    pfree(id);
+}
+
 void
 free_id_content(struct id *id)
 {
@@ -159,6 +256,16 @@
     case ID_USER_FQDN:
 	pfree(id->name.ptr);
 	break;
+#ifdef OPENSSL
+    case ID_KEY_ID:
+	pfree(id->name.ptr);
+	pfree(id->key_id.ptr);
+	break;
+    case ID_DER_ASN1_DN:
+	pfree(id->name.ptr);
+	pfree(id->der_asn1_dn.ptr);
+	break;
+#endif /* OPENSSL */
     case ID_NONE:
     case ID_IPV4_ADDR:
     case ID_IPV6_ADDR:
@@ -185,10 +292,20 @@
 
     case ID_FQDN:
     case ID_USER_FQDN:
+#ifdef OPENSSL
+    case ID_KEY_ID:
 	/* assumption: case should be ignored */
+#endif
 	return a->name.len == b->name.len
 	    && strncasecmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
+#ifdef OPENSSL
+    case ID_DER_ASN1_DN:
+	/* assumption: case should be ignored */
 
+	return (a->der_asn1_dn.len == b->der_asn1_dn.len)
+	    && strncasecmp(a->der_asn1_dn.ptr, 
+	      b->der_asn1_dn.ptr, a->der_asn1_dn.len) == 0;
+#endif /* OPENSSL */
     default:
 	passert(FALSE);
     }
@@ -220,7 +337,49 @@
 	tl->len = addrbytesptr(&end->host_addr
 	    , (const unsigned char **)&tl->ptr);
 	break;
+#ifdef OPENSSL
+    case ID_KEY_ID:
+	*tl = end->id.key_id;
+	break;
+    case ID_DER_ASN1_DN:
+	*tl = end->id.der_asn1_dn;
+	break;
+#endif /* OPENSSL */
     default:
 	passert(FALSE);
     }
 }
+
+#ifdef OPENSSL
+err_t
+check_der_asn1_dn(struct id *id)
+{
+	err_t ugh = NULL;
+	u_char *temp_ptr;
+
+	X509_NAME *xn = X509_NAME_new();
+	char dnout[256];
+
+	if (xn == NULL) {
+		ugh="Unable to malloc X509_NAME *xn";
+	}
+
+	/* temp_ptr because d2i_X509_NAME will mangle the pointer. */
+	temp_ptr = id->der_asn1_dn.ptr;
+	xn = d2i_X509_NAME(&xn, &(id->der_asn1_dn.ptr),
+		(long)id->der_asn1_dn.len);
+	id->der_asn1_dn.ptr = temp_ptr;
+
+	if (xn != NULL) {
+		DBG(DBG_PARSING,
+		X509_NAME_oneline(xn,dnout,256);
+		DBG_log("Valid DN == %s", dnout);
+		);
+	} else {
+		ugh="Invalid DER string";
+	}
+
+	X509_NAME_free(xn);
+	return ugh;
+}
+#endif
diff -BbruN freeswan-1.91.orig/pluto/id.h freeswan-1.91/pluto/id.h
--- freeswan-1.91.orig/pluto/id.h	Mon Feb 26 18:50:11 2001
+++ freeswan-1.91/pluto/id.h	Tue Jul  3 02:12:07 2001
@@ -17,6 +17,10 @@
 struct id {
     int kind;	/* ID_* value */
     ip_address ip_addr;	/* ID_IPV4_ADDR, ID_IPV6_ADDR */
+#ifdef OPENSSL
+    chunk_t key_id;   /* ID_KEY_ID */
+    chunk_t der_asn1_dn;      /* ID_DER_ASN1_DN */
+#endif
     chunk_t name;	/* ID_FQDN, ID_USER_FQDN (with @) */
 };
 
@@ -25,9 +29,10 @@
 extern err_t atoid(char *src, struct id *id);
 extern void iptoid(const ip_address *ip, struct id *id);
 extern int idtoa(const struct id *id, char *dst, size_t dstlen);
-#define IDTOA_BUF 256
+#define IDTOA_BUF 512
 struct end;	/* forward declaration of tag (defined in connections.h) */
 extern void unshare_id_content(struct id *id);
+extern void free_id(struct id *id);
 extern void free_id_content(struct id *id);
 extern bool same_id(const struct id *a, const struct id *b);
 #define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR)
@@ -35,3 +40,6 @@
 struct isakmp_ipsec_id;	/* forward declaration of tag (defined in packet.h) */
 extern void
     build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end);
+#ifdef OPENSSL
+err_t check_der_asn1_dn(struct id *id);
+#endif
diff -BbruN freeswan-1.91.orig/pluto/ipsec_doi.c freeswan-1.91/pluto/ipsec_doi.c
--- freeswan-1.91.orig/pluto/ipsec_doi.c	Fri Jun  1 03:38:32 2001
+++ freeswan-1.91/pluto/ipsec_doi.c	Tue Jul  3 02:16:57 2001
@@ -49,12 +49,26 @@
 #include "md5.h"
 #include "crypto.h" /* requires sha1.h and md5.h */
 
+#ifdef OPENSSL
+#include "openssl.h"
+#endif
+
 /* MAGIC: perform f, a function that returns notification_t
  * and return from the ENCLOSING stf_status returning function if it fails.
  */
 #define RETURN_STF_FAILURE(f) \
     { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; }
 
+stf_status send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP);
+static bool encrypt_message(pb_stream *pbs, struct state *st);
+extern bool build_and_ship_KE(struct state *st, chunk_t *g, 
+	const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np);
+
+/* needed for PGPnet Vendor ID */
+char pgp_vid[] = { 0x4f, 0x70, 0x65, 0x6e,
+		   0x50, 0x47, 0x50, 0x31,
+		   0x30, 0x31, 0x37, 0x31};
+
 /* Compute DH shared secret from our local secret and the peer's public value.
  * We make the leap that the length should be that of the group
  * (see quoted passage at start of ACCEPT_KE).
@@ -80,13 +94,92 @@
     DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
 }
 
+#ifdef OPENSSL
+static bool
+build_and_ship_KE_rpk(struct state *st, bool init,
+                    chunk_t *g,
+                    const struct oakley_group_desc *group, pb_stream *outs,
+                    u_int8_t np)
+{
+  keysched *ks;
+  u_char *iv;
+  chunk_t op;
+  bool res;
+
+    if (!st->st_sec_in_use)
+    {
+      u_char tmp[LOCALSECRETSIZE];
+      MP_INT mp_g;
+
+      get_rnd_bytes(tmp, LOCALSECRETSIZE);
+      st->st_sec_in_use = TRUE;
+      n_to_mpz(&st->st_sec, tmp, LOCALSECRETSIZE);
+
+      mpz_init(&mp_g);
+      mpz_powm(&mp_g, &groupgenerator, &st->st_sec, group->modulus);
+      freeanychunk(*g);       /* happens in odd error cases */
+      *g = mpz_to_n(&mp_g, group->bytes);
+      mpz_clear(&mp_g);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+      if (g->ptr[0] == 0)
+      {
+          /* generate a new secret to avoid this situation */
+          log("regenerating DH private secret to avoid Pluto 1.0 bug"
+              " handling public value with leading zero");
+          mpz_clear(&st->st_sec);
+          st->st_sec_in_use = FALSE;
+          return build_and_ship_KE_rpk(st, init, g, group, outs, np);
+      }
+       /* if we're the responder, we can compute the shared secret
+        * to see if it would turn out OK.
+        */
+       if (g == &st->st_gr)
+       {
+           compute_dh_shared(st, st->st_gi
+               , IS_PHASE1(st->st_state)
+                   ? st->st_oakley.group : st->st_pfs_group);
+           if (st->st_shared.ptr[0] == 0)
+           {
+               /* generate a new secret to avoid this situation */
+               loglog(RC_LOG_SERIOUS, "regenerating DH private secret to avoid Pluto 1.0 bug"
+                   " handling shared secret with leading zero");
+               freeanychunk(st->st_shared);
+               mpz_clear(&st->st_sec);
+               st->st_sec_in_use = FALSE;
+               return build_and_ship_KE(st, g, group, outs, np);
+           }
+       }
+#endif
+
+      DBG(DBG_CRYPT,
+      DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
+      DBG_dump_chunk("Public DH value sent:\n", *g);
+      );
+    }
+    /* Encrypt the chunk */
+    if (init) {
+      ks = &st->st_ks_i;
+      iv = st->st_ne_i_iv;
+    } else {
+      ks = &st->st_ks_r;
+      iv = st->st_ne_r_iv;
+    }
+    setchunk(op, NULL, 0);
+    if (!encrypt_payload( st, ks, iv, *g, &op )) return FALSE;
+    res = out_generic_chunk(np, &isakmp_keyex_desc, outs, op,
+                          "encrypted keyex value");
+    freeanychunk(op);
+    return res;
+}
+#endif
+
 /* if we haven't already done so, compute a local DH secret (st->st_sec) and
  * the corresponding public value (g).  This is emitted as a KE payload.
  * KLUDGE: if DODGE_DH_MISSING_ZERO_BUG and we're the responder,
  * this routine computes the shared secret to see if it would
  * have a leading zero.  If so, we try again.
  */
-static bool
+extern bool
 build_and_ship_KE(struct state *st, chunk_t *g
 , const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np)
 {
@@ -137,7 +230,8 @@
 
 	DBG(DBG_CRYPT,
 	    DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
-	    DBG_dump_chunk("Public DH value sent:\n", *g));
+	DBG_dump_chunk("Public DH value sent:\n", *g);
+	);
     }
     return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
 }
@@ -220,6 +314,23 @@
     return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name);
 }
 
+#ifdef OPENSSL
+static bool
+build_and_ship_nonce_pk(struct state *st, chunk_t *n, pb_stream *outs, u_int8_t np, const char *name)
+{
+    chunk_t c;
+
+    setchunk(*n, alloc_bytes(DEFAULT_NONCE_SIZE, name), DEFAULT_NONCE_SIZE);
+    get_rnd_bytes(n->ptr, DEFAULT_NONCE_SIZE);
+    c.len = n->len;
+    c.ptr = clone_bytes(n->ptr, c.len, name);
+    if (! pubkey_encrypt_chunk(&c, st)) {
+      return FALSE;
+    }
+    return out_generic_chunk(np, &isakmp_nonce_desc, outs, c, name);
+}
+#endif
+
 /*
  * Send a notification to the peer. We could make a decision on
  * whether to send the notification, based on the type and the
@@ -282,11 +393,128 @@
 //	    show_sa(&sa)));
 //    else
 //    {
-//	DBG(DBG_CONTROL, DBG_log("transmitted %d bytes", ntohl(isa->isa_length)));
+//	DBG(DBG_CONTROL, 
+//	DBG_log("transmitted %d bytes", ntohl(isa->isa_length));
+//	);
 //    }
 //}
 #endif /* not currently used */
 
+
+stf_status
+send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP)
+{
+     
+     pb_stream reply_pbs;
+     pb_stream r_hdr_pbs;
+     msgid_t	msgid;
+     u_char 	old_new_iv[MAX_DIGEST_LEN];
+     u_char 	old_iv[MAX_DIGEST_LEN];         
+     u_char buffer[8192];
+     struct state *p1st;
+     
+     u_char spilen = sizeof(ipsec_spi_t);
+     u_char
+ 	*r_hashval,	/* where in reply to jam hash value */
+ 	*r_hash_start;	/* start of what is to be hashed */
+     
+     zero(buffer);
+     init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
+ 
+     /* find the related P1-State to the calling P2-state */
+     p1st = find_state(p2st->st_icookie, p2st->st_rcookie, 
+     			&(p2st->st_connection->that.host_addr), 0);
+     if (p1st == NULL) 
+     {
+ 	DBG_log("no phase 1 state where one should be");
+	return STF_INTERNAL_ERROR;
+     }
+ 
+     msgid = generate_msgid(p1st);
+
+     /* HDR* */
+     {
+ 	struct isakmp_hdr hdr;
+ 
+ 	hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+ 	hdr.isa_np = ISAKMP_NEXT_HASH;
+ 	hdr.isa_xchg = ISAKMP_XCHG_INFO;
+ 	hdr.isa_msgid = msgid;
+ 	hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
+ 	memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE);
+ 	memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE);
+ 	if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs))
+ 	    return STF_INTERNAL_ERROR;
+     }
+ 
+     /* HASH -- space to be filled later */
+     {
+ 	pb_stream hash_pbs;
+ 
+ 	if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
+     	    return STF_INTERNAL_ERROR;
+ 	r_hashval = hash_pbs.cur;	/* remember where to plant value */
+ 	if (!out_zero(p1st->st_oakley.hasher->hash_digest_len, &hash_pbs, "HASH(1)"))
+ 	    return STF_INTERNAL_ERROR;
+ 	close_output_pbs(&hash_pbs);
+ 	r_hash_start = r_hdr_pbs.cur;	/* hash from after HASH(1) */
+     }
+ 
+     /* DELETE PAYLOAD */
+     {
+ 	pb_stream del_pbs;
+ 	struct isakmp_delete isad;
+ 	
+        isad.isad_doi = ISAKMP_DOI_IPSEC;
+ 	isad.isad_np = ISAKMP_NEXT_NONE;
+ 	isad.isad_spisize = spilen;
+        if (ESP) isad.isad_protoid = PROTO_IPSEC_ESP;
+        else isad.isad_protoid = PROTO_IPSEC_AH;
+ 	isad.isad_nospi = 0x0001;
+         if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs))
+ 	    return STF_INTERNAL_ERROR;
+ 	if (!out_raw(spi, spilen, &del_pbs, "delete payload"))
+ 	    return STF_INTERNAL_ERROR;;
+         close_output_pbs(&del_pbs);
+     }
+     
+     {
+         struct hmac_ctx ctx;
+ 	hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a);
+         hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));
+         hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);
+ 	hmac_final(r_hashval, &ctx);
+ 
+         DBG(DBG_CRYPT,
+     	    DBG_log("HASH(1) computed:");
+ 	    DBG_dump("", r_hashval, ctx.hmac_digest_len));
+     }
+ 
+     /* save old IV (this prevents from copying a whole new state object 
+      * for NOTIFICATION / DELETE messages we don't need to maintain a state
+      * because there are no retransmissions...
+      */
+      
+     memcpy(old_new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
+     memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
+     init_phase2_iv(p1st, &msgid);
+ 
+     if(!encrypt_message(&r_hdr_pbs, p1st)) passert(FALSE);
+     
+     clonetochunk(p1st->st_tpacket, reply_pbs.start, pbs_offset(&reply_pbs)
+ 	, "reply packet for main_outI1");
+ 
+     send_packet(p1st, "delete notify");
+     
+     /* get back old IV for this state */
+     memcpy(p1st->st_new_iv, old_new_iv, p1st->st_new_iv_len);
+     memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);    
+     
+     return STF_IGNORE; 
+}
+ 
+
+
 /* The whole message must be a multiple of 4 octets.
  * I'm not sure where this is spelled out, but look at
  * rfc2408 3.6 Transform Payload.
@@ -318,6 +546,10 @@
 
     struct state *st;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_outI1");
+    );
+
     /* set up new state */
     cur_state = st = new_state();
     st->st_connection = c;
@@ -372,7 +604,11 @@
 
 	    if (get_RSA_private_key(c) != NULL
 	    && get_his_RSA_public_key(c) != NULL)
+#ifndef OPENSSL
 		auth_policy |= POLICY_RSASIG;
+#else
+		auth_policy |= POLICY_OPENSSL;
+#endif
 	    /* Not clear what we should do if neither is possible.
 	     * Perhaps we should not have entered negotiations at all.
 	     */
@@ -383,6 +619,23 @@
 		return STF_INTERNAL_ERROR;
 	    }
 	}
+
+#ifdef OPENSSL
+if (use_openssl(c)) 
+{
+	loglog(RC_LOG_SERIOUS, "Using OPENSSL sadb.");
+	if (!out_sa(&rbody
+	, &oakley_sadb2[auth_policy >> POLICY_ISAKMP_SHIFT]
+	, st, TRUE, ISAKMP_NEXT_NONE))
+	{
+	    cur_state = NULL;
+	    return STF_INTERNAL_ERROR;
+	}
+}
+else
+{
+#endif /* OPENSSL */
+	loglog(RC_LOG_SERIOUS, "Using standard sadb.");
 	if (!out_sa(&rbody
 	, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
 	, st, TRUE, ISAKMP_NEXT_NONE))
@@ -390,6 +643,10 @@
 	    cur_state = NULL;
 	    return STF_INTERNAL_ERROR;
 	}
+#ifdef OPENSSL
+}
+#endif /* ! OPENSSL */
+
 
 	/* save initiator SA for later HASH */
 	passert(st->st_p1isa.ptr == NULL);	/* no leak!  (MUST be first time) */
@@ -564,6 +820,57 @@
     return TRUE;
 }
 
+#ifdef OPENSSL
+#if 0
+static const chunk_t
+chunk_concat( const chunk_t c1, const chunk_t c2 )
+{
+    chunk_t cc;
+
+    cc.len = c1.len + c2.len;
+    if ((cc.ptr = malloc(cc.len)) != NULL) {
+      memcpy(cc.ptr, c1.ptr, c1.len);
+      memcpy(&(cc.ptr[c1.len]), c2.ptr, c2.len);
+    }
+    return cc;
+}
+#endif
+
+static bool
+skeyid_pke(struct state *st)
+{
+    /* This routine lifted straight from Kai Martius' patches */
+    /* and updated to use chunks */
+    struct hmac_ctx ctx;
+    union hash_ctx ictx;
+    const struct hash_desc *h = st->st_oakley.hasher;
+    u_char *nonce;
+    u_int16_t nonce_len;
+    chunk_t noncechunk, cky_i, cky_r;
+
+    nonce_len = h->hash_digest_len;
+    nonce=alloc_bytes(nonce_len, "nonce in skeyid_pke()");
+
+    h->hash_init(&ictx);
+    h->hash_update(&ictx, st->st_ni.ptr, st->st_ni.len);
+    h->hash_update(&ictx, st->st_nr.ptr, st->st_nr.len);
+    h->hash_final(nonce, &ictx);
+
+    setchunk(noncechunk, nonce, nonce_len);
+    setchunk(cky_i, st->st_icookie, COOKIE_SIZE);
+    setchunk(cky_r, st->st_rcookie, COOKIE_SIZE);
+
+    hmac_init_chunk(&ctx, h, noncechunk);
+    hmac_update_chunk(&ctx, cky_i);
+    hmac_update_chunk(&ctx, cky_r);
+    hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_pke()", &ctx);
+
+    free(nonce);
+
+    return TRUE;
+}
+#endif
+
 /* Generate the SKEYID_* and new IV
  * See draft-ietf-ipsec-ike-01.txt 4.1
  */
@@ -584,13 +891,21 @@
 	    break;
 
 	case OAKLEY_DSS_SIG:
-	    /* XXX */
+#ifdef OPENSSL
+          if (!skeyid_digisig(st))
+              return FALSE;
+          break;
+#endif
 
 	case OAKLEY_RSA_ENC:
 	case OAKLEY_RSA_ENC_REV:
 	case OAKLEY_ELGAMAL_ENC:
 	case OAKLEY_ELGAMAL_ENC_REV:
-	    /* XXX */
+#ifdef OPENSSL
+          if (!skeyid_pke(st))
+              return FALSE;
+          break;
+#endif
 
 	default:
 	    exit_log("generate_skeyids_iv(): unsupported authentication method %s",
@@ -779,7 +1094,7 @@
     return ctx.hmac_digest_len;
 }
 
-#if 0	/* only needed for DSS */
+#ifdef OPENSSL
 static void
 main_mode_sha1(struct state *st, u_char *hash_val, size_t *hash_len
 , bool hashi, bool hashus)
@@ -987,6 +1302,13 @@
     switch (st->st_oakley.auth)
     {
     case OAKLEY_PRESHARED_KEY:
+#ifdef OPENSSL
+     case OAKLEY_RSA_ENC:
+     case OAKLEY_RSA_ENC_REV:
+     case OAKLEY_DSS_SIG:
+     case OAKLEY_ELGAMAL_ENC:
+     case OAKLEY_ELGAMAL_ENC_REV:
+#endif
 	{
 	    pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
 
@@ -1246,6 +1567,10 @@
 
     log("initiating Quick Mode %s", bitnamesof(sa_policy_bit_names, policy));
 
+    DBG(DBG_PARSING,
+    DBG_log("starting quick_outI1");
+    );
+
     /* set up reply */
     init_pbs(&reply, space, sizeof(space), "reply packet");
 
@@ -1342,6 +1667,11 @@
     whack_log(RC_NEW_STATE + STATE_QUICK_I1
 	, "%s: initiate", enum_name(&state_names, st->st_state));
     cur_state = NULL;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished quick_outI1");
+    );
+
     return STF_NO_REPLY;
 }
 
@@ -1358,6 +1688,15 @@
     pb_stream *const id_pbs = &id_pld->pbs;
     struct isakmp_id *const id = &id_pld->payload.id;
     struct id peer;
+    const u_int max_len = 512;
+
+#ifdef OPENSSL
+    u_char key_id[max_len];
+    u_int i, len;
+
+    peer.key_id.len = 0;
+    peer.der_asn1_dn.len = 0;
+#endif
 
     /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
      * It talks about the protocol ID and Port fields of the ID
@@ -1411,8 +1751,8 @@
     case ID_FQDN:
 	if (memchr(id_pbs->cur, '\0', pbs_left(id_pbs)) != NULL)
 	{
-	    loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NUL"
-		, enum_show(&ident_names, peer.kind));
+	  loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NULL"
+	    ,enum_show(&ident_names, peer.kind));
 	    return FALSE;
 	}
 
@@ -1421,6 +1761,76 @@
 	setchunk(peer.name, id_pbs->cur, pbs_left(id_pbs));
 	break;
 
+#ifdef OPENSSL
+    case ID_KEY_ID:
+	if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0))
+	{
+	log("protocol/port in Phase 1 ID Payload must be 0/0"
+			" but are %d/%d"
+			, id->isaid_doi_specific_a, id->isaid_doi_specific_b);
+		return FALSE;
+	}
+
+	len = pbs_left(id_pbs);
+
+	/* we need double size for ASCII representation of key id */
+	if (2*len > max_len)
+	{
+		log("too large key id");
+		return FALSE;
+	}
+
+	DBG(DBG_PARSING,
+	DBG_dump("Received Key ID:", id_pbs->cur, pbs_left(id_pbs));
+	);
+
+	/* hold the binary representation of KEY_ID */
+	/* possible memory hole? */
+	peer.key_id.ptr = alloc_bytes(len, "key_id");
+	peer.key_id.len = len;
+	memcpy(peer.key_id.ptr, id_pbs->cur, len);
+
+	for (i=0; i<len; i++, id_pbs->cur++)
+		sprintf(&key_id[i*2], "%02x", *(id_pbs->cur));
+
+	peer.name.ptr = alloc_bytes(2*len, "name");
+	peer.name.len = 2*len;
+	memcpy(peer.name.ptr, key_id, peer.name.len);
+	break;  
+
+    case ID_DER_ASN1_DN:
+	if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0))
+	{
+	log("protocol/port in Phase 1 ID Payload must be 0/0"
+			" but are %d/%d", id->isaid_doi_specific_a, 
+			id->isaid_doi_specific_b);
+		return FALSE;
+	}
+	len = pbs_left(id_pbs);
+
+	if (len > max_len)
+	{
+		log("too large DER ASN1 DN");
+		return FALSE;
+	}
+
+	if (id_pbs->cur == NULL) {
+		loglog(RC_LOG_SERIOUS, 
+			"ID_DER_ASN1_DN received, but is 0 length.");
+		return FALSE;
+	}
+
+	peer.der_asn1_dn.ptr = alloc_bytes(len,"der asn1 dn");
+	peer.der_asn1_dn.len = len;
+	memcpy(peer.der_asn1_dn.ptr, id_pbs->cur, len);
+
+	DBG(DBG_PARSING,
+	DBG_dump_chunk("Received peer.id (processed ID_DER_ASN1_DN):", 
+		peer.der_asn1_dn);       
+	);
+	break; 
+#endif OPENSSL
+
     default:
 	/* XXX Could send notification back */
 	loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload"
@@ -1432,6 +1842,7 @@
     st->st_peeridentity_protocol = id->isaid_doi_specific_a;
     st->st_peeridentity_port = id->isaid_doi_specific_b;
 
+#if 0 /* Commented out because DER_AS1_DN creates LOTS of output here. */
     DBG(DBG_PARSING,
 	{
 	    char buf[IDTOA_BUF];
@@ -1441,6 +1852,7 @@
 		enum_show(&ident_names, id->isaid_idtype),
 		buf);
 	});
+#endif
 
     /* Now that we've decoded the ID payload, let's see if we
      * need to switch connections.
@@ -1491,7 +1903,25 @@
 	    st->st_connection = r;	/* kill reference to c */
 	    SET_CUR_CONNECTION(r);
 	    connection_discard(c);
+
 	}
+#ifdef OPENSSL
+      /* if we have a binary key_id, set it now into conn */
+      if (peer.key_id.len)
+      {
+              r->that.id.key_id.ptr = clone_bytes(peer.key_id.ptr,
+                      peer.key_id.len, "KEY-ID");
+              r->that.id.key_id.len = peer.key_id.len;
+      }
+
+      /* if we have a binary der_asn1_dn, set it now into conn */
+      if (peer.der_asn1_dn.len)
+      {
+              r->that.id.der_asn1_dn.ptr = clone_bytes(peer.der_asn1_dn.ptr,
+                      peer.der_asn1_dn.len, "ID_DER_ASN1_DN");
+              r->that.id.der_asn1_dn.len = peer.der_asn1_dn.len;
+      }
+#endif /* OPENSSL */
     }
 
     return TRUE;
@@ -1863,6 +2292,10 @@
 
     pb_stream r_sa_pbs;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI1_outR1");
+    );
+
     if (c == NULL)
     {
 	/* see if a wildcarded connection can be found */
@@ -1947,6 +2381,10 @@
     /* save initiator SA for HASH */
     clonereplacechunk(st->st_p1isa, sa_pd->pbs.start, pbs_room(&sa_pd->pbs), "sa in main_inI1_outR1()");
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI1_outR1");
+    );
+
     return STF_REPLY;
 }
 
@@ -1964,15 +2402,30 @@
 main_inR1_outI2(struct msg_digest *md)
 {
     struct state *const st = md->st;
+#ifdef OPENSSL
+  u_int8_t np;
+#endif
+
+  DBG(DBG_PARSING,
+  DBG_log("in main_inR1_outI2");
+  );
 
     /* verify echoed SA */
     {
 	struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
 
-	RETURN_STF_FAILURE(parse_isakmp_sa_body(&sapd->pbs
-	    , &sapd->payload.sa, NULL, TRUE, st));
+    RETURN_STF_FAILURE(parse_isakmp_sa_body(&sapd->pbs, 
+      &sapd->payload.sa, NULL, TRUE, st));
     }
 
+  /* 
+   * Here, we have to decide if the outgoing packet is going to be created 
+   * for the classic RSASIG, or the OPENSSL functions.
+   */
+#ifdef OPENSSL
+  if (!use_openssl(st->st_connection)) 
+  {
+#endif
     /**************** build output packet HDR;KE;Ni ****************/
 
     /* HDR out.
@@ -1988,105 +2442,961 @@
     }
 
     /* KE out */
-    if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group
-    , &md->rbody, ISAKMP_NEXT_NONCE))
+    if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group, 
+      &md->rbody, ISAKMP_NEXT_NONCE))
 	return STF_INTERNAL_ERROR;
 
     /* Ni out */
     if (!build_and_ship_nonce(&st->st_ni, &md->rbody, ISAKMP_NEXT_NONE, "Ni"))
 	return STF_INTERNAL_ERROR;
 
-    /* finish message */
-    close_message(&md->rbody);
+#ifdef OPENSSL
+  }
+  else /* use_openssl == TRUE */
+  {
+    DBG(DBG_PARSING, 
+    DBG_log("main_inR1_outI2: auth chosen is %s",
+      enum_show(&oakley_auth_names, st->st_oakley.auth));
+    );
 
-    /* Reinsert the state, using the responder cookie we just received */
-    unhash_state(st);
-    memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE);
-    insert_state(st);	/* needs cookies, connection, and msgid (0) */
+    if ((st->st_oakley.auth == OAKLEY_RSA_ENC_REV) ||
+      (st->st_oakley.auth == OAKLEY_ELGAMAL_ENC_REV)) {
+      struct isakmp_hdr r_hdr = md->hdr;
 
-    st->st_state = STATE_MAIN_I2;
+      /* HDR out */
+      r_hdr.isa_np = ISAKMP_NEXT_NONCE;
+      if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+        return STF_INTERNAL_ERROR;
 
-    return STF_REPLY;
-}
+      if (!build_and_ship_nonce_pk(st, &st->st_ni, &md->rbody,
+        ISAKMP_NEXT_KE, "<Ni_b>PubKey_r"))
+        return STF_INTERNAL_ERROR;
 
-/* STATE_MAIN_R1:
- * PSK_AUTH, DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr
- *
- * The following are not yet implemented:
- * PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- *	    --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * RPKE_AUTH:
- *	    HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
- *	    --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- */
-stf_status
+      if (derive_symmetric_key(st, st->st_ni,
+        st->st_icookie, COOKIE_SIZE,
+        &st->st_ks_i,
+        &st->st_ne_i) < 0) {
+	log("error while deriving symmetric key in revised mode");
+	return STF_INTERNAL_ERROR;
+      }
+      memset(st->st_ne_i_iv, 0, MAX_DIGEST_LEN);
+      DBG(DBG_PARSING,
+      DBG_dump_chunk("Generated Ke_i:", st->st_ne_i);
+      );
+
+      /* KE out */
+      if (!build_and_ship_KE_rpk(st, TRUE, &st->st_gi, st->st_oakley.group,
+        &md->rbody, ISAKMP_NEXT_ID))
+        return STF_INTERNAL_ERROR;
+
+      /* <IDi1_b>Ke_i,[<cert>Ke_i] out */
+      {
+        chunk_t ch, out;
+
+        /*
+         * Switch for different ID types to send
+         */
+	if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+          ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+          ch.ptr = alloc_bytes(ch.len, "encrypted der_asn1_dn identity");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), 
+            st->st_connection->this.id.der_asn1_dn.ptr, 
+            st->st_connection->this.id.der_asn1_dn.len);
+        } else {
+          ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+          ch.ptr = alloc_bytes(ch.len, "encrypted identity");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr), 
+            sizeof(st->st_connection->this.id.ip_addr));
+	}
+
+        if (!encrypt_payload(st, &st->st_ks_i, st->st_ne_i_iv,
+          ch, &out))
+          return STF_INTERNAL_ERROR;
+        freeanychunk(ch);
+
+        /* Are we going to send CERT? */
+        if ((st->st_connection->cert_options & CERT_OPTION_SEND) == 0) {
+          if (!out_generic_chunk(ISAKMP_NEXT_NONE, &isakmp_generic_desc,
+            &md->rbody, out, "my identity (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        } else {
+          if (!out_generic_chunk(ISAKMP_NEXT_CERT, &isakmp_generic_desc,
+            &md->rbody, out, "my identity (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        }
+
+        /* Well, if we do send CERT, let's start on it from here */
+        if ((st->st_connection->cert_options & CERT_OPTION_SEND) != 0) {
+          chunk_t crt, cx;
+          unsigned long ulen;
+          PKCS7 *p7 = NULL; 
+          /* Send the signing certificate */
+
+          if ((st->st_connection->cert_options & CERT_OPTION_PKCS7) != 0) {
+            PKCS7_SIGNED *p7s = NULL;
+            X509_CRL *tempcrl=NULL;
+            X509 *tempcert = X509_dup(st->st_connection->cert);
+            STACK_OF(X509_CRL) *crl_stack=NULL;
+            STACK_OF(X509) *cert_stack=NULL;
+
+            if ((p7=PKCS7_new()) == NULL) return STF_INTERNAL_ERROR;
+            if ((p7s=PKCS7_SIGNED_new()) == NULL) return STF_INTERNAL_ERROR;
+            p7->type=OBJ_nid2obj(NID_pkcs7_signed);
+            p7->d.sign=p7s;
+            p7s->contents->type=OBJ_nid2obj(NID_pkcs7_data);
+
+            if (!ASN1_INTEGER_set(p7s->version,1)) return STF_INTERNAL_ERROR;
+
+            crl_stack=sk_X509_CRL_new(NULL);
+            if (crl_stack == NULL) return STF_INTERNAL_ERROR;
+            p7s->crl=crl_stack;
+
+            /* DO crl lookup */
+            tempcrl = lookup_crl(st->st_connection->lu, 
+              X509_get_issuer_name(st->st_connection->cert));
+            if (tempcrl != NULL)
+            {
+              sk_X509_CRL_push(crl_stack,tempcrl);
+              tempcrl=NULL; /* now part of p7 for Freeing */
+            } else {
+              return STF_INTERNAL_ERROR;
+            }
+
+            /* DO add cert chain ? */
+            if ((cert_stack=sk_X509_new(NULL)) == NULL) 
+              return STF_INTERNAL_ERROR;
+            p7s->cert=cert_stack;
+            if (tempcert != NULL)
+            {
+              sk_X509_push(cert_stack,tempcert);
+              tempcert=NULL; /* now part of p7 for Freeing */
+            } else {
+              return STF_INTERNAL_ERROR;
+            }
+
+            ulen = i2d_PKCS7(p7, NULL);
+            ulen++;
+            if ((cx.ptr = alloc_bytes(ulen, "ASN.1 PKCS7 cert chain")) == NULL)
+            { 
+              return STF_INTERNAL_ERROR; 
+            }
+            (cx.ptr)[0] = (u_char)(CERT_TYPE_PKCS7);
+            cx.len = ulen;
+            crt.ptr = &(cx.ptr[1]);
+            crt.len = i2d_PKCS7(p7, &(crt.ptr));
+
+            DBG(DBG_CRYPT,
+            DBG_log("plaintext PKCS7 chain length: %d", cx.len);
+            DBG_dump_chunk("plaintext PKCS7 chain", cx);
+            );
+
+          } else { /* not PKCS7. Send normal X.509 ASN.1 object */
+
+            ulen = i2d_X509(st->st_connection->cert, NULL);
+            ulen++;
+            if ((cx.ptr = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+            { 
+              return STF_INTERNAL_ERROR; 
+            }
+            (cx.ptr)[0] = (u_char)(CERT_TYPE_X509_SIG);
+            cx.len = ulen;
+            crt.ptr = &(cx.ptr[1]);
+            crt.len = i2d_X509(st->st_connection->cert, &(crt.ptr));
+
+            DBG(DBG_CRYPT,
+            DBG_log("plaintext Certificate length: %d", cx.len);
+            DBG_dump_chunk("plaintext Certificate", cx);
+            );
+          }
+
+          /* encrypt the certificate to send */
+          if (!encrypt_payload(st, &st->st_ks_i, st->st_ne_i_iv,
+            cx, &out))
+          return STF_INTERNAL_ERROR;
+
+/* test encryption */
+
+          if ((st->st_connection->cert_options & CERT_OPTION_PKCS7) != 0) {
+            DBG(DBG_CRYPT,
+            DBG_log("cyphertext PKCS7 chain length: %d", out.len);
+            DBG_dump_chunk("cyphertext PKCS7 chain", out);
+            if (p7 != NULL) PKCS7_free(p7);
+            );
+          } else {
+            DBG(DBG_CRYPT,
+            DBG_log("cyphertext Certificate length: %d", out.len);
+            DBG_dump_chunk("cyphertext Certificate", out);
+            );
+          }
+
+          if (!out_generic_chunk(ISAKMP_NEXT_NONE, 
+            &isakmp_ipsec_certificate_desc,
+            &md->rbody, out, "my certificate (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        }
+        /* end of sending out cert */
+
+        freeanychunk(out);
+      }
+    } else {
+      struct isakmp_hdr r_hdr = md->hdr;
+      
+      r_hdr.isa_np = ISAKMP_NEXT_KE;
+      if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+        return STF_INTERNAL_ERROR;
+
+      if ((st->st_oakley.auth == OAKLEY_RSA_ENC) ||
+        (st->st_oakley.auth == OAKLEY_ELGAMAL_ENC))
+        np = ISAKMP_NEXT_ID;
+      else /* Digital Sig or Preshared key */
+        np = ISAKMP_NEXT_NONCE;
+      
+      /* KE out */
+      if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group, 
+        &md->rbody, np))
+        return STF_INTERNAL_ERROR;
+      
+      if ((st->st_oakley.auth == OAKLEY_RSA_ENC) ||
+	  (st->st_oakley.auth == OAKLEY_ELGAMAL_ENC)) {
+
+	/* <IDii_b>PubKey_r out */
+	chunk_t ch;
+
+        /* Switch for different ID types to send */
+        if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+          ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+          ch.ptr = alloc_bytes(ch.len, "plaintext der_asn1_dn identity");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), 
+            st->st_connection->this.id.der_asn1_dn.ptr, 
+            st->st_connection->this.id.der_asn1_dn.len);
+        } else {
+          ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+          ch.ptr = alloc_bytes(ch.len, "my identity (plaintext)");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr), 
+            sizeof(st->st_connection->this.id.ip_addr));
+        }
+
+        /* PK encrypt this */
+        if (! pubkey_encrypt_chunk( &ch, st )) {
+          return STF_INTERNAL_ERROR;
+        }
+        if (!out_generic_chunk(ISAKMP_NEXT_NONCE, &isakmp_generic_desc,
+          &md->rbody, ch, "my identity (ciphertext)"))
+        return STF_INTERNAL_ERROR;
+        memset(ch.ptr, 0, ch.len);
+        freeanychunk(ch);
+
+        if (!build_and_ship_nonce_pk(st, &st->st_ni, &md->rbody,
+          ISAKMP_NEXT_NONE, "<Ni_b>PubKey_r"))
+          return STF_INTERNAL_ERROR;
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Shipping nonce_i");
+        );
+        if (!build_and_ship_nonce(&st->st_ni, &md->rbody, 
+          ISAKMP_NEXT_NONE, "Ni"))
+          return STF_INTERNAL_ERROR;
+      }
+    }
+  }
+#endif
+
+  /* finish message */
+  close_message(&md->rbody);
+
+  /* Reinsert the state, using the responder cookie we just received */
+  unhash_state(st);
+  memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE);
+  insert_state(st);	/* needs cookies, connection, and msgid (0) */
+
+  st->st_state = STATE_MAIN_I2;
+
+  DBG(DBG_PARSING,
+  DBG_log("finished main_inR1_outI2");
+  );
+
+  return STF_REPLY;
+}
+
+/* STATE_MAIN_R1:
+ * PSK_AUTH, DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr
+ *
+ * The following are not yet implemented:
+ * PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
+ *	    --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ * RPKE_AUTH:
+ *	    HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
+ *	    --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
+ */
+stf_status
 main_inI2_outR2(struct msg_digest *md)
 {
     struct state *const st = md->st;
     pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI2_outR2");
+    );
+
     /* KE in */
     RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs));
 
-    /* Ni in */
-    RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni"));
+    /* Ni in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni"));
+
+
+    /**************** build output packet HDR;KE;Nr ****************/
+
+    /* HDR out done */
+
+    /* KE out */
+    if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group
+    , &md->rbody, ISAKMP_NEXT_NONCE))
+	return STF_INTERNAL_ERROR;
+
+    /* Nr out */
+    if (!build_and_ship_nonce(&st->st_nr, &md->rbody, ISAKMP_NEXT_NONE, "Nr"))
+	return STF_INTERNAL_ERROR;
+
+    /* finish message */
+    close_message(&md->rbody);
+
+    /* next message will be encrypted, but not this one.
+     * We could defer this calculation.
+     */
+    compute_dh_shared(st, st->st_gi, st->st_oakley.group);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+      return STF_REPLACE_DOOMED_EXCHANGE;
+#endif
+
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+    update_iv(st);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R2;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2");
+    );
+
+    return STF_REPLY;
+}
+
+#ifdef OPENSSL
+/* Handle HDR;KE;<IDii_b>PubKey_r;<Ni_b>PubKey_r from Initiator.
+ * Send a HDR;KE;<IDir_b>PubKey_i;<Nr_b>PubKey_i back.
+ */
+stf_status
+main_inI2_outR2_pk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI2_outR2_pk");
+    );
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", 
+      st->st_oakley.group, keyex_pbs));
+
+    if (!decode_peer_id(md, FALSE))
+    return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* Ni_b<PubKey_r> in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "<Ni_b>PubKey_r"));
+
+    /** build output packet HDR;KE;<IDir_b>_PubKey_i;<Nr_b>PubKey_i*********/
+
+    /* HDR out done */
+
+    /* KE out */
+    if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group, 
+    &md->rbody, ISAKMP_NEXT_ID))
+	return STF_INTERNAL_ERROR;
+
+    {
+      /* <IDir_b>PubKey_i out */
+      chunk_t ch;
+      
+      if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+        ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+        ch.ptr = alloc_bytes(ch.len, "plaintext der_asn1_dn identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), 
+          st->st_connection->this.id.der_asn1_dn.ptr, 
+          st->st_connection->this.id.der_asn1_dn.len);     
+      } else {
+        ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+        ch.ptr = alloc_bytes(ch.len, "plaintext identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr),
+          sizeof(st->st_connection->this.id.ip_addr));
+      }
+
+
+      /* PK encrypt this */
+      if (! pubkey_encrypt_chunk( &ch, st )) {
+        return STF_INTERNAL_ERROR;
+      }
+      if (!out_generic_chunk(ISAKMP_NEXT_NONCE, &isakmp_generic_desc, &md->rbody, ch, "my identity (ciphertext)"))
+	return STF_INTERNAL_ERROR;
+      memset(ch.ptr, 0, ch.len);
+      freeanychunk(ch);
+    }
+    
+    /* Nr out */
+    if (!build_and_ship_nonce_pk(st, &st->st_nr, &md->rbody, ISAKMP_NEXT_NONE, "<Nr_b>PubKey_i"))
+      return STF_INTERNAL_ERROR;
+
+    /* finish message */
+    close_message(&md->rbody);
+
+    /* next message will be encrypted, but not this one.
+     * We could defer this calculation.
+     */
+#ifndef DODGE_DH_MISSING_ZERO_BUG
+    compute_dh_shared(st, st->st_gi, st->st_oakley.group);
+#endif
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+    update_iv(st);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R2;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2_pk");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+#ifdef OPENSSL
+/* Handle HDR;<Ni_b>Pubkey_r;<KE_b>Ke_i;<IDi1_b>Ke_i[;<cert>Ke_r] from Initiator
+ * Send a HDR;<Nr_b>Pubkey_i;<KE_b>Ke_r;<IDr1_b>Ke_r[;<cert>Ke_r] back.
+ */
+stf_status
+main_inI2_outR2_rpk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI2_outR2_rpk");
+    );
+
+    /* Ni_b<PubKey_r> in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "<Ni_b>PubKey_r"));
+
+    /* KE<Ke_r> in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", 
+      st->st_oakley.group, keyex_pbs));
+
+    if (!decode_peer_id(md, FALSE))
+      return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /**************** build output packet ****************/
+
+    /* HDR out done */
+
+    /* Nr out */
+    if (!build_and_ship_nonce_pk(st, &st->st_nr, &md->rbody, 
+      ISAKMP_NEXT_KE, "<Nr_b>PubKey_i")) 
+      return STF_INTERNAL_ERROR;
+
+    if (derive_symmetric_key(st, st->st_nr,
+			     st->st_rcookie, COOKIE_SIZE,
+			     &st->st_ks_r,
+			     &st->st_ne_r) < 0) {
+      log("error while deriving symmetric key in revised mode");
+      return STF_INTERNAL_ERROR;
+    }
+    memset(st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
+
+    DBG(DBG_PARSING,
+    DBG_dump_chunk("Generated Ke_r:", st->st_ne_r);
+    );
+
+    /* KE out */
+    if (!build_and_ship_KE_rpk(st, FALSE, &st->st_gr, st->st_oakley.group
+			       , &md->rbody, ISAKMP_NEXT_ID))
+      return STF_INTERNAL_ERROR;
+
+    /* <IDr1_b>Ke_r[<cert>Ke_r] out */
+    {
+      chunk_t ch, out;
+
+      if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+        ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+        ch.ptr = alloc_bytes(ch.len, "encrypted der_asn1_dn identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), 
+          st->st_connection->this.id.der_asn1_dn.ptr, 
+          st->st_connection->this.id.der_asn1_dn.len);     
+      } else {
+        ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+        ch.ptr = alloc_bytes(ch.len, "encrypted identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr),
+          sizeof(st->st_connection->this.id.ip_addr));
+      }
+
+      if (!encrypt_payload(st, &st->st_ks_r, st->st_ne_r_iv,
+        ch, &out))
+      return STF_INTERNAL_ERROR;
+      freeanychunk(ch);
+
+      /* Are we going to send CERT? */
+      if ((st->st_connection->cert_options & CERT_OPTION_SEND) == 0) {
+        if (!out_generic_chunk(ISAKMP_NEXT_NONE, &isakmp_generic_desc,
+          &md->rbody, out, "my identity (ciphertext)")) 
+        {
+	  freeanychunk(out);
+	  return STF_INTERNAL_ERROR;
+        }
+      } else {
+        if (!out_generic_chunk(ISAKMP_NEXT_CERT, &isakmp_generic_desc,
+          &md->rbody, out, "my identity (ciphertext)")) 
+        {
+	  freeanychunk(out);
+	  return STF_INTERNAL_ERROR;
+        }
+      }
+      freeanychunk(out);
+    }
+
+        /* Well, if we do send CERT, let's start on it from here */
+        if ((st->st_connection->cert_options & CERT_OPTION_SEND) != 0) {
+
+          chunk_t crt, cx, out;
+          unsigned long ulen;
+          /* Send the signing certificate */
+
+          ulen = i2d_X509(st->st_connection->cert, NULL);
+          ulen++;
+          if ((cx.ptr = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+          { 
+            return STF_INTERNAL_ERROR; 
+          }
+          (cx.ptr)[0] = (u_char)(CERT_TYPE_X509_SIG);
+          cx.len = ulen;
+          crt.ptr = &(cx.ptr[1]);
+          crt.len = i2d_X509(st->st_connection->cert, &(crt.ptr));
+
+          DBG(DBG_CRYPT,
+          DBG_log("plaintext Certificate length: %d", cx.len);
+          DBG_dump_chunk("plaintext Certificate", cx);
+          );
+
+          /* encrypt the certificate to send */
+          if (!encrypt_payload(st, &st->st_ks_r, st->st_ne_r_iv,
+            cx, &out))
+          return STF_INTERNAL_ERROR;
+
+          DBG(DBG_CRYPT,
+          DBG_log("cyphertext Certificate length: %d", out.len);
+          DBG_dump_chunk("cyphertext Certificate", out);
+          );
+
+          if (!out_generic_chunk(ISAKMP_NEXT_NONE, 
+            &isakmp_ipsec_certificate_desc,
+            &md->rbody, out, "my certificate (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        }
+        /* end of sending out cert */
+    
+    /* finish message */
+    close_message(&md->rbody);
+
+    /* next message will be encrypted, but not this one.
+     * We could defer this calculation.
+     */
+#ifndef DODGE_DH_MISSING_ZERO_BUG
+    compute_dh_shared(st, st->st_gi, st->st_oakley.group);
+#endif
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+    update_iv(st);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R2;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2_rpk");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+
+/* STATE_MAIN_I2:
+ * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
+ * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
+ *
+ * The following are not yet implemented.
+ * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ *	    --> HDR*, HASH_I
+ * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
+ *	    --> HDR*, HASH_I
+ */
+stf_status
+main_inR2_outI3(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+#ifdef OPENSSL
+    struct connection *c = st->st_connection;
+#endif
+
+    pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
+	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR2_outI3");
+    );
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", 
+		st->st_oakley.group, keyex_pbs));
+
+    /* Nr in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
+
+    /* done parsing; initialize crypto  */
+
+    compute_dh_shared(st, st->st_gr, st->st_oakley.group);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+       return STF_REPLACE_DOOMED_EXCHANGE;
+#endif
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+
+    /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
+    /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
+
+    /* HDR* out done */
+
+    /* IDii out */
+    {
+	struct isakmp_ipsec_id id_hd;
+	chunk_t id_b;
+	pb_stream id_pbs;
+
+	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
+#ifdef OPENSSL
+if (use_openssl(st->st_connection)) 
+{
+  switch(st->st_oakley.auth) {
+  case OAKLEY_RSA_SIG:
+  case OAKLEY_DSS_SIG:
+    if ((c->cert_options & CERT_OPTION_SEND) == 0)
+      id_hd.isaiid_np = ISAKMP_NEXT_SIG;
+    else
+      id_hd.isaiid_np = ISAKMP_NEXT_CERT;
+    break;
+  case OAKLEY_RSA_ENC:
+  case OAKLEY_RSA_ENC_REV:
+    log("RSA method not supported yet");
+    return STF_INTERNAL_ERROR;
+    break;
+  default:
+    id_hd.isaiid_np = ISAKMP_NEXT_HASH;
+    break;
+  }
+}
+else
+{
+#endif /* OPENSSL */
+	id_hd.isaiid_np = auth_payload;
+#ifdef OPENSSL
+}
+#endif /* OPENSSL */
+
+	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
+		|| !out_chunk(id_b, &id_pbs, "my identity")) 
+		return STF_INTERNAL_ERROR;
+	close_output_pbs(&id_pbs);
+    } /* IDii out done */
+
+#ifdef OPENSSL
+if (use_openssl(st->st_connection)) 
+{
+    if (((c->cert_options & CERT_OPTION_SEND) != 0) &&
+  ((st->st_oakley.auth == OAKLEY_RSA_SIG) ||
+   (st->st_oakley.auth == OAKLEY_DSS_SIG))) {
+      u_char *crt, *cx;
+      unsigned long ulen;
+      /* Send the signing certificate */
+
+      ulen = i2d_X509(c->cert, NULL);
+      ulen++;
+      if ((cx = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+  { return STF_INTERNAL_ERROR; }
+      cx[0] = (u_char)(CERT_TYPE_X509_SIG);
+      crt = &(cx[1]);
+      i2d_X509(c->cert, &crt);
+      if (!out_generic_raw(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc
+             , &md->rbody, cx, ulen, "CERT_I"))
+  return STF_INTERNAL_ERROR;
+      pfree(cx);
+    }
+
+  /* HASH_I out, OPENSSL */
+  {
+	u_char hash_val[MAX_DIGEST_LEN];
+	size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
+    u_char *buf;
+    u_int elen;
+    bool ok;
+
+  /* Output the signature/hash as defined by the selected Oakley transform */
+
+  switch (st->st_oakley.auth) {
+  case OAKLEY_RSA_SIG: /* output signed HASH_I */
+    if ((buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+               "RSA signature")) == NULL)
+        return STF_INTERNAL_ERROR;
+    elen = RSA_private_encrypt(hash_len, hash_val, buf,
+                   ((EVP_PKEY *)(c->key))->pkey.rsa,
+                   RSA_PKCS1_PADDING);
+    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc, &md->rbody
+                 , buf, elen, "SIG_I"))
+      return STF_INTERNAL_ERROR;
+    pfree(buf);
+   
+	DBG(DBG_PARSING,
+	    DBG_log("Selected auth mechanism is %s",
+        	enum_show(&oakley_auth_names, st->st_oakley.auth));
+	)
+    break;
+
+  case OAKLEY_DSS_SIG:
+    /* We don't have to check whether the hash is a SHA1 */
+    /* one, since the ciphersuite offering DSA is only */
+    /* configured with SHA1. Don't change this configuration */
+    if (c->cert_options & CERT_OPTION_DSS_SHA)
+      main_mode_sha1(st, hash_val, &hash_len, TRUE, TRUE);
+
+    buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+              "DSA signature");
+    if (buf) {
+      ok = (c->cert_options & CERT_OPTION_DSS_ALT)
+        ? DSA_sign_raw(hash_val, hash_len,
+               buf, &elen, ((EVP_PKEY *)(c->key))->pkey.dsa)
+        : DSA_sign(EVP_PKEY_DSA, hash_val, hash_len,
+           buf, &elen, ((EVP_PKEY *)(c->key))->pkey.dsa);
+      if (!ok) {
+        /* DSA signing failed */
+        log_err();
+        return STF_INTERNAL_ERROR;
+      }
+      if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc,
+               &md->rbody, buf, elen, "SIG_I"))
+        return STF_INTERNAL_ERROR;
+      pfree(buf);
+    } else
+      return STF_INTERNAL_ERROR;
+   
+	DBG(DBG_PARSING | DBG_CONTROL, 
+	DBG_log("Selected auth mechanism is %s",
+	  enum_show(&oakley_auth_names, st->st_oakley.auth));
+	);
+    break;
+    /* If we get to any of these, something has gone WAY wrong */
+  case OAKLEY_RSA_ENC:
+    return STF_INTERNAL_ERROR;
+  case OAKLEY_ELGAMAL_ENC:
+    return STF_INTERNAL_ERROR;
+  case OAKLEY_RSA_ENC_REV:
+    return STF_INTERNAL_ERROR;
+  case OAKLEY_ELGAMAL_ENC_REV:
+    return STF_INTERNAL_ERROR;
+  default:
+	} /* switch done */
+  } /* HASH_I out, openssl done. */
+}
+else
+{
+#endif /* OPENSSL */
+  /* HASH_I or SIG_I out, !OPENSSL */
+  {
+	u_char hash_val[MAX_DIGEST_LEN];
+	size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
+
+	if (auth_payload == ISAKMP_NEXT_HASH)
+	{
+	    /* HASH_I out */
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+	    , hash_val, hash_len, "HASH_I"))
+		return STF_INTERNAL_ERROR;
+	}
+	else
+	{
+	    /* SIG_I out */
+	    u_char sig_val[RSA_MAX_OCTETS];
+	    size_t sig_len = RSA_sign_hash(st->st_connection, 
+			sig_val, hash_val, hash_len);
+
+	    if (sig_len == 0)
+	    {
+		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
+		return STF_FAIL + AUTHENTICATION_FAILED;
+	    }
+
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
+	    , &md->rbody, sig_val, sig_len, "SIG_I"))
+		return STF_INTERNAL_ERROR;
+	}
+  }
+#ifdef OPENSSL
+}
+#endif /* OPENSSL */
+
+    /* encrypt message, except for fixed part of header */
+
+    /* st_new_iv was computed by generate_skeyids_iv */
+    if (!encrypt_message(&md->rbody, st))
+	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I3;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR2_outI3");
+    );
+
+    return STF_REPLY;
+}
+
+#ifdef OPENSSL
+/*
+ * Handle HDR;KE;<IDir_b>PubKey_i;<Nr_b>PubKey_i from responder.
+ * Send a HDR*;HASH_I back.
+ */
+stf_status main_inR2_outI3_pk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR2_outI3_pk");
+    );
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", 
+	st->st_oakley.group, keyex_pbs));
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+    return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* Nr in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "<Nr_b>PubKey_i"));
+
+    /* done parsing; initialize crypto  */
 
+    compute_dh_shared(st, st->st_gr, st->st_oakley.group);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+       return STF_REPLACE_DOOMED_EXCHANGE;
+#endif
+    if (!generate_skeyids_iv(st))
+    return STF_FAIL + AUTHENTICATION_FAILED;
 
-    /**************** build output packet HDR;KE;Nr ****************/
+    /**************** build output packet HDR*;HASH_I ****************/
 
-    /* HDR out done */
+    /* HDR* out done */
 
-    /* KE out */
-    if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group
-    , &md->rbody, ISAKMP_NEXT_NONCE))
-	return STF_INTERNAL_ERROR;
+    /* HASH_I out */
+    {
+  u_char hash_val[MAX_DIGEST_LEN];
+  size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
 
-    /* Nr out */
-    if (!build_and_ship_nonce(&st->st_nr, &md->rbody, ISAKMP_NEXT_NONE, "Nr"))
+  if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+  , hash_val, hash_len, "HASH_I"))
 	return STF_INTERNAL_ERROR;
+    }
 
-    /* finish message */
-    close_message(&md->rbody);
+    /* encrypt message, except for fixed part of header */
 
-    /* next message will be encrypted, but not this one.
-     * We could defer this calculation.
-     */
-#ifndef DODGE_DH_MISSING_ZERO_BUG
-    compute_dh_shared(st, st->st_gi, st->st_oakley.group);
-#endif
-    if (!generate_skeyids_iv(st))
-	return STF_FAIL + AUTHENTICATION_FAILED;
-    update_iv(st);
+    /* st_new_iv was computed by generate_skeyids_iv */
+    if (!encrypt_message(&md->rbody, st))
+    return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
 
     /* Advance state */
-    st->st_state = STATE_MAIN_R2;
+    st->st_state = STATE_MAIN_I3;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR2_outI3_pk");
+    );
 
     return STF_REPLY;
 }
+#endif /* OPENSSL */
 
-/* STATE_MAIN_I2:
- * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
- * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
- *
- * The following are not yet implemented.
- * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- *	    --> HDR*, HASH_I
- * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- *	    --> HDR*, HASH_I
+#ifdef OPENSSL
+/* Handle HDR;KE;<Nr_b>PubKey_i;<KE_b>Ke_r;<IDr1_b>Ke_r from responder.
+ * Send a HDR*;HASH_I back.
  */
 stf_status
-main_inR2_outI3(struct msg_digest *md)
+main_inR2_outI3_rpk(struct msg_digest *md)
 {
     struct state *const st = md->st;
     pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
-    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
-	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
 
-    /* KE in */
-    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR2_outI3_rpk");
+    );
 
     /* Nr in */
-    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "<Nr_b>PubKey_i"));
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", 
+      st->st_oakley.group, keyex_pbs));
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+      return STF_FAIL + INVALID_ID_INFORMATION;
 
     /* done parsing; initialize crypto  */
 
@@ -2098,55 +3408,20 @@
     if (!generate_skeyids_iv(st))
 	return STF_FAIL + AUTHENTICATION_FAILED;
 
-    /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
-    /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
+    /**************** build output packet HDR*;HASH_I ****************/
 
     /* HDR* out done */
 
-    /* IDii out */
-    {
-	struct isakmp_ipsec_id id_hd;
-	chunk_t id_b;
-	pb_stream id_pbs;
-
-	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
-	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
-	|| !out_chunk(id_b, &id_pbs, "my identity"))
-	    return STF_INTERNAL_ERROR;
-	close_output_pbs(&id_pbs);
-    }
-
-    /* HASH_I or SIG_I out */
-    {
-	u_char hash_val[MAX_DIGEST_LEN];
-	size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
-
-	if (auth_payload == ISAKMP_NEXT_HASH)
-	{
 	    /* HASH_I out */
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
-	    , hash_val, hash_len, "HASH_I"))
-		return STF_INTERNAL_ERROR;
-	}
-	else
 	{
-	    /* SIG_I out */
-	    u_char sig_val[RSA_MAX_OCTETS];
-	    size_t sig_len = RSA_sign_hash(st->st_connection
-		, sig_val, hash_val, hash_len);
+      u_char hash_val[MAX_DIGEST_LEN];
 
-	    if (sig_len == 0)
-	    {
-		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
-		return STF_FAIL + AUTHENTICATION_FAILED;
-	    }
+      size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
 
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
-	    , &md->rbody, sig_val, sig_len, "SIG_I"))
+      if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody, 
+        hash_val, hash_len, "HASH_I"))
 		return STF_INTERNAL_ERROR;
 	}
-    }
 
     /* encrypt message, except for fixed part of header */
 
@@ -2157,8 +3432,30 @@
     /* Advance state */
     st->st_state = STATE_MAIN_I3;
 
+    DBG(DBG_PARSING,
+    DBG_log("fnished main_inR2_outI3_rpk");
+    );
+
     return STF_REPLY;
 }
+#endif /* OPENSSL */
+
+
+#ifdef OPENSSL
+/* STATE_MAIN_R2:
+ * Which type of DS are we currently handling?
+ * Classic? OPENSSL?
+ */
+stf_status
+main_inI3_outR3_whichds(struct msg_digest *md)
+{ 
+	if (! use_openssl(md->st->st_connection)) {
+		return main_inI3_outR3(md);
+	} else {
+		return main_inI3_outR3_ds(md);
+	}
+}
+#endif /* OPENSSL */
 
 /* STATE_MAIN_R2:
  * PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
@@ -2172,6 +3470,10 @@
     int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
 	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI3_outR3");
+    );
+
     /* input code similar to main_inR3 -- should be factored */
 
     /* IDii in */
@@ -2219,52 +3521,394 @@
 
 	    if (sig_len == 0)
 	    {
-		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
-		return STF_FAIL + AUTHENTICATION_FAILED;
+		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
+		return STF_FAIL + AUTHENTICATION_FAILED;
+	    }
+
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
+	    , &md->rbody, sig_val, sig_len, "SIG_R"))
+		return STF_INTERNAL_ERROR;
+	}
+    }
+
+    /* encrypt message, sans fixed part of header */
+
+    if (!encrypt_message(&md->rbody, st))
+	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
+
+    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
+    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
+	, st->st_new_iv, st->st_new_iv_len);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R3;
+    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+
+    /* ??? If st->st_connectionc->gw_info != NULL,
+     * we should keep the public key -- it tested out.
+     */
+
+    return STF_REPLY;
+}
+
+/* STATE_MAIN_I3:
+ * Handle HDR*;IDir;HASH/SIG_R from responder.
+ */
+stf_status
+main_inR3(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    struct connection *c = st->st_connection;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3");
+    );
+
+    /* input code similar to main_inI3_outR3 -- should be factored */
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+	return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* HASH_R or SIG_R in */
+    RETURN_STF_FAILURE(check_main_authenticator(md, FALSE));
+
+    /**************** done input ****************/
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I4;
+    ISAKMP_SA_established(c, st->st_serialno);
+
+    /* ??? If c->gw_info != NULL,
+     * we should keep the public key -- it tested out.
+     */
+
+    update_iv(st);	/* finalize our Phase 1 IV */
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3");
+    );
+
+    return STF_UNPEND_QUICK;
+}
+
+#ifdef OPENSSL
+/* Handle HDR*;IDir;[CERT];SIG_R from responder.
+ */
+stf_status
+main_inR3_ds(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    struct connection *c = st->st_connection;
+    u_char hash_val[MAX_DIGEST_LEN], *buf;
+    pb_stream *sig_pbs;
+    unsigned int dlen;
+    struct payload_digest *id_pld;
+    size_t hash_len = main_mode_hash(st, hash_val, FALSE, FALSE);
+    // size_t hash_len;
+    // main_mode_hash(st, hash_val, &hash_len, FALSE, FALSE);
+
+    /* input code similar to main_inI3_outR3 -- should be factored */
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3_ds");
+    );
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+      return STF_FAIL + INVALID_ID_INFORMATION;
+
+    switch (st->st_oakley.auth) {
+    case OAKLEY_RSA_SIG: /* check SIG_I */
+      {
+      RSA *rsa;
+      STACK_OF(X509) *peerlist;
+      X509 *recv_cert, *cert;
+      pb_stream *cert_pbs;
+      int i, success;
+
+      recv_cert = NULL;
+      /* First check to see if we have a certificate sent to us */
+      if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+          ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+        u_char *crt;
+        unsigned long len;
+
+        switch(cert_pbs->cur[0]) {
+        case CERT_TYPE_X509_SIG:
+          crt = &(cert_pbs->cur[1]);
+          len = pbs_left(cert_pbs)-1;
+          recv_cert = d2i_X509(NULL, &crt, len);
+          break;
+        default:
+              DBG(DBG_PARSING,
+                      DBG_log("Unhandled certificate encoding: %s",
+                      enum_show(&cert_names, cert_pbs->cur[0]));
+              );
+          break;
+        }
+      }
+
+      if (recv_cert) {
+        char buf[200];
+
+        X509_NAME_oneline(X509_get_subject_name(recv_cert)
+                          , buf, sizeof(buf));
+              DBG(DBG_PARSING,
+                      DBG_log("Sent certificate \"%s\"", buf);
+              );
+      }
+
+      id_pld = md->chain[ISAKMP_NEXT_ID];
+      if ((peerlist =
+           peer_cert_list((STACK_OF(XMAP) *)c->lu,
+                          EVP_PKEY_RSA, recv_cert, id_pld,
+                          (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE)) == NULL) {
+        log("Verification certificate(s) unavailable to check signature in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if (sk_X509_num(peerlist) == 0) {
+        log("Unable to get any certificate for peer in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+              ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+        log("Signature not present in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+      DBG(DBG_PARSING,
+              DBG_dump("Computed hash", hash_val, hash_len);
+      );
+      /* Iterate through all certificates in the peer list until */
+      /* we have one which verifies the signature, or we have no */
+      /* more certificates to verify with */
+      for(i=0, success=0, buf = NULL; ((success == 0) && (i < sk_X509_num(peerlist))); i++) {
+        rsa = X509_get_pubkey(sk_X509_value(peerlist, i))->pkey.rsa;
+        if ((buf = alloc_bytes(EVP_PKEY_size(X509_get_pubkey(sk_X509_value(peerlist, i))),
+                               "RSA decrypt sig")) != NULL) {
+          dlen = RSA_public_decrypt(pbs_left(sig_pbs), sig_pbs->cur, buf, rsa
+                                    , RSA_PKCS1_PADDING);
+              DBG(DBG_PARSING,
+                      DBG_dump("Decrypted hash", buf, (dlen > hash_len)
+                              ? hash_len : dlen);
+              );
+          if ((dlen == hash_len) && (memcmp(buf, hash_val, hash_len) == 0)) {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_R matches computed hash");
+                      )
+            success = 1;
+            cert = X509_dup(sk_X509_value(peerlist, i));
+          } else {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_R does not match computed hash");
+                      );
+          }
+          pfree(buf);
+          buf = NULL;
+        }
+      }
+      if (buf) pfree(buf);
+
+      if (!success) {
+        log_err();
+        DBG_cond_dump(DBG_CRYPT,
+                      "received SIG_R does not match computed value in Main R3:"
+                      , sig_pbs->cur, pbs_left(sig_pbs));
+        sk_X509_pop_free(peerlist, X509_free);
+        return STF_FAIL + INVALID_SIGNATURE;
+      } else {
+        /* We know that certificate 'cert' was used to */
+        /* sign the accurate hash which accompanied the method */
+        /* Now we have to verify that it is a valid certificate */
+        /* to be signing anything */
+              DBG(DBG_PARSING,
+                      DBG_log("Verifying certificate along path %s", c->path);
+              );
+              if (verify_certificate( cert, c->lu, c->path,
+                      (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+              {
+                      DBG(DBG_PARSING,
+                              DBG_log("Signing certificate is valid");
+                      );
+              } else {
+                      sk_X509_pop_free(peerlist, X509_free);
+                      return STF_FAIL + INVALID_CERTIFICATE;
+              }
+      }
+      sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+    case OAKLEY_DSS_SIG:
+      {
+      DSA *dsa;
+      STACK_OF(X509) *peerlist;
+      X509 *recv_cert, *cert;
+      pb_stream *cert_pbs;
+      int i, success;
+
+      if (c->cert_options & CERT_OPTION_DSS_SHA)
+        main_mode_sha1(st, hash_val, &hash_len, FALSE, FALSE);
+      recv_cert = NULL;
+      /* First check to see if we have a certificate sent to us */
+      if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+          ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+        u_char *crt;
+        unsigned long len;
+
+        switch(cert_pbs->cur[0]) {
+        case CERT_TYPE_X509_SIG:
+          crt = &(cert_pbs->cur[1]);
+          len = pbs_left(cert_pbs)-1;
+          recv_cert = d2i_X509(NULL, &crt, len);
+          break;
+        default:
+              DBG(DBG_PARSING,
+                  DBG_log("Unhandled certificate encoding: %s",
+                          enum_show(&cert_names, cert_pbs->cur[0]));
+              );
+          break;
+        }
+      }
+
+      if (recv_cert) {
+        char buf[200];
+
+        X509_NAME_oneline(X509_get_subject_name(recv_cert)
+                          , buf, sizeof(buf));
+              DBG(DBG_PARSING,
+                      DBG_log("Sent certificate \"%s\"", buf);
+              );
+      }
+
+      /* We know this field is legitimate, because the */
+      /* decode_peer_id has been called before */
+      id_pld = md->chain[ISAKMP_NEXT_ID];
+
+      if ((peerlist =
+           peer_cert_list((STACK_OF(XMAP) *)c->lu,
+                          EVP_PKEY_DSA, recv_cert,
+                          id_pld,
+                          (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE )) == NULL) {
+        log("Verification certificate(s) unavailable to check signature in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if (sk_X509_num(peerlist) == 0) {
+        log("Unable to get any certificate for peer in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+          ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+        log("Signature not present in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+      DBG(DBG_PARSING,
+              DBG_dump("Computed hash", hash_val, hash_len);
+      );
+      /* Iterate through all certificates in the peer list until */
+      /* we have one which verifies the signature, or we have no */
+      /* more certificates to verify with */
+      for(i=0, success=0, buf=NULL; ((success == 0) && (i < sk_X509_num(peerlist))); i++) {
+        dsa = X509_get_pubkey(sk_X509_value(peerlist, i))->pkey.dsa;
+        if ((buf = alloc_bytes(SHA1_DIGEST_SIZE, "DSA decrypt sig")) != NULL) {
+          success = (c->cert_options & CERT_OPTION_DSS_ALT)
+            ? DSA_verify_raw(hash_val, hash_len,
+                             sig_pbs->cur, pbs_left(sig_pbs),
+                             dsa)
+            : DSA_verify(EVP_PKEY_DSA,
+                         hash_val, hash_len,
+                         sig_pbs->cur, pbs_left(sig_pbs),
+                         dsa);
+          if (success == 1) {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_I matches computed hash");
+                      );
+            cert = X509_dup(sk_X509_value(peerlist, i));;
+          } else if (success == 0) {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_I does not match computed hash");
+                      );
+          } else {
+                      DBG(DBG_PARSING,
+                    DBG_log("Verification error");
+                      );
+            log_err();
+          }
+          pfree(buf);
+          buf = NULL;
+        }
+      }
+      if (buf) pfree(buf);
+      if (!success) {
+        log_err();
+        DBG_cond_dump(DBG_CRYPT, "received SIG_I does not match computed value in Main I3:"
+                      , sig_pbs->cur, pbs_left(sig_pbs));
+        sk_X509_pop_free(peerlist, X509_free);
+        return STF_FAIL + INVALID_SIGNATURE;
+      } else {
+        /* We know that certificate 'cert' was used to */
+        /* sign the accurate hash which accompanied the method */
+        /* Now we have to verify that it is a valid certificate */
+        /* to be signing anything */
+              DBG(DBG_PARSING,
+                      DBG_log("Verifying certificate along path %s", c->path);
+              );
+        if (verify_certificate( cert, c->lu, c->path, (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+              {
+                      DBG(DBG_PARSING,
+                              DBG_log("Signing certificate is valid");
+                      );
 	    }
-
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
-	    , &md->rbody, sig_val, sig_len, "SIG_R"))
-		return STF_INTERNAL_ERROR;
+        else {
+          sk_X509_pop_free(peerlist, X509_free);
+          return STF_FAIL + INVALID_CERTIFICATE;
 	}
     }
+      sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+    default:
+      return STF_INTERNAL_ERROR;
+      break;
+    }
 
-    /* encrypt message, sans fixed part of header */
-
-    if (!encrypt_message(&md->rbody, st))
-	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
-
-    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
-    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
-	, st->st_new_iv, st->st_new_iv_len);
+    /**************** done input ****************/
 
     /* Advance state */
-    st->st_state = STATE_MAIN_R3;
-    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+    st->st_state = STATE_MAIN_I4;
+    ISAKMP_SA_established(c, st->st_serialno);
 
-    /* ??? If st->st_connectionc->gw_info != NULL,
-     * we should keep the public key -- it tested out.
-     */
+    update_iv(st);    /* finalize our Phase 1 IV */
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3_ds");
+    );
 
-    return STF_REPLY_UNPEND_QUICK;
+    return STF_UNPEND_QUICK;
 }
+#endif
 
-/* STATE_MAIN_I3:
- * Handle HDR*;IDir;HASH/SIG_R from responder.
+#ifdef OPENSSL
+/* Handle HDR*;HASH_R from responder.
  */
 stf_status
-main_inR3(struct msg_digest *md)
+main_inR3_pk(struct msg_digest *md)
 {
     struct state *const st = md->st;
     struct connection *c = st->st_connection;
 
     /* input code similar to main_inI3_outR3 -- should be factored */
 
-    /* IDir in */
-    if (!decode_peer_id(md, TRUE))
-	return STF_FAIL + INVALID_ID_INFORMATION;
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3_pk");
+    );
 
-    /* HASH_R or SIG_R in */
+    /* HASH_R in */
+    // CHECK_HASH(main_mode_hash(st, hash_val, &hash_len, FALSE, FALSE)
+      // , "HASH_R", "Main R3");
     RETURN_STF_FAILURE(check_main_authenticator(md, FALSE));
 
     /**************** done input ****************/
@@ -2273,14 +3917,16 @@
     st->st_state = STATE_MAIN_I4;
     ISAKMP_SA_established(c, st->st_serialno);
 
-    /* ??? If c->gw_info != NULL,
-     * we should keep the public key -- it tested out.
-     */
-
     update_iv(st);	/* finalize our Phase 1 IV */
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3_pk");
+    );
+
     return STF_UNPEND_QUICK;
 }
+#endif
+
 
 /* Handle first message of Phase 2 -- Quick Mode.
  * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] -->
@@ -2413,6 +4059,8 @@
 	}
 	else if (p != c)
 	{
+	    /* use p, not c */
+
 	    /* We've got a better connection: it can support the
 	     * specified clients.  But it may need instantiation.
 	     */
@@ -2420,8 +4068,7 @@
 	    {
 		/* Yup, it needs instantiation.  How much?
 		 * Is it a Road Warrior connection (simple)
-		 * or is it an Opportunistic connection (needing gw validation)?
-		 */
+                 * or is it an Opportunistic connection (needing gw validation)?                 */
 		if (HasWildcardClient(p))
 		{
 		    /* Opportunistic.
@@ -2721,8 +4369,510 @@
     if (c->gw_info != NULL)
 	c->gw_info->last_worked_time = now();
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI3_outR3");
+    );
+
+    return STF_REPLY;
+}
+
+#ifdef OPENSSL
+/*
+ * Handle HDR*;IDii;HASH_I from initiator. Send a HDR*;IDir;HASH_R back.
+ */
+stf_status
+main_inI3_outR3_ds(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+
+    struct connection *c = st->st_connection;
+    u_char hash_val[MAX_DIGEST_LEN], *buf;
+    pb_stream *sig_pbs;
+    unsigned int dlen;
+    struct payload_digest *id_pld;
+    size_t hash_len = main_mode_hash(st, hash_val, TRUE, FALSE);
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI3_outR3_ds");
+    );
+
+    /* input code similar to main_inR3 -- should be factored */
+
+    /* IDii in */
+    if (!decode_peer_id(md, FALSE))
+    return STF_FAIL + INVALID_ID_INFORMATION;
+
+    switch (st->st_oakley.auth) {
+    case OAKLEY_RSA_SIG: /* check SIG_I */
+      {
+  RSA *rsa;
+  STACK_OF(X509) *peerlist;
+  X509 *recv_cert, *cert;
+  pb_stream *cert_pbs;
+  int i, success;
+
+  recv_cert = NULL;
+  /* First check to see if we have a certificate sent to us */
+  if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+      ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+    u_char *crt;
+    unsigned long len;
+
+    switch(cert_pbs->cur[0]) {
+    case CERT_TYPE_X509_SIG:
+      crt = &(cert_pbs->cur[1]);
+      len = pbs_left(cert_pbs)-1;
+      recv_cert = d2i_X509(NULL, &crt, len);
+      break;
+    default:
+      DBG(DBG_PARSING,
+      DBG_log("Unhandled certificate encoding: %s",
+        enum_show(&cert_names, cert_pbs->cur[0]));
+      );
+      break;
+    }
+  }
+
+  if (recv_cert) {
+    char buf[200];
+
+    X509_NAME_oneline(X509_get_subject_name(recv_cert)
+              , buf, sizeof(buf));
+    DBG(DBG_PARSING,
+    DBG_log("Received certificate \"%s\"", buf);
+    );
+  }
+
+  /* We know this field is legitimate, because the */
+  /* decode_peer_id has been called before */
+  id_pld = md->chain[ISAKMP_NEXT_ID];
+
+  if ((peerlist = peer_cert_list((STACK_OF(XMAP) *)(c->lu),
+                     EVP_PKEY_RSA,
+                     recv_cert,
+                     id_pld,
+                     (c->cert_options & CERT_OPTION_STRICT)
+                     ? TRUE : FALSE)) == NULL) {
+    log("Verification certificate(s) unavailable to check signature in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if (sk_X509_num(peerlist) == 0) {
+    log("Unable to get any certificate for peer in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+      ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+    log("Signature not present in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+  DBG(DBG_PARSING,
+  DBG_dump("Computed hash", hash_val, hash_len);
+  );
+  /* Iterate through all certificates in the peer list until */
+  /* we have one which verifies the signature, or we have no */
+  /* more certificates to verify with */
+  for (i=0, success = 0; (success == 0) && (i<sk_X509_num(peerlist)); i++) {
+    X509 *xx = sk_X509_value(peerlist, i);
+
+    rsa = X509_get_pubkey(xx)->pkey.rsa;
+    if ((buf = alloc_bytes(EVP_PKEY_size(X509_get_pubkey(xx)),
+     "RSA decrypt sig")) != NULL) {
+      dlen = RSA_public_decrypt(pbs_left(sig_pbs), sig_pbs->cur, buf,
+        rsa, RSA_PKCS1_PADDING);
+      DBG(DBG_PARSING,
+      DBG_dump("Decrypted hash", buf, (dlen > hash_len) 
+        ? hash_len : dlen);
+      );
+      if ((dlen == hash_len) && (memcmp(buf, hash_val, hash_len) == 0)) {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I matches computed hash");
+        );
+        success = 1;
+        cert = X509_dup(xx);
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I does not computed hash");
+        );
+      }
+      pfree(buf);
+    }
+  }
+  if (!success) {
+    log_err();
+    DBG_cond_dump(DBG_CRYPT, 
+      "received SIG_I does not match computed value in Main I3:"
+      , sig_pbs->cur, pbs_left(sig_pbs));
+    sk_X509_pop_free(peerlist, X509_free);
+    return STF_FAIL + INVALID_SIGNATURE;
+  } else {
+    /* We know that certificate 'cert' was used to */
+    /* sign the accurate hash which accompanied the method */
+    /* Now we have to verify that it is a valid certificate */
+    /* to be signing anything */
+    DBG(DBG_PARSING,
+    DBG_log("Verifying certificate along path %s", c->path);
+    );
+    if (verify_certificate( cert, c->lu, c->path, 
+      (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+      {
+        DBG(DBG_PARSING,
+        DBG_log("Signing certificate is valid.");
+        );
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Signing certificate NOT valid.");
+        );
+        sk_X509_pop_free(peerlist, X509_free);
+        return STF_FAIL + INVALID_CERTIFICATE;
+      }
+  }
+  sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+    case OAKLEY_DSS_SIG:
+      {
+  DSA *dsa;
+  STACK_OF(X509) *peerlist;
+  X509 *recv_cert, *cert;
+  pb_stream *cert_pbs;
+  int i, success;
+
+  if (c->cert_options & CERT_OPTION_DSS_SHA)
+    main_mode_sha1(st, hash_val, &hash_len, TRUE, FALSE);
+  recv_cert = NULL;
+  /* First check to see if we have a certificate sent to us */
+  if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+      ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+    u_char *crt;
+    unsigned long len;
+
+    switch(cert_pbs->cur[0]) {
+    case CERT_TYPE_X509_SIG:
+      crt = &(cert_pbs->cur[1]);
+      len = pbs_left(cert_pbs)-1;
+      recv_cert = d2i_X509(NULL, &crt, len);
+      break;
+    default:
+		DBG(DBG_PARSING,
+			DBG_log("Unhandled certificate encoding: %s",
+				enum_show(&cert_names, cert_pbs->cur[0]));
+		);
+      break;
+    }
+  }
+
+  if (recv_cert) {
+    char buf[200];
+
+    X509_NAME_oneline(X509_get_subject_name(recv_cert)
+              , buf, sizeof(buf));
+    DBG(DBG_PARSING,
+    DBG_log("Received certificate \"%s\"", buf);
+    );
+  }
+
+  /* We know this field is legitimate, because the */
+  /* decode_peer_id has been called before */
+  id_pld = md->chain[ISAKMP_NEXT_ID];
+
+  if ((peerlist =
+       peer_cert_list((STACK_OF(XMAP) *)(c->lu), EVP_PKEY_DSA,
+              recv_cert, id_pld,
+              (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE)) == NULL) {
+    log("Verification certificate(s) unavailable to check signature in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if (sk_X509_num(peerlist) == 0) {
+    log("Unable to get any certificate for peer in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+      ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+    log("Signature not present in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  DBG(DBG_PARSING,
+  DBG_dump("Computed hash", hash_val, hash_len);
+  );
+  /* Iterate through all certificates in the peer list until */
+  /* we have one which verifies the signature, or we have no */
+  /* more certificates to verify with */
+  for(i=0, success=0, buf = NULL;
+      ((success == 0) && (i < sk_X509_num(peerlist))); i++) {
+    dsa = X509_get_pubkey(sk_X509_value(peerlist, i))->pkey.dsa;
+    if ((buf = alloc_bytes(SHA1_DIGEST_SIZE, "DSA sig space")) != NULL) {
+      success = (c->cert_options & CERT_OPTION_DSS_ALT)
+        ? DSA_verify_raw(hash_val, hash_len,
+                 sig_pbs->cur, pbs_left(sig_pbs),
+                 dsa)
+        : DSA_verify(EVP_PKEY_DSA,
+             hash_val, hash_len,
+             sig_pbs->cur, pbs_left(sig_pbs),
+             dsa)
+        ;
+      if (success == 1) {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I matches computed hash");
+        );
+        cert = X509_dup(sk_X509_value(peerlist, i));
+      } else if (success == 0) {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I does not computed hash");
+        );
+      } else {
+        DBG(DBG_PARSING,
+       	DBG_log("Verification error");
+        );
+        log_err();
+      }
+      pfree(buf);
+      buf = NULL;
+    }
+  }
+  if (buf) pfree(buf);
+  if (!success) {
+    log_err();
+    DBG_cond_dump(DBG_CRYPT, "received SIG_I does not match computed value in Main I3:"
+          , sig_pbs->cur, pbs_left(sig_pbs));
+    sk_X509_pop_free(peerlist, X509_free);
+    return STF_FAIL + INVALID_SIGNATURE;
+  } else {
+    /* We know that certificate 'cert' was used to */
+    /* sign the accurate hash which accompanied the method */
+    /* Now we have to verify that it is a valid certificate */
+    /* to be signing anything */
+    DBG(DBG_PARSING,
+    DBG_log("Verifying certificate along path %s", c->path);
+    );
+    if (verify_certificate( cert, c->lu, c->path, 
+      (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+    {
+      DBG(DBG_PARSING,
+      DBG_log("Signing certificate is valid");
+      );
+    } else {
+      sk_X509_pop_free(peerlist, X509_free);
+      return STF_FAIL + INVALID_CERTIFICATE;
+    }
+  }
+  sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+      /* Should never get here */
+    default:
+      return STF_INTERNAL_ERROR;
+    }
+
+    /************* build output packet HDR*;IDir;[CERT];SIG_R ******/
+    /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
+
+    /* IDir out */
+    {
+  struct isakmp_ipsec_id r_id;
+  pb_stream r_id_pbs;
+  chunk_t r_id_chunk;
+
+  // r_id.isaiid_idtype = st->st_myidentity_type;
+  r_id.isaiid_idtype = st->st_connection->this.id.kind;
+  r_id.isaiid_protoid = 0;    /* ??? is this right? */
+  r_id.isaiid_port = 0;   /* ??? is this right? */
+
+  build_id_payload(&r_id, &r_id_chunk, &st->st_connection->this);
+
+  if ((c->cert_options & CERT_OPTION_SEND) == 0)
+    r_id.isaiid_np = ISAKMP_NEXT_SIG;
+  else
+    r_id.isaiid_np = ISAKMP_NEXT_CERT;
+
+  if (!out_struct(&r_id, &isakmp_ipsec_identification_desc, &md->rbody, 
+    &r_id_pbs) || !out_chunk(r_id_chunk, &r_id_pbs, "my identity"))
+      return STF_INTERNAL_ERROR;
+  close_output_pbs(&r_id_pbs);
+
+#if 0
+  /* if a permanent cast is needed, we'll need to rethink this. */
+  r_id_chunk.len = sizeof(st->st_connection->this.id.ip_addr);
+  memcpy(&(r_id_chunk.ptr), &(st->st_connection->this.id.ip_addr), r_id_chunk.len);
+ 
+  if (!out_struct(&r_id, &isakmp_ipsec_identification_desc,
+          &md->rbody, &r_id_pbs)
+      || !out_chunk(r_id_chunk, &r_id_pbs, "my identity"))
+    return STF_INTERNAL_ERROR;
+  close_output_pbs(&r_id_pbs);
+#endif
+    }
+
+    if ((c->cert_options & CERT_OPTION_SEND) != 0) {
+      /* Send the signing certificate */
+      u_char *crt, *cx;
+      unsigned long ulen;
+      /* Send the signing certificate */
+    
+      ulen = i2d_X509(c->cert, NULL);
+      ulen++;
+      if ((cx = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+  { return STF_INTERNAL_ERROR; }
+      cx[0] = (u_char)(CERT_TYPE_X509_SIG);
+      crt = &(cx[1]);
+      i2d_X509(c->cert, &crt);
+      if (!out_generic_raw(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc
+             , &md->rbody, cx, ulen, "CERT_R"))
+  return STF_INTERNAL_ERROR;
+      pfree(cx);
+    }
+
+    /* SIG_R out */
+    {
+  u_char hash_val[MAX_DIGEST_LEN];
+  u_int elen;
+  bool ok;
+
+  // size_t hash_len;
+  // main_mode_hash(st, hash_val, &hash_len, FALSE, TRUE);
+  size_t hash_len = main_mode_hash(st, hash_val, FALSE, TRUE);
+
+  /* Output the signature/hash as defined by the selected Oakley transform */
+  switch (st->st_oakley.auth) {
+  case OAKLEY_RSA_SIG: /* output signed HASH_R */
+    if ((buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+               "RSA sig")) == NULL)
+      return STF_INTERNAL_ERROR;
+    elen = RSA_private_encrypt(hash_len, hash_val, buf,
+                   ((EVP_PKEY *)(c->key))->pkey.rsa,
+                   RSA_PKCS1_PADDING);
+    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc,
+                 &md->rbody, buf, elen, "SIG_R"))
+      return STF_INTERNAL_ERROR;
+    break;
+  case OAKLEY_DSS_SIG:
+    if (c->cert_options & CERT_OPTION_DSS_SHA)
+      main_mode_sha1(st, hash_val, &hash_len, FALSE, TRUE);
+
+    if ((buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+              "DSA sig")) == NULL)
+      return STF_INTERNAL_ERROR;
+    ok = (c->cert_options & CERT_OPTION_DSS_ALT)
+      ? DSA_sign_raw(hash_val, hash_len,
+             buf, &elen,
+             ((EVP_PKEY *)(c->key))->pkey.dsa)
+      : DSA_sign(EVP_PKEY_DSA, hash_val, hash_len,
+             buf, &elen,
+             ((EVP_PKEY *)(c->key))->pkey.dsa);
+    if (!ok) {
+      log_err();
+      return STF_INTERNAL_ERROR;
+    }
+    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc,
+                 &md->rbody, buf, elen, "SIG_I"))
+      return STF_INTERNAL_ERROR;
+   
+	DBG(DBG_PARSING,
+	    DBG_log("Selected auth mechanism is %s",
+			enum_show(&oakley_auth_names, st->st_oakley.auth));
+	);
+    break;
+  default:
+    return STF_INTERNAL_ERROR;
+  }
+  pfree(buf);
+    }
+
+    /* encrypt message, sans fixed part of header */
+
+    if (!encrypt_message(&md->rbody, st))
+  return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
+
+    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
+    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
+  , st->st_new_iv, st->st_new_iv_len);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R3;
+    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI3_outR3_ds");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+#ifdef OPENSSL
+/*
+ * Handle HDR*;HASH_I from initiator. Send a HDR*;HASH_R back.
+ */
+stf_status
+main_inI3_outR3_pk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+
+    /* input code similar to main_inR3 -- should be factored */
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI3_outR3_pk");
+    );
+
+    /* HASH_I in */
+    // CHECK_HASH(main_mode_hash(st, hash_val, &hash_len, TRUE, FALSE)
+  	// , "HASH_I", "Main I3");
+	RETURN_STF_FAILURE(check_main_authenticator(md, TRUE));
+
+    /**************** build output packet HDR*;HASH_R ****************/
+
+    /* HASH_R out */
+    {
+  u_char hash_val[MAX_DIGEST_LEN];
+  
+  // size_t hash_len;
+  // main_mode_hash(st, hash_val, &hash_len, FALSE, TRUE);
+  size_t hash_len = main_mode_hash(st, hash_val, FALSE, TRUE);
+
+  if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+  , hash_val, hash_len, "HASH_R"))
+      return STF_INTERNAL_ERROR;
+    }
+   
+    /* encrypt message, sans fixed part of header */
+    if (!encrypt_message(&md->rbody, st))
+  return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
+
+    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
+    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
+  , st->st_new_iv, st->st_new_iv_len);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R3;
+    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI3_outR3_pk");
+    );
+
     return STF_REPLY;
 }
+#endif
+
+#ifdef OPENSSL
+/* STATE_MAIN_I3:
+ * Handle HDR*;IDir;HASH/SIG_R from responder.
+ */
+stf_status
+main_inR3_whichds(struct msg_digest *md)
+{
+	if (!use_openssl(md->st->st_connection)) {
+		return main_inR3(md);
+	} else {
+		return main_inR3_ds(md);
+	}
+}
+#endif /* OPENSSL */
+
 
 /* Handle last message of Quick Mode.
  * HDR*, HASH(3) -> done
diff -BbruN freeswan-1.91.orig/pluto/ipsec_doi.h freeswan-1.91/pluto/ipsec_doi.h
--- freeswan-1.91.orig/pluto/ipsec_doi.h	Tue May  8 01:37:22 2001
+++ freeswan-1.91/pluto/ipsec_doi.h	Tue Jul  3 02:19:23 2001
@@ -28,9 +28,27 @@
     main_inI1_outR1,
     main_inR1_outI2,
     main_inI2_outR2,
+#ifdef OPENSSL
+    main_inI2_outR2_pk,
+    main_inI2_outR2_rpk,
+#endif
     main_inR2_outI3,
+#ifdef OPENSSL
+    main_inR2_outI3_pk,
+    main_inR2_outI3_rpk,
+#endif
     main_inI3_outR3,
+#ifdef OPENSSL
+    main_inI3_outR3_whichds,
+    main_inI3_outR3_ds,
+    main_inI3_outR3_pk,
+#endif
     main_inR3,
+#ifdef OPENSSL
+    main_inR3_whichds,
+    main_inR3_ds,
+    main_inR3_pk,
+#endif
     quick_inI1_outR1,
     quick_inR1_outI2,
     quick_inI2;
diff -BbruN freeswan-1.91.orig/pluto/kernel.c freeswan-1.91/pluto/kernel.c
--- freeswan-1.91.orig/pluto/kernel.c	Sat Jun 16 18:02:39 2001
+++ freeswan-1.91/pluto/kernel.c	Tue Jul  3 03:19:43 2001
@@ -50,6 +50,7 @@
 #include "server.h"
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
+extern int send_delete(struct state *st, ipsec_spi_t *spi, bool ESP);
 
 bool can_do_IPcomp = TRUE;  /* can system actually perform IPCOMP? */
 
@@ -2145,6 +2144,8 @@
 	passert(FALSE);	/* neither AH nor ESP in outbound SA bundle! */
     }
 
+    send_delete(st, &f->our_spi, proto==SA_ESP?TRUE:FALSE);
+
     return inbound
 	? del_spi(f->our_spi, proto, &c->that.host_addr, &c->this.host_addr)
 	: del_spi(f->attrs.spi, proto, &c->this.host_addr, &c->that.host_addr);
@@ -2242,9 +2242,6 @@
 	eroute_installed = st == NULL
 	    ? shunt_eroute(c, ERO_REPLACE, "replace")
 	    : sag_eroute(st, ERO_REPLACE, "replace");
-
-	if (eroute_installed && bspp != NULL)
-	    free_bare_shunt(bspp);
     }
     else
     {
@@ -2252,6 +2249,9 @@
 	eroute_installed = st == NULL
 	    ? shunt_eroute(c, ERO_ADD, "add")
 	    : sag_eroute(st, ERO_ADD, "add");
+
+       if (eroute_installed && bspp != NULL)
+           free_bare_shunt(bspp);
     }
 
     /* notify the firewall of a new tunnel */
diff -BbruN freeswan-1.91.orig/pluto/main.c freeswan-1.91/pluto/main.c
--- freeswan-1.91.orig/pluto/main.c	Tue Jun 12 17:40:38 2001
+++ freeswan-1.91/pluto/main.c	Tue Jul  3 02:54:17 2001
@@ -29,6 +29,11 @@
 
 #include <freeswan.h>
 
+#ifdef OPENSSL
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#endif
+
 #include "constants.h"
 #include "defs.h"
 #include "id.h"
@@ -42,6 +47,20 @@
 #include "rnd.h"
 #include "state.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#include "xmap_dir.h"
+#include "xmap_file.h"
+#ifdef HAVE_DB
+#include "xmap_db.h"
+#endif
+#ifdef HAVE_LDAP
+#include "xmap_ldap.h"
+#endif
+#include "xmap.h"
+
+#endif /* OPENSSL */
+
 #include "sha1.h"
 #include "md5.h"
 #include "crypto.h"	/* requires sha1.h and md5.h */
@@ -166,6 +185,21 @@
     bool log_to_stderr_desired = FALSE;
     int lockfd;
 
+#ifdef OPENSSL
+    SSLeay_add_all_algorithms();
+    X509V3_add_standard_extensions();
+    ERR_load_crypto_strings();
+    ERR_load_ElGamal_strings();
+    XMAP_register(XMAP_METHOD_file());
+    XMAP_register(XMAP_METHOD_dir());
+#ifdef HAVE_DB
+    XMAP_register(XMAP_METHOD_db());
+#endif /* HAVE_DB */
+#ifdef HAVE_LDAP
+    XMAP_register(XMAP_METHOD_ldap());
+#endif /* HAVE_LDAP */
+#endif
+
     /* handle arguments */
     for (;;)
     {
@@ -405,6 +439,8 @@
 	    abort();
     }
 
+    close(lockfd);
+
     init_constants();
     init_log();
     /* Note: some scripts may look for this exact message -- don't change */
@@ -439,6 +475,10 @@
 #ifdef LEAK_DETECTIVE
     report_leaks();
 #endif /* LEAK_DETECTIVE */
+#ifdef OPENSSL
+    X509V3_EXT_cleanup();
+    ERR_free_strings();
+#endif
     close_log();
     exit(status);
 }
diff -BbruN freeswan-1.91.orig/pluto/md5.c freeswan-1.91/pluto/md5.c
--- freeswan-1.91.orig/pluto/md5.c	Sat Dec 11 20:31:36 1999
+++ freeswan-1.91/pluto/md5.c	Tue Jul  3 02:54:40 2001
@@ -139,7 +139,11 @@
 /* MD5 initialization. Begins an MD5 operation, writing a new context.
  */
 void MD5Init (context)
+#ifndef OPENSSL
 MD5_CTX *context;                                        /* context */
+#else
+PLUTO_MD5_CTX *context;                                  /* context */
+#endif
 {
   context->count[0] = context->count[1] = 0;
   /* Load magic initialization constants.
@@ -155,7 +159,11 @@
   context.
  */
 void MD5Update (context, input, inputLen)
+#ifndef OPENSSL
 MD5_CTX *context;                                        /* context */
+#else
+PLUTO_MD5_CTX *context;                                  /* context */
+#endif
 unsigned char *input;                                /* input block */
 UINT4 inputLen;                            /* length of input block */
 {
@@ -194,7 +202,11 @@
  */
 void MD5Final (digest, context)
 unsigned char digest[16];                         /* message digest */
+#ifndef OPENSSL
 MD5_CTX *context;                                       /* context */
+#else
+PLUTO_MD5_CTX *context;
+#endif /* OPENSSL */
 {
   unsigned char bits[8];
   unsigned int index, padLen;
diff -BbruN freeswan-1.91.orig/pluto/md5.h freeswan-1.91/pluto/md5.h
--- freeswan-1.91.orig/pluto/md5.h	Sat Dec 11 20:31:36 1999
+++ freeswan-1.91/pluto/md5.h	Tue Jul  3 02:54:40 2001
@@ -61,11 +61,22 @@
   UINT4 state[4];                                   /* state (ABCD) */
   UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
   unsigned char buffer[64];                         /* input buffer */
+#ifndef OPENSSL
 } MD5_CTX;
+#else
+} PLUTO_MD5_CTX;
+#endif /* OPENSSL */
 
+#ifndef OPENSSL
 void MD5Init PROTO_LIST ((MD5_CTX *));
 void MD5Update PROTO_LIST
   ((MD5_CTX *, unsigned char *, UINT4));
 void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+#else
+void MD5Init PROTO_LIST ((PLUTO_MD5_CTX *));
+void MD5Update PROTO_LIST
+  ((PLUTO_MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], PLUTO_MD5_CTX *));
+#endif /* OPENSSL */
 
 #define _MD5_H_
diff -BbruN freeswan-1.91.orig/pluto/openssl.c freeswan-1.91/pluto/openssl.c
--- freeswan-1.91.orig/pluto/openssl.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/openssl.c	Tue Jul  3 02:54:53 2001
@@ -0,0 +1,2285 @@
+#ifdef OPENSSL
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <freeswan.h>
+
+#include <openssl/pem.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "id.h"
+#include "connections.h" /* needs id.h */
+#include "state.h"
+#include "kernel.h"
+#include "log.h"
+#include "packet.h"
+#include "preshared.h" /* for RSA_public_key used in FreeS/WAN */
+#include "spdb.h"
+#include "demux.h"
+#include "openssl.h"
+#include "xmap.h"
+
+#include "whack.h" /* for RC_LOG_SERIOUS value, for loglog()s. */
+
+struct _tok_node {
+  char *s;
+  struct _tok_node *next;
+};
+
+typedef struct _tok_node *tok_list;
+
+enum tok_state { TOK_NORMAL, TOK_QUOTE, TOK_BACKSLASH, TOK_BACKSLASH_Q };
+
+void tok_append(tok_list *t, const char *s);
+tok_list tokenize( const char *s, const char sep );
+void tok_free( tok_list t );
+static STACK_OF(X509) *lookup_certs_by_subject(STACK_OF(XMAP) *lu, 
+					X509_NAME *name);
+
+#if 0 /* not used */
+static STACK_OF(X509) *lookup_certs_by_issuer(STACK_OF(XMAP) *lu, 
+					X509_NAME *name);
+#endif
+
+void build_cert_chain( STACK_OF(X509) **ch, STACK_OF(XMAP) *lu, X509 *x );
+static int cert_compare(X509 *a, X509 *b);
+static STACK_OF(X509) *lookup_certs_by_ip(STACK_OF(XMAP) *lu,
+					  const char *id,
+					  const size_t len);
+static int ASN1_UTCTIME_cmp(ASN1_UTCTIME *a, ASN1_UTCTIME *b);
+static int cb( int ok, X509_STORE_CTX *ctx );
+
+void
+tok_append(tok_list *t, const char *s) {
+  tok_list p, pp;
+
+  if (!t) return;
+  if ((p = malloc(sizeof(struct _tok_node))) == NULL) return;
+  if ((p->s = strdup(s)) == NULL) { free(p); return; }
+  p->next = NULL;
+
+  if (*t == NULL) { *t = p; return; }; /* Empty list */
+  pp = *t;
+  while (pp->next != NULL) pp = pp->next;
+  pp->next = p;
+}
+
+tok_list
+tokenize( const char *s, const char sep )
+{
+  tok_list t = NULL;
+  int len, i, cnt, size;
+  char *buf;
+  enum tok_state st = TOK_NORMAL;
+
+  cnt = 0;
+  len = strlen(s);
+  size = 256; /* Initial size */
+  if ((buf = malloc(size)) == NULL) return t;
+  memset(buf, 0, size);
+  for(i=0; i<len; i++) {
+    /* resize buf if necessary */
+    if (cnt == size-1) {
+      size += 256;
+      if ((buf = realloc(buf, size)) == NULL) return t;
+    }
+    switch(st) {
+    case TOK_NORMAL:
+      if (s[i] == '\\')
+	st = TOK_BACKSLASH;
+      else if (s[i] == '\'')
+	st = TOK_QUOTE;
+      else if (s[i] == sep) {
+	/* Reached the end of a token */
+	tok_append(&t, buf);
+	memset(buf, 0, size);
+	cnt = 0;
+      } else {
+	buf[cnt] = s[i];
+	cnt++;
+	buf[cnt] = '\0';
+      }
+      break;
+    case TOK_QUOTE:
+      if (s[i] == '\\')
+	st = TOK_BACKSLASH_Q;
+      else if (s[i] == '\'') {
+	st = TOK_NORMAL;
+      } else {
+	buf[cnt] = s[i];
+	cnt++;
+	buf[cnt] = '\0';
+      }
+      break;
+    case TOK_BACKSLASH:
+      buf[cnt] = s[i];
+      cnt++;
+      buf[cnt] = '\0';
+      st = TOK_NORMAL;
+      break;
+    case TOK_BACKSLASH_Q:
+      buf[cnt] = s[i];
+      cnt++;
+      buf[cnt] = '\0';
+      st = TOK_QUOTE;
+      break;
+    }
+  }
+  tok_append(&t, buf);
+  memset(buf, 0, size);
+  cnt = 0;
+  free(buf);
+  return t;
+}
+
+void
+tok_free( tok_list t )
+{
+  tok_list p = t;
+
+  while (p) {
+    tok_list pp = p->next;
+
+    free(p->s);
+    free(p);
+    p = pp;
+  }
+}
+
+void
+log_err( void )
+{
+  unsigned long l;
+  char buf[200];
+  const char *file, *data;
+  int line, flags;
+  unsigned long es;
+  
+  es=CRYPTO_thread_id();
+  while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
+    {
+      log("%lu:%s:%s:%d:%s\n",es,ERR_error_string(l,buf),
+	  file,line,(flags&ERR_TXT_STRING)?data:"");
+    }
+}
+
+bool
+make_lookups( STACK_OF(XMAP) **lu, const char *spec )
+{
+#define MAXSPEC 10
+  const char *delim = ", ";
+  char *s, *p, *specs[MAXSPEC];
+  int i;
+  XMAP *xm;
+  bool retval = TRUE;
+
+  for(i=0; i<MAXSPEC; i++) specs[i] = NULL;
+  s = clone_bytes(spec, strlen(spec)+1, "lookup specification");
+  p = strtok(s, delim);
+  i = 0;
+  while ((i < MAXSPEC) && (p)) {
+    char *sp = clone_bytes(p, strlen(p)+1, "lookup spec");
+    specs[i++] = sp;
+    p = strtok( NULL, delim );
+  }
+
+  if ((*lu = sk_XMAP_new_null()) != NULL) {
+    for(i=0; specs[i]; i++) {
+      DBG(DBG_PARSING,
+      DBG_log("Adding LU spec: %s", specs[i]);
+      );
+      if ((xm = XMAP_new(specs[i])) != NULL) {
+        sk_XMAP_push(*lu, xm);
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Could not add LU spec: %s", specs[i]);
+        );
+	retval = FALSE;
+      }
+    }
+  }
+  
+  for(i=0; specs[i]; i++) pfree(specs[i]);
+  pfree(s);
+
+  return retval;
+}
+
+/* Really need to make this routine far more tolerant */
+/* of other formats for certs & keys. For example, it */
+/* would be nice to be able to use PKCS8 private key forms */
+/* or a PKCS12 bag to hold both certificate and key */
+/* For the moment, though, we can handle certs in DER or */
+/* PEM format, and keys in PEM format only -- nd */
+void
+load_cert_and_key( const char *cert, const char *key,
+		   X509 **x, EVP_PKEY **k , char *conn_name )
+{
+  BIO *b = NULL;
+  char keystr[32] = "PEM private key";
+
+  PKCS7 *p7 = NULL;
+  STACK_OF(X509) *p7_stack = NULL;
+  X509_SIG *p8 = NULL;
+  bool pub_PKCS7_found = FALSE;
+  bool pub_PKCS8_found = FALSE;
+
+  if (conn_name[0] != '\0') {
+    log("Loading certificates and key for connection \"%s\"", conn_name);
+  } else {
+    log("Loading certificates and key");
+  }
+  if ((! x) || (! k)) return;
+  *x = NULL;
+  *k = NULL;
+
+  if (cert[0] == '\0') return;
+  if (key[0] == '\0') return;
+
+  if ((b = BIO_new_file(cert, "r")) == NULL) {
+    log_err();
+    return;
+  }
+
+#if OPENSSL_VERSION_NUMBER > 0x00903000L
+  p7 = PEM_read_bio_PKCS7(b, NULL, NULL, NULL);
+#else
+  p7 = PEM_read_bio_PKCS7(b, NULL, NULL);
+#endif
+  if (p7 == NULL) {
+    /* Try DER read */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    if ((p7 = d2i_PKCS7_bio(b, NULL)) != NULL) pub_PKCS7_found = TRUE;
+  } else {
+    pub_PKCS7_found = TRUE;
+  }
+
+  if (pub_PKCS7_found)
+  {
+    if ((p7_stack = extract_STACK_OF_X509_from_PKCS7(p7)) == NULL)
+    {
+      log_err();
+      PKCS7_free(p7);
+      BIO_free(b);
+      return;
+    } else {
+      if (sk_X509_num(p7_stack) == 0) {
+        loglog(RC_LOG_SERIOUS, "No certificates in PKCS7 chain");
+        PKCS7_free(p7);
+        BIO_free(b);
+        return;
+      } else if (sk_X509_num(p7_stack) > 1) {
+        loglog(RC_LOG_SERIOUS, "Too many certificates in PKCS7 chain");
+        PKCS7_free(p7);
+        BIO_free(b);
+        return;
+      } else {
+        {
+        X509 *tempcert = sk_X509_value(p7_stack,0);
+        /*  *x needs to be allocated memory. a read_bio would normally
+         *  handle that, but in this case, it's just being copied the 
+         *  pointer from p7_stack. Let's duplicate it instead of
+         *  a simple assignment, keeping it clean.
+         */
+	*x = X509_dup(tempcert);
+        PKCS7_free(p7);
+        }
+      }
+    }
+  } else {
+    /* Now for non PKCS7, loading direct x509 cert. */
+#if OPENSSL_VERSION_NUMBER > 0x00903000L
+    *x = PEM_read_bio_X509(b, NULL, NULL, NULL);
+#else
+    *x = PEM_read_bio_X509(b, NULL, NULL);
+#endif
+    if (*x == NULL) {
+      /* Try DER read */
+      BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+      if ((*x = d2i_X509_bio(b, NULL)) == NULL) {
+        log_err();
+        BIO_free(b);
+        return;
+      }
+    }
+  }
+  DBG(DBG_PARSING,
+  DBG_log("Read certificate from %s", cert);
+  );
+  BIO_free(b);
+
+
+  if ((b = BIO_new_file(key, "r")) == NULL) {
+    log_err();
+    X509_free(*x);
+    *x = NULL;
+    return;
+  }
+  
+  /* start with PKCS8 PEM */
+#if OPENSSL_VERSION_NUMBER > 0x00903000L
+  p8 = PEM_read_bio_PKCS8(b, NULL, NULL, NULL);
+#else
+  p8 = PEM_read_bio_PKCS8(b, NULL, NULL);
+#endif
+  if (p8 == NULL) {
+    /* Try DER read */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    if ((p8 = d2i_PKCS8_bio(b, NULL)) != NULL) pub_PKCS8_found = TRUE;
+  } else {
+    pub_PKCS8_found = TRUE;
+  }
+
+  if (pub_PKCS8_found) {
+    loglog(RC_LOG_SERIOUS, 
+	"Cannot load private key: Private Key file for \"%s\" found"
+        " but is encrypted in PKCS#8 format", conn_name);
+
+    /* clear out pub cert first */
+    X509_free(*x);
+    *x = NULL;
+
+    /* next clean out priv key */
+    X509_SIG_free(p8);
+    BIO_free(b);
+    return;
+  } 
+
+  BIO_free(b);
+  if ((b = BIO_new_file(key, "r")) == NULL) {
+    log_err();
+    X509_free(*x);
+    *x = NULL;
+    return;
+  }
+
+/* read in an unencrypted priv key */
+#if OPENSSL_VERSION_NUMBER > 0x00903000L
+  *k = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
+#else
+  *k = PEM_read_bio_PrivateKey(b, NULL, NULL);
+#endif
+  if (!*k) {
+    RSA *r;
+    
+    /* Try DER reading of RSA Key */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    r = d2i_RSAPrivateKey_bio(b, NULL);
+    if (r) {
+      if ((*k = EVP_PKEY_new()) != NULL) {
+	(*k)->type = EVP_PKEY_RSA;
+	(*k)->pkey.rsa = r;
+	strncpy(keystr, "DER RSA private key", sizeof(keystr)-1);
+      } else
+	RSA_free(r);
+    }
+  }
+  
+  if (!*k) {
+    DSA *d;
+    
+    /* Try DER reading of DSA/El Gamal Key */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    d = d2i_DSAPrivateKey_bio(b, NULL);
+    if (d) {
+      if ((*k = EVP_PKEY_new()) != NULL) {
+	(*k)->type = EVP_PKEY_DSA;
+	(*k)->pkey.dsa = d;
+	strncpy(keystr, "DER DSA private key", sizeof(keystr)-1);
+      } else
+	DSA_free(d);
+    }
+  }
+  
+  if (!*k) {
+    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+    
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    /* try PKCS8 (unencrypted) keyform */
+    
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(b, NULL, NULL, NULL);
+    if (!p8inf) {
+      /* Try reading PKCS8 in DER format */
+      BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+      p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(b, NULL);
+    } else 
+      strncpy(keystr, "PEM PKCS-8 private key", sizeof(keystr)-1);
+    if (!p8inf) {
+      log("Error in loading PKCS-8 private key");
+      log_err();
+      X509_free(*x);
+      *x = NULL;
+      BIO_free(b);
+      return;
+    } else
+      strncpy(keystr, "DER PKCS-8 private key", sizeof(keystr)-1);
+    if ((*k = EVP_PKCS82PKEY(p8inf)) == NULL) {
+      log("Error in converting PKCS-8 private key");
+      log_err();
+      X509_free(*x);
+      *x = NULL;
+      BIO_free(b);
+      return;
+    }
+  }
+  DBG(DBG_PARSING,
+  DBG_log("Read %s from %s", keystr, key);
+  );
+  BIO_free(b);
+}
+
+static int
+cert_compare(X509 *a, X509 *b)
+{
+  /* Check for equality of 2 X509 certificates */
+  /* certs are equal if their issuers, serial numbers */
+  /* subject names and public keys are the same */
+  /* We could probably do all of this by converting the */
+  /* certs to DER format and comparing the byte streams */
+  /* but that's likely to be inefficient -- nd */
+  int c;
+  EVP_PKEY *ka, *kb;
+
+  if ((c = X509_issuer_and_serial_cmp(a, b)) != 0)
+    return c;
+  if ((c = X509_NAME_cmp(X509_get_issuer_name(a),
+			 X509_get_issuer_name(b))) != 0)
+    return c;
+  ka = X509_get_pubkey(a);
+  kb = X509_get_pubkey(b);
+  if (ka->type != kb->type) return 1;
+  switch (ka->type) {
+  case EVP_PKEY_RSA:
+    {
+      /* RSA compare - if public exponent and modulus are equal, return 0 */
+      RSA *ra, *rb;
+
+      ra = ka->pkey.rsa;
+      rb = ka->pkey.rsa;
+
+      if (BN_cmp(ra->e, rb->e) != 0) return 1;
+      if (BN_cmp(ra->n, rb->n) != 0) return 1;
+    }
+    break;
+  case EVP_PKEY_DSA:
+    {
+      /* DSA compare, g, modulus and pubkey must be equal */
+      DSA *da, *db;
+
+      da = ka->pkey.dsa;
+      db = ka->pkey.dsa;
+
+      if (BN_cmp(da->g, db->g) != 0) return 1;
+      if (BN_cmp(da->p, db->p) != 0) return 1;
+      if (BN_cmp(da->pub_key, db->pub_key) != 0) return 1;
+    }
+    break;
+  default:
+    DBG(DBG_PARSING,
+    DBG_log("Unknown key type presented: %d", ka->type);
+    );
+    return 1;
+    break;
+  }
+  return 0;
+}
+
+static STACK_OF(X509) *
+lookup_certs_by_ip(STACK_OF(XMAP) *lu,
+		   const char *id,
+		   const size_t len)
+{
+  STACK_OF(X509) *osk = sk_X509_new_null();
+  int i;
+
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    XMAP *xm = sk_XMAP_value(lu, i);
+    u_char *cl = clone_bytes(id, len, "IPv4 address");
+    STACK_OF(X509_OBJECT) *op = NULL;
+
+    DBG(DBG_PARSING | DBG_CONTROL,
+    DBG_log("Searching map %d", i+1);
+    DBG_dump("IPv4:", cl, len);
+    );
+    if ((op = XMAP_lookup(xm, X509_LU_X509, "ip", cl)) != NULL) {
+      int j;
+
+      DBG(DBG_PARSING,
+      DBG_log("Search returns %d certificates", sk_X509_OBJECT_num(op));
+      );
+      for(j=0; j < sk_X509_OBJECT_num(op); j++) {
+	X509_OBJECT *o = sk_X509_OBJECT_value(op, j);
+	X509 *c = X509_dup(o->data.x509);
+	int k, found;
+
+	for(k=0, found=0; (!found) && (k < sk_X509_num(osk)); k++) {
+	  if (cert_compare(sk_X509_value(osk, k), c) == 0)
+	    found = 1;
+	}
+
+	if (!found) {
+	  if (sk_X509_num(osk) == 0) {
+	    sk_X509_push(osk, c);
+	  } else {
+	    ASN1_UTCTIME *new_notBefore = X509_get_notBefore(c);
+	    ASN1_UTCTIME *new_notAfter = X509_get_notAfter(c);
+	    
+	    for(k=0; k<sk_X509_num(osk); k++) {
+	      /* certificate already in stack */
+	      X509 *tx = sk_X509_value(osk, k); 
+	      ASN1_UTCTIME *notBefore = X509_get_notBefore(tx);
+	      ASN1_UTCTIME *notAfter = X509_get_notAfter(tx);
+	      int c1 = ASN1_UTCTIME_cmp(new_notBefore, notBefore);
+	      int c2 = ASN1_UTCTIME_cmp(new_notAfter, notAfter);
+	      
+	      if (c1 == 0) {
+		/* certs start at same time */
+		/* insert here if c expiry is later than tx */
+		if (c2 > 0) break; 
+	      } else
+	      /* insert here is c start date is later than tx */
+	      if (c1 > 0) break; 
+	      /* else move on to the next certificate in the 
+	      current output stack */
+	    }
+	    sk_X509_insert(osk, c, k); /* Insert into the output stack */
+	  }
+	}
+      }
+      sk_X509_OBJECT_pop_free(op, X509_OBJECT_free);
+      pfree(cl);
+    }
+  }
+  if (osk) DBG(DBG_PARSING,
+           DBG_log("Returning %d certs in list", sk_X509_num(osk))
+           );
+  return osk;
+} 
+
+/* peer_cert_list takes a supplied list of XMAPs */
+/* and adds all of the X509 certificates whose */
+/* public key matches 'type' into a safe stack certificates */
+/* If the parameter 'cert' is non-NULL, only the certificate */
+/* which matches it will be added to the list */
+STACK_OF(X509) *
+peer_cert_list( STACK_OF(XMAP) *lu, int type, X509 *cert,
+		struct payload_digest *const id_pld,
+		bool strict )
+{
+  STACK_OF(X509) *sk = NULL, *osk = NULL;
+  pb_stream *const id_pbs = &id_pld->pbs;
+  struct isakmp_id *const id = &id_pld->payload.id;
+  int i, found;
+
+  switch(id->isaid_idtype) {
+  case ID_IPV4_ADDR:
+    if (pbs_left(id_pbs) != sizeof(struct in_addr)) {
+      DBG(DBG_PARSING,
+      DBG_log("ID size is not equal to that of an IPv4 address");
+      );
+      return NULL;
+    }
+    /* 
+     * lookup_certs_by_ip(STACK_OF(XMAP) *lu, 
+     *   const char *id, const size_t len)
+     */
+    if ((sk = lookup_certs_by_ip(lu,
+				id_pbs->cur,
+				sizeof(struct in_addr))) == NULL) {
+      DBG(DBG_PARSING,
+      DBG_log("No certs for this IP address");
+      );
+      return NULL;
+    }
+    break;
+  case ID_DER_ASN1_DN:
+    {
+      X509_NAME *xn = NULL;
+      long derlen;
+      unsigned char *der;
+
+      derlen = (long)pbs_left(id_pbs);
+      der = (unsigned char *)(id_pbs->cur);
+
+     xn = d2i_X509_NAME(&xn, &der, derlen);
+
+      if (xn != NULL) {
+        if ((sk = lookup_certs_by_subject(lu, xn)) == NULL) {
+          DBG(DBG_PARSING,
+          DBG_log("No certs for this ID_DER_ASN1_DN");
+          );
+          return NULL;
+        } 
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Error in DER string. (Not a DER string?)");
+        );
+        return NULL;
+      }
+      X509_NAME_free(xn);
+      break;
+    }
+  default:
+    DBG(DBG_PARSING,
+    DBG_log("No means to check certificates for ID type = %s",
+	    enum_show(&ident_names, id->isaid_idtype));
+    );
+    return NULL;
+  }
+
+  /* Now filter out any certificates not of type 'type' */
+  if ((osk = sk_X509_new_null()) != NULL) {
+    for(i=0; i<sk_X509_num(sk); i++) {
+      X509 *x = sk_X509_value(sk, i);
+      EVP_PKEY *pk = X509_get_pubkey(x);
+
+      if (pk->type == type) {
+	sk_X509_push(osk, X509_dup(x));
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Rejecting certificate: wrong type: %d", pk->type);
+        );
+      }
+    }
+    sk_X509_pop_free(sk, X509_free);
+    sk = osk; /* Make sk the new filtered list */
+  } else {
+    DBG(DBG_PARSING,
+    DBG_log("Error in allocating new sk_X509");
+    );
+    sk_X509_pop_free(sk, X509_free);
+    sk = NULL;
+  }
+
+  if ((sk) && (cert)) {
+    /* If a certificate was presupplied, we want to check */
+    /* whether it is in the list of acceptable certificates */
+    /* for this connection. If no certificate is presupplied */
+    /* then it is assumed that one of the certificates in */
+    /* the list will correctly decrypt the signature/nonces */
+
+    for(i=0, found=0; ((!found) && (i < sk_X509_num(sk))); i++)
+      if (cert_compare(sk_X509_value(sk, i), cert) == 0) found = 1;
+
+    if (found) {
+      DBG(DBG_PARSING,
+      DBG_log("Certificate supplied is in list");
+      );
+    } else {
+      DBG(DBG_PARSING,
+      DBG_log("Certificate supplied is NOT in list");
+      );
+
+      /* If strict is not set, this certificate will be allowed */
+      /* to pass, even though the host cannot recognise it as */
+      /* in the list of known certificates for this ID. Otherwise */
+      /* we erase the list and return NULL -- an error condition */
+      if (strict) {
+	sk_X509_pop_free(sk, X509_free);
+	sk = NULL;
+      }
+    }
+  }
+
+  return sk;
+}
+
+bool
+have_rsa_key( struct state *st )
+{
+  struct connection *c = st->st_connection;
+
+  if (c->key == NULL) { 
+	DBG(DBG_PARSING,
+	DBG_log("No key present");
+	);
+	return FALSE; 
+  }
+  if ( ((EVP_PKEY *)(c->key))->type != EVP_PKEY_RSA ) { return FALSE; }
+  return TRUE;
+}
+
+bool
+have_dss_key( struct state *st )
+{
+  struct connection *c = st->st_connection;
+
+  if (c->key == NULL) { 
+	DBG(DBG_PARSING,
+	DBG_log("No key present"); 
+	);
+	return FALSE; 
+  }
+  if ( ((EVP_PKEY *)(c->key))->type != EVP_PKEY_DSA ) { return FALSE; }
+  return TRUE;
+}
+
+bool
+have_othercert( struct connection *c, int type )
+{
+  struct end *that = &c->that;
+  STACK_OF(X509) *op = NULL;
+  X509 *x;
+  int i;
+  bool found;
+
+  /* First check to see if we've already done */
+  /* this lookup and stored the certificate in */
+  /* c->other[] */
+
+  for(i=0; i<MAX_OTHER; i++)
+    if ((c->other[i].type == type) &&
+	(c->other[i].cert != NULL)) {
+      DBG(DBG_PARSING,
+      DBG_log("Already stored a type %d cert", type);
+      );
+      return TRUE;
+    }
+
+  switch (c->that.id.kind)
+  {
+    case ID_IPV4_ADDR:
+    op = lookup_certs_by_ip((STACK_OF(XMAP) *)c->lu,
+      (const char *)&that->host_addr,
+      sizeof(that->host_addr));
+    break;
+
+    case ID_DER_ASN1_DN:
+    {
+
+/*
+ * The 'd2i' function copies a binary representation into a C structure.  It
+ * operates as follows.  'a' is a pointer to a pointer to
+ * the structure to populate, 'pp' is a pointer to a pointer to where the DER
+ * byte string is located and 'length' is the length of the '*pp' data.
+ * If there are no errors, a pointer to the populated structure is returned.
+ *
+ * X509_NAME *     X509_NAME_new(void);
+ * void            X509_NAME_free(X509_NAME *a);
+ * int             i2d_X509_NAME(X509_NAME *a,unsigned char **pp);
+ * X509_NAME *     d2i_X509_NAME(X509_NAME **a,unsigned char **pp,long length);
+ * int             X509_NAME_set(X509_NAME **xn, X509_NAME *name);
+ */
+      X509_NAME *xn = X509_NAME_new();
+      chunk_t temp_ptr = c->that.id.der_asn1_dn;
+
+      xn = d2i_X509_NAME(&xn, &(c->that.id.der_asn1_dn.ptr), 
+        (long)c->that.id.der_asn1_dn.len);
+	c->that.id.der_asn1_dn = temp_ptr;
+
+      if (xn != NULL) {
+        op = lookup_certs_by_subject((STACK_OF(XMAP) *)c->lu, xn);
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Error in DER string. (Not a DER string?)");
+        );
+      }
+
+      X509_NAME_free(xn);
+    }
+    break;
+  }
+
+  if (!op) {
+    DBG(DBG_PARSING,
+    DBG_log("Lookup returns NULL");
+    );
+  } else {
+    int i;
+
+    for(i=0, found = FALSE; ((!found) && (i < sk_X509_num(op))); i++) {
+      x = sk_X509_value(op, i);
+      if (X509_get_pubkey(x)->type == type) {
+	found = TRUE;
+	for(i=0; i<MAX_OTHER; i++) {
+ 	  if (c->other[i].cert == NULL) {
+            DBG(DBG_PARSING,
+            DBG_log("Storing type %d cert at position %d", type, i);
+            );
+	    c->other[i].type = type;
+	    c->other[i].cert = (void *)X509_dup(x);
+	    break;
+	  }
+	}
+      }
+    }
+
+    if (found) {
+      DBG(DBG_PARSING,
+      DBG_log("Found type %d cert at position %d:",
+	      type, i+1);
+      );
+    }
+    sk_X509_pop_free(op, X509_free);
+  }
+  return (found);
+}
+
+bool
+have_rsa_keypair( struct state *st )
+{
+  bool r = have_othercert(st->st_connection, EVP_PKEY_RSA);
+  if (r) r = have_rsa_key(st);
+
+  DBG(DBG_PARSING,
+  DBG_log("Have RSA other cert = %s", r  ? "TRUE" : "FALSE");
+  );
+  return r;
+}
+
+bool
+have_elgamal_keypair( struct state *st )
+{
+  bool r = have_othercert(st->st_connection, EVP_PKEY_DSA); 
+  if (r) r = have_dss_key(st);
+
+  DBG(DBG_PARSING,
+  DBG_log("Have El Gamal other cert = %s", r  ? "TRUE" : "FALSE");
+  );
+  return r;
+}
+
+static int
+cb( int ok, X509_STORE_CTX *ctx )
+{
+  char buf[200];
+  
+  if (!ok) {
+    if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
+      /* Check to see if it is a CA certificate, ie with */
+      /* basicConstraints, and perhaps other checks */
+      /* For the moment, we just let it slide */
+      ok = 1;
+    } else {
+      X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
+      
+      DBG(DBG_PARSING,
+      DBG_log("Error for certificate: %s", buf);
+      DBG_log("Error %d: Depth %d: %s",
+              ctx->error,
+              ctx->error_depth,
+              X509_verify_cert_error_string(ctx->error));
+      );
+    }
+  }
+  return (ok);
+}
+
+static int
+ASN1_UTCTIME_cmp(ASN1_UTCTIME *a, ASN1_UTCTIME *b)
+{
+  char buff1[14],buff2[14],*p;
+  int i,j;
+ 
+  /* Degenerate cases */
+  if (!a && !b) return 0;
+  if (a && !b) return 1;
+  if (!a && b) return -1;
+ 
+  memset(buff1, 0, sizeof(buff1));
+  memset(buff2, 0, sizeof(buff2));
+ 
+  p=buff1;
+  i=a->length;
+  if ((i < 11) || (i > 17)) return(0);
+  memcpy(p,a->data,12);
+ 
+  p=buff2;
+  j=b->length;
+  if ((j < 11) || (j > 17)) return(0);
+  memcpy(p,b->data,12);
+ 
+  /* Correct for Y2K */
+  i=(buff1[0]-'0')*10+(buff1[1]-'0');
+  if (i < 50) i+=100; /* cf. RFC 2459 */
+  j=(buff2[0]-'0')*10+(buff2[1]-'0');
+  if (j < 50) j+=100;
+ 
+  if (i < j) return (-1);
+  if (i > j) return (1);
+ 
+  i=strcmp(buff1,buff2);
+ 
+  if (i == 0)
+    return 0;
+  else if (i < 0)
+    return(-1);
+  else
+    return(1);
+}
+
+extern X509_CRL *
+lookup_crl(STACK_OF(XMAP) *lu, X509_NAME *name)
+{
+  X509_CRL *x = NULL;
+  STACK_OF(X509_CRL) *osk = sk_X509_CRL_new_null();
+  int i, j, k, found;
+
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    XMAP *xm = sk_XMAP_value(lu, i);
+    STACK_OF(X509_OBJECT) *xo = NULL;
+
+    if (xm) {
+      XMAP_dump(xm);
+      if ((xo = XMAP_lookup(xm, X509_LU_CRL, "issuer", name)) != NULL) {
+	for(j=0; j<sk_X509_OBJECT_num(xo); j++) {
+	  X509_OBJECT *o = sk_X509_OBJECT_value(xo, j);
+	  X509_CRL *xx = X509_CRL_dup(o->data.crl);
+	  
+	  for(k=0, found = 0; (!found) && (k<sk_X509_CRL_num(osk)); k++) {
+	    X509_CRL *tx = sk_X509_CRL_value(osk, k);
+	    
+	    if ((X509_NAME_cmp(X509_CRL_get_issuer(xx),
+			       X509_CRL_get_issuer(tx))==0) &&
+		(ASN1_UTCTIME_cmp(X509_CRL_get_lastUpdate(xx),
+				  X509_CRL_get_lastUpdate(tx)) == 0) &&
+		(ASN1_UTCTIME_cmp(X509_CRL_get_nextUpdate(xx),
+				  X509_CRL_get_nextUpdate(tx)) == 0))
+	      found = 1;
+	  }
+	  
+	  if (!found) {
+	    if (sk_X509_CRL_num(osk) == 0)
+	      sk_X509_CRL_push(osk, xx);
+	    else {
+	      /* insert the certificate into the stack in date order */
+	      for(k=0; k<sk_X509_CRL_num(osk); k++) {
+		/* certificate already in stack */
+		X509_CRL *tx = sk_X509_CRL_value(osk, k); 
+		
+		if (ASN1_UTCTIME_cmp(X509_CRL_get_lastUpdate(xx),
+				     X509_CRL_get_lastUpdate(tx)) > 0)
+		  /* insert here if last Update is newer than current crl */
+		  break; 
+	      }
+	      /* Insert into the output stack */
+	      sk_X509_CRL_insert(osk, xx, k); 
+	    }
+	  } else
+	    X509_CRL_free(xx);
+	}
+	/* drop search return values */
+	sk_X509_OBJECT_pop_free(xo, X509_OBJECT_free); 
+      }
+    }
+  }
+
+  if (sk_X509_CRL_num(osk) > 0)
+    /* use first certificate in stack */
+    x = X509_CRL_dup(sk_X509_CRL_value(osk, 0)); 
+  /* get rid of output stack */
+  sk_X509_CRL_pop_free(osk, X509_CRL_free); 
+  return x; 
+}
+
+static STACK_OF(XMAP) *lookups = NULL;
+static bool verify_strict;
+/* only way I can think to get the verify function (which is) */
+/* used as a callback to access the 'strict verification' flag */
+/* The problem is that there isn't any space in the parameters */
+/* to the verify_func in which to add this flag. Pity, because */
+/* a static global controlling verification policy is a fairly */
+/* stinky idea -- nd */
+
+
+/* The following code is simply the code from x509_vfy.c */
+/* with CRL checking added, and basicConstraints checking */
+static int
+verify_func(X509_STORE_CTX *ctx)
+{
+  int i,ok=0,n;
+  X509 *xs,*xi;
+  EVP_PKEY *pkey=NULL;
+  int (*cb)();
+  X509_CRL *crl;
+  
+  cb=ctx->ctx->verify_cb;
+  
+  n=sk_X509_num(ctx->chain);
+  DBG(DBG_PARSING,
+  DBG_log("%d certs in chain", n);
+  );
+  ctx->error_depth=n-1;
+  n--;
+  xi=sk_X509_value(ctx->chain,n);
+
+  if (X509_NAME_cmp(X509_get_subject_name(xi),
+		    X509_get_issuer_name(xi)) == 0)
+    xs=xi;
+  else {
+    if (n <= 0) {
+      ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+      ctx->current_cert=xi;
+      ok=cb(0,ctx);
+      goto end;
+    } else {
+      n--;
+      ctx->error_depth=n;
+      xs=sk_X509_value(ctx->chain,n);
+    }
+  }
+  
+  while (n >= 0) {
+    ctx->error_depth=n;
+    if (!xs->valid) {
+      if ((pkey=X509_get_pubkey(xi)) == NULL)
+	{
+	  ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+	  ctx->current_cert=xi;
+	  ok=(*cb)(0,ctx);
+	  if (!ok) goto end;
+	}
+      if (X509_verify(xs,pkey) <= 0) {
+	EVP_PKEY_free(pkey);
+	ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      EVP_PKEY_free(pkey);
+      pkey=NULL;
+
+      i=X509_cmp_current_time(X509_get_notBefore(xs));
+      if (i == 0) {
+	ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      if (i > 0) {
+	ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      xs->valid=1;
+    }
+
+    i=X509_cmp_current_time(X509_get_notAfter(xs));
+    if (i == 0) {
+      ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+      ctx->current_cert=xs;
+      ok=(*cb)(0,ctx);
+      if (!ok) goto end;
+    }
+    
+    if (i < 0) {
+      ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
+      ctx->current_cert=xs;
+      ok=(*cb)(0,ctx);
+      if (!ok) goto end;
+    }
+
+    if (n == sk_X509_num(ctx->chain)-1) {
+      /* This is the root certificate */
+      int loc = X509_get_ext_by_NID(xs, NID_basic_constraints, -1);
+      if (loc >= 0) {
+	X509_EXTENSION *ext;
+	BASIC_CONSTRAINTS *p = NULL;
+	
+	ext = X509_get_ext(xs, loc);
+	if (ext) {
+	  p = X509V3_EXT_d2i(ext);
+	  if (! p->ca) {
+	    BASIC_CONSTRAINTS_free(p);
+	    ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+	    ctx->current_cert=xs;
+	    ok=(*cb)(0,ctx);
+	    if (!ok) goto end;
+	  } else {
+        DBG(DBG_PARSING,
+	    DBG_log("Root certificate has CA = True");
+        );
+	    BASIC_CONSTRAINTS_free(p);
+	  }
+	} else {
+	  /* The cert has a basicConstraints extension, but */
+	  /* we couldn't get it */
+	  ctx->error=X509_V_ERR_APPLICATION_VERIFICATION;
+	  ctx->current_cert=xs;
+	  ok=(*cb)(0,ctx);
+	  if (!ok) goto end;
+	}
+      } else {
+#ifndef DONT_BE_FASCIST
+	ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+#endif
+      }
+    }
+
+    /* CRL CHECK */
+    if ((crl = lookup_crl(lookups, X509_get_issuer_name(xs))) != NULL) {
+      EVP_PKEY *pkey = X509_get_pubkey(xi);
+      STACK_OF(X509_REVOKED) *rev;
+      int nrev;
+      
+      DBG(DBG_PARSING,
+      DBG_log("Checking CRL for issuer");
+      );
+      
+      if (pkey == NULL) {
+	ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      if (X509_CRL_verify(crl, pkey) <= 0) {
+	ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      i = X509_cmp_current_time(X509_CRL_get_lastUpdate(crl));
+      if (i == 0) {
+	ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      if (i > 0) {
+	ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
+      if (i == 0) {
+	ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      if (i < 0) {
+	ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      rev = X509_CRL_get_REVOKED(crl);
+      nrev = sk_X509_REVOKED_num(rev);
+      DBG(DBG_PARSING,
+      DBG_log("%d certificates revoked in CRL", nrev);
+      );
+      for(i=0; i<nrev; i++) {
+	X509_REVOKED *rv = sk_X509_REVOKED_value(rev, i);
+	
+	if (ASN1_INTEGER_cmp(X509_get_serialNumber(xs), 
+	  rv->serialNumber) == 0) {
+	  /* It's this certificate that's been revoked */
+	  int c = X509_cmp_current_time(rv->revocationDate);
+	  if (c < 0) {
+	    ctx->error=X509_V_ERR_CERT_REVOKED;
+	    X509_CRL_free(crl);
+	    ctx->current_cert=xs;
+	    ok=(*cb)(0,ctx);
+	    if (!ok) goto end;
+	  }
+      DBG(DBG_PARSING,
+	  DBG_log("Serial Number matches");
+      );
+	}
+      }
+
+      X509_CRL_free(crl);
+    } else {
+      char buf[200];
+      
+      X509_NAME_oneline(X509_get_issuer_name(xs), buf, sizeof(buf));
+      DBG(DBG_PARSING,
+      DBG_log("Cant locate a CRL for issuer %s", buf);
+      );
+      /* If we're being paranoid here, we really should fail */
+      /* the verification. An attacker capable of mounting */
+      /* a denial of service attack could cause us fail to */
+      /* load the CRL, and use a revoked, but otherwise valid */
+      /* certificate in the  exchange to set up a valid SA */
+      /* In this case, we let it go, but an idea might be */
+      /* to have an ipsec.conf specified policy on how mandatory */
+      /* CRLs are in the verification sequence -- nd */
+      if (verify_strict) {
+	ctx->error=X509_V_ERR_UNABLE_TO_GET_CRL;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+    }
+
+    /* The last error (if any) is still in the error value */
+    ctx->current_cert=xs;
+    ok=(*cb)(1,ctx);
+    if (!ok) goto end;
+
+    n--;
+    if (n >= 0) {
+      xi=xs;
+      xs=sk_X509_value(ctx->chain,n);
+    }
+  }
+  ok=1;
+ end:
+  return(ok);
+}
+
+static STACK_OF(X509) *
+lookup_certs_by_subject(STACK_OF(XMAP) *lu, X509_NAME *xn)
+{
+  /* output stack - concatenation of certificates */
+  /* return value */
+  STACK_OF(X509) *osk = sk_X509_new_null(); 
+  int i, j, k, found;
+  
+  DBG(DBG_PARSING,
+  DBG_log("Looking up certificate by subject");
+  );
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    /* individual searchable directory */
+    XMAP *xm = sk_XMAP_value(lu, i); 
+    /* list of objects from individual searches */
+    STACK_OF(X509_OBJECT) *xo = NULL; 
+
+    if (xm) {
+     if (xm->pmap) {
+      DBG(DBG_PARSING,
+      DBG_log("by_subject: Searching map %d", i+1);
+      );
+      if ((xo = XMAP_lookup( xm, X509_LU_X509, "subject", xn)) != NULL) {
+        DBG(DBG_PARSING,
+        DBG_log("by_subject: Got %d certificates", sk_X509_OBJECT_num(xo));
+        );
+        for(j=0; j<sk_X509_OBJECT_num(xo); j++) {
+          X509_OBJECT *o = sk_X509_OBJECT_value(xo, j);
+          X509 *xx = X509_dup(o->data.x509);
+ 
+          for(k=0, found = 0; (!found) && (k<sk_X509_num(osk)); k++) {
+            X509 *tx = sk_X509_value(osk, k);
+
+            if (X509_issuer_and_serial_cmp(xx, tx) == 0) found = 1;
+          }
+ 
+          if (!found) {
+            if (sk_X509_num(osk) == 0) {
+              sk_X509_push(osk, xx);
+
+              DBG(DBG_PARSING,
+              DBG_log("by_subject: Initialized cert stack");
+              );
+
+            } else {
+              /* insert the certificate into the stack in date order */
+              ASN1_UTCTIME *new_notBefore = X509_get_notBefore(xx);
+              ASN1_UTCTIME *new_notAfter = X509_get_notAfter(xx);
+ 
+              for(k=0; k<sk_X509_num(osk); k++) {
+                /* certificate already in stack */
+                X509 *tx = sk_X509_value(osk, k); 
+                ASN1_UTCTIME *notBefore = X509_get_notBefore(tx);
+                ASN1_UTCTIME *notAfter = X509_get_notAfter(tx);
+                int c1 = ASN1_UTCTIME_cmp(new_notBefore, notBefore);
+                int c2 = ASN1_UTCTIME_cmp(new_notAfter, notAfter);
+ 
+                if (c1 == 0) {
+                  /* certs start at same time */
+                  /* insert here if xx expiry is later than tx */
+                  if (c2 > 0) break; 
+                } else
+                  /* insert here is xx start date is later than tx */
+                  if (c1 > 0) break; 
+                /* else move on to the next certificate 
+                 * in the current output stack */
+              }
+              /* Insert into the output stack */
+              sk_X509_insert(osk, xx, k); 
+            }
+          } else
+            X509_free(xx);
+        }
+        sk_X509_OBJECT_pop_free(xo, X509_OBJECT_free);
+      } /* if (xo != NULL) */
+      else
+      {
+        DBG(DBG_PARSING,
+        DBG_log("xo = XMAP_lookup( xm, X509_LU_X509, 
+          \"subject\", xn) == NULL.");
+        );
+      }
+     } /* if (xm->pmap) */
+    } /* if (xm) */
+  } /* for */
+  DBG(DBG_PARSING,
+  DBG_log("by_subject: Finished lookups");
+  );
+
+  if (osk) DBG(DBG_PARSING,
+	DBG_log("by_subject: Returning %d certs in list", sk_X509_num(osk)));
+  return osk;
+}
+
+#if 0 /* not currently used */
+static STACK_OF(X509) *
+lookup_certs_by_issuer(STACK_OF(XMAP) *lu, X509_NAME *xn)
+{
+  STACK_OF(X509) *osk = sk_X509_new_null(); 
+  int i, j, k, found;
+  
+  DBG(DBG_PARSING,
+  DBG_log("Looking up certificate by issuer");
+  );
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    /* individual searchable directory */
+    XMAP *xm = sk_XMAP_value(lu, i); 
+    /* list of objects from individual searches */
+    STACK_OF(X509_OBJECT) *xo = NULL; 
+
+    if (xm) {
+      DBG(DBG_PARSING,
+      DBG_log("by_issuer: Searching map %d", i+1);
+      );
+      if ((xo = XMAP_lookup( xm, X509_LU_X509, "issuer", xn)) != NULL) {
+        DBG(DBG_PARSING,
+        DBG_log("by_issuer: Got %d certificates", sk_X509_OBJECT_num(xo));
+        );
+        for(j=0; j<sk_X509_OBJECT_num(xo); j++) {
+          X509_OBJECT *o = sk_X509_OBJECT_value(xo, j);
+          X509 *xx = X509_dup(o->data.x509);
+ 
+          for(k=0, found = 0; (!found) && (k<sk_X509_num(osk)); k++) {
+            X509 *tx = sk_X509_value(osk, k);
+
+            if (X509_issuer_and_serial_cmp(xx, tx) == 0) found = 1;
+          }
+ 
+          if (!found) {
+            if (sk_X509_num(osk) == 0) {
+              sk_X509_push(osk, xx);
+
+              DBG(DBG_PARSING,
+              DBG_log("by_issuer: Initialized cert stack");
+              );
+
+            } else {
+              /* insert the certificate into the stack in date order */
+              ASN1_UTCTIME *new_notBefore = X509_get_notBefore(xx);
+              ASN1_UTCTIME *new_notAfter = X509_get_notAfter(xx);
+ 
+              for(k=0; k<sk_X509_num(osk); k++) {
+                /* certificate already in stack */
+                X509 *tx = sk_X509_value(osk, k); 
+                ASN1_UTCTIME *notBefore = X509_get_notBefore(tx);
+                ASN1_UTCTIME *notAfter = X509_get_notAfter(tx);
+                int c1 = ASN1_UTCTIME_cmp(new_notBefore, notBefore);
+                int c2 = ASN1_UTCTIME_cmp(new_notAfter, notAfter);
+ 
+                if (c1 == 0) {
+                  /* certs start at same time */
+                  /* insert here if xx expiry is later than tx */
+                  if (c2 > 0) break; 
+                } else
+                  /* insert here is xx start date is later than tx */
+                  if (c1 > 0) break; 
+                /* else move on to the next certificate 
+                 * in the current output stack */
+              }
+              /* Insert into the output stack */
+              sk_X509_insert(osk, xx, k); 
+            }
+          } else
+            X509_free(xx);
+        }
+        sk_X509_OBJECT_pop_free(xo, X509_OBJECT_free);
+      } /* if (xo != NULL) */
+      else
+      {
+        DBG(DBG_PARSING,
+        DBG_log("xo = XMAP_lookup( xm, X509_LU_X509, 
+          \"issuer\", xn) == NULL.");
+        );
+      }
+    } /* if (xm) */
+  } /* for */
+  DBG(DBG_PARSING,
+  DBG_log("by_issuer: Finished lookups");
+  );
+
+  if (osk) DBG(DBG_PARSING,
+    DBG_log("by_issuer: Returning %d certs in list", sk_X509_num(osk)));
+  return osk;
+}
+#endif /* not used */
+
+void
+build_cert_chain( STACK_OF(X509) **ch, STACK_OF(XMAP) *lu, X509 *x )
+{
+  int done = 0;
+  X509 *xx;
+
+  if (!ch) return;
+  if ((*ch = sk_X509_new_null()) == NULL) return;
+  xx = x;
+
+  sk_X509_push(*ch, X509_dup(xx));
+  while (!done) {
+    X509 *xi;
+
+    /* look for self-signed cert. It would have issuer data 
+     * same as subject field */
+    if ((xi = sk_X509_value(lookup_certs_by_subject(lu, 
+	X509_get_issuer_name(xx)), 0)) != NULL) 
+    {
+      sk_X509_push(*ch, xi);
+      if (X509_NAME_cmp(X509_get_subject_name(xi),
+			X509_get_issuer_name(xi)) == 0) {
+        DBG(DBG_PARSING,
+        DBG_log("Found the issuer's self-signed cert.");
+        );
+	done = 1;
+      } else {
+        /* the 2 fields are not exactly the same. Narrowing search. */
+	xx = xi;
+      }
+    } else 
+      /* Did not find self-signed certificate */
+      DBG(DBG_PARSING,
+      DBG_log("Did not find the issuer's self-signed cert.");
+      );
+      done = 1; 
+  }
+}
+
+bool
+verify_certificate( X509 *x, STACK_OF(XMAP) *lu,
+		    const char *path, bool strict )
+{
+  X509_STORE *ctx = NULL;
+  X509_STORE_CTX csc;
+  int ver;
+
+
+  if ((ctx = X509_STORE_new()) == NULL) {
+    DBG(DBG_PARSING,
+    DBG_log("Cant allocate file lookup");
+    );
+    log_err();
+    return 0;
+  }
+
+  X509_STORE_set_verify_cb_func(ctx, cb);
+
+  ERR_clear_error();
+  verify_strict = strict;
+  lookups = lu;
+  X509_STORE_CTX_init(&csc, ctx, x, NULL);
+
+  build_cert_chain(&(csc.chain), lu, x);
+  ver = verify_func(&csc);
+  X509_STORE_CTX_cleanup(&csc);
+
+  if (ctx) X509_STORE_free(ctx);
+
+  if (ver) {
+    DBG(DBG_PARSING,
+    DBG_log("Certificate verification succeeded");
+    );
+  } else {
+    DBG(DBG_PARSING,
+    DBG_log("Verification failed");
+    );
+    log_err();
+  }
+
+  return ver;
+}
+
+struct cert_options {
+  const char *opt;
+  u_int32_t optflag;
+};
+
+static struct cert_options certopts[] = {
+  { "send", CERT_OPTION_SEND },
+  { "pkcs7", CERT_OPTION_PKCS7 },
+  { "pk", CERT_OPTION_PK },
+  { "rev", CERT_OPTION_REV },
+  { "strict", CERT_OPTION_STRICT },
+  { "dss-sha", CERT_OPTION_DSS_SHA },
+  { "dss-alt", CERT_OPTION_DSS_ALT },
+  { NULL, 0 }
+};
+
+u_int32_t
+parse_options( const char *s )
+{
+  tok_list tl, p;
+  u_int32_t i, ret = 0, b4;
+
+  tl = tokenize(s, ',');
+  for(p=tl; p; p=p->next) {
+    int found = 0;
+    char *st = p->s;
+
+    while (isspace(*st)) st++; /* skip whitespace */
+    for(i=0; (!found) && (certopts[i].opt != NULL); i++) {
+      if ((st[0] == '!') &&
+	  (strncasecmp(&(st[1]), certopts[i].opt,
+		       strlen(certopts[i].opt)) == 0)) {
+	found = 1;
+	b4 = ret;
+	ret &= ~certopts[i].optflag;
+
+	DBG(DBG_PARSING,
+	DBG_log("Cert option: Clearing option %s: %08x -> %08x", 
+	  certopts[i].opt, b4, ret);
+	);
+      } else if (strncasecmp(st, certopts[i].opt,
+			     strlen(certopts[i].opt)) == 0) {
+	found = 1;
+	b4 = ret;
+	ret |= certopts[i].optflag;
+
+	DBG(DBG_PARSING,
+	DBG_log("Cert option: Setting option %s: %08x -> %08x", 
+	  certopts[i].opt, b4, ret);
+	);
+      }
+    }
+  }
+  tok_free(tl);
+
+  /* now for a few special cases: 
+   *   if "rev", then turn on "pk".
+   *   if "pkcs7", then turn on "send".
+   */
+  if (((ret & CERT_OPTION_REV) != 0) && ((ret & CERT_OPTION_PK) == 0)) 
+    ret |= CERT_OPTION_PK;
+  if (((ret & CERT_OPTION_PKCS7) != 0) && ((ret & CERT_OPTION_SEND) == 0)) 
+    ret |= CERT_OPTION_SEND;
+
+  return ret;
+}
+
+int
+DSA_sign_raw(unsigned char *dgst,int dlen,
+	     unsigned char *sig, unsigned int *siglen, DSA *dsa)
+{
+  DSA_SIG *s;
+  int offset;
+
+  DBG(DBG_PARSING,
+  DBG_log("DSA_sign_raw called");
+  );
+  s= DSA_do_sign(dgst, dlen, dsa);
+  if (s == NULL) {
+    *siglen=0;
+    return 0;
+  }
+  memset(sig, 0, SHA1_DIGEST_SIZE * 2);
+  offset = SHA1_DIGEST_SIZE - BN_num_bytes(s->r);
+  BN_bn2bin(s->r, &(sig[offset]));
+  offset = SHA1_DIGEST_SIZE - BN_num_bytes(s->s);
+  BN_bn2bin(s->s, &(sig[SHA1_DIGEST_SIZE + offset]));
+  *siglen = SHA1_DIGEST_SIZE * 2;
+  DSA_SIG_free(s);
+  return 1;
+}
+
+int DSA_verify_raw(const unsigned char *dgst,int dgst_len,
+		   unsigned char *sigbuf, int siglen, DSA *dsa)
+{
+  DSA_SIG *s;
+  int ret = -1;
+
+  DBG(DBG_PARSING,
+  DBG_log("DSA_verify_raw called");
+  );
+  if (siglen != (2 * SHA1_DIGEST_SIZE)) return ret;
+  s = DSA_SIG_new();
+  if (s == NULL) return ret;
+  s->r = BN_bin2bn(sigbuf, SHA1_DIGEST_SIZE,
+		   s->r);
+  s->s = BN_bin2bn(&(sigbuf[SHA1_DIGEST_SIZE]),
+		   SHA1_DIGEST_SIZE,
+		   s->s);
+  ret=DSA_do_verify(dgst, dgst_len,s,dsa);
+  DSA_SIG_free(s);
+  return ret;
+}
+
+/*
+ * The following code implements ElGamal encryption using DSA keys
+ * in a (hopefully) OpenSSL compatible fashion. It really belongs in 
+ * OpenSSL itself, when the code approaches being both tested and
+ * more efficient. In order to make things a bit faster, the modular
+ * operations use montogomery representation.
+ *
+ * NB - this implementation is pretty naive, and contains just the
+ * simplest implementation of ElGamal as per HAC, Ch8, Section 8.4,
+ * pp 294-295.
+ */
+
+static ERR_STRING_DATA ElGamal_str_functs[] =
+{
+  {ERR_PACK(0,ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT,0),  "ElGamal_public_encrypt"},
+  {ERR_PACK(0,ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT,0), "ElGamal_private_decrypt"},
+  { 0, NULL }
+};
+
+static ERR_STRING_DATA ElGamal_str_reasons[] = 
+{
+  { ELGAMAL_R_UNKNOWN_PADDING_TYPE, "unknown padding type" },
+  { ELGAMAL_R_DATA_GREATER_THAN_MOD_LEN, "data longer than modulus length" },
+  { ELGAMAL_R_PADDING_CHECK_FAILED, "padding check failed" },
+  { 0, NULL }
+};
+
+void
+ERR_load_ElGamal_strings( void )
+{
+  static int init = 1;
+
+  if (init)
+    {
+      init = 0;
+
+      ERR_load_strings(ERR_LIB_ELGAMAL, ElGamal_str_functs);
+      ERR_load_strings(ERR_LIB_ELGAMAL, ElGamal_str_reasons);
+    }
+}
+
+int
+ElGamal_public_check( DSA *dsa )
+{
+  BIGNUM res;
+  BN_MONT_CTX *mont;
+  BN_CTX *ctx;
+  int r = 0;
+
+  /* Check that g^q = 1 (mod p), and that y^q = 1 (mod p) */
+  /* to avoid attacks involving generators which produce small */
+  /* subgroups */
+
+  BN_init(&res);
+  if ((ctx = BN_CTX_new()) == NULL) goto err;
+  if ((mont = BN_MONT_CTX_new()) == NULL) goto err;
+  if (! BN_MONT_CTX_set(mont, dsa->p, ctx)) goto err;
+
+  if (! BN_mod_exp_mont(&res, dsa->g, dsa->q, dsa->p, ctx, mont)) goto err;
+  if (! BN_is_one(&res)) goto err;
+  if (! BN_mod_exp_mont(&res, dsa->pub_key, dsa->q, dsa->p, ctx, mont)) goto err;
+  if (! BN_is_one(&res)) goto err;
+  r = 1; /* Key is OK */
+
+ err:
+  BN_clear_free(&res);
+  if (ctx) BN_CTX_free(ctx);
+  if (mont) BN_MONT_CTX_free(mont);
+
+  return r;
+}
+
+int
+ElGamal_public_encrypt( int flen, unsigned char *from,
+			unsigned char *to,
+			DSA *dsa, int padding )
+			    
+{
+  unsigned char *buf, *p;
+  int num = 0, i, j, k, r = -1;
+  BIGNUM kappa, alpha, beta, f;
+  BIGNUM BETA, F;
+  BN_MONT_CTX *pmont;
+  BN_CTX *ctx = NULL;
+
+  num = BN_num_bytes(dsa->p) ;
+  BN_init(&alpha);
+  BN_init(&beta);
+  BN_init(&kappa);
+  BN_init(&f);
+  BN_init(&BETA);
+  BN_init(&F);
+
+  if ((ctx = BN_CTX_new()) == NULL) goto err;
+  if ((pmont = BN_MONT_CTX_new()) == NULL) goto err;
+  if (! BN_MONT_CTX_set(pmont, dsa->p, ctx)) goto err;
+  if ((buf = (unsigned char *)Malloc(num)) == NULL) {
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  /* generate k s.t. 1 <= k <= q-1 */
+  do {
+    if (! BN_rand(&kappa, BN_num_bits(dsa->q), 1, 1)) goto err;
+  } while (BN_cmp(&kappa, dsa->q) < 0);
+
+  switch (padding) {
+  case ELGAMAL_PKCS1_PADDING:
+    i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
+    break;
+  case ELGAMAL_PKCS1_OAEP_PADDING:
+    i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
+    break;
+  case ELGAMAL_NO_PADDING:
+    i = RSA_padding_add_none(buf, num, from, flen);
+    break;
+  default:
+    ElGamalerr( ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT, 
+      ELGAMAL_R_UNKNOWN_PADDING_TYPE );
+    goto err;
+  }
+
+  if (i <= 0) goto err;
+
+  if (BN_bin2bn(buf, num, &f) == NULL) goto err;
+
+  /* Set alpha = g^k (mod p) */
+  if (!BN_mod_exp_mont(&alpha, dsa->g, &kappa, dsa->p, ctx, pmont)) goto err;
+
+  /* Set beta = M * y^k (mod p) */
+  if (!BN_mod_exp_mont(&beta, dsa->pub_key, &kappa, dsa->p, ctx, 
+    pmont)) goto err;
+
+  BN_to_montgomery(&F, &f, pmont, ctx);
+  BN_to_montgomery(&BETA, &beta, pmont, ctx);
+  if (!BN_mod_mul_montgomery(&BETA, &BETA, &F, pmont, ctx)) goto err;
+  BN_from_montgomery(&beta, &BETA, pmont, ctx);
+
+  /* Squirt out alpha, left padded to modulus size with zero bytes */
+  j = BN_num_bytes(&alpha);
+  i = BN_bn2bin(&alpha, &(to[num-j]));
+  for(k=0; k<(num-i); k++) to[k]=0;
+
+  /* Follow this with beta */
+  p = &(to[num]);
+  j = BN_num_bytes(&beta);
+  i = BN_bn2bin(&beta, &(p[num-j]));
+  for(k=0; k<(num-i); k++) p[k]=0;
+
+  r = num*2;
+
+ err:
+  if (ctx != NULL) BN_CTX_free(ctx);
+  if (pmont != NULL) BN_MONT_CTX_free(pmont);
+  BN_clear_free(&alpha);
+  BN_clear_free(&beta);
+  BN_clear_free(&beta);
+  BN_clear_free(&kappa);
+  BN_clear_free(&f);
+  BN_clear_free(&BETA);
+  BN_clear_free(&F);
+  if (buf != NULL) {
+    memset(buf, 0, num);
+    Free(buf);
+  }
+  return r;
+}
+
+int ElGamal_private_decrypt( int flen, unsigned char *from,
+			     unsigned char *to,
+			     DSA *dsa, int padding )
+{
+
+  BIGNUM alpha, beta, gamma, delta, p1a;
+  BIGNUM BETA, GAMMA, DELTA;
+  BN_CTX *ctx;
+  BN_MONT_CTX *pmont;
+  unsigned char *p, *buf = NULL;
+  int j, r = -1, num;
+
+  BN_init(&alpha);
+  BN_init(&beta);
+  BN_init(&gamma);
+  BN_init(&delta);
+  BN_init(&p1a);
+  BN_init(&BETA);
+  BN_init(&GAMMA);
+  BN_init(&DELTA);
+  if ((ctx = BN_CTX_new()) == NULL) goto err;
+  if ((pmont = BN_MONT_CTX_new()) == NULL) goto err;
+  if (! BN_MONT_CTX_set(pmont, dsa->p, ctx)) goto err;
+
+  num = BN_num_bytes(dsa->p);
+
+  /* set p1a to be equal to p-1-x, where x is the private key */
+  if (BN_copy(&p1a, dsa->p) == NULL) goto err;
+  if (! BN_sub_word(&p1a, 1)) goto err;
+  if (! BN_sub(&p1a, &p1a, dsa->priv_key)) goto err;
+
+  if ((buf = (unsigned char *)Malloc(num)) == NULL) {
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (flen > num*2) {
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, ELGAMAL_R_DATA_GREATER_THAN_MOD_LEN);
+    goto err;
+  }
+
+  /* Copy the cipher text into the two numbers alpha and beta */
+  if (BN_bin2bn(from, flen / 2, &alpha) == NULL) goto err;
+  if (BN_bin2bn(&(from[flen/2]), flen / 2, &beta) == NULL) goto err;
+  
+  if (! BN_mod_exp_mont(&gamma, &alpha, &p1a, dsa->p, ctx, pmont)) goto err;
+  BN_to_montgomery(&GAMMA, &gamma, pmont, ctx);
+  BN_to_montgomery(&BETA, &beta, pmont, ctx);
+  if (! BN_mod_mul_montgomery(&DELTA, &GAMMA, &BETA, pmont, ctx)) goto err;
+  BN_from_montgomery(&delta, &DELTA, pmont, ctx);
+
+  /* Now delta should contain the (possibly padded) plaintext */
+  p = buf;
+  j = BN_bn2bin(&delta, p);
+
+  switch( padding ) {
+  case ELGAMAL_PKCS1_PADDING:
+    r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
+    break;
+  case ELGAMAL_PKCS1_OAEP_PADDING:
+    r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
+    break;
+  case ELGAMAL_NO_PADDING:
+    r = RSA_padding_check_none(to, num, buf, j, num);
+    break;
+  default:
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, 
+      ELGAMAL_R_UNKNOWN_PADDING_TYPE);
+    goto err;
+  }
+
+  if (r < 0)
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, 
+      ELGAMAL_R_PADDING_CHECK_FAILED);
+
+ err:
+  if (ctx != NULL) BN_CTX_free(ctx);
+  if (pmont != NULL) BN_MONT_CTX_free(pmont);
+  BN_clear_free(&alpha);
+  BN_clear_free(&beta);
+  BN_clear_free(&gamma);
+  BN_clear_free(&delta);
+  BN_clear_free(&p1a);
+  BN_clear_free(&BETA);
+  BN_clear_free(&GAMMA);
+  BN_clear_free(&DELTA);
+  if (buf != NULL) {
+    memset(buf, 0, num);
+    Free(buf);
+  }
+  return r;
+}
+bool
+valid_ciphertext_length( const u_int32_t len, struct connection *c )
+{
+  EVP_PKEY *pk = c->key;
+  bool ret = FALSE;
+
+  if ((!pk) || (len == 0)) return FALSE;
+  switch(pk->type) {
+  case EVP_PKEY_RSA:
+    if (len % BN_num_bytes(pk->pkey.rsa->n) == 0) ret = TRUE;
+    break;
+  case EVP_PKEY_DSA:
+    if (len % (2 * BN_num_bytes(pk->pkey.dsa->p)) == 0) ret = TRUE;
+    break;
+  default:
+    return FALSE;
+  }
+
+  return ret;
+}
+
+static void
+alloc_ciphertext( const u_int32_t len,
+		  EVP_PKEY *pk,
+		  u_char **c,
+		  u_int32_t *ms,
+		  u_int32_t *bsize,
+		  u_int32_t *bl )
+{
+  int modsize, chunksize, blocks;
+  u_int32_t clen;
+
+  switch(pk->type)
+    {
+    case EVP_PKEY_RSA:
+      {
+	RSA *rsa = pk->pkey.rsa;
+	modsize = BN_num_bytes(rsa->n);
+      }
+      break;
+    case EVP_PKEY_DSA:
+      {
+	DSA *dsa = pk->pkey.dsa;
+	modsize = BN_num_bytes(dsa->p) * 2;
+      }
+      break;
+    }
+  chunksize = modsize - 2 * SHA1_DIGEST_SIZE - 1;
+  blocks = (len + chunksize - 1) / chunksize;
+  clen = blocks * modsize;
+  *c = malloc(clen);
+  memset(*c, 0, clen);
+  *bsize = chunksize - 1;
+  *bl = blocks;
+  *ms = modsize;
+}
+
+bool
+pubkey_encrypt_chunk( chunk_t *ch, struct state *st )
+{
+  struct connection *c = st->st_connection;
+  u_char *str = ch->ptr;
+  u_int32_t len = ch->len;
+  EVP_PKEY *pk = NULL;
+  u_char *ciph;
+  u_int32_t ms, bs, bl;
+  u_int16_t auth = st->st_oakley.auth;
+  int i;
+  long clen = 0;
+
+  switch(auth) {
+  case OAKLEY_RSA_ENC:
+  case OAKLEY_RSA_ENC_REV:
+    for(i=0; i<MAX_OTHER; i++) {
+      if ((c->other[i].type == EVP_PKEY_RSA) &&
+	  (c->other[i].cert != NULL)) {
+	pk = X509_get_pubkey((X509 *)c->other[i].cert);
+	break;
+      }
+    }
+    break;
+  case OAKLEY_ELGAMAL_ENC:
+  case OAKLEY_ELGAMAL_ENC_REV:
+    for(i=0; i<MAX_OTHER; i++) {
+      if ((c->other[i].type == EVP_PKEY_DSA) &&
+	  (c->other[i].cert != NULL)) {
+	pk = X509_get_pubkey((X509 *)c->other[i].cert);
+	break;
+      }
+    }
+    break;
+  default:
+    log("Non PK authentication scheme in state");
+    return FALSE;
+  }
+
+  if (!pk) {
+    log("Unable to select an encryption key");
+    return FALSE;
+  }
+
+  switch(pk->type) {
+  case EVP_PKEY_RSA:
+    {
+      alloc_ciphertext(len, pk, &ciph, &ms, &bs, &bl);
+    }
+    break;
+  case EVP_PKEY_DSA:
+    {
+      alloc_ciphertext(len, pk, &ciph, &ms, &bs, &bl);
+    }
+    break;
+  default:
+    log("Unknown key type: %d", pk->type);
+    break;
+  }
+
+    for(i=0; ((i<bl)&&(clen>=0)); i++) {
+    u_char *pst = &str[i * bs];
+    u_char *cst = &ciph[i * ms];
+    u_int32_t plen = (i < bl-1) ? bs : len % bs;
+
+    switch(pk->type) {
+    case EVP_PKEY_RSA:
+      {
+	RSA *rsa = pk->pkey.rsa;
+
+	clen = RSA_public_encrypt(plen, pst, cst, rsa, RSA_PKCS1_OAEP_PADDING);
+      }
+      break;
+    case EVP_PKEY_DSA:
+      {
+	DSA *dsa = pk->pkey.dsa;
+
+	clen = ElGamal_public_encrypt(plen, pst, cst, dsa, ELGAMAL_PKCS1_OAEP_PADDING);
+      }
+      break;
+    default:
+      log("Unknown cert type: %d", pk->type);
+      return FALSE;
+      break;
+    }
+  }
+
+  memset(ch->ptr, 0, ch->len);
+  if (clen < 0) {
+    log("Failed to encrypt payload with certificate's public key.");
+    return FALSE;
+  } else {
+    freeanychunk(*ch);
+    ch->len=bl*ms;
+    ch->ptr=ciph;
+    return TRUE;
+  }
+}
+
+bool
+privkey_decrypt_chunk( chunk_t *ch, struct state *st )
+{
+  u_int32_t i, bl, bs, clen;
+  struct connection *c = st->st_connection;
+  EVP_PKEY *pk = c->key;
+  u_char *str = ch->ptr;
+  u_char *pst;
+  u_int32_t ptr, plen;
+
+  switch(pk->type) {
+  case EVP_PKEY_RSA:
+    {
+      RSA *rsa = pk->pkey.rsa;
+      bs = BN_num_bytes(rsa->n);
+    }
+    break;
+  case EVP_PKEY_DSA:
+    {
+      DSA *dsa = pk->pkey.dsa;
+      bs = 2 * BN_num_bytes(dsa->p);
+    }
+    break;
+  default:
+    log("Unknown key type: %d", pk->type);
+    break;
+  }
+
+  clen = ch->len;
+  bl = clen / bs;
+
+  pst = malloc(clen);
+  ptr = 0;
+  plen = 0;
+	
+  for(i=0; ((i<bl)&&(plen >= 0)); i++) {
+    switch(pk->type) {
+    case EVP_PKEY_RSA:
+      {
+	RSA *rsa = pk->pkey.rsa;
+
+	if (clen >= bs) {
+/*
+ * int     RSA_private_decrypt(int flen, unsigned char *from, 
+ *               unsigned char *to, RSA *rsa,int padding);
+ *
+ *         This function implements RSA private decryption, the rsa variable
+ *         should be a private key.  'from_len' bytes are taken
+ *         from 'from' and decrypted.  The decrypted data is
+ *         put into 'to'.  The number of bytes encrypted is returned.  -1 is
+ *         returned to indicate an error. The operation performed is
+ *         to = from^rsa->d mod rsa->n.
+ */
+
+	  plen = RSA_private_decrypt( bs, &(str[i * bs]), &(pst[ptr]), rsa, 
+	     RSA_PKCS1_OAEP_PADDING );
+	  if (plen == -1) {
+	    log_err();
+	  }
+	} else /* Ciphertext is too short */
+	  plen = 0;
+      }
+      break;
+    case EVP_PKEY_DSA:
+      {
+	DSA *dsa = pk->pkey.dsa;
+	
+	if (clen >= bs) {
+	  plen = ElGamal_private_decrypt( bs, &str[i * bs], &pst[ptr], 
+	    dsa, ELGAMAL_PKCS1_OAEP_PADDING );
+	  if (plen == -1 ) {
+	    log_err();
+	  }
+	} else /* Short ciphertext - don't try and decrypt */
+	  plen = 0;
+      }
+      break;
+    default:
+      log("Unknown key type: %d", pk->type);
+      plen = 0;
+      break;
+    }
+    ptr += plen;
+  }
+
+  if (plen != -1) {
+    freeanychunk(*ch);
+    ch->ptr = pst;
+    ch->len = ptr;
+    return TRUE;
+  } else {
+    pfree(pst);
+    return FALSE;
+  }
+}
+
+bool
+use_openssl( struct connection *c )
+{
+	/* Using data from connection *c, we can determine if we are 
+	 * currently using the openssl-related functions or not.
+	 * ie: 
+	 *   c->cert
+	 *   c->key
+	 *   c->cert_options
+	 * 
+	 * also use c->policy to determine policy.
+	 * 
+	 * Return 0 if openssl, otherwise 1.
+	 */
+
+	if (c->policy & POLICY_OPENSSL) {
+		if ((c->cert != NULL) || 
+			(c->key != NULL) || 
+			(c->cert_options != 0)) 
+		{
+			// OPENSSL
+			return 1;
+		}
+		else
+		{
+			// RSASIG only
+			return 0;
+		}
+	}
+    else 
+	{
+		// PSK
+		return 0;
+	}
+}
+
+bool
+check_idtype_and_path( struct connection *c, const char *spec )
+{
+
+  return TRUE;
+}
+
+const struct RSA_public_key *
+fs_RSA ( EVP_PKEY *evp_pkey ) {
+  struct RSA_public_key *fs_rsa;
+
+ /*
+  * MP_INT:
+  * int _mp_alloc;
+  * int _mp_size;
+  * mp_limb_t *_mp_d;
+  */
+
+ /* BIGNUM
+  * BN_ULONG *d;
+  * int top;
+  * int max;
+  * int neg;
+  * int flags;
+  */
+
+/* So:
+    mp_limb_t *_mp_d = BN_ULONG *d 
+    int _mp_alloc = int max 
+    int _mp_size = int top
+*/
+
+/*   fs_rsa->n = (MP_INT)(evp_pkey->pkey.rsa->n); */
+  {
+  BIGNUM *temp_bignum;
+  MP_INT *temp_mp_int;
+
+  temp_bignum = evp_pkey->pkey.rsa->n;
+  temp_mp_int->_mp_d = (mp_limb_t *)&(temp_bignum->d);
+  temp_mp_int->_mp_alloc = temp_bignum->max;
+  temp_mp_int->_mp_size = temp_bignum->top;
+  fs_rsa->n = *(temp_mp_int);
+  }
+
+  {
+/*   fs_rsa->e = (MP_INT)(evp_pkey->pkey.rsa->e); */
+  BIGNUM *temp_bignum;
+  MP_INT *temp_mp_int;
+
+  temp_bignum = evp_pkey->pkey.rsa->e;
+  temp_mp_int->_mp_d = (mp_limb_t *)&(temp_bignum->d);
+  temp_mp_int->_mp_alloc = temp_bignum->max;
+  temp_mp_int->_mp_size = temp_bignum->top;
+  fs_rsa->e = *(temp_mp_int);
+  }
+
+  fs_rsa->k = mpz_sizeinbase(&fs_rsa->n, 2);        /* size in bits, for a start */
+  fs_rsa->k = (fs_rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE;      /* now octets */
+  
+  return fs_rsa;
+}
+
+STACK_OF(X509) *
+extract_STACK_OF_X509_from_PKCS7 (PKCS7 *p7)
+{
+	STACK_OF(X509) *certs=NULL;
+	int i=OBJ_obj2nid(p7->type);
+
+	switch (i)
+	{
+		case NID_pkcs7_signed:
+			certs=p7->d.sign->cert;
+			break;
+		case NID_pkcs7_signedAndEnveloped:
+			certs=p7->d.signed_and_enveloped->cert;
+			break;
+		default:
+			break;
+	}
+
+	return certs;
+}
+
+STACK_OF(X509_CRL) *
+extract_STACK_OF_X509_CRL_from_PKCS7 (PKCS7 *p7)
+{
+	STACK_OF(X509_CRL) *crls=NULL;
+	int i=OBJ_obj2nid(p7->type);
+
+	switch (i)
+	{
+		case NID_pkcs7_signed:
+			crls=p7->d.sign->crl;
+			break;
+		case NID_pkcs7_signedAndEnveloped:
+			crls=p7->d.signed_and_enveloped->crl;
+			break;
+		default:
+			break;
+	}
+
+	return crls;
+}
+
+
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/openssl.h freeswan-1.91/pluto/openssl.h
--- freeswan-1.91.orig/pluto/openssl.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/openssl.h	Tue Jul  3 02:54:53 2001
@@ -0,0 +1,142 @@
+#ifdef OPENSSL
+#ifndef OPENSSL_INC_H
+#define OPENSSL_INC_H
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/safestack.h>
+
+#include <freeswan.h>
+
+#include "xmap.h"
+
+struct _x509_cert_node {
+  X509 *x;
+  struct _x509_cert_node *next;
+};
+
+typedef struct _x509_cert_node *X509_cert_list;
+
+typedef bool discrim_fn( X509 *x, STACK_OF(XMAP) *lu,
+			 struct payload_digest *const id_pld, bool strict);
+
+extern bool make_lookups(STACK_OF(XMAP) **lu, const char *spec );
+extern bool check_idtype_and_path( struct connection *c, const char *spec );
+
+extern void log_err( void );
+extern void load_cert_and_key( const char *cert, const char *key,
+			       X509 **x, EVP_PKEY **k, char *conn_name );
+extern bool use_openssl( struct connection *c );
+extern STACK_OF(X509) *
+	peer_cert_list( STACK_OF(XMAP) *lu,
+		int type,
+		X509 *cert, struct payload_digest *const id_pld,
+		bool strict );
+extern STACK_OF(X509) *extract_STACK_OF_X509_from_PKCS7 (PKCS7 *p7);
+extern STACK_OF(X509_CRL) *extract_STACK_OF_X509_CRL_from_PKCS7 (PKCS7 *p7);
+
+extern bool have_rsa_key( struct state *st );
+extern bool have_dss_key( struct state *st );
+extern bool have_rsa_keypair( struct state *st );
+extern bool have_elgamal_keypair( struct state *st );
+
+extern bool verify_certificate( X509 *x, STACK_OF(XMAP) *lu,
+				const char *path, bool strict );
+
+extern u_int32_t parse_options( const char *s );
+
+extern int DSA_sign_raw(unsigned char *dgst,int dlen,
+			unsigned char *sig, unsigned int *siglen, DSA *dsa);
+
+extern int DSA_verify_raw(const unsigned char *dgst,int dgst_len,
+			  unsigned char *sigbuf, int siglen, DSA *dsa);
+
+#define ERR_LIB_ELGAMAL 127
+
+#define ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT 100
+#define ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT  101
+
+#define ELGAMAL_R_UNKNOWN_PADDING_TYPE      100
+#define ELGAMAL_R_DATA_GREATER_THAN_MOD_LEN 101
+#define ELGAMAL_R_PADDING_CHECK_FAILED      102
+
+#define ELGAMAL_PKCS1_PADDING RSA_PKCS1_PADDING
+#define ELGAMAL_PKCS1_OAEP_PADDING RSA_PKCS1_OAEP_PADDING
+#define ELGAMAL_NO_PADDING RSA_NO_PADDING
+
+#define ElGamalerr(f, r) ERR_PUT_error(ERR_LIB_ELGAMAL, (f), (r), ERR_file_name, __LINE__)
+
+void ERR_load_ElGamal_strings( void );
+int ElGamal_public_check( DSA *dsa );
+int ElGamal_public_encrypt( int flen, unsigned char *from,
+			    unsigned char *to,
+			    DSA *dsa, int padding );
+int ElGamal_private_decrypt( int flen, unsigned char *from,
+			     unsigned char *to,
+			     DSA *dsa, int padding );
+
+/* Function pointer pointing to an encryption routine */
+typedef void encryptor_fn( chunk_t *ch, struct state *c );
+
+extern bool valid_ciphertext_length( const u_int32_t len,
+				     struct connection *c );
+extern bool privkey_decrypt_chunk ( chunk_t *ch, struct state *c );
+extern bool pubkey_encrypt_chunk ( chunk_t *ch, struct state *c );
+
+/* get the other end's cert based */
+extern bool have_othercert( struct connection *c, int type );
+
+/* Macro to duplicate Private key. Used in unshare_connection_strings */
+#define EVP_PKEY_dup(pkey) \
+  (EVP_PKEY *)ASN1_dup((int (*)())i2d_PrivateKey, \
+  (char *(*)())d2i_AutoPrivateKey,(char *)pkey)
+
+/* convert EVP_PKEY to freeswan's RSA_public_key */
+extern const struct RSA_public_key *fs_RSA ( EVP_PKEY *evp_pkey );
+
+#if 0 /* an interesting struct for certs */
+struct x509cert {
+  chunk_t        certificate;
+  chunk_t          tbsCertificate;
+  u_int              version;
+  chunk_t            serialNumber;
+                /*   signature */
+  chunk_t            sigAlg;
+  chunk_t            issuer;
+                /*   validity */
+  chunk_t              notBefore;
+  chunk_t              notAfter;
+  chunk_t            subject;
+                /*   subjectPublicKeyInfo */
+  enum pubkey_alg      subjectPublicKeyAlgorithm;
+                /*     subjectPublicKey */
+  chunk_t                modulus;
+  chunk_t                publicExponent;
+  chunk_t            issuerUniqueID;
+  chunk_t            subjectUniqueID;
+                /*   v3 extensions */
+                /*   extension */
+                /*     extension */
+                /*       extnID */
+                /*        critical */
+                /*        extnValue */
+                /*          generalNames */
+  chunk_t                     dnsName;
+  chunk_t                     ipAddress;
+  chunk_t                     rfc822Name;
+                /* signatureAlgorithm */
+  chunk_t            algorithm;
+  chunk_t          signature;
+};
+#endif
+
+/* to lookup CRLs */
+extern X509_CRL *lookup_crl(STACK_OF(XMAP) *lu, X509_NAME *name);
+
+#endif
+#endif
+
+
diff -BbruN freeswan-1.91.orig/pluto/openssl_defs.h freeswan-1.91/pluto/openssl_defs.h
--- freeswan-1.91.orig/pluto/openssl_defs.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/openssl_defs.h	Tue Jul  3 02:54:53 2001
@@ -0,0 +1,5 @@
+
+#define FILE_NAME_LIMIT 80
+#define PATH_NAME_LIMIT 256
+#define CERT_OPTIONS_LIMIT 128
+#define MAX_OTHER 2 /* only know about two type of certificate at the moment (RSA,DSA) */
diff -BbruN freeswan-1.91.orig/pluto/spdb.c freeswan-1.91/pluto/spdb.c
--- freeswan-1.91.orig/pluto/spdb.c	Mon Apr  9 15:48:43 2001
+++ freeswan-1.91/pluto/spdb.c	Tue Jul  3 02:56:34 2001
@@ -39,6 +39,11 @@
 #include "md5.h"
 #include "crypto.h" /* requires sha1.h and md5.h */
 
+#ifdef OPENSSL
+#include "demux.h"
+#include "openssl.h"
+#endif
+
 #define AD(x) x, elemsof(x)	/* Array Description */
 #define AD_NULL NULL, 0
 
@@ -46,6 +51,12 @@
 
 /* arrays of attributes for transforms, preshared key */
 
+static struct db_attr otpsk1024desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otpsk1024des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -53,6 +64,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otpsk1536desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otpsk1536des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -60,6 +77,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
 	};
 
+static struct db_attr otpsk1024dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otpsk1024des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -67,6 +90,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otpsk1536dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otpsk1536des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -76,6 +105,12 @@
 
 /* arrays of attributes for transforms, RSA signatures */
 
+static struct db_attr otrsasig1024desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otrsasig1024des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -83,6 +118,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otrsasig1536desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otrsasig1536des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -90,6 +131,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
 	};
 
+static struct db_attr otrsasig1024dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otrsasig1024des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -97,6 +144,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otrsasig1536dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otrsasig1536des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -104,11 +157,305 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
 	};
 
+#ifdef OPENSSL /* OPENSSL */
+static struct db_attr ot1024desmd5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1536desmd5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+#endif /* OPENSSL */
+
 /* We won't accept this, but by proposing it, we get to test
  * our rejection.  We better not propose it to an IKE daemon
  * that will accept it!
  */
 #ifdef TEST_INDECENT_PROPOSAL
+static struct db_attr otpsk1024destiger[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_TIGER },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otpsk1024des3tiger[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_TIGER },
@@ -127,6 +475,14 @@
 	{ KEY_IKE, AD(otpsk1024des3md5) },
 	{ KEY_IKE, AD(otpsk1536des3md5) },
 	{ KEY_IKE, AD(otpsk1536des3sha) },
+/* DES */
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024destiger) },
+#endif
+	{ KEY_IKE, AD(otpsk1024dessha) },
+	{ KEY_IKE, AD(otpsk1024desmd5) },
+	{ KEY_IKE, AD(otpsk1536desmd5) },
+	{ KEY_IKE, AD(otpsk1536dessha) },
     };
 
 static struct db_trans oakley_trans_rsasig[] = {
@@ -134,8 +490,139 @@
 	{ KEY_IKE, AD(otrsasig1024des3md5) },
 	{ KEY_IKE, AD(otrsasig1536des3md5) },
 	{ KEY_IKE, AD(otrsasig1536des3sha) },
+/* DES */
+	{ KEY_IKE, AD(otrsasig1024dessha) },
+	{ KEY_IKE, AD(otrsasig1024desmd5) },
+	{ KEY_IKE, AD(otrsasig1536desmd5) },
+	{ KEY_IKE, AD(otrsasig1536dessha) },
     };
 
+#ifdef OPENSSL
+static struct db_trans oakley_trans_psk2[] = {
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024des3tiger), NULL },
+#endif
+	{ KEY_IKE, AD(otpsk1024des3sha), NULL },
+	{ KEY_IKE, AD(otpsk1024des3md5), NULL },
+	{ KEY_IKE, AD(otpsk1536des3md5), NULL },
+	{ KEY_IKE, AD(otpsk1536des3sha), NULL },
+/* DES */
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024destiger), NULL },
+#endif
+	{ KEY_IKE, AD(otpsk1024dessha), NULL },
+	{ KEY_IKE, AD(otpsk1024desmd5), NULL },
+	{ KEY_IKE, AD(otpsk1536desmd5), NULL },
+	{ KEY_IKE, AD(otpsk1536dessha), NULL },
+    };
+
+static struct db_trans oakley_trans_openssl[] = {
+	{ KEY_IKE, AD(ot1024des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024des3md5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536des3md5_ds_rsa), have_rsa_key },
+/* DES */
+	{ KEY_IKE, AD(ot1024dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024desmd5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536desmd5_ds_rsa), have_rsa_key },
+  };
+
+static struct db_trans oakley_trans_psk2openssl[] = {
+	{ KEY_IKE, AD(ot1024des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024des3md5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1024des3sha), NULL },
+	{ KEY_IKE, AD(otpsk1024des3md5), NULL },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536des3md5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1536des3md5), NULL },
+	{ KEY_IKE, AD(otpsk1536des3sha), NULL },
+/* DES */
+	{ KEY_IKE, AD(ot1024dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024desmd5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1024dessha), NULL },
+	{ KEY_IKE, AD(otpsk1024desmd5), NULL },
+
+	{ KEY_IKE, AD(ot1536dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536desmd5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1536desmd5), NULL },
+	{ KEY_IKE, AD(otpsk1536dessha), NULL },
+  };
+#endif /* #ifdef OPENSSL */
+
+
 /* In this table, either PSK or RSA sig is accepted.
  * The order matters, but I don't know what would be best.
  */
@@ -151,6 +638,18 @@
 	{ KEY_IKE, AD(otpsk1536des3md5) },
 	{ KEY_IKE, AD(otrsasig1536des3sha) },
 	{ KEY_IKE, AD(otpsk1536des3sha) },
+/* DES */
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024destiger) },
+#endif
+	{ KEY_IKE, AD(otrsasig1024dessha) },
+	{ KEY_IKE, AD(otpsk1024dessha) },
+	{ KEY_IKE, AD(otrsasig1024desmd5) },
+	{ KEY_IKE, AD(otpsk1024desmd5) },
+	{ KEY_IKE, AD(otrsasig1536desmd5) },
+	{ KEY_IKE, AD(otpsk1536desmd5) },
+	{ KEY_IKE, AD(otrsasig1536dessha) },
+	{ KEY_IKE, AD(otpsk1536dessha) },
     };
 
 /* array of proposals to be conjoined (can only be one for Oakley) */
@@ -164,6 +663,17 @@
 static struct db_prop oakley_pc_pskrsasig[] =
     { { PROTO_ISAKMP, AD(oakley_trans_pskrsasig) } };
 
+#ifdef OPENSSL
+static struct db_prop oakley_pc_psk2[] =
+    { { PROTO_ISAKMP, AD(oakley_trans_psk2) } };
+
+static struct db_prop oakley_pc_openssl[] =
+    { { PROTO_ISAKMP, AD(oakley_trans_openssl) } };
+
+static struct db_prop oakley_pc_psk2openssl[] =
+    { { PROTO_ISAKMP, AD(oakley_trans_psk2openssl) } };
+#endif
+
 /* array of proposal conjuncts (can only be one) */
 
 static struct db_prop_conj oakley_props_psk[] = { { AD(oakley_pc_psk) } };
@@ -172,6 +682,14 @@
 
 static struct db_prop_conj oakley_props_pskrsasig[] = { { AD(oakley_pc_pskrsasig) } };
 
+#ifdef OPENSSL
+static struct db_prop_conj oakley_props_psk2[] = { { AD(oakley_pc_psk2) } };
+
+static struct db_prop_conj oakley_props_openssl[] = { { AD(oakley_pc_openssl) } };
+
+static struct db_prop_conj oakley_props_psk2openssl[] = { { AD(oakley_pc_psk2openssl) } };
+#endif
+
 /* the sadb entry, subscripted by POLICY_PSK and POLICY_RSASIG bits */
 struct db_sa oakley_sadb[] = {
     { AD_NULL },	/* none */
@@ -180,6 +698,16 @@
     { AD(oakley_props_pskrsasig) },	/* POLICY_PSK + POLICY_RSASIG */
     };
 
+#ifdef OPENSSL
+/* the sadb entry, subscripted by POLICY_PSK and POLICY_OPENSSL bits */
+struct db_sa oakley_sadb2[] = {
+    { NULL, 0 },	/* none */
+    { AD(oakley_props_psk2) },	/* POLICY_PSK */
+    { AD(oakley_props_openssl) },	/* POLICY_OPENSSL */
+    { AD(oakley_props_psk2openssl) },	/* POLICY_PSK + POLICY_OPENSSL */
+    };
+#endif
+
 /**************** IPsec (quick mode) SA database ****************/
 
 /* arrays of attributes for transforms */
@@ -203,12 +731,22 @@
 /* arrays of transforms, each in in preference order */
 
 static struct db_trans espa_trans[] = {
+#ifndef OPENSSL
     { ESP_3DES, AD(espmd5_attr) },
     { ESP_3DES, AD(espsha1_attr) },
+    { ESP_DES, AD(espmd5_attr) },
+    { ESP_DES, AD(espsha1_attr) },
+#else
+    { ESP_3DES, AD(espmd5_attr), NULL },
+    { ESP_3DES, AD(espsha1_attr), NULL },
+    { ESP_DES, AD(espmd5_attr), NULL },
+    { ESP_DES, AD(espsha1_attr), NULL },
+#endif
     };
 
 static struct db_trans esp_trans[] = {
     { ESP_3DES, AD_NULL },
+    { ESP_DES, AD_NULL },
     };
 
 #ifdef SUPPORT_ESP_NULL
@@ -219,8 +757,13 @@
 #endif /* SUPPORT_ESP_NULL */
 
 static struct db_trans ah_trans[] = {
+#ifndef OPENSSL
     { AH_MD5, AD(ah_HMAC_MD5_attr) },
     { AH_SHA, AD(ah_HMAC_SHA1_attr) },
+#else
+    { AH_MD5, AD(ah_HMAC_MD5_attr), NULL },
+    { AH_SHA, AD(ah_HMAC_SHA1_attr), NULL },
+#endif
     };
 
 static struct db_trans ipcomp_trans[] = {
@@ -434,7 +977,19 @@
 	    proposal.isap_spisize = oakley_mode ? 0
 		: p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
 		: IPSEC_DOI_SPI_SIZE;
+
+#ifndef OPENSSL
 	    proposal.isap_notrans = p->trans_cnt;
+#else
+	    proposal.isap_notrans = 0;
+	    for(tn = 0; tn < p->trans_cnt; tn++) {
+	      struct db_trans *t = &(p->trans[tn]);
+	      if (t->offer == NULL)
+	        proposal.isap_notrans++;
+	      else if ((t->offer(st))) /* only offer a propsal if we can carry it out */
+	        proposal.isap_notrans++;
+	    }
+#endif
 	    if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
 		return FALSE;
 
@@ -533,6 +1088,14 @@
 
 		trans.isat_np = (tn == p->trans_cnt - 1)
 		    ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_T;
+#ifdef OPENSSL
+		if ((t->offer != NULL) && ((t->offer)(st) == FALSE)) {
+		  DBG(DBG_PARSING,
+		  DBG_log("Skipping unavailable cipher: %d", tn);
+		  );
+		  continue; /* skip unavailable cipher */
+		}
+#endif
 		trans.isat_transnum = tn;
 		trans.isat_transid = t->transid;
 		if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs))
@@ -645,6 +1208,180 @@
     return val;
 }
 
+#ifdef OPENSSL
+struct _trans_node {
+  struct oakley_trans_attrs ta;
+  struct isakmp_transform trans;
+  u_char *attr_start;
+  size_t attr_len;
+  bool elim; /* has this node been eliminated from the selection process */
+  struct _trans_node *next;
+};
+
+typedef struct _trans_node *trans_list;
+
+/* Free a list of Oakley transforms */
+static void
+trans_list_free( trans_list *l )
+{
+  trans_list p;
+
+  if (!l) return;
+  while (*l) {
+    p = *l;
+    *l = p->next;
+    pfree(p->attr_start);
+    pfree(p);
+  }
+}
+
+static void
+trans_list_append(trans_list *l,
+		  struct oakley_trans_attrs *ta,
+		  struct isakmp_transform *trans,
+		  u_char *attr_start,
+		  size_t attr_len) {
+  trans_list p, pp;
+
+  if (!l) return;
+  if ((p = alloc_bytes(sizeof(struct _trans_node),
+		       "transformation node")) == NULL) return;
+  p->ta = *ta;
+  p->trans = *trans;
+  p->attr_len = attr_len;
+  if ((p->attr_start = alloc_bytes(attr_len, "attribute")) == NULL) {
+    pfree(p);
+    return;
+  }
+  memcpy(p->attr_start, attr_start, attr_len);
+  p->elim = FALSE;
+  p->next = NULL;
+  if (*l == NULL) {
+    *l = p;
+  } else {
+    for(pp = *l; pp->next ; pp = pp->next);
+    pp->next = p;
+  }
+}
+
+static bool
+select_trans_candidate(trans_list l,
+		       struct oakley_trans_attrs *ta,
+		       struct isakmp_transform *trans,
+		       u_char **attr_start,
+		       size_t *attr_len,
+		       u_int32_t opts)
+{
+  bool ret = FALSE;
+  trans_list auth[OAKLEY_ELGAMAL_ENC_REV+1], p;
+  uint i, numprefs, pref[10];
+
+  if (!l) {
+    DBG(DBG_PARSING,
+    DBG_log("No candidate transforms to choose from");
+    );
+    return FALSE;
+  }
+
+  if ((!ta) || (!attr_len) || (!trans) || (!attr_start)) {
+    DBG(DBG_PARSING,
+    DBG_log("No space to store selected transform");
+    );
+    return FALSE;
+  }
+
+  /* Separate all elements of the list by authentication method */
+
+  for(i=OAKLEY_PRESHARED_KEY; i<=OAKLEY_ELGAMAL_ENC_REV; i++)
+    auth[i] = NULL;
+  for(p=l; p; p=p->next)
+    if ((p->ta.auth >= OAKLEY_PRESHARED_KEY) &&
+	(p->ta.auth <= OAKLEY_ELGAMAL_ENC_REV )) {
+      trans_list_append(&(auth[p->ta.auth]),
+			&(p->ta),
+			&(p->trans),
+			p->attr_start,
+			p->attr_len);
+    }
+
+  numprefs = 7;
+  pref[numprefs-1] = OAKLEY_PRESHARED_KEY;
+  DBG(DBG_PARSING | DBG_CRYPT,
+  DBG_log("select_trans_candidate: %08x", opts);
+  );
+  if (opts & CERT_OPTION_PK) {
+    if (opts & CERT_OPTION_REV) {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring revised PK encryption schemes");
+      );
+      pref[0] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[1] = OAKLEY_RSA_ENC_REV;
+      pref[2] = OAKLEY_ELGAMAL_ENC;
+      pref[3] = OAKLEY_RSA_ENC;
+      pref[4] = OAKLEY_RSA_SIG;
+      pref[5] = OAKLEY_DSS_SIG;
+    } else {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring standard PK encryption schemes");
+      );
+      pref[0] = OAKLEY_ELGAMAL_ENC;
+      pref[1] = OAKLEY_RSA_ENC;
+      pref[2] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[3] = OAKLEY_RSA_ENC_REV;
+      pref[4] = OAKLEY_RSA_SIG;
+      pref[5] = OAKLEY_DSS_SIG;
+    }
+  } else {
+    if (opts & CERT_OPTION_REV) {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring digisig schemes, then revised pk");
+      );
+      pref[0] = OAKLEY_RSA_SIG;
+      pref[1] = OAKLEY_DSS_SIG;
+      pref[2] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[3] = OAKLEY_RSA_ENC_REV;
+      pref[4] = OAKLEY_ELGAMAL_ENC;
+      pref[5] = OAKLEY_RSA_ENC;
+    } else {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring digisig schemes, then standard pk");
+      );
+      pref[0] = OAKLEY_RSA_SIG;
+      pref[1] = OAKLEY_DSS_SIG;
+      pref[2] = OAKLEY_ELGAMAL_ENC;
+      pref[3] = OAKLEY_RSA_ENC;
+      pref[4] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[5] = OAKLEY_RSA_ENC_REV;
+    }
+  }
+
+  for(i=0; ((i<numprefs) && (!ret)); i++) {
+    DBG(DBG_PARSING,
+    DBG_log("Trying out: %s", enum_show(&oakley_auth_names, pref[i]));
+    );
+    if ((pref[i]) && (auth[pref[i]])) {
+      ret = TRUE;
+      *ta = auth[pref[i]]->ta;
+      *trans = auth[pref[i]]->trans;
+      *attr_start = alloc_bytes(auth[pref[i]]->attr_len, "attribute");
+      if (*attr_start) {
+	*attr_len = auth[pref[i]]->attr_len;
+	memcpy(*attr_start, auth[pref[i]]->attr_start, *attr_len);
+      }
+      DBG(DBG_PARSING,
+      DBG_log("Candidate selected: %s", 
+        enum_show(&oakley_auth_names, pref[i]));
+      );
+    }
+}
+  
+  for(i=OAKLEY_PRESHARED_KEY; i<=OAKLEY_RSA_ENC_REV; i++) {
+    trans_list_free(&auth[i]);
+  }
+  return ret;
+}
+#endif
+
 /* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode).
  * Various shortcuts are taken.  In particular, the policy, such as
  * it is, is hardwired.
@@ -674,6 +1411,12 @@
     struct isakmp_proposal proposal;
     unsigned no_trans_left;
     int last_transnum;
+    const struct connection *c = st->st_connection;
+    
+#ifdef OPENSSL
+    bool selected;
+    trans_list tl = NULL;
+#endif
 
     /* DOI */
     if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
@@ -859,12 +1602,25 @@
 		case OAKLEY_ENCRYPTION_ALGORITHM | ISAKMP_ATTR_AF_TV:
 		    switch (val)
 		    {
-#if 0	/* we don't feel DES is safe */
 		    case OAKLEY_DES_CBC:
-#endif
+			if ((c->block_cypher == ALL_BLOCK_CYPHER) ||
+			  (c->block_cypher == DES_BLOCK_CYPHER)) {
+			  ta.encrypt = val;
+			  ta.encrypter = &oakley_encrypter[val];
+			} else {
+                       ugh = builddiag("%s is not supported",
+			    enum_show(&oakley_enc_names, val));
+			}
+			break;
 		    case OAKLEY_3DES_CBC:
+			if ((c->block_cypher == ALL_BLOCK_CYPHER) ||
+			  (c->block_cypher == DES3_BLOCK_CYPHER)) {
 			ta.encrypt = val;
 			ta.encrypter = &oakley_encrypter[val];
+			} else {
+                       ugh = builddiag("%s is not supported",
+			    enum_show(&oakley_enc_names, val));
+			}
 			break;
 		    default:
 			ugh = builddiag("%s is not supported"
@@ -923,9 +1679,54 @@
 			    ta.auth = val;
 			}
 			break;
+
+#ifdef OPENSSL
+                  case OAKLEY_DSS_SIG:
+                    if ((st->st_connection->key == NULL) ||
+                        (((EVP_PKEY *)(st->st_connection->key))->type != EVP_PKEY_DSA))
+                      ugh = builddiag(
+                      "OAKLEY_DSS_SIG requested, but no DSA key available to sign with. Still unsupported.");
+                    ta.auth = val;
+                    break;
+/*
+ *                case OAKLEY_RSA_SIG:
+ * see after #endif OPENSSL
+ */
+                  case OAKLEY_RSA_ENC:
+                    if (!have_rsa_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_RSA_ENC requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_ELGAMAL_ENC:
+                    if (!have_elgamal_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_ELGAMAL_ENC requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_RSA_ENC_REV:
+                    if (!have_rsa_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_RSA_ENC_REV requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_ELGAMAL_ENC_REV:
+                    if (!have_elgamal_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_ELGAMAL_ENC_REV requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+
 		    case OAKLEY_RSA_SIG:
+		    if (!use_openssl(st->st_connection))
+		    {
+#endif /* OPENSSL, !use_openssl */
 			/* Accept if policy specifies RSASIG or is default */
+#ifndef OPENSSL
 			if ((iap & POLICY_RSASIG) == LEMPTY)
+#else
+                       if ((iap & POLICY_OPENSSL) == LEMPTY)
+#endif
 			{
 			    ugh = "policy does not allow OAKLEY_RSA_SIG authentication";
 			}
@@ -941,6 +1742,15 @@
 			     */
 			    ta.auth = val;
 			}
+#ifdef OPENSSL
+		    } else { /* use_openssl */
+		      if ((st->st_connection->key == NULL) ||
+		        (((EVP_PKEY *)(st->st_connection->key))->type != EVP_PKEY_RSA))
+                      ugh = builddiag(
+		      "OAKLEY_RSA_SIG requested, but no key available to sign with");
+		      ta.auth = val;
+		    }
+#endif
 			break;
 
 		    default:
@@ -1055,6 +1865,7 @@
 	     * Lets finish early and leave.
 	     */
 
+#ifndef OPENSSL
 	    DBG(DBG_PARSING | DBG_CRYPT
 		, DBG_log("Oakley Transform %u accepted", trans.isat_transnum));
 
@@ -1108,6 +1920,14 @@
 	    /* copy over the results */
 	    st->st_oakley = ta;
 	    return NOTHING_WRONG;
+#else
+	    /*
+	     * We store the ta result into the list of candidates
+	     * Afterwards, site policy dictates which of the
+	     * candidates we should select
+	     */
+	    trans_list_append(&tl, &ta, &trans, attr_start, attr_len);
+#endif
 	}
 
 	/* on to next transform */
@@ -1128,9 +1948,77 @@
 		, enum_show(&payload_names, proposal.isap_np));
 	    return BAD_PROPOSAL_SYNTAX;
 	}
-    }
+    } /* for */
+
+#ifndef OPENSSL
     loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform");
     return NO_PROPOSAL_CHOSEN;
+#else
+    /* We should have a list of hopefuls in the list tl */
+    { /* open scope */
+      u_char *attr_start;
+      size_t attr_len;
+      struct isakmp_transform trans;
+
+      selected = select_trans_candidate(tl, &st->st_oakley, &trans, 
+        &attr_start, &attr_len, st->st_connection->cert_options);
+      trans_list_free(&tl);
+      if (! selected) {
+        log("no acceptable Oakley Transform");
+        return NO_PROPOSAL_CHOSEN;
+      } else {
+        DBG(DBG_PARSING | DBG_CRYPT,
+        DBG_log("Oakley Transform %u accepted", trans.isat_transnum)
+        );
+
+        if (r_sa_pbs != NULL)
+        {
+          struct isakmp_proposal r_proposal = proposal;
+          pb_stream r_proposal_pbs;
+          struct isakmp_transform r_trans = trans;
+          pb_stream r_trans_pbs;
+
+          /* Situation */
+          if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
+            passert(FALSE);
+
+          /* Proposal */
+#ifdef EMIT_ISAKMP_SPI
+          r_proposal.isap_spisize = COOKIE_SIZE;
+#else
+          r_proposal.isap_spisize = 0;
+#endif
+          r_proposal.isap_notrans = 1;
+          if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
+            passert(FALSE);
+
+          /* SPI */
+#ifdef EMIT_ISAKMP_SPI
+          if (!out_raw(my_cookie, COOKIE_SIZE, &r_proposal_pbs, "SPI"))
+            passert(FALSE);
+          r_proposal.isap_spisize = COOKIE_SIZE;
+#else
+          /* none (0) */
+#endif
+
+          /* Transform */
+          r_trans.isat_np = ISAKMP_NEXT_NONE;
+          if (!out_struct(&r_trans, &isakmp_isakmp_transform_desc, 
+            &r_proposal_pbs, &r_trans_pbs))
+            passert(FALSE);
+
+          if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes"))
+            passert(FALSE);
+          if (attr_start) pfree(attr_start);
+
+          close_output_pbs(&r_trans_pbs);
+          close_output_pbs(&r_proposal_pbs);
+          close_output_pbs(r_sa_pbs);
+        }     /* if (r_sa_pbs != NULL) */
+      return NOTHING_WRONG;
+      }       /* if (! selected) */
+    }  /* end this scope */
+#endif        /* OPENSSL */
 }
 
 /* Parse the body of an IPsec SA Payload (i.e. Phase 2 / Quick Mode).
@@ -1802,9 +2690,7 @@
 
 		switch (esp_attrs.transid)
 		{
-#if 0	/* we don't feel single DES is safe */
 		    case ESP_DES:
-#endif
 		    case ESP_3DES:
 			break;
 
diff -BbruN freeswan-1.91.orig/pluto/spdb.h freeswan-1.91/pluto/spdb.h
--- freeswan-1.91.orig/pluto/spdb.h	Fri Sep 15 05:09:28 2000
+++ freeswan-1.91/pluto/spdb.h	Tue Jul  3 02:56:35 2001
@@ -24,11 +24,32 @@
     u_int16_t val;
 };
 
+#ifdef OPENSSL
+typedef bool offer_fn(struct state *st);
+/* Addition for OpenSSL: we don't want to offer cipher suites */
+/* which we aren't capable of generating, so I added a function */
+/* parameter 'offer', which takes the state as a parameter, and */
+/* returns either TRUE or FALSE, depending on whether the cipher */
+/* suite is supportable. For instance, there's no point in */
+/* offering to sign things with a DSA signature key, if all you've */
+/* got is an RSA one. */
+/* NB: If the function pointer is set to NULL, it means offer the */
+/* cipher suite under all conditions. The downside to this is that */
+/* another parameter must be added to all the IPsec cipher transforms */
+/* which is always NULL. I suppose we could embed policy information */
+/* within that parameter, e.g. If a pair of endpoints must have */
+/* a particular cipher between them. Trouble is, that information is */
+/* present within ipsec.conf, to some extent -- nd */
+#endif
+
 /* transform */
 struct db_trans {
     u_int8_t transid;	/* Transform-Id */
     struct db_attr *attrs;	/* array */
     int attr_cnt;	/* number of elements */
+#ifdef OPENSSL
+    offer_fn *offer;
+#endif
 };
 
 /* proposal */
@@ -56,9 +77,12 @@
 };
 
 /* The oakley sadb is subscripted by a bitset with members
- * from POLICY_PSK and POLICY_RSASIG.
+ * from POLICY_PSK and POLICY_RSASIG/OPENSSL.
  */
 extern struct db_sa oakley_sadb[1 << 2];
+#ifdef OPENSSL
+extern struct db_sa oakley_sadb2[1 << 2];
+#endif
 
 /* The ipsec sadb is subscripted by a bitset with members
  * from POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS
diff -BbruN freeswan-1.91.orig/pluto/state.c freeswan-1.91/pluto/state.c
--- freeswan-1.91.orig/pluto/state.c	Mon Jun  4 23:14:28 2001
+++ freeswan-1.91/pluto/state.c	Tue Jul  3 02:58:33 2001
@@ -359,6 +359,16 @@
     pfreeany(st->st_esp.our_keymat);
     pfreeany(st->st_esp.peer_keymat);
 
+#ifdef OPENSSL
+    /* Clean out the stuff for revised PK encryption mode */
+    pfreeany(st->st_ne_i.ptr);
+    memset(&st->st_ks_i, 0, sizeof(st->st_ks_i));
+    memset(st->st_ne_i_iv, 0, MAX_DIGEST_LEN);
+    pfreeany(st->st_ne_r.ptr);
+    memset(&st->st_ks_r, 0, sizeof(st->st_ks_r));
+    memset(st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
+#endif
+
     pfree(st);
 }
 
diff -BbruN freeswan-1.91.orig/pluto/state.h freeswan-1.91/pluto/state.h
--- freeswan-1.91.orig/pluto/state.h	Thu Mar  1 22:19:46 2001
+++ freeswan-1.91/pluto/state.h	Tue Jul  3 02:58:39 2001
@@ -145,6 +145,15 @@
     u_int8_t           st_rcookie[COOKIE_SIZE];/* Responder Cookie */
     chunk_t            st_nr;                  /* Nr nonce */
 
+#ifdef OPENSSL
+    /* key material for revised public key information */
+    u_int8_t           st_ne_i_iv[MAX_DIGEST_LEN];
+    chunk_t            st_ne_i;                /* key for initiator payloads */
+    keysched           st_ks_i;
+    u_int8_t           st_ne_r_iv[MAX_DIGEST_LEN];
+    chunk_t            st_ne_r;                /* key for responder payloads */
+    keysched           st_ks_r;
+#endif
 
   /* my stuff */
 
diff -BbruN freeswan-1.91.orig/pluto/version.c freeswan-1.91/pluto/version.c
--- freeswan-1.91.orig/pluto/version.c	Wed May 30 09:02:20 2001
+++ freeswan-1.91/pluto/version.c	Tue Jul  3 04:02:32 2001
@@ -1,2 +1,2 @@
 /* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
-static const char freeswan_version[] = "1.91";
+static const char freeswan_version[] = "FreeSWAN-1.91-pkix1";
diff -BbruN freeswan-1.91.orig/pluto/whack.c freeswan-1.91/pluto/whack.c
--- freeswan-1.91.orig/pluto/whack.c	Mon May 14 16:37:48 2001
+++ freeswan-1.91/pluto/whack.c	Tue Jul  3 03:00:13 2001
@@ -1,4 +1,6 @@
 /* command interface to Pluto
+ *
+ * Modified by Luc Lanthier based on work from:
  * Copyright (C) 1997 Angelos D. Keromytis.
  * Copyright (C) 1998, 1999  D. Hugh Redelmeier.
  *
@@ -82,6 +84,10 @@
 	    " [--compress]"
 	    " [--tunnel]"
 	    " [--pfs]"
+#ifdef OPENSSL
+	    " [--openssl]"
+#endif
+
 	    " \\\n   "
 	    " [--ikelifetime <seconds>]"
 	    " [--ipseclifetime <seconds>]"
@@ -90,6 +96,14 @@
 	    " [--reykeyfuzz <percentage>]"
 	    " \\\n   "
 	    " [--keyingtries <count>]"
+#ifdef OPENSSL
+	    " \\\n   "
+	    " [--certfile <file name>]"
+	    " [--certopts <[!]opt1,[!]opt2,...,[!]optN>]"
+	    " [--peerfile <file name>]"
+	    " [--keyfile <file name>]"
+	    " [--certpath <file name>]"
+#endif
 	    "\n\n"
 	"routing: whack"
 	    " (--route | --unroute)"
@@ -142,6 +156,9 @@
 	"shutdown: whack"
 	    " --shutdown"
 	    "\n\n"
+	"DES type: whack"
+	    " [--force_encrypt_cypher <des/3des>]"
+	    "\n\n"
 	"FreeS/WAN %s\n",
 	freeswan_version);
 }
@@ -203,6 +220,14 @@
     OPT_KEYID,
     OPT_PUBKEYRSA,
 
+#ifdef OPENSSL
+    OPT_CERTFILE,
+    OPT_CERTOPTS,
+    OPT_PEERFILE,
+    OPT_KEYFILE,
+    OPT_CERTPATH,
+#endif
+
     OPT_ROUTE,
     OPT_UNROUTE,
 
@@ -234,7 +259,11 @@
 
 #   define CD_POLICY_FIRST  CD_PSK
     CD_PSK,	/* same order as POLICY_* */
+#ifndef OPENSSL
     CD_RSASIG,	/* same order as POLICY_* */
+#else
+    CD_OPENSSL,	/* same order as POLICY_* */
+#endif
     CD_ENCRYPT,	/* same order as POLICY_* */
     CD_AUTHENTICATE,	/* same order as POLICY_* */
     CD_COMPRESS,	/* same order as POLICY_* */
@@ -247,6 +277,8 @@
     CD_CONNIPV4,
     CD_CONNIPV6,
 
+    CD_FORCE_ENCRYPT_CYPHER,   /* to force DES or 3DES only */
+
     CD_IKELIFETIME,
     CD_IPSECLIFETIME,
     CD_RKMARGIN,
@@ -319,7 +351,12 @@
     { "updown", required_argument, NULL, CD_UPDOWN + OO },
 
     { "psk", no_argument, NULL, CD_PSK + OO },
+#ifndef OPENSSL
     { "rsasig", no_argument, NULL, CD_RSASIG + OO },
+#else
+    { "rsasig", no_argument, NULL, CD_OPENSSL + OO },
+    { "openssl", no_argument, NULL, CD_OPENSSL + OO },
+#endif
 
     { "encrypt", no_argument, NULL, CD_ENCRYPT + OO },
     { "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO },
@@ -339,6 +376,16 @@
     { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },	/* OBSOLETE */
     { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
     { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
+/* DES Support */
+    { "force_encrypt_cypher", required_argument, NULL, CD_FORCE_ENCRYPT_CYPHER + OO },
+
+#ifdef OPENSSL
+    { "certfile", required_argument, NULL, OPT_CERTFILE + OO },
+    { "certopts", required_argument, NULL, OPT_CERTOPTS + OO },
+    { "peerfile", required_argument, NULL, OPT_PEERFILE + OO },
+    { "keyfile", required_argument, NULL, OPT_KEYFILE + OO },
+    { "certpath", required_argument, NULL, OPT_CERTPATH + OO },
+#endif
 
 #ifdef DEBUG
     { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
@@ -443,7 +490,11 @@
 	    /* client is 0.0.0.0/32: Opportunism connection */
 	    if (!isanyaddr(&this->host_addr))
 		diag("normal client network must not be 0.0.0.0/32 or 0::0/128");
+#ifndef OPENSSL
 	    if ((policy & (POLICY_PSK | POLICY_RSASIG)) != POLICY_RSASIG)
+#else
+	    if ((policy & (POLICY_PSK | POLICY_OPENSSL)) != POLICY_OPENSSL)
+#endif
 		diag("only RSASIG is supported for opportunism");
 	    if ((policy & POLICY_PFS) == 0)
 		diag("PFS required for opportunism");
@@ -492,6 +544,7 @@
     msg.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
     msg.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
     msg.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
+    msg.block_cypher = FORCE_ENCRYPT_CYPHER_DEFAULT;
 
     msg.addr_family = AF_INET;
     msg.tunnel_addr_family = AF_INET;
@@ -672,6 +725,37 @@
 	    msg.whack_async = TRUE;
 	    continue;
 
+#ifdef OPENSSL
+      case OPT_CERTFILE:
+          if (strlen(optarg) >= FILE_NAME_LIMIT)
+              diagq("certificate file name too long", optarg);
+              strcpy(msg.whack_certfile, optarg);
+        continue;
+
+      case OPT_CERTOPTS:
+          if (strlen(optarg) >= CERT_OPTIONS_LIMIT)
+              diagq("certificate file name too long", optarg);
+              strcpy(msg.whack_certopts, optarg);
+        continue;
+
+      case OPT_PEERFILE:
+          if (strlen(optarg) >= FILE_NAME_LIMIT)
+              diagq("peer certificate file name too long", optarg);
+              strcpy(msg.whack_peerfile, optarg);
+        continue;
+
+      case OPT_KEYFILE:
+          if (strlen(optarg) >= FILE_NAME_LIMIT)
+              diagq("key file name too long", optarg);
+              strcpy(msg.whack_keyfile, optarg);
+        continue;
+
+      case OPT_CERTPATH:
+          if (strlen(optarg) >= PATH_NAME_LIMIT)
+              diagq("certificate path name too long", optarg);
+              strcpy(msg.whack_certpath, optarg);
+        continue;
+#endif
 
 	/* Connection Description options */
 
@@ -750,7 +834,11 @@
 	    continue;
 
 	case CD_PSK:		/* --psk */
+#ifndef OPENSSL
 	case CD_RSASIG:	/* --rsasig */
+#else
+	case CD_OPENSSL:	/* --rsasig */
+#endif
 	case CD_ENCRYPT:	/* --encrypt */
 	case CD_AUTHENTICATE:	/* --authenticate */
 	case CD_COMPRESS:	/* --compress */
@@ -781,6 +869,20 @@
 	    msg.sa_keying_tries = opt_whole;
 	    continue;
 
+	/* DES support */
+	case CD_FORCE_ENCRYPT_CYPHER:   /* --force_encrypt_cypher <des/3des> */
+	if (strcmp("des", optarg) == 0) {
+	  msg.block_cypher = DES_BLOCK_CYPHER;
+	}
+	if (strcmp("3des", optarg) == 0) {
+	  msg.block_cypher = DES3_BLOCK_CYPHER;
+	}
+	/* else */
+	if ((strcmp("3des", optarg) != 0) && (strcmp("des", optarg) != 0)) {
+	  diag("--force_encrypt_cypher must have a parameter of either 'des' or '3des'");
+	}
+	continue;
+
 	case OPT_KEYID:	/* --keyid <identity> */
 	    msg.whack_key = TRUE;
 	    msg.keyid = optarg;	/* decoded by Pluto */
diff -BbruN freeswan-1.91.orig/pluto/whack.h freeswan-1.91/pluto/whack.h
--- freeswan-1.91.orig/pluto/whack.h	Sun Jan 28 16:03:05 2001
+++ freeswan-1.91/pluto/whack.h	Tue Jul  3 03:00:14 2001
@@ -16,6 +16,10 @@
 
 #include <freeswan.h>
 
+#ifdef OPENSSL
+#include "openssl_defs.h"
+#endif
+
 /*
  * Since the message remains on one host, native representation is used.
  * Think of this as horizontal microcode: all selected operations are
@@ -83,6 +87,14 @@
     enum pubkey_alg pubkey_alg;
     chunk_t keyval;	/* chunk */
 
+#ifdef OPENSSL
+    char whack_certfile[FILE_NAME_LIMIT];
+    char whack_certopts[CERT_OPTIONS_LIMIT];
+    char whack_peerfile[FILE_NAME_LIMIT];
+    char whack_keyfile[FILE_NAME_LIMIT];
+    char whack_certpath[PATH_NAME_LIMIT];
+#endif
+
     /* for WHACK_ROUTE: */
     bool whack_route;
 
@@ -110,6 +122,10 @@
 
     /* for WHACK_SHUTDOWN */
     bool whack_shutdown;
+
+    /* for des type to use */
+    lset_t block_cypher;
+
 
     /* space for strings (hope there is enough room):
      * Note that pointers don't travel on wire.
diff -BbruN freeswan-1.91.orig/pluto/x_sobj.c freeswan-1.91/pluto/x_sobj.c
--- freeswan-1.91.orig/pluto/x_sobj.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/x_sobj.c	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,36 @@
+#ifdef OPENSSL
+#include "x_sobj.h"
+
+IMPLEMENT_STACK_OF(X509_OBJECT)
+
+X509_OBJECT *
+X509_OBJECT_new( const int type, void *p )
+{
+  X509_OBJECT *ret = Malloc(sizeof(X509_OBJECT));
+
+  if (ret == NULL) return ret;
+  switch(type) {
+  case X509_LU_X509:
+    ret->type = type;
+    ret->data.x509 = (X509 *)p;
+    break;
+  case X509_LU_CRL:
+    ret->type = type;
+    ret->data.crl = (X509_CRL *)p;
+    break;
+  default: /* Unknown type */
+    Free((char *)ret);
+    ret = NULL;
+    break;
+  }
+  return ret;
+}
+
+void
+X509_OBJECT_free(X509_OBJECT *x)
+{
+  if (!x) return;
+  X509_OBJECT_free_contents(x);
+  Free((char *)x);
+}
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/x_sobj.h freeswan-1.91/pluto/x_sobj.h
--- freeswan-1.91.orig/pluto/x_sobj.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/x_sobj.h	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,12 @@
+#ifndef X_SOBJ_H
+#define X_SOBJ_H
+
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+DECLARE_STACK_OF(X509_OBJECT)
+
+X509_OBJECT *X509_OBJECT_new( const int type, void *ptr );
+void X509_OBJECT_free(X509_OBJECT *x);
+
+#endif
diff -BbruN freeswan-1.91.orig/pluto/xmap.c freeswan-1.91/pluto/xmap.c
--- freeswan-1.91.orig/pluto/xmap.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap.c	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,401 @@
+#ifdef OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/stack.h>
+#include <openssl/asn1.h>
+#include <openssl/safestack.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "x_sobj.h"
+#include "xmap_file.h"
+#include "xmap_dir.h"
+#include "xmap_db.h"
+#include "xmap_ldap.h"
+#include "xmap.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static XMAP_METHOD_LIST *xmth = NULL;
+
+XMAP *XMAP_new(const char *spec);
+STACK_OF(X509_OBJECT) *
+XMAP_lookup( XMAP *xm, const int type, const char *index, void *p );
+void XMAP_free(XMAP *xm);
+void XMAP_dump(XMAP *xm);
+
+int
+XMAP_register(XMAP_METHOD *meth)
+{
+  XMAP_METHOD_LIST *p;
+  int found;
+
+  for(p=xmth,found=0; ((!found) && (p)); p=p->next)
+    if (strcasecmp(meth->prefix, p->meth->prefix) == 0) found=1;
+
+  if (found) {
+    return 0;
+  } else {
+    p = malloc(sizeof(XMAP_METHOD_LIST));
+    if (p) {
+      p->next = xmth;
+      p->meth = meth;
+      xmth = p;
+    } else
+      return 0;
+  }
+  return 1;
+}
+
+void
+XMAP_METHOD_LIST_free( void )
+{
+  XMAP_METHOD_LIST *p, *q;
+
+  for(p=xmth; p;) {
+    q = p->next;
+    free(p);
+    q = p;
+  }
+}
+
+int
+XMAP_unregister(const char *prefix)
+{
+  XMAP_METHOD_LIST *p, *q;
+  int found;
+
+  for(p = xmth, found = 0; ((!found) && (p)); )
+    if (strcasecmp(p->meth->prefix, prefix) == 0)
+      found = 1;
+    else
+      p=p->next;
+
+  if (!found)
+    return 0;
+  else {
+    if ( p == xmth ) {
+      xmth = xmth->next;
+      free(p);
+    } else {
+      for(q = xmth; q->next != p; q = q->next);
+      q->next = p->next;
+      free(p);
+    }
+  }
+  return 1;
+}
+
+XMAP *
+XMAP_new(const char *spec)
+{
+  XMAP *ret;
+  char *s;
+
+  if ((ret = malloc(sizeof(XMAP))) == NULL) goto end;
+  if ((ret->spec = strdup(spec)) == NULL) goto end;
+  ret->methp = NULL;
+
+  if ((s = strchr(spec, DICT_SEPARATOR)) == NULL) {
+    log("No type prefix");
+  } else {
+    int l = (int)(s - spec) + 1;
+    XMAP_METHOD_LIST *p;
+    int found;
+
+    for(p=xmth, found = 0; ((!found) && (p));) {
+      if (strncasecmp(p->meth->prefix, spec, l-1) == 0)
+	found = 1;
+      else
+	p = p->next;
+    }
+
+    if (found) {
+      ret->pmap = p->meth->new(&s[1]);
+      if (! ret->pmap) goto end;
+      ret->methp = p;
+    } else {
+      log("Unknown map type spec: %s", spec);
+      goto end;
+    }
+  }
+  return ret;
+ end:
+  if (ret->spec) free(ret->spec);
+  if (ret) free(ret);
+  return NULL;
+}
+
+static int
+check_methp(XMAP *xm)
+{
+  XMAP_METHOD_LIST *p;
+
+  for(p = xmth; p; p = p->next)
+    if (xm->methp == p) {
+      return 1;
+    }
+
+  return 0;
+}
+
+STACK_OF(X509_OBJECT) *
+XMAP_lookup( XMAP *xm, const int type, const char *index, void *p )
+{
+  if ((!xm) || (!check_methp(xm)) || (! xm->methp->meth->lookup) )
+  {
+    return NULL;
+  }
+  return xm->methp->meth->lookup(xm->pmap, type, index, p);
+}
+
+void
+XMAP_free(XMAP *xm)
+{
+  if (!xm) return;
+  if (!xm->pmap) return;
+  if (!check_methp(xm)) return;
+  if (xm->methp->meth->free) xm->methp->meth->free(xm->pmap);
+  if (xm->spec) free(xm->spec);
+  free(xm);
+}
+
+void
+XMAP_dump(XMAP *xm)
+{
+  if (! xm->pmap) return;
+  if (!check_methp(xm)) return;
+  if (! xm->methp->meth->dump) return;
+  xm->methp->meth->dump(xm->pmap);
+}
+
+int
+X509_subjAltName_check_dns(X509 *x, const char *dns)
+{
+  int i, loc, ret;
+  X509_EXTENSION *ext;
+  u_char *p;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  GENERAL_NAME *gn;
+
+  ret = 0;
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) >= 0) {
+    if ((ext = X509_get_ext(x, loc)) != NULL) {
+      p = ext->value->data;
+      d2i_GENERAL_NAMES(&nsk, &p, ext->value->length);
+      if (nsk) {
+	for(i=0; i < sk_GENERAL_NAME_num(nsk); i++) {
+	  gn = sk_GENERAL_NAME_value(nsk, i);
+	  
+	  if (gn->type == GEN_DNS) {
+	    if (strncasecmp(dns, gn->d.ia5->data, gn->d.ia5->length) == 0) {
+	      ret = 1;
+	      break;
+	    }
+	  }
+	}
+	sk_GENERAL_NAME_free(nsk);
+	nsk = NULL;
+      }
+    }
+  }
+  return ret;
+}
+
+int
+X509_subjAltName_check_ip(X509 *x, const struct in_addr ip)
+{
+  int i, loc, ret;
+  X509_EXTENSION *ext;
+  u_char *p;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  GENERAL_NAME *gn;
+
+  ret = 0;
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) >= 0) {
+	if ((ext = X509_get_ext(x, loc)) != NULL) {
+		p = ext->value->data;
+		d2i_GENERAL_NAMES(&nsk, &p, ext->value->length);
+		if (nsk) {
+			for(i=0; i < sk_GENERAL_NAME_num(nsk); i++) {
+				gn = sk_GENERAL_NAME_value(nsk, i);
+	  
+				if (gn->type == GEN_IPADD) {
+					if (memcmp(&ip.s_addr, gn->d.ip->data, gn->d.ip->length) == 0) {
+						ret = 1;
+						break;
+					}
+				}
+			}
+			sk_GENERAL_NAME_free(nsk);
+			nsk = NULL;
+		}
+ 	 }
+  }
+  return ret;
+}
+
+
+/* some cloning procedures. needed to unshare connection
+ * for road warrior support.
+ */
+
+STACK_OF(XMAP) 
+*clone_sk_XMAP ( STACK_OF(XMAP) *sk_xm )
+{
+	/* declare new stack */
+	STACK_OF(XMAP) *temp_sk_xm;
+	int i;
+
+	/* clone contents of stack. Memory pointers stay the same
+	 * so further cloning for each sub-structure is needed.
+	 *
+	 * typedef struct stack_st
+	 * {
+	 *  int num;
+	 *  char **data;
+	 *  int sorted;
+	 *  int num_alloc;
+	 *  int (*comp)();
+	 * } STACK;
+	 */
+
+	temp_sk_xm = sk_XMAP_new_null();
+	for (i=0; i<sk_XMAP_num(sk_xm); i++) {
+	  XMAP *xm = sk_XMAP_value(sk_xm, i);
+
+	  /* clone XMAP */
+	  xm = clone_XMAP(xm);
+
+	  sk_XMAP_push(temp_sk_xm, xm);
+	}
+
+	/* return the newly cloned STACK_OF(XMAP) */
+	return temp_sk_xm;     
+}
+
+XMAP 
+*clone_XMAP ( XMAP *xm )
+{
+	XMAP *temp_xm;
+	/* cloning of XMAP....... 
+	 * typedef struct _xmap_st {
+	 *   char *spec;
+	 *   void *pmap;
+	 *   XMAP_METHOD_LIST *methp;
+	 * } XMAP;
+	 */
+
+	temp_xm = malloc(sizeof(XMAP));
+
+	temp_xm->spec = clone_str(xm->spec, "cloning XMAP spec");
+	temp_xm->pmap = clone_XMAP_pmap(xm->pmap, xm->spec);
+
+	/* let's try without cloning the XMAP_METHOD_LIST, so that
+	 * check_methp will work.
+	 * temp_xm->methp = clone_XMAP_METHOD_LIST(xm->methp);
+	 */ 
+	temp_xm->methp = xm->methp;
+
+	return temp_xm;
+}
+
+XMAP_METHOD_LIST 
+*clone_XMAP_METHOD_LIST ( XMAP_METHOD_LIST *xm_l )
+{
+	XMAP_METHOD_LIST *temp_xm_l;
+
+	/*
+	 * typedef struct _xmap_method_list_st {
+	 *   XMAP_METHOD *meth;
+	 *   struct _xmap_method_list_st *next;
+	 * } XMAP_METHOD_LIST;
+	 *
+	 * Recursive cloning...
+	 */
+
+	temp_xm_l = malloc(sizeof(XMAP_METHOD_LIST));
+	if (xm_l->next) {
+		temp_xm_l->next = clone_XMAP_METHOD_LIST(xm_l->next);
+	} else {
+		temp_xm_l->next = NULL;
+	}
+
+	temp_xm_l->meth = clone_XMAP_METHOD(xm_l->meth);
+	return temp_xm_l;
+}
+
+
+XMAP_METHOD
+*clone_XMAP_METHOD ( XMAP_METHOD *xm_m )
+{
+	XMAP_METHOD *temp_xm_m;
+
+	/*
+	 * typedef struct _xmap_method_st {
+	 *   char *prefix;
+	 *     STACK_OF(X509_OBJECT) *(*lookup)( void *this, 
+	 *        const int type, const char *index, void *p );
+	 *   void (*dump)(void *pmap);
+	 *   void (*free)(void *pmap);
+	 *   void *(*new) (const char *spec);
+	 * } XMAP_METHOD;
+	 */
+
+
+	temp_xm_m = malloc(sizeof(XMAP_METHOD));
+
+	if (xm_m->prefix) {
+		temp_xm_m->prefix = clone_str(xm_m->prefix, 
+			"cloning XMAP_METHOD prefix");
+	}
+
+	/* don't clone the following */
+	temp_xm_m->lookup = xm_m->lookup;
+	temp_xm_m->dump = xm_m->dump;
+	temp_xm_m->free = xm_m->free;
+	temp_xm_m->new = xm_m->new;
+
+	return temp_xm_m;
+}
+
+void
+*clone_XMAP_pmap ( void *pmap, char *spec )
+{
+	void *t_pmap;
+	char *s;
+	int l, found;
+	XMAP_METHOD_LIST *p;
+
+	s = strchr(spec, DICT_SEPARATOR);
+	l = (int)(s - spec) + 1;
+
+	for(p=xmth, found = 0; ((!found) && (p));) {
+	  if (strncasecmp(p->meth->prefix, spec, l-1) == 0) {
+	    found = 1;
+	   } else {
+	    p = p->next;
+           }
+	}
+
+	if (found) {
+	  t_pmap = p->meth->new(&s[1]);
+	}
+
+	return t_pmap;
+}
+
+
+IMPLEMENT_STACK_OF(XMAP)
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/xmap.h freeswan-1.91/pluto/xmap.h
--- freeswan-1.91.orig/pluto/xmap.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap.h	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,62 @@
+#ifndef XMAP_H
+#define XMAP_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#include "x_sobj.h"
+
+typedef struct _xmap_method_st {
+  char *prefix;
+    STACK_OF(X509_OBJECT) *(*lookup)( void *this, const int type, const char *index, void *p );
+  void (*dump)(void *pmap);
+  void (*free)(void *pmap);
+  void *(*new) (const char *spec);
+} XMAP_METHOD;
+
+typedef struct _xmap_method_list_st {
+  XMAP_METHOD *meth;
+  struct _xmap_method_list_st *next;
+} XMAP_METHOD_LIST;
+
+typedef struct _xmap_st {
+  char *spec;
+  void *pmap;
+  XMAP_METHOD_LIST *methp;
+} XMAP;
+
+DECLARE_STACK_OF(XMAP)
+
+#ifndef DICT_SEPARATOR
+#define DICT_SEPARATOR ':'
+#endif
+
+#define XMAP_UNKNOWN_TYPE 0
+#define XMAP_FILE_TYPE    1
+#define XMAP_DIR_TYPE     2
+#define XMAP_DB_TYPE      3
+
+int XMAP_register(XMAP_METHOD *meth);
+void XMAP_METHOD_LIST_free( void );
+int XMAP_unregister(const char *prefix);
+
+int X509_subjAltName_check_dns(X509 *x, const char *dns);
+int X509_subjAltName_check_ip(X509 *x, const struct in_addr in);
+
+XMAP *XMAP_new(const char *spec);
+STACK_OF(X509_OBJECT) *XMAP_lookup( XMAP *xm, const int type, const char *index, void *p );
+void XMAP_free(XMAP *xm);
+void XMAP_dump(XMAP *xm);
+
+extern STACK_OF(XMAP) *clone_sk_XMAP ( STACK_OF(XMAP) *sk_xm );
+extern XMAP *clone_XMAP ( XMAP *xm );
+extern void *clone_XMAP_pmap ( void *pmap, char *spec );
+extern XMAP_METHOD_LIST *clone_XMAP_METHOD_LIST ( XMAP_METHOD_LIST *xm_l );
+extern XMAP_METHOD *clone_XMAP_METHOD ( XMAP_METHOD *xm_m );
+
+#endif /* XMAP_H */
diff -BbruN freeswan-1.91.orig/pluto/xmap_db.c freeswan-1.91/pluto/xmap_db.c
--- freeswan-1.91.orig/pluto/xmap_db.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_db.c	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,574 @@
+#ifdef OPENSSL
+#if defined(HAVE_DB) || (HAVE_DB185)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+
+#include "xmap_db.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static void XMAP_DB_dump(void *this);
+static void XMAP_DB_free(void *this);
+static void *XMAP_DB_new(const char *dbname);
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_subject( XMAP_DB *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_issuer( XMAP_DB *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_crl_by_issuer( XMAP_DB *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_uid( XMAP_DB *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_dns( XMAP_DB *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_ip( XMAP_DB *xm, const struct in_addr ip);
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_ca_certs( XMAP_DB *xm );
+
+#define TAGLEN 4
+
+static unsigned char tag_cert[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char tag_subj[] = { 0x00, 0x00, 0x00, 0x01 };
+static unsigned char tag_csub[] = { 0x00, 0x00, 0x00, 0x02 };
+static unsigned char tag_uid[] = { 0x00, 0x00, 0x00, 0x03 };
+static unsigned char tag_crl[] = { 0x00, 0x00, 0x00, 0x04 };
+static unsigned char tag_ca[] = { 0x00, 0x00, 0x00, 0x05 };
+static unsigned char tag_dns[] = { 0x00, 0x00, 0x00, 0x06 };
+static unsigned char tag_ip[] = { 0x00, 0x00, 0x00, 0x07 };
+
+#define DBZ(x) memset(&(x), 0, sizeof((x)))
+
+static XMAP_METHOD xmap_db_methods = {
+  "db",
+  XMAP_DB_lookup,
+  XMAP_DB_dump,
+  XMAP_DB_free,
+  XMAP_DB_new
+};
+
+void *
+XMAP_DB_new(const char *dbname)
+{
+  XMAP_DB *ret;
+
+  if ((ret = alloc_thing(XMAP_DB, "xmap_db")) == NULL) goto end;
+  if ((ret->dbname = clone_bytes(dbname, strlen(dbname)+1, "dbname")) == NULL)
+    goto end;
+  if ((ret->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
+    goto end;
+
+  ret->meth = &xmap_db_methods;
+
+  return (void *)ret;
+ end:
+  if (ret->db) ret->db->close(ret->db);
+  if (ret->dbname) pfree(ret->dbname);
+  if (ret) pfree(ret);
+  return NULL;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_DB *xm = (XMAP_DB *)this;
+
+  switch(type) {
+  case X509_LU_X509:
+    if (strcasecmp(index, "subject") == 0)
+      return XMAP_DB_lookup_cert_by_subject( xm, (X509_NAME *)p);
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DB_lookup_cert_by_issuer( xm, (X509_NAME *)p);
+    else if (strcasecmp(index, "uid") == 0)
+      return XMAP_DB_lookup_cert_by_uid( xm, (char  *)p);
+    else if (strcasecmp(index, "dns") == 0)
+      return XMAP_DB_lookup_cert_by_dns( xm, (char  *)p);
+    else if (strcasecmp(index, "ip") == 0)
+      return XMAP_DB_lookup_cert_by_ip( xm, *((struct in_addr *)p));
+    else if (strcasecmp(index, "ca") == 0)
+      return XMAP_DB_lookup_ca_certs( xm );
+    else
+      return NULL;
+    break;
+  case X509_LU_CRL:
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DB_lookup_crl_by_issuer( xm, (X509_NAME *)p);
+    else
+      return NULL;
+    break;
+  default:
+    return NULL;
+  }
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_subject(XMAP_DB *xm, X509_NAME *name)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  dlen = i2d_X509_NAME(name, NULL);
+  if ((d = alloc_bytes(dlen + TAGLEN, "ASN.1 name")) == NULL) goto end;
+  dum = &d[TAGLEN];
+  memcpy(d, tag_subj, TAGLEN);
+  i2d_X509_NAME(name, &dum);
+  k.data = d;
+  k.size = dlen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[i*SHA_DIGEST_LENGTH+TAGLEN], SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	  if (x)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_issuer(XMAP_DB *xm, X509_NAME *name)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  dlen = i2d_X509_NAME(name, NULL);
+  if ((d = alloc_bytes(dlen + TAGLEN, "ASN.1 name")) == NULL) goto end;
+  dum = &d[TAGLEN];
+  memcpy(d, tag_subj, TAGLEN);
+  i2d_X509_NAME(name, &dum);
+  k.data = d;
+  k.size = dlen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[i*SHA_DIGEST_LENGTH+TAGLEN], SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	  if (x)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_crl_by_issuer(XMAP_DB *xm, X509_NAME *name)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  dlen = i2d_X509_NAME(name, NULL);
+  if ((d = alloc_bytes(dlen + TAGLEN, "ASN.1 name")) == NULL) goto end;
+  dum = &d[TAGLEN];
+  memcpy(d, tag_csub, TAGLEN);
+  i2d_X509_NAME(name, &dum);
+  k.data = d;
+  k.size = dlen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_crl, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[i*SHA_DIGEST_LENGTH+TAGLEN], SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509_CRL *c;
+	dum = (unsigned char *)v2.data;
+	if ((c = d2i_X509_CRL(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, c);
+
+	  if (xo)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_CRL_free(c);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_ca_certs( XMAP_DB *xm )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  if ((d = alloc_bytes(TAGLEN, "CA tag")) == NULL) goto end;
+  memcpy(d, tag_ca, TAGLEN);
+  k.data = d;
+  k.size = TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if (((x = d2i_X509(NULL, &dum, v2.size)) != NULL) && (isCA(x))) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+
+	  if (xo) 
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_uid(XMAP_DB *xm, const char *uid)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, ulen, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  ulen = strlen(uid);
+  if ((d = alloc_bytes(ulen + TAGLEN, "uid tag")) == NULL) goto end;
+  memcpy(d, tag_uid, TAGLEN);
+  strncpy(&d[TAGLEN], uid, ulen);
+  k.data = d;
+  k.size = ulen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+
+	  if (xo) 
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_dns(XMAP_DB *xm, const char *dns)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, ulen, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  ulen = strlen(dns);
+  if ((d = alloc_bytes(ulen + TAGLEN, "dns tag")) == NULL) goto end;
+  memcpy(d, tag_dns, TAGLEN);
+  strncpy(&d[TAGLEN], dns, ulen);
+  k.data = d;
+  k.size = ulen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  if (X509_subjAltName_check_dns(x, dns)) {
+	    X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	    
+	    if (xo) 
+	      sk_X509_OBJECT_push(sk, xo);
+	    else
+	      X509_free(x);
+	  } else 
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) free(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_ip(XMAP_DB *xm, const struct in_addr ip)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, ulen, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  ulen = sizeof(ip.s_addr);
+  if ((d = alloc_bytes(ulen + TAGLEN, "ip tag")) == NULL) goto end;
+  memcpy(d, tag_ip, TAGLEN);
+  memcpy(&d[TAGLEN], &ip.s_addr, ulen);
+  k.data = d;
+  k.size = ulen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+
+        DBG(DBG_PARSING | DBG_RAW,
+        DBG_log("** v2 length: %d", v2.size);
+        );
+        DBG(DBG_RAW,
+        DBG_dump("** v2: ", v2.data, v2.size);
+        );
+
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  if (X509_subjAltName_check_ip(x, ip)) {
+	    X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	    
+	    if (xo) 
+	      sk_X509_OBJECT_push(sk, xo);
+	    else
+	      X509_free(x);
+	  }
+	} else
+	  X509_free(x);
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static void
+XMAP_DB_dump(void *this)
+{
+  XMAP_DB *xm = (XMAP_DB *)this;
+  DBG(DBG_PARSING,
+  DBG_log("XMAP_DB: %s", xm->dbname);
+  );
+}
+
+static void
+XMAP_DB_free(void *this)
+{
+  XMAP_DB *xm = (XMAP_DB *)this;
+
+  if (!xm) return;
+  if (xm->dbname) pfree(xm->dbname);
+  if (xm->db) xm->db->close(xm->db);
+  pfree(xm);
+}
+
+XMAP_METHOD *
+XMAP_METHOD_db( void )
+{
+  return (&xmap_db_methods);
+}
+#endif /* HAVE_DB */
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/xmap_db.h freeswan-1.91/pluto/xmap_db.h
--- freeswan-1.91.orig/pluto/xmap_db.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_db.h	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,27 @@
+#ifndef XMAP_DB_H
+#define XMAP_DB_H
+
+#if defined(HAVE_DB) || defined(HAVE_DB185)
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+
+#ifdef HAVE_DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct xmap_db_st {
+  char *dbname;
+  DB *db;
+  XMAP_METHOD *meth;
+} XMAP_DB;
+
+XMAP_METHOD *XMAP_METHOD_db( void );
+
+#endif /* HAVE_DB */
+#endif /* XMAP_DB_H */
diff -BbruN freeswan-1.91.orig/pluto/xmap_dir.c freeswan-1.91/pluto/xmap_dir.c
--- freeswan-1.91.orig/pluto/xmap_dir.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_dir.c	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,545 @@
+#ifdef OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "xmap_dir.h"
+#include "xmap.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static void XMAP_DIR_dump(void *this);
+static void XMAP_DIR_free(void *this);
+static void *XMAP_DIR_new(const char *dir);
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_subject( XMAP_DIR *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_issuer( XMAP_DIR *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_crl_by_issuer( XMAP_DIR *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_uid( XMAP_DIR *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_dns( XMAP_DIR *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_ip( XMAP_DIR *xm, const struct in_addr ip );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_ca_certs( XMAP_DIR *xm );
+
+static XMAP_METHOD xmap_dir_methods = {
+  "dir",
+  XMAP_DIR_lookup,
+  XMAP_DIR_dump,
+  XMAP_DIR_free,
+  XMAP_DIR_new
+};
+
+static void *
+XMAP_DIR_new(const char *dir)
+{
+  XMAP_DIR *ret;
+
+  if ((ret = alloc_thing(XMAP_DIR, "xmap_dir")) == NULL) goto end;
+  if ((ret->dir = clone_bytes(dir, strlen(dir)+1, "directory name")) == NULL)
+    goto end;
+  ret->meth = &xmap_dir_methods;
+
+  return (void *)ret;
+ end:
+  if (ret->dir) pfree(ret->dir);
+  if (ret) pfree(ret);
+  return NULL;
+}
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_DIR *xm = (XMAP_DIR *)this;
+
+  switch(type) {
+  case X509_LU_X509:
+    if (strcasecmp(index, "subject") == 0)
+      return XMAP_DIR_lookup_cert_by_subject( xm, (X509_NAME *)p);
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DIR_lookup_cert_by_issuer( xm, (X509_NAME *)p);
+    else if (strcasecmp(index, "uid") == 0)
+      return XMAP_DIR_lookup_cert_by_uid( xm, (char  *)p);
+    else if (strcasecmp(index, "dns") == 0)
+      return XMAP_DIR_lookup_cert_by_dns( xm, (char  *)p);
+    else if (strcasecmp(index, "ip") == 0)
+      return XMAP_DIR_lookup_cert_by_ip( xm, *(struct in_addr *)p);
+    else if (strcasecmp(index, "ca") == 0)
+      return XMAP_DIR_lookup_ca_certs( xm );
+    else
+      return NULL;
+    break;
+  case X509_LU_CRL:
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DIR_lookup_crl_by_issuer( xm, (X509_NAME *)p);
+    else
+      return NULL;
+    break;
+  default:
+    return NULL;
+  }
+}
+
+static char hashval[PATH_MAX+1] = "";
+static char dirname[PATH_MAX+1] = "";
+
+static int
+hash_select(const struct dirent *de)
+{
+  int l = strlen(hashval);
+
+  if (strncmp(de->d_name, hashval, l) == 0) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+static int
+select_files(const struct dirent *de)
+{
+  struct stat st;
+  char path[PATH_MAX+1];
+  
+  snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
+  if (lstat(path, &st) == 0) {
+    if (S_ISREG(st.st_mode))
+      return 1;
+    else
+      return 0;
+  } else {
+    log("error in stat: %s", strerror(errno));
+    return 0;
+  }     
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_subject( XMAP_DIR *xm, X509_NAME *name )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "%08lx.cert", X509_NAME_hash(name));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error on scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_NAME_cmp(X509_get_subject_name(x), name) == 0) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+
+	    if (x) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else
+	      X509_free(x);
+	  } else
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_issuer( XMAP_DIR *xm, X509_NAME *name )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "%08lx.cert", X509_NAME_hash(name));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error on scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_NAME_cmp(X509_get_issuer_name(x), name) == 0) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+
+	    if (x) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else
+	      X509_free(x);
+	  } else
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_ca_certs( XMAP_DIR *xm )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  strncpy(dirname, xm->dir, sizeof(dirname)-1);
+  n = scandir(xm->dir, &flist, select_files, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (isCA(x)) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+
+	    if (xo) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else
+	      X509_free(x);
+	  } else
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_crl_by_issuer( XMAP_DIR *xm, X509_NAME *name )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "%08lx.crl", X509_NAME_hash(name));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509_CRL *c;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((c = PEM_read_bio_X509_CRL(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  c = d2i_X509_CRL_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (c) {
+	  if (X509_NAME_cmp(X509_CRL_get_issuer(c), name) == 0) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, c);
+	    if (xo)
+	      sk_X509_OBJECT_push(sk, xo);
+	    else
+	      X509_CRL_free(c);
+	  } else
+	    X509_CRL_free(c);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_uid( XMAP_DIR *xm, const char *uid )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "uid-%s", uid);
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	  if (xo)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else 
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_dns( XMAP_DIR *xm, const char *dns )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "dns-%s", dns);
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_subjAltName_check_dns(x, dns)) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	    if (xo)
+	      sk_X509_OBJECT_push(sk, xo);
+	    else 
+	      X509_free(x);
+	  }
+	} else {
+	  X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_ip( XMAP_DIR *xm, const struct in_addr ip )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  
+  snprintf(hashval, sizeof(hashval)-1, "ip-%s", inet_ntoa(ip));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_subjAltName_check_ip(x, ip)) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	    if (xo)
+	      sk_X509_OBJECT_push(sk, xo);
+	    else 
+	      X509_free(x);
+	  }
+	} else {
+	  X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static void
+XMAP_DIR_dump(void *this)
+{
+  XMAP_DIR *xm = (XMAP_DIR *)this;
+  DBG_log("XMAP_DIR: %s", xm->dir);
+}
+
+static void
+XMAP_DIR_free(void *this)
+{
+  XMAP_DIR *xm = (XMAP_DIR *)this;
+
+  if (!xm) return;
+  if (xm->dir) pfree(xm->dir);
+  free(xm);
+}
+
+XMAP_METHOD *
+XMAP_METHOD_dir( void )
+{
+  return (&xmap_dir_methods);
+}
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/xmap_dir.h freeswan-1.91/pluto/xmap_dir.h
--- freeswan-1.91.orig/pluto/xmap_dir.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_dir.h	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,17 @@
+#ifndef XMAP_DIR_H
+#define XMAP_DIR_H
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct xmap_dir_st {
+  char *dir;
+  XMAP_METHOD *meth;
+} XMAP_DIR;
+
+XMAP_METHOD *XMAP_METHOD_dir( void );
+
+#endif /* XMAP_DIR_H */
diff -BbruN freeswan-1.91.orig/pluto/xmap_file.c freeswan-1.91/pluto/xmap_file.c
--- freeswan-1.91.orig/pluto/xmap_file.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_file.c	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,359 @@
+#ifdef OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <regex.h>
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+
+#include "xmap.h"
+#include "xmap_file.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static void XMAP_FILE_dump(void *this);
+static void XMAP_FILE_free(void *this);
+static void *XMAP_FILE_new(const char *file);
+static int isCA( X509 *x );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_subject( XMAP_FILE *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_issuer( XMAP_FILE *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_crl_by_issuer( XMAP_FILE *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_uid( XMAP_FILE *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_dns( XMAP_FILE *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_ip( XMAP_FILE *xm, const struct in_addr ip );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_ca_certs( XMAP_FILE *xm );
+
+static XMAP_METHOD xmap_file_methods = {
+  "file",
+  XMAP_FILE_lookup,
+  XMAP_FILE_dump,
+  XMAP_FILE_free,
+  XMAP_FILE_new
+};
+
+/* Pattern is (ignoring lower/upper case --
+ * <whitespace>uid:<whitespace><alphanumeric user id><whitespace>
+ */
+#define UID_REGEX \
+"^[[:space:]]*[Uu][Ii][Dd]:[[:space:]]*([[:alnum:]]+)[[:space:]]$"
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+XMAP_METHOD *
+XMAP_METHOD_file( void )
+{
+  return (&xmap_file_methods);
+}
+
+static void *
+XMAP_FILE_new(const char *file)
+{
+  XMAP_FILE *ret;
+  int re_code;
+  char errbuf[257];
+
+  if ((ret = alloc_thing(XMAP_FILE, "xmap_file")) == NULL) goto end;
+  if ((ret->file = clone_bytes(file, strlen(file)+1, "file name")) == NULL)
+    goto end;
+  if ((ret->bio = BIO_new_file(ret->file, "r")) == NULL) goto end;
+
+  if ((re_code = regcomp(&ret->uidreg, UID_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &ret->uidreg, errbuf, sizeof(errbuf-1));
+    log("Regex Error: %s", errbuf);
+    goto end;
+  }
+
+  ret->meth = &xmap_file_methods;
+  return (void *)ret;
+ end:
+  if (ret->bio) BIO_free(ret->bio);
+  if (ret->file) pfree(ret->file);
+  if (ret) pfree(ret);
+  return NULL;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_FILE *xm = (XMAP_FILE *)this;
+
+  switch(type) {
+  case X509_LU_X509:
+    if (strcasecmp(index, "issuer") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_issuer( xm, (X509_NAME *)p);
+	}
+    if (strcasecmp(index, "subject") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_subject( xm, (X509_NAME *)p);
+	}
+    else if (strcasecmp(index, "uid") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_uid( xm, (char  *)p);
+	}
+    else if (strcasecmp(index, "dns") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_dns( xm, (char  *)p);
+	}
+    else if (strcasecmp(index, "ip") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_ip( xm, *((struct in_addr *)p));
+	}
+    else if (strcasecmp(index, "ca") == 0)
+	{
+		return XMAP_FILE_lookup_ca_certs( xm );
+	}
+    else
+	{
+		return NULL;
+	}
+    break;
+  case X509_LU_CRL:
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_FILE_lookup_crl_by_issuer( xm, (X509_NAME *)p);
+    else
+      return NULL;
+    break;
+  default:
+    return NULL;
+  }
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_subject( XMAP_FILE *xm, X509_NAME *name )
+{
+  X509 *x;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (X509_NAME_cmp(X509_get_subject_name(x), name) == 0) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_free(x);
+    } else
+      X509_free(x);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_issuer( XMAP_FILE *xm, X509_NAME *name )
+{
+  X509 *x;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (X509_NAME_cmp(X509_get_issuer_name(x), name) == 0) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_free(x);
+    } else
+      X509_free(x);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_ca_certs( XMAP_FILE *xm  )
+{
+  X509 *x;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (isCA(x)) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_free(x);
+    } else
+      X509_free(x);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_crl_by_issuer( XMAP_FILE *xm, X509_NAME *name )
+{
+  X509_CRL *c;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((c = PEM_read_bio_X509_CRL(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (X509_NAME_cmp(X509_CRL_get_issuer(c), name) == 0) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, c);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_CRL_free(c);
+    } else
+      X509_CRL_free(c);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_uid( XMAP_FILE *xm, const char *uid )
+{
+  char line[BUFSIZ+1], user[BUFSIZ+1];
+  regmatch_t pmatch[2];
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  X509 *x;
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while (BIO_gets(xm->bio, line, sizeof(line)-1)) {
+    if (!regexec(&xm->uidreg, line, 2, pmatch, 0))
+      if ((pmatch[1].rm_so != -1) && (pmatch[1].rm_eo != -1)) {
+	memset(user, 0, sizeof(user));
+	strncpy(user, &line[pmatch[1].rm_so],
+		pmatch[1].rm_eo - pmatch[1].rm_so);
+	if (strcmp(uid, user) == 0) {
+	  /* Found a match for the user id */
+	  if ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+	    X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	    if (xo) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else 
+	      X509_free(x);
+	  }
+	}
+      }
+  }
+
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_dns( XMAP_FILE *xm, const char *dns )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  X509 *x;
+  int zap;
+  X509_OBJECT *xo;
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    zap = X509_subjAltName_check_dns(x, dns) ? 0 : 1;
+    
+    if (zap)
+      X509_free(x);
+    else {
+      xo = X509_OBJECT_new( X509_LU_X509, x);
+      if (xo)
+	sk_X509_OBJECT_push(sk, xo);
+      else 
+	X509_free(x);
+    }
+  }
+
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_ip( XMAP_FILE *xm, struct in_addr ip )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  X509 *x;
+  int zap;
+  X509_OBJECT *xo;
+
+  if (sk == NULL) {
+    DBG(DBG_PARSING,
+    DBG_log("sk is NULL, returning NULL.");
+    );
+	return sk;
+  }
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    zap = X509_subjAltName_check_ip(x, ip) ? 0 : 1;
+
+    if (zap)
+      X509_free(x);
+    else {
+      xo = X509_OBJECT_new( X509_LU_X509, x);
+      if (xo)
+		sk_X509_OBJECT_push(sk, xo);
+      else 
+		X509_free(x);
+    }
+  }
+
+  return sk;
+}
+
+static void
+XMAP_FILE_dump(void *this)
+{
+  XMAP_FILE *xm = (XMAP_FILE *)this;
+  DBG(DBG_CONTROL | DBG_PARSING,
+  DBG_log("XMAP_FILE: %s\n", xm->file);
+  );
+}
+
+static void
+XMAP_FILE_free(void *this)
+{
+  XMAP_FILE *xm = (XMAP_FILE *)this;
+
+  if (!xm) return;
+  regfree(&xm->uidreg);
+  if (xm->bio) BIO_free(xm->bio);
+  if (xm->file) pfree(xm->file);
+  pfree(xm);
+}
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/xmap_file.h freeswan-1.91/pluto/xmap_file.h
--- freeswan-1.91.orig/pluto/xmap_file.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_file.h	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,28 @@
+#ifndef XMAP_FILE_H
+#define XMAP_FILE_H
+
+#include <regex.h>
+
+#include <openssl/safestack.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct xmap_file_st {
+  char *file;
+  BIO *bio;
+  regex_t uidreg;
+  regex_t ipreg;
+  XMAP_METHOD *meth;
+} XMAP_FILE;
+
+XMAP_METHOD *XMAP_METHOD_file( void );
+#endif /* XMAP_FILE_H */
+
+
+
+
+
diff -BbruN freeswan-1.91.orig/pluto/xmap_ldap.c freeswan-1.91/pluto/xmap_ldap.c
--- freeswan-1.91.orig/pluto/xmap_ldap.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_ldap.c	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,1369 @@
+#ifdef OPENSSL
+#ifdef HAVE_LDAP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <regex.h>
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+#include "xmap_ldap.h"
+
+#include <openssl/x509v3.h>
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "whack.h"
+
+static void XMAP_LDAP_dump(void *this);
+static void XMAP_LDAP_free(void *this);
+static void *XMAP_LDAP_new(const char *ldap);
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_subject( XMAP_LDAP *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_issuer( XMAP_LDAP *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_crl_by_issuer( XMAP_LDAP *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_uid( XMAP_LDAP *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_dns( XMAP_LDAP *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_ip( XMAP_LDAP *xm, const struct in_addr ip );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_ca_certs( XMAP_LDAP *xm );
+static char **make_attrs( const char *a );
+static void attrs_free( char **attrs );
+
+char *find_filter( const char *index, const int type, flist *fl );
+char **find_attrs( const char *index, const int type, alist *al );
+
+static XMAP_METHOD xmap_ldap_methods = {
+  "ldap",
+  XMAP_LDAP_lookup,
+  XMAP_LDAP_dump,
+  XMAP_LDAP_free,
+  XMAP_LDAP_new
+};
+
+#define HOST_REGEX "^([[:alnum:]]+)_host_name[[:space:]]*=[[:space:]]*([[:punct:][:alnum:]]+)"
+#define PORT_REGEX "^([[:alnum:]]+)_port[[:space:]]*=[[:space:]]*([[:digit:]]+)"
+#define BASE_REGEX "^([[:alnum:]]+)_base[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define TIMEOUT_REGEX "^([[:alnum:]]+)_timeout[[:space:]]*=[[:space:]]*([[:digit:]]+)"
+#define BINDDN_REGEX "^([[:alnum:]]+)_bind_dn[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define BINDPW_REGEX "^([[:alnum:]]+)_password[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define FILTER_REGEX "^([[:alnum:]]+)_filter(:(([\\*[:alnum:]]+)(:([[:alnum:]]+))?))?[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define ATTRS_REGEX "^([[:alnum:]]+)_attributes(:(([\\*[:alnum:]]+)(:([[:alnum:]]+))?))?[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+
+static void
+insert_filter( const char *index, const int type, const char *filter, flist *fl )
+{
+  int i;
+  char *f, *in;
+
+  for(i=0; ((i < MAXFLIST) && (fl[i].index)) ;i++)
+    if ((strcasecmp(index, fl[i].index) == 0) && (fl[i].type == type)) break;
+
+  if (i == MAXFLIST) return; /* No more room */
+  if (fl[i].index) {
+    /* A replacement operation */
+    if ((f = clone_bytes(filter, strlen(filter)+1, "filter")) == NULL) return;
+    pfree(fl[i].filter);
+    fl[i].filter = f;
+  } else {
+    if ((in = clone_bytes(index, strlen(index)+1, "index string")) == NULL)
+      return;
+    if ((f = clone_bytes(filter, strlen(filter)+1, "filter string")) == NULL)
+      { pfree(in); return; }
+    fl[i].index = in;
+    fl[i].type = type;
+    fl[i].filter = f;
+
+    DBG(DBG_PARSING,
+    DBG_log("Insert filter: %d (%s,%d,%s)", i+1, in, type, f);
+    );
+  }
+}
+
+static void
+insert_attrs( const char *index, const int type, const char *attr, alist *al )
+{
+  int i, j;
+  char **af, *in;
+
+  for(i=0; ((i < MAXFLIST) && (al[i].index)) ;i++) {
+    if ((strcasecmp(index, al[i].index) == 0) && (al[i].type == type)) {
+      break;
+    }
+  }
+
+  if (i == MAXFLIST) return; /* No more room */
+  if (al[i].index) {
+    /* A replacement operation */
+    if ((af = make_attrs(attr)) == NULL) return;
+    attrs_free(al[i].attrs);
+    al[i].attrs = af;
+  } else {
+    if ((in = clone_bytes(index, strlen(index)+1, "index string")) == NULL)
+      return;
+    if ((af = make_attrs(attr)) == NULL) { pfree(in); return; }
+    al[i].index = in;
+    al[i].type = type;
+    al[i].attrs = af;
+    DBG(DBG_PARSING,
+    DBG_log("Insert attribute: %d (%s,%d)", i+1, in, type);
+    );
+    for(j=0; af[j]; j++)
+      DBG(DBG_PARSING,
+      DBG_log("Attribute %d: %s", j+1, af[j]);
+      );
+  }
+}
+
+char *
+find_filter( const char *index, const int type, flist *fl )
+{
+  int i, OKind;
+  unsigned char OK, indOK, typeOK;
+
+  OK = 0x00;
+  for(i=0, OKind=0; ((i < MAXFLIST) && (fl[i].index)); i++) {
+    typeOK = (fl[i].type == X509_LU_FAIL) ? 0x01 :
+      ((fl[i].type == type) ? 0x04 : 0);
+    indOK = (strcasecmp(fl[i].index, "*") == 0) ? 0x02 :
+      ((strcasecmp(fl[i].index, index) == 0) ? 0x08 : 0);
+    if ((typeOK | indOK) > OK) { OKind = i; OK = typeOK | indOK; }
+  }
+
+  return fl[OKind].filter;
+}
+
+char **
+find_attrs( const char *index, const int type, alist *al )
+{
+  int i, OKind;
+  unsigned char OK, indOK, typeOK;
+
+  OK = 0x00;
+  for(i=0, OKind=0; ((i < MAXFLIST) && (al[i].index)); i++) {
+    typeOK = (al[i].type == X509_LU_FAIL) ? 0x01 :
+      ((al[i].type == type) ? 0x04 : 0);
+    indOK = (strcasecmp(al[i].index, "*") == 0) ? 0x02 :
+      ((strcasecmp(al[i].index, index) == 0) ? 0x08 : 0);
+    if ((typeOK | indOK) > OK) { OKind = i; OK = typeOK | indOK; }
+  }
+
+  return al[OKind].attrs;
+}
+
+static void
+extract_re_sub( const char *buf, regmatch_t *rm, char **lv)
+{
+  if (!buf || !lv || !rm) return;
+  if (*lv) return;
+  if ((rm->rm_so == -1) || (rm->rm_eo == -1)) return;
+  if ((*lv = alloc_bytes(rm->rm_eo - rm->rm_so + 1, "subexpression")) == NULL)
+    return;
+  strncpy(*lv, &buf[rm->rm_so], rm->rm_eo - rm->rm_so);
+  (*lv)[rm->rm_eo - rm->rm_so] = '\0';
+}
+
+static char **
+make_attrs( const char *a )
+{
+  char *s = clone_bytes(a, strlen(a)+1, "attribute list");
+  char *at;
+  int i = 0, j;
+  char **ret = NULL;
+  const char *delim = ", ";
+
+  if (!s) return NULL;
+  at = strtok(s, delim);
+  while (at != NULL) {
+    i++;
+    at = strtok(NULL, delim);
+  }
+  ret = alloc_bytes((i+1) * sizeof(char *), "attribute array");
+  if (!ret) { pfree(s); return NULL; }
+  for(j=0; j<=i; j++) ret[j] = NULL;
+  pfree(s);
+
+  if ((s = clone_bytes(a, strlen(a)+1, "attribute list")) == NULL) return NULL;
+  at = strtok(s, delim);
+  i = 0;
+  while (at != NULL) {
+    if ((ret[i++] = clone_bytes(at, strlen(at)+1, "attribute")) == NULL) {
+      for(i=0; ret[i]; i++) pfree(ret[i]);
+      pfree(ret);
+      pfree(s);
+      return NULL;
+    }
+    at = strtok(NULL, delim);
+  }
+  
+  pfree(s);
+  return ret;
+}
+
+static void
+attrs_free( char **attrs )
+{
+  int i=0;
+
+  for(i=0; attrs[i]; i++) pfree(attrs[i]);
+  pfree(attrs);
+}
+
+static jmp_buf env;
+static void
+ldap_timeout(int unused_sig __attribute__((unused)))
+{
+  longjmp(env, 1);
+}
+
+static int
+open_bind( XMAP_LDAP *xm )
+{
+  void (*saved_alarm)(int);
+
+  if ((saved_alarm = signal(SIGALRM, ldap_timeout)) == SIG_ERR) {
+    log("signal: %s", strerror(errno));
+    return 0;
+  }
+
+  alarm(xm->ldap_timeout);
+  if (setjmp(env) == 0) {
+    if ((xm->ld = ldap_open(xm->ldap_host, xm->ldap_port)) == NULL) {
+      alarm(0); /* turn it off */
+      DBG(DBG_PARSING,
+      DBG_log("Open to %s:%d failed", xm->ldap_host, xm->ldap_port);
+      );
+      loglog(RC_LOG_SERIOUS, "ldap_open: %s", strerror(errno));
+      return 0;
+    }
+  } else {
+    DBG(DBG_PARSING,
+    DBG_log("Open to %s:%d failed", xm->ldap_host, xm->ldap_port);
+    );
+    loglog(RC_LOG_SERIOUS, "ldap_open: Connection timed out.");
+    return 0;
+  }
+  alarm(0);
+
+  if ((ldap_bind_s(xm->ld, xm->ldap_bindDN, xm->ldap_bindPW,
+		   LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) return 0;
+
+  return 1;
+}
+
+void *
+XMAP_LDAP_new(const char *ldapspec)
+{
+  char *ls = NULL, *s, *ldapvar = NULL, *ldapfile;
+  FILE *fp;
+  XMAP_LDAP *ret = NULL;
+  int i, re_code;
+  char re_err[256];
+  regmatch_t re_match[10];
+
+  regex_t host_re;
+  regex_t port_re;
+  regex_t timeout_re;
+  regex_t base_re;
+  regex_t binddn_re;
+  regex_t bindpw_re;
+  regex_t filter_re;
+  regex_t attrs_re;
+
+  /* Default values */
+  char *ldap_host = clone_bytes("localhost", strlen("localhost")+1,
+				"ldap_host");
+  int ldap_port = LDAP_PORT;
+  int ldap_timeout = 10; /* seconds */
+  char *ldap_bindDN = clone_bytes("", 1, "bindDN");
+  char *ldap_bindPW = clone_bytes("", 1, "bindPW");
+  char *ldap_base = NULL;
+  flist ldap_filter[MAXFLIST];
+  alist ldap_attrs[MAXFLIST];
+
+  memset(ldap_filter, 0, sizeof(ldap_filter));
+  insert_filter("*", X509_LU_FAIL, "(cn=%s)", ldap_filter);
+
+  memset(ldap_attrs, 0, sizeof(ldap_attrs));
+  insert_attrs("*", X509_LU_FAIL, "usercertificate, usercertificate;binary, cacertificate, cacertificate;binary", ldap_attrs);
+
+  if ((re_code = regcomp(&host_re, HOST_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &host_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&port_re, PORT_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &port_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&base_re, BASE_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &base_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&timeout_re, TIMEOUT_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &timeout_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&binddn_re, BINDDN_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &binddn_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&bindpw_re, BINDPW_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &bindpw_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&filter_re, FILTER_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &filter_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&attrs_re, ATTRS_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &attrs_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((!ldap_host) || (!ldap_bindDN) || (!ldap_bindPW) ||
+      (!ldap_filter) || (!ldap_attrs)) goto end;
+
+  if (!ldapspec) goto end;
+  ls = clone_bytes(ldapspec, strlen(ldapspec)+1, "ldap spec");
+  if (!ls) goto end;
+  s = strchr(ls, ':');
+  ldapfile = ls;
+  if (s) {
+    ldapvar = clone_bytes(&s[1], strlen(&s[1])+1, "ldap name");
+    *s = '\0';
+  } else {
+    ldapvar = NULL;
+  }
+
+  fp = fopen( ldapfile, "r" );
+  if (!fp) {
+    perror("fopen");
+    goto end;
+  }
+
+  while (!feof(fp)) {
+    char buf[BUFSIZ], *ptr;
+
+    if (fgets(buf, sizeof(buf), fp)) {
+      int l;
+
+      for(ptr = buf; ((*ptr) && (isspace(*ptr))); ptr++);
+      if (! *ptr) continue; /* Blank Line */
+      if (*ptr == '#') continue; /* Comment */
+      l = strlen(buf)-1;
+      while ((l > 0) && (isspace(buf[l]))) { buf[l] = '\0'; l--; }
+
+      /* Check for host name spec */
+      if ((re_code = regexec(&host_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_host) { pfree(ldap_host); ldap_host = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_host);
+	}
+	pfree(lv);
+      }
+
+      /* Check for port spec */
+      if ((re_code = regexec(&port_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *ps = NULL;
+
+	  extract_re_sub(buf, &re_match[2], &ps);
+	  ldap_port = atoi(ps);
+	  pfree(ps);
+	}
+	pfree(lv);
+      }
+
+      /* Check for base spec */
+      if ((re_code = regexec(&base_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_base) { free(ldap_base); ldap_base = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_base);
+	}
+	pfree(lv);
+      }
+
+      /* Check for timeout spec */
+      if ((re_code = regexec(&timeout_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *to = NULL;
+
+	  extract_re_sub(buf, &re_match[2], &to);
+	  ldap_timeout = atoi(to);
+	  free(to);
+	}
+	pfree(lv);
+      }
+
+      /* Check for bind DN spec */
+      if ((re_code = regexec(&binddn_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_bindDN) { free(ldap_bindDN); ldap_bindDN = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_bindDN);
+	}
+	pfree(lv);
+      }
+
+      /* Check for bind PW spec */
+      if ((re_code = regexec(&bindpw_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_bindPW) { free(ldap_bindPW); ldap_bindPW = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_bindPW);
+	}
+	pfree(lv);
+      }
+
+      /* Check for filter spec */
+      if ((re_code = regexec(&filter_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *filt = NULL, *sf = NULL, *ssf = NULL;
+	  int ssftype = X509_LU_FAIL; /* Use this as a catchall */
+
+	  if (re_match[2].rm_so != -1) {
+	    extract_re_sub(buf, &re_match[4], &sf);
+	    if (re_match[5].rm_so != -1) {
+	      extract_re_sub(buf, &re_match[6], &ssf);
+	      if (strcasecmp(ssf, "cert") == 0)
+		ssftype = X509_LU_X509;
+	      else if (strcasecmp(ssf, "crl") == 0)
+		ssftype = X509_LU_CRL;
+	      else
+		ssftype = X509_LU_RETRY; /* Use as an "invalid" value */
+	      pfree(ssf);
+	    }
+	  }
+	  extract_re_sub(buf, &re_match[7], &filt);
+	  if (ssftype != X509_LU_RETRY)
+	    insert_filter((sf == NULL) ? "*" : sf, ssftype, filt, ldap_filter);
+	  else
+	    if (filt) pfree(filt);
+	  if (sf) pfree(sf);
+	}
+	pfree(lv);
+      }
+
+      /* Check for attributes spec */
+      if ((re_code = regexec(&attrs_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *attr = NULL;
+	  char *sf = NULL, *ssf = NULL;
+	  int ssftype = X509_LU_FAIL; /* Use this as a catchall */
+
+	  if (re_match[2].rm_so != -1) {
+	    extract_re_sub(buf, &re_match[4], &sf);
+	    if (re_match[5].rm_so != -1) {
+	      extract_re_sub(buf, &re_match[6], &ssf);
+	      if (strcasecmp(ssf, "cert") == 0)
+		ssftype = X509_LU_X509;
+	      else if (strcasecmp(ssf, "crl") == 0)
+		ssftype = X509_LU_CRL;
+	      else if (strcasecmp(ssf, "*") == 0)
+		ssftype = X509_LU_FAIL;
+	      else
+		ssftype = X509_LU_RETRY; /* Use as an "invalid" value */
+	      pfree(ssf);
+	    }
+	  }
+	  extract_re_sub(buf, &re_match[7], &attr);
+	  if (ssftype != X509_LU_RETRY)
+	    insert_attrs((sf == NULL) ? "*" : sf, ssftype, attr, ldap_attrs);
+	  else
+	    if (attr) pfree(attr);
+	  if (sf) pfree(sf);
+	}
+	pfree(lv);
+      }
+
+    }
+  }
+
+  if (!ldap_base) goto end; /* No search base - and we can't default to one */
+
+  if ((ret = alloc_thing(XMAP_LDAP, "xmap_ldap")) == NULL) goto end;
+
+  ret->ldapsource = ldapvar;
+  ret->ldap_host = ldap_host;
+  ret->ldap_port = ldap_port;
+  ret->ldap_base = ldap_base;
+  ret->ldap_timeout = ldap_timeout;
+  ret->ldap_bindDN = ldap_bindDN;
+  ret->ldap_bindPW = ldap_bindPW;
+  memcpy(ret->ldap_filter, ldap_filter, MAXFLIST * sizeof(flist));
+  memcpy(ret->ldap_attrs, ldap_attrs, MAXFLIST * sizeof(alist));
+  
+  fclose(fp); fp = NULL;
+
+  if (!open_bind(ret)) goto end;
+
+  if (ls) pfree(ls);
+  return (void *)ret;
+
+ end:
+  if (ldap_host) pfree(ldap_host);
+  if (ldap_base) pfree(ldap_base);
+  if (ldap_bindDN) pfree(ldap_bindDN);
+  if (ldap_bindPW) pfree(ldap_bindPW);
+  for(i=0; ldap_filter[i].index; i++)
+    { pfree(ldap_filter[i].index); pfree(ldap_filter[i].filter); }
+  for(i=0; ldap_attrs[i].index; i++)
+    { pfree(ldap_attrs[i].index); attrs_free(ldap_attrs[i].attrs); }
+  if (ldapvar) pfree(ldapvar);
+  if (ls) pfree(ls);
+  if (fp) fclose(fp);
+  return NULL;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_LDAP *xm = (XMAP_LDAP *)this;
+
+  if (type == X509_LU_X509) {
+    if (strcasecmp(index, "subject") == 0)
+      return XMAP_LDAP_lookup_cert_by_subject(xm, (X509_NAME *)p);
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_LDAP_lookup_cert_by_issuer(xm, (X509_NAME *)p);
+    else if (strcasecmp(index, "uid") == 0)
+      return XMAP_LDAP_lookup_cert_by_uid(xm, (char *)p);
+    else if (strcasecmp(index, "dns") == 0)
+      return XMAP_LDAP_lookup_cert_by_dns(xm, (char *)p);
+    else if (strcasecmp(index, "ip") == 0)
+      return XMAP_LDAP_lookup_cert_by_ip(xm, *((struct in_addr *)p));
+    else if (strcasecmp(index, "ca") == 0)
+      return XMAP_LDAP_lookup_ca_certs( xm );
+    else
+      return NULL;
+  } else if (type == X509_LU_CRL) {
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_LDAP_lookup_crl_by_issuer(xm, (X509_NAME *)p);
+    else
+      return NULL;
+  } else {
+    log("Unknown search type");
+    return NULL;
+  }
+}
+
+static int
+ASN1_UTCTIME_cmp(ASN1_UTCTIME *a, ASN1_UTCTIME *b)
+{
+  char buff1[14],buff2[14],*p;
+  int i,j;
+ 
+  /* Degenerate cases */
+  if (!a && !b) return 0;
+  if (a && !b) return 1;
+  if (!a && b) return -1;
+ 
+  memset(buff1, 0, sizeof(buff1));
+  memset(buff2, 0, sizeof(buff2));
+ 
+  p=buff1;
+  i=a->length;
+  if ((i < 11) || (i > 17)) return(0);
+  memcpy(p,a->data,12);
+ 
+  p=buff2;
+  j=b->length;
+  if ((j < 11) || (j > 17)) return(0);
+  memcpy(p,b->data,12);
+ 
+  /* Correct for Y2K */
+  i=(buff1[0]-'0')*10+(buff1[1]-'0');
+  if (i < 50) i+=100; /* cf. RFC 2459 */
+  j=(buff2[0]-'0')*10+(buff2[1]-'0');
+  if (j < 50) j+=100;
+ 
+  if (i < j) return (-1);
+  if (i > j) return (1);
+ 
+  i=strcmp(buff1,buff2);
+ 
+  if (i == 0)
+    return 0;
+  else if (i < 0)
+    return(-1);
+  else
+    return(1);
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_subject( XMAP_LDAP *xm, X509_NAME *name )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *str, *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+/*
+ * Searching by 'common name' alone is wrong. Will let the code
+ * from the original author remain until a better solution is found.
+ * 
+ *  // First find the 'common name' attribute from the subject
+ *  for(i=0; i<sk_X509_NAME_ENTRY_num(ns); i++) {
+ *    X509_NAME_ENTRY *ne = sk_X509_NAME_ENTRY_value(ns, i);
+ *    int nid = OBJ_obj2nid(ne->object);
+ * 
+ *    if (nid == NID_commonName) {
+ *      if (!(str = alloc_bytes(ASN1_STRING_length(ne->value)+1, "common name")))
+ * return sk;
+ *      memset(str, 0, ASN1_STRING_length(ne->value)+1);
+ *      memcpy(str, ASN1_STRING_data(ne->value),
+ *             ASN1_STRING_length(ne->value));
+ *      break; 
+ *    }
+ *  }
+ */
+
+/* Use the whole DN */
+  str = X509_NAME_oneline(name, NULL, 0);
+
+  ff = find_filter("subject", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("subject", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(str);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, str);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+
+
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+
+		if (X509_NAME_cmp(X509_get_subject_name(x), name) == 0) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		  if (xo) {
+		    int i, found = 0;
+
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+
+		      if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+			found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else {
+		      X509_free(x); /* duplicate of existing item */
+		    }
+		  } else {
+		    X509_free(x); /* cannot allocate X509_OBJECT */
+		  }
+		} else {
+		  X509_free(x); /* subject name doesn't match */
+		}
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  pfree(str);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_issuer( XMAP_LDAP *xm, X509_NAME *name )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *str, *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  str = X509_NAME_oneline(name, NULL, 0);
+
+  ff = find_filter("issuer", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("issuer", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(str);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, str);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+
+
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+
+		if (X509_NAME_cmp(X509_get_issuer_name(x), name) == 0) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		  if (xo) {
+		    int i, found = 0;
+
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+
+		      if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+			found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else {
+		      X509_free(x); /* duplicate of existing item */
+		    }
+		  } else {
+		    X509_free(x); /* cannot allocate X509_OBJECT */
+		  }
+		} else {
+		  X509_free(x); /* subject name doesn't match */
+		}
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  pfree(str);
+  return sk;
+}
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_ca_certs( XMAP_LDAP *xm )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *ff, **af;
+  int i, j, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  ff = find_filter("ca", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("ca", X509_LU_X509, xm->ldap_attrs);
+  tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+  rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+		      ff, af, 0, &tv, &res);
+  if (rc == LDAP_SUCCESS) {
+    for(ent = ldap_first_entry(xm->ld, res); ent ;
+	ent = ldap_next_entry(xm->ld, ent)) {
+      for(i = 0; af[i]; i++) {
+	bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	if (bv) {
+	  for(j=0; bv[j]; j++) {
+	    unsigned char *p;
+	    X509 *x;
+	    
+	    p = bv[j]->bv_val;
+	    x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	    if ((x) && (isCA(x))) {
+	      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	      if (xo) {
+		int i, found = 0;
+		
+		for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		  X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		  
+		  if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+		    found = 1;
+		}
+		if (!found)
+		  sk_X509_OBJECT_push(sk, xo);
+		else
+		  X509_free(x); /* duplicate of existing item */
+	      } else
+		X509_free(x); /* cannot allocate X509_OBJECT */
+	    } else
+	      X509_free(x); /* subject name doesn't match */
+	  }
+	  ldap_value_free_len(bv);
+	}
+      }
+    }
+  } else {
+    log("ldap_search_st error: %s", ldap_err2string(rc));
+    ldap_unbind(xm->ld);
+    xm->ld = NULL;
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_crl_by_issuer( XMAP_LDAP *xm, X509_NAME *name )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  STACK_OF(X509_NAME_ENTRY) *ns = name->entries;
+  char *str, *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  /* First find the 'common name' attribute from the subject */
+  for(i=0; i<sk_X509_NAME_ENTRY_num(ns); i++) {
+    X509_NAME_ENTRY *ne = sk_X509_NAME_ENTRY_value(ns, i);
+    int nid = OBJ_obj2nid(ne->object);
+
+    if (nid == NID_commonName) {
+      if (!(str = alloc_bytes(ASN1_STRING_length(ne->value)+1,
+			      "common name")))
+	return sk;
+      memset(str, 0, ASN1_STRING_length(ne->value)+1);
+      memcpy(str, ASN1_STRING_data(ne->value),
+             ASN1_STRING_length(ne->value));
+      break; 
+    }
+  }
+  ff = find_filter("issuer", X509_LU_CRL, xm->ldap_filter);
+  af = find_attrs("issuer", X509_LU_CRL, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(str);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, str);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    DBG(DBG_PARSING,
+    DBG_log("LDAP search: \"%s\"", s1);
+    );
+    for(i=0; af[i]; i++) {
+      DBG(DBG_PARSING,
+      DBG_log("Attr %d: %s", i+1, af[i]);
+      );
+    }
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509_CRL *x;
+	      
+	      p = bv[j]->bv_val;
+	      x = d2i_X509_CRL(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+		if (X509_NAME_cmp(X509_CRL_get_issuer(x), name) == 0) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, x);
+
+		  if (xo) {
+		    int i, found = 0;
+
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+
+		      if ((X509_CRL_cmp(o->data.crl, x) == 0) &&
+			  (ASN1_UTCTIME_cmp(X509_CRL_get_lastUpdate(o->data.crl),
+					    X509_CRL_get_lastUpdate(x)) == 0) &&
+			  (ASN1_UTCTIME_cmp(X509_CRL_get_nextUpdate(o->data.crl),
+					    X509_CRL_get_nextUpdate(x)) == 0))
+			  found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else
+		      X509_CRL_free(x); /* duplicate of existing item */
+		  } else
+		    X509_CRL_free(x); /* cannot allocate X509_OBJECT */
+		} else
+		  X509_CRL_free(x); /* subject name doesn't match */
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  pfree(str);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_uid( XMAP_LDAP *xm, const char *uid )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  ff = find_filter("uid", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("uid", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(uid);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, uid);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+	      
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+		X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		if (xo) {
+		  int i, found = 0;
+		  
+		  for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		    X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		    
+		    if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+		      found = 1;
+		  }
+		  if (!found)
+		    sk_X509_OBJECT_push(sk, xo);
+		  else
+		    X509_free(x); /* duplicate of existing item */
+		} else
+		  X509_free(x); /* cannot allocate X509_OBJECT */
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_dns( XMAP_LDAP *xm, const char *dns )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  ff = find_filter("dns", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("dns", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(dns);
+  if ((s1 = alloc_bytes(tlen, "filter patten")) != NULL) {
+    snprintf(s1, tlen, ff, dns);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+	      
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+		if (X509_subjAltName_check_dns(x, dns)) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		  if (xo) {
+		    int i, found = 0;
+		    
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		      
+		      if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+			found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else
+		      X509_free(x); /* duplicate of existing item */
+		  } else
+		    X509_free(x); /* cannot allocate X509_OBJECT */
+		} else
+		  X509_free(x); /* subjAltName mismatch */
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_ip( XMAP_LDAP *xm, const struct in_addr ip )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *s1, *ff, **af, *ipt;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  if ((ipt = inet_ntoa(ip)) == NULL) return NULL;
+  ff = find_filter("ip", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("ip", X509_LU_X509, xm->ldap_attrs);
+  
+  tlen = strlen(ff) + strlen(ipt);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, ipt);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+
+    DBG(DBG_PARSING, 
+    DBG_log("xm->ldap_base: %s -- s1: %s -- *af: %s", xm->ldap_base, s1, *af);
+    );
+
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+        for(i = 0; af[i]; i++) {
+          DBG(DBG_PARSING,
+          DBG_log("af[%d]: [%s]", i, af[i]);
+          );
+
+          bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+	      
+          DBG(DBG_PARSING,
+          DBG_log("** We got LDAP. Trying to process. j=%d.", j);
+          );
+
+          DBG(DBG_PARSING | DBG_RAW,
+          DBG_log("** length of X509 cert: %d", (int )bv[j]->bv_len);
+          );
+          DBG(DBG_RAW,
+          DBG_dump("** p: ", bv[j]->bv_val, bv[j]->bv_len);
+          );
+
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+            if (X509_subjAltName_check_ip(x, ip)) {
+              X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+              if (xo) {
+                int i, found = 0;
+		    
+                for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+                  X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		      
+                  if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+                    found = 1;
+                } /* end for */
+                if (!found)
+                  sk_X509_OBJECT_push(sk, xo);
+                else
+                  X509_free(x); /* duplicate of existing item */
+              }  /* end if (xo) */
+              else
+                X509_free(x); /* cannot allocate X509_OBJECT */
+            } /* end if (X509_subjAltName_check_ip(x, ip)) */
+            else
+              X509_free(x); /* SubjectAltName mismatch */
+          } /* end if (x) */
+          else
+          {
+          }
+        }
+        ldap_value_free_len(bv);
+      }
+    }
+  }
+    } else {
+      DBG(DBG_PARSING,
+      DBG_log("ldap_search_st error: %s", ldap_err2string(rc));
+      );
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  return sk;
+}
+
+static void
+sanitize(const char *buf, char *buf2, int buf2len)
+{
+  int l = strlen(buf), i, nl, p;
+  char *b;
+
+  for(i=0, nl=l; i<l; i++) if (buf[i] == '%') nl++;
+  b = alloc_bytes(nl+1, "temporary string");
+  memset(b, 0, nl+1);
+  for(i=0, p=0; i < nl; i++) {
+    if (buf[i] == '%') {
+      b[p] = '%';
+      b[p+1] = '%';
+      p++;
+    } else {
+      b[p] = buf[i];
+    }
+    p++;
+  }
+  strncpy(buf2, b, buf2len-1);
+  pfree(b);
+}
+
+static void
+XMAP_LDAP_dump(void *this)
+{
+  char buf[256];
+  XMAP_LDAP *xm = (XMAP_LDAP *)this;
+  int i, j;
+
+  DBG(DBG_PARSING,
+  DBG_log("XMAP_LDAP: %s", xm->ldapsource);
+  DBG_log("Host = %s:%d (Timeout = %d seconds)",
+	  xm->ldap_host, xm->ldap_port, xm->ldap_timeout);
+  DBG_log("Search base = %s", xm->ldap_base);
+  DBG_log("Bind = (\"%s\", \"%s\")", xm->ldap_bindDN, xm->ldap_bindPW);
+  );
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_filter[i].index)); i++) {
+    snprintf(buf, sizeof(buf)-1, "Filter[%d] (%s,",
+	     i+1, xm->ldap_filter[i].index);
+    switch(xm->ldap_filter[i].type) {
+      case X509_LU_X509: strncat(buf, "Cert", sizeof(buf)-1); break;
+      case X509_LU_CRL: strncat(buf, "CRL", sizeof(buf)-1); break;
+      default: strncat(buf, "*", sizeof(buf)-1); break;
+    }
+    strncat(buf, ") ", sizeof(buf)-1);
+    strncat(buf, xm->ldap_filter[i].filter, sizeof(buf)-1);
+    sanitize(buf, buf, sizeof(buf)-1);
+    DBG(DBG_PARSING,
+    DBG_log(buf);
+    );
+  }
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_attrs[i].index)); i++) {
+    snprintf(buf, sizeof(buf), "Attributes[%d] (%s,",
+	     i+1, xm->ldap_attrs[i].index);
+    switch(xm->ldap_attrs[i].type) {
+      case X509_LU_X509: strncat(buf, "Cert", sizeof(buf)-1); break;
+      case X509_LU_CRL: strncat(buf, "CRL", sizeof(buf)-1); break;
+      default: strncat(buf, "*", sizeof(buf)-1); break;
+    }
+    strncat(buf, ") ", sizeof(buf)-1);
+    for(j=0; xm->ldap_attrs[i].attrs[j]; j++) {
+      strncat(buf, ",", sizeof(buf)-1);
+      strncat(buf, xm->ldap_attrs[i].attrs[j], sizeof(buf)-1);
+    }
+    sanitize(buf, buf, sizeof(buf)-1);
+    DBG(DBG_PARSING,
+    DBG_log(buf);
+    );
+  }
+}
+
+static void
+XMAP_LDAP_free(void *this)
+{
+  XMAP_LDAP *xm = (XMAP_LDAP *)this;
+  int i;
+
+  if (!xm) return;
+  if (xm->ld) ldap_unbind(xm->ld);
+  if (xm->ldapsource) pfree(xm->ldapsource);
+  if (xm->ldap_host) pfree(xm->ldap_host);
+  if (xm->ldap_base) pfree(xm->ldap_base);
+  if (xm->ldap_bindDN) pfree(xm->ldap_bindDN);
+  if (xm->ldap_bindPW) pfree(xm->ldap_bindPW);
+
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_filter[i].index)); i++) {
+    pfree(xm->ldap_filter[i].index);
+    pfree(xm->ldap_filter[i].filter);
+  }
+  
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_attrs[i].index)); i++) {
+    pfree(xm->ldap_attrs[i].index);
+    attrs_free(xm->ldap_attrs[i].attrs);
+  }
+
+  pfree(xm);
+}
+
+XMAP_METHOD *
+XMAP_METHOD_ldap( void )
+{
+  return (&xmap_ldap_methods);
+}
+
+#endif /* HAVE_LDAP */
+#endif /* OPENSSL */
diff -BbruN freeswan-1.91.orig/pluto/xmap_ldap.h freeswan-1.91/pluto/xmap_ldap.h
--- freeswan-1.91.orig/pluto/xmap_ldap.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/pluto/xmap_ldap.h	Tue Jul  3 03:00:39 2001
@@ -0,0 +1,49 @@
+#ifndef XMAP_LDAP_H
+#define XMAP_LDAP_H
+
+#ifdef HAVE_LDAP
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct _flist_st {
+  char *index;
+  int type;
+  char *filter;
+} flist;
+
+#define MAXFLIST 10
+
+typedef struct _alist_st {
+  char *index;
+  int type;
+  char **attrs;
+} alist;
+
+typedef struct xmap_ldap_st {
+  char *ldapsource;
+  char *ldap_host;
+  int ldap_port;
+  char *ldap_base;
+  int ldap_timeout;
+  char *ldap_bindDN;
+  char *ldap_bindPW;
+  flist ldap_filter[MAXFLIST];
+  alist ldap_attrs[MAXFLIST];
+
+  LDAP *ld;
+
+  XMAP_METHOD *meth;
+} XMAP_LDAP;
+
+XMAP_METHOD *XMAP_METHOD_ldap( void );
+
+#endif /* HAVE_LDAP */
+
+#endif /* XMAP_LDAP_H */
diff -BbruN freeswan-1.91.orig/utils/Makefile freeswan-1.91/utils/Makefile
--- freeswan-1.91.orig/utils/Makefile	Thu Jun 14 09:20:14 2001
+++ freeswan-1.91/utils/Makefile	Mon Jul  2 21:49:48 2001
@@ -11,22 +11,30 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: Makefile,v 1.85 2001/06/14 13:20:14 henry Exp $
+# RCSID $Id: Makefile,v 1.74 2001/02/06 18:11:41 henry Exp $
 
 # pathnames, subject to overrides from main Makefile
 PUBDIR=/usr/local/sbin
 PRIVDIR=/usr/local/lib/ipsec
 REALPRIVDIR=/usr/local/lib/ipsec
+FINALPRIVDIR=/usr/local/lib/ipsec
 RCDIR=/etc/rc.d/init.d
 REALRCDIR=/etc/rc.d/init.d
 CONFDIR=/etc
-MANTREE=/usr/local/man
+MANTREE=/usr/man
 
 FMANDIR=$(MANTREE)/man5
 CMANDIR=$(MANTREE)/man8
 PUBS=ipsec
-BINS=ranbits rsasigkey
+
+ifeq "$(USEOPENSSL)" "1"
+SCRIPTS=barf manual auto look showdefaults showhostkey rehashcertdir rsakeygen updown.firewall
+BINS=ranbits rsasigkey fswcert
+else
 SCRIPTS=barf manual auto look showdefaults showhostkey
+BINS=ranbits rsasigkey
+endif
+
 INTERNALS=_include _confread _keycensor _secretcensor _updown \
 	_realsetup _startklips _plutorun _plutoload
 PRIVS=$(PUBS) $(SCRIPTS) $(INTERNALS) $(BINS)
@@ -49,6 +57,10 @@
 
 all:	$(PUBS) $(PRIVS) $(GENDFILES) $(LOCALS)
 
+fswcert: fswcert-0.4/fswcert.c
+	cd fswcert-0.4; $(MAKE)
+	cp fswcert-0.4/fswcert .
+
 ranbits:	ranbits.o
 	$(CC) $(CFLAGS) ranbits.o $(LIB) -o $@
 
@@ -93,43 +105,46 @@
 	./randomize conf.proto | egrep -v RCSI >$@
 
 install:	$(PUBS) $(PRIVS) $(MANS) $(GENDFILES)
-	mkdir -p $(PUBDIR) $(PRIVDIR) $(FMANDIR) $(CMANDIR) $(CONFDIR)
-	$(INSTALL) $(PUBS) $(PUBDIR)
-	$(INSTALL) $(PRIVS) $(PRIVDIR)
-	$(INSTALL) $(PUB) ipsec.conf.5 $(FMANDIR)
-	$(INSTALL) $(PUB) $(PLAIN_MANS) $(CMANDIR)
+	mkdir -p $(PREFIX)/$(PUBDIR) $(PREFIX)/$(PRIVDIR) 
+	mkdir -p $(PREFIX)/$(FMANDIR) $(PREFIX)/$(CMANDIR) 
+	mkdir -p $(PREFIX)/$(CONFDIR)
+	$(INSTALL) $(PUBS) $(PREFIX)/$(PUBDIR)
+	$(INSTALL) $(PRIVS) $(PREFIX)/$(PRIVDIR)
+	$(INSTALL) $(PUB) ipsec.conf.5 $(PREFIX)/$(FMANDIR)
+	$(INSTALL) $(PUB) $(PLAIN_MANS) $(PREFIX)/$(CMANDIR)
 	for f in $(IPSEC_CMANS) ; \
 	do \
-		$(INSTALL) $(PUB) $$f $(CMANDIR)/ipsec_$$f || exit 1 ; \
-		./manlink $(CMANDIR) ipsec_$$f ; \
+		$(INSTALL) $(PUB) $$f $(PREFIX)/$(CMANDIR)/ipsec_$$f || exit 1 ; \
+		./manlink $(PREFIX)/$(CMANDIR) ipsec_$$f ; \
 	done
-	test -f $(CONFDIR)/ipsec.secrets || \
-		$(INSTALL) $(PRIV) secrets.eg $(CONFDIR)/ipsec.secrets
-	test -f $(CONFDIR)/ipsec.conf || \
-		$(INSTALL) $(PUB) conf.eg $(CONFDIR)/ipsec.conf
+	test -d $(PREFIX)/$(CONFDIR) || $(INSTALL) -d $(PREFIX)/$(CONFDIR)
+	test -f $(PREFIX)/$(CONFDIR)/ipsec.secrets || \
+		$(INSTALL) $(PRIV) secrets.eg $(PREFIX)/$(CONFDIR)/ipsec.secrets
+	test -f $(PREFIX)/$(CONFDIR)/ipsec.conf || \
+		$(INSTALL) $(PUB) conf.eg $(PREFIX)/$(CONFDIR)/ipsec.conf
 	# main copy must go in RCDIR, PRIVDIR may not be mounted at boot time
-	mkdir -p $(RCDIR)
-	$(INSTALL) setup $(RCDIR)/ipsec
-	rm -f $(PRIVDIR)/setup
-	ln -s $(REALRCDIR)/ipsec $(PRIVDIR)/setup
-	PATH=/sbin:/usr/sbin:$$PATH ; export PATH ; \
-	if test " $(DESTDIR)" != " " ; \
-	then : do nothing ; \
-	elif which chkconfig >/dev/null 2>&1 ; \
+	test -d $(PREFIX)/$(RCDIR) || mkdir -p $(PREFIX)/$(RCDIR)
+	$(INSTALL) setup $(PREFIX)/$(RCDIR)/ipsec
+	rm -f $(PREFIX)/$(PRIVDIR)/setup
+	ln -s $(PREFIX)/$(REALRCDIR)/ipsec $(PREFIX)/$(PRIVDIR)/setup
+	# Only turn on the service if doing default install
+	if [ $(PREFIX) = '/' ] ; then \
+		if which chkconfig >/dev/null 2>&1 ; \
 	then chkconfig --add ipsec ; \
 	else $(MAKE) setup4 ; \
+		fi ; \
 	fi
 
+
 setup4:	$(RCDIR)/ipsec
-	# fallback rc install -- on in run states 2345, off in 016, with
-	# priorities matching those in setup's chkconfig line
-	-cd $(RCDIR)/../rc0.d ; ln -s ../init.d/ipsec K68ipsec
-	-cd $(RCDIR)/../rc1.d ; ln -s ../init.d/ipsec K68ipsec
-	-cd $(RCDIR)/../rc2.d ; ln -s ../init.d/ipsec S47ipsec
-	-cd $(RCDIR)/../rc3.d ; ln -s ../init.d/ipsec S47ipsec
-	-cd $(RCDIR)/../rc4.d ; ln -s ../init.d/ipsec S47ipsec
-	-cd $(RCDIR)/../rc5.d ; ln -s ../init.d/ipsec S47ipsec
-	-cd $(RCDIR)/../rc6.d ; ln -s ../init.d/ipsec K68ipsec
+	# fallback rc install -- on in run states 2345, off in 016
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc0.d ; ln -s ../init.d/ipsec K68ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc1.d ; ln -s ../init.d/ipsec K68ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc2.d ; ln -s ../init.d/ipsec S47ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc3.d ; ln -s ../init.d/ipsec S47ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc4.d ; ln -s ../init.d/ipsec S47ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc5.d ; ln -s ../init.d/ipsec S47ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc6.d ; ln -s ../init.d/ipsec K68ipsec
 
 clean:
 	rm -f *.o $(BINS) $(GENDFILES) $(GENDSCRIPTS) $(LOCALS)
diff -BbruN freeswan-1.91.orig/utils/_confread freeswan-1.91/utils/_confread
--- freeswan-1.91.orig/utils/_confread	Wed Jun 13 16:09:19 2001
+++ freeswan-1.91/utils/_confread	Mon Jul  2 21:38:15 2001
@@ -1,6 +1,6 @@
 #!/bin/sh
 # configuration-file reader utility
-# Copyright (C) 1999, 2000, 2001  Henry Spencer.
+# Copyright (C) 1999, 2000  Henry Spencer.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: _confread,v 1.41 2001/06/13 20:09:19 henry Exp $
+# RCSID $Id: _confread,v 1.39 2001/06/01 15:49:13 henry Exp $
 #
 # Extract configuration info from /etc/ipsec.conf, repackage as assignments
 # to shell variables or tab-delimited fields.  Success or failure is reported
@@ -47,7 +47,6 @@
 fieldfmt=yes
 prefix=
 search=
-export=0
 me="ipsec _confread"
 
 for dummy
@@ -120,10 +119,11 @@
 			fail("invalid section name " bq na[i] eq)
 	}
 
-	good = "also type auto authby"
+	good = "also type auto authby force_encrypt_cypher"
 	left = " left leftsubnet leftnexthop leftfirewall leftupdown"
 	akey = " keyexchange auth pfs keylife rekeymargin rekeyfuzz compress"
 	obs = " lifetime rekeystart rekeytries"
+	cert = " certfile keyfile peerfile certopts certpath"
 	akey = akey " keyingtries ikelifetime" obs
 	mkey = " spibase spi esp espenckey espauthkey espreplay_window"
 	left = left " leftespenckey leftespauthkey leftahkey"
@@ -131,7 +131,7 @@
 	mkey = mkey " ah ahkey ahreplay_window"
 	right = left
 	gsub(/left/, "right", right)
-	n = split(good left right akey mkey, g)
+	n = split(good left right akey mkey cert, g)
 	for (i = 1; i <= n; i++)
 		goodnames["conn:" g[i]] = 1
 
@@ -231,7 +232,7 @@
 	# referencing is transitive:  xyz->from->to
 	if (from in refsto) {
 		listnum = split(refsto[from], reflist, ";")
-		for (i = 1; i <= listnum; i++)
+		for (i=1; i <= listnum; i++)
 			chainref(reflist[i], to)
 	}
 	addref(from, to)
@@ -337,7 +338,7 @@
 			searchfound(sectionname)
 	} else {
 		# rather a kludge, but must check this somewhere
-		if (search == "auto" && rest !~ /^(add|route|start|ignore)$/)
+		if (search == "auto" && rest !~ /^(add|route|start|ignore|background)$/)
 			fail("illegal auto value " bq rest eq)
 	}
 	next
diff -BbruN freeswan-1.91.orig/utils/auto freeswan-1.91/utils/auto
--- freeswan-1.91.orig/utils/auto	Fri Jun  1 11:49:13 2001
+++ freeswan-1.91/utils/auto	Mon Jun  4 10:44:49 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: auto,v 1.61 2001/06/01 15:49:13 henry Exp $
+# RCSID $Id: auto,v 1.59 2001/05/04 05:31:50 henry Exp $
 
 me='ipsec auto'
 usage="Usage:
@@ -323,8 +323,10 @@
 			s["rightupdown"] = s["rightupdown"] " ipfwadm"
 
 		default("authby", "secret")
+		authbyfound = "0"
 		authtype = "--psk"
 		if (s["authby"] == "rsasig") {
+			authbyfound = "1"
 			authtype = "--rsasig"
 			need("leftrsasigkey")
 			need("rightrsasigkey")
@@ -332,8 +334,45 @@
 				fail("ID \"" id("left") "\" cannot have RSA key")
 			if (id("right") == "%any")
 				fail("ID \"" id("right") "\" cannot have RSA key")
-		} else if (s["authby"] != "secret")
+		}
+
+
+		if (s["authby"] == "cert") {
+			authbyfound = "1"
+			default("certfile", "")
+			default("certopts", "send")
+			default("keyfile", "")
+			default("certpath", "")
+			authtype = "--openssl"
+			need("certfile")
+			need("certopts")
+			need("keyfile")
+			need("certpath")
+		}
+
+		if (s["authby"] != "secret") {
+		  if (s["authby"] != "psk") {
+			if (authbyfound != "1") {
 			fail("unknown authby value \"" s["authby"] "\"")
+			}
+		  }
+		}
+
+		default("force_encrypt_cypher", "")
+		if ("force_encrypt_cypher" in s) {
+			if (s["force_encrypt_cypher"] == "des") {
+				force_encrypt_cypher = "des"
+			}
+			if (s["force_encrypt_cypher"] == "DES") {
+				force_encrypt_cypher = "des"
+			}
+			if (s["force_encrypt_cypher"] == "3des") {
+				force_encrypt_cypher = "3des"
+			}
+			if (s["force_encrypt_cypher"] == "3DES") {
+				force_encrypt_cypher = "3des"
+			}
+		}
 
 		settings = "--encrypt"
 		if (s["type"] != "transport")
@@ -368,6 +407,17 @@
 		if ("rekeyfuzz" in s)
 			fuzz = "--rekeyfuzz " s["rekeyfuzz"]
 
+		if (authtype == "--openssl") {
+			if ("certfile" in s)
+				certfile = "--certfile " s["certfile"]
+			if ("certopts" in s)
+				certopts = "--certopts " s["certopts"]
+			if ("keyfile" in s)
+				keyfile = "--keyfile " s["keyfile"]
+			if ("certpath" in s)
+				certpath = "--certpath " s["certpath"]
+		}
+
 		print "ipsec whack --name", name, settings, "\\"
 		print "\t--host", s["left"], lc,
 				"--nexthop", s["leftnexthop"], lud, lid, "\\"
@@ -375,8 +425,23 @@
 				"--nexthop", s["rightnexthop"], rud, rid, "\\"
 		print "\t--ipseclifetime", s["keylife"],
 			"--rekeywindow", s["rekeymargin"], "\\"
+		if (authtype == "--openssl") {
+			if (certfile != "--certfile ")
+				print certfile, "\\"
+			if (certopts != "--certopts ")
+				print certopts, "\\"
+			if (keyfile != "--keyfile ")
+				print keyfile, "\\"
+			if (certpath != "--certpath ")
+				print certpath, "\\"
+		}
+
+		if (force_encrypt_cypher != "") {
+			print "\t--force_encrypt_cypher", s["force_encrypt_cypher"], "\\"
+		}
+
 		print "\t--keyingtries", s["keyingtries"], fuzz
-		if (authtype != "--psk") {
+		if (authtype == "--rsasig") {
 			whackkey("left")
 			whackkey("right")
 		}
diff -BbruN freeswan-1.91.orig/utils/barf freeswan-1.91/utils/barf
--- freeswan-1.91.orig/utils/barf	Fri Jun 15 12:18:22 2001
+++ freeswan-1.91/utils/barf	Mon Jun  4 10:45:44 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: barf,v 1.50 2001/06/15 16:18:22 henry Exp $
+# RCSID $Id: barf,v 1.47 2001/06/01 15:49:13 henry Exp $
 
 KERNSRC=${KERNSRC-/usr/src/linux}
 LOGS=${LOGS-/var/log}
@@ -75,10 +75,6 @@
 hostname ; date
 set -x
 _________________________
-ipsec --version
-_________________________
-cat /proc/version
-_________________________
 cat /proc/net/ipsec_eroute
 _________________________
 cat /proc/net/ipsec_spi
@@ -91,14 +87,14 @@
 _________________________
 cat /proc/net/pf_key
 _________________________
-( cd /proc/net ; egrep '^' pf_key_* )
-_________________________
 ( cd /proc/sys/net/ipsec ; egrep '^' * )
 _________________________
 ipsec auto --status
 _________________________
 ifconfig -a
 _________________________
+ipsec --version
+_________________________
 ipsec --directory
 _________________________
 hostname --fqdn
@@ -128,6 +124,8 @@
 _________________________
 uname -a
 _________________________
+cat /proc/version
+_________________________
 if test -r /etc/redhat-release
 then
 	cat /etc/redhat-release
@@ -137,15 +135,15 @@
 _________________________
 ipchains -L -v -n
 _________________________
-ipfwadm -F -l -n -e
+ipfwadm -F -l -n
 _________________________
-ipfwadm -I -l -n -e
+ipfwadm -I -l -n
 _________________________
-ipfwadm -O -l -n -e
+ipfwadm -O -l -n
 _________________________
 ipchains -M -L -v -n
 _________________________
-ipfwadm -M -l -n -e
+ipfwadm -M -l -n
 _________________________
 cat /proc/modules
 _________________________
diff -BbruN freeswan-1.91.orig/utils/fswcert-0.4/Makefile freeswan-1.91/utils/fswcert-0.4/Makefile
--- freeswan-1.91.orig/utils/fswcert-0.4/Makefile	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/fswcert-0.4/Makefile	Wed May 16 10:57:20 2001
@@ -0,0 +1,26 @@
+###################################################
+# Adjust SSLDIR before make ...
+SSLDIR=/usr/ssl
+
+# Adjust IPSECDIR before make install ...
+IPSECDIR=/usr/lib/ipsec
+###################################################
+
+VERSION = 0.4
+
+CFLAGS = -g -Wall -O2 -DVERSION=\"$(VERSION)\" -I$(SSLDIR)/include -I$(OPENSSLROOT)/include
+LDFLAGS = -g -L$(SSLDIR)/lib -L$(OPENSSLROOT)/lib
+LDLIBS = -lcrypto
+
+DISTFILES=Makefile README fswcert.c _confread.patch
+
+all : fswcert
+
+fswcert : fswcert.o
+	$(CC) $(LDFLAGS) -o fswcert fswcert.o $(LDLIBS)
+
+fswcert.o: fswcert.c
+	$(CC) $(CFLAGS) -c fswcert.c
+
+clean :
+	rm -f fswcert fswcert.o
diff -BbruN freeswan-1.91.orig/utils/fswcert-0.4/README freeswan-1.91/utils/fswcert-0.4/README
--- freeswan-1.91.orig/utils/fswcert-0.4/README	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/fswcert-0.4/README	Wed May 16 10:57:20 2001
@@ -0,0 +1,94 @@
+fswcert Utility
+===============
+
+
+This replaces the grabkey and grabsubject utilities from the
+FreeS/WAN X.509 patch, and supports the new configuration
+options leftcert=... and rightcert=...
+
+Dependencies:
+  fswcert requires the openssl 0.9.5a package.
+
+Bugs:
+  Due to openssl, the fswcert binary is HUGE.
+
+
+These are the options supported:
+--------------------------------
+
+-c --certificate	print certificate data
+
+	Prints the certificate data needed for FreeS/WAN's
+	ipsec.conf. Input can be from an X.509 file in PEM
+	or DER format, or from a PKCS12 (*.p12) file.
+
+-k --key	print private RSA key data
+
+	Prints the private key data needed for FreeS/WAN's
+	ipsec.secrets. Input can be from an RSA private key
+	file, or from a PKCS12 (*.p12) file.
+
+-l --left	left-side parameters for ipsec.conf
+
+	Prefix certificate data with `left'
+
+-r --right	right-side parameters for ipsec.conf
+
+	Prefix certificate data with `left'
+
+--type=[x509|rsa|pkcs12]	select input file type
+
+	Select input file type. Defaults to x509.
+
+--format=[PEM|DER]	select input file format
+
+	Select input file format. Defaults to PEM.
+
+-C --directory=dir	change into dir first
+
+	Change into dir at startup. (Files are then
+	read relative to this directory).
+
+-q --quiet	single line error messages to stdout
+
+	This is a hack to better integrate with _confread.
+	Don't use manually.
+
+-d --der-output		outputs DN in DER binary format
+
+	This is also a hack. Useful to give the CA the DN in DER
+	so that it can insert the 'subject' search field in its
+	LDAP tables. 
+
+-v --version	returns version of fswcert
+
+Either --key or --certificate is required. It makes no sense to
+specify both --left and --right; the last option wins.
+
+
+To use X.509 PEM-encoded certificates with FreeS/WAN directly, do this:
+-----------------------------------------------------------------------
+
+- Adjust the IPSECDIR and SSLDIR in Makefile
+
+- Build fswcert with `make'
+
+- Install fswcert with `make install'
+
+- Patch FreeS/WAN's _confread with the patch provided
+
+- Put all the certificates you want to use with FreeS/WAN
+  in the /etc/ipsec.d/ directory
+
+
+Then you can use these new options in ipsec.conf and includes:
+--------------------------------------------------------------
+
+leftcert=filename.pem
+	Reads the identity and public key from filename.pem
+	(Replaces both leftid=@~... and leftrsasigkex=0x...)
+
+rightcert=filename.pem
+	Reads the identity and public key from filename.pem
+	(Replaces both rightid=@~... and rightrsasigkex=0x...)
+
diff -BbruN freeswan-1.91.orig/utils/fswcert-0.4/_confread.patch freeswan-1.91/utils/fswcert-0.4/_confread.patch
--- freeswan-1.91.orig/utils/fswcert-0.4/_confread.patch	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/fswcert-0.4/_confread.patch	Wed May 16 10:57:20 2001
@@ -0,0 +1,51 @@
+--- freeswan-1.5/utils/_confread	Wed May 31 14:10:40 2000
++++ freeswan-1.5-x509/utils/_confread	Tue Sep 19 16:29:42 2000
+@@ -42,6 +42,7 @@
+ # fi
+ 
+ config=/etc/ipsec.conf
++fswcert="$IPSECDIR/fswcert --directory /etc/ipsec.d"
+ include=yes
+ type=conn
+ fieldfmt=yes
+@@ -71,7 +72,7 @@
+ else
+ 	cat $config
+ fi |
+-awk 'BEGIN {
++awk -v "fswcert=$fswcert" 'BEGIN {
+ 	type = "'"$type"'"
+ 	names = "'"$*"'"
+ 	prefix = "'"$prefix"'"
+@@ -122,6 +123,7 @@
+ 	mkey = " spibase spi esp espenckey espauthkey espreplay_window"
+ 	left = left " leftespenckey leftespauthkey leftahkey"
+ 	left = left " leftespspi leftahspi leftid leftrsasigkey"
++	left = left " leftcert"
+ 	mkey = mkey " ah ahkey ahreplay_window"
+ 	right = left
+ 	gsub(/left/, "right", right)
+@@ -313,6 +315,23 @@
+ 	value = substr($0, equal+1)
+ 	if (value ~ /^"/)
+ 		value = substr(value, 2, length(value)-2)
++}
++name ~ /^(left|right)cert$/ {
++	side = name
++	gsub(/cert$/, "", side)
++	pipe = fswcert " --quiet --cert " value
++	pipe | getline ID
++	pipe | getline RSASIGKEY
++	if (close(pipe) != 0)
++		fail(ID);
++	gsub(/^.*id=/, "", ID)
++	gsub(/^.*rsasigkey=/, "", RSASIGKEY)
++	seen[side "cert"] = 1
++	seen[side "id"] = 1
++	seen[side "rsasigkey"] = 1
++	output(o_parm, side "id", ID)
++	output(o_parm, side "rsasigkey", RSASIGKEY)
++	next
+ }
+ indefault {
+ 	if (name in default)
diff -BbruN freeswan-1.91.orig/utils/fswcert-0.4/fswcert.c freeswan-1.91/utils/fswcert-0.4/fswcert.c
--- freeswan-1.91.orig/utils/fswcert-0.4/fswcert.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/fswcert-0.4/fswcert.c	Wed May 16 11:20:34 2001
@@ -0,0 +1,550 @@
+/* Certificate and Private Key Format Conversions for FreeS/WAN
+ *
+ * Copyright (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <termio.h>
+
+#include <openssl/crypto.h>
+#include <openssl/buffer.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+struct option long_options[] = {
+	{"certificate",   0, 0, 'c'},
+	{"key",           0, 0, 'k'},
+	{"left",          0, 0, 'l'},
+	{"right",         0, 0, 'r'},
+	{"type",          1, 0,  1 },
+	{"format",        1, 0,  2 },
+	{"quiet",         0, 0, 'q'},
+	{"der-output",    0, 0, 'd'},
+	{"directory",     1, 0, 'C'},
+	{"version",       0, 0, 'v'},
+	{"help",          0, 0, 'h'},
+	{NULL,            0, 0,  0 }
+};
+
+int prompt_for_passwords = 0;
+const char *peer_prefix = NULL;
+int opt_quiet = 0;
+int der_output = 0;
+int der_binary = 0;
+const char *input_file = NULL;
+
+#define DUMP_CERTIFICATE	1
+#define DUMP_KEY		2
+int opt_what = 0;
+
+BIO *bio_err = NULL;
+
+enum input_file_type { IN_PKCS12 = 1, IN_X509 = 2, IN_RSA = 3 };
+enum input_format { FORMAT_ASN1 = 1, FORMAT_PEM = 3 };
+
+void print_errors(int ssl, const char *fmt, ...)
+{
+	if (fmt) {
+		va_list args;
+	
+		va_start(args, fmt);
+		if (input_file)
+			fprintf(stderr, "%s: ", input_file);
+		fprintf(stderr, "Error ");
+		vfprintf(stderr, fmt, args);
+		fprintf(stderr, "\n");
+		va_end(args);
+	}
+	if (ssl && !opt_quiet)
+		ERR_print_errors(bio_err);
+}
+
+const char *read_password(void)
+{
+	static char password[1024];
+	struct termio saved, no_echo;
+
+	printf("Password: ");
+
+	(void) ioctl(0, TCGETA, &saved);
+	no_echo = saved;
+	no_echo.c_lflag &= ~ECHO;
+	(void) ioctl(0, TCSETA, &no_echo);
+	fgets(password, sizeof(password), stdin);
+	(void) ioctl(0, TCSETA, &saved);
+	puts("");
+
+	if (strchr(password, '\n'))
+		*strchr(password, '\n') = '\0';
+	return password;
+}
+
+void BN_print_0(BIGNUM *num)
+{
+	int bits = BN_num_bits(num);
+
+	if ((bits-1) % 8 < 3)
+		putchar('0');
+	BN_print_fp(stdout, num);
+}
+
+#define print(what, num) do { \
+	printf("\t%s: 0x", what); \
+	BN_print_0(num); \
+	putchar('\n'); \
+	} while(0)
+
+int dump_rsa_private_key(RSA *rsa)
+{
+	if (rsa->d == NULL) {
+		print_errors(0, "no private exponent");
+		return 1;
+	}
+	if (opt_what & DUMP_KEY) {
+		print("Modulus", rsa->n);
+		print("PublicExponent", rsa->e);
+		print("PrivateExponent", rsa->d);
+		print("Prime1", rsa->p);
+		print("Prime2", rsa->q);
+		print("Exponent1", rsa->dmp1);
+		print("Exponent2", rsa->dmq1);
+		print("Coefficient", rsa->iqmp);
+	}
+	return 0;
+}
+
+#undef print
+
+int dump_x509_certificate(X509 *x509)
+{
+	BUF_MEM *subject;
+	EVP_PKEY *pkey;
+	RSA *rsa;
+	int i, error = 0;
+	char derbuf[256];
+	
+	if (!x509->cert_info || !x509->cert_info->subject ||
+            !x509->cert_info->subject->bytes) {
+		fprintf(stderr, "Certificate contains no subject\n");
+		return 1;
+	}
+	subject = &x509->cert_info->subject->bytes[0];
+
+	if (opt_what & DUMP_CERTIFICATE) {
+		if (!der_output) {
+			printf("\t%sid=@~", peer_prefix);
+			for (i = 0; i < subject->length; i++)
+				printf("%02X", (unsigned char)subject->data[i]);
+			printf("\n");
+		} else if (der_output) {
+			int derlen;
+			unsigned char *derbytes, *derout;
+
+			derlen=i2d_X509_NAME(x509->cert_info->subject, NULL);
+			derbytes=malloc(derlen);
+			derout=(unsigned char *)derbytes;
+
+			derlen=i2d_X509_NAME(X509_get_subject_name(x509), &derout);
+			derout=(unsigned char *)derbytes;
+
+			if (der_binary) {
+				for (i = 0; i < derlen; i++)
+					printf("%c", derout[i]);
+			} else {
+				X509_NAME_oneline(x509->cert_info->subject,
+					derbuf, 256);
+				printf("\t#%s DN: %s\n", peer_prefix, derbuf);
+				printf("\t%sid=@~", peer_prefix);
+				for (i = 0; i < derlen; i++)
+					printf("%02X", (unsigned char)derout[i]);
+				printf("\n");
+
+#if 0
+{ /* DEBUGGING ON */
+  X509_NAME *xn = X509_NAME_new();
+  char dnout[256];
+  if (xn == NULL) {
+    printf("\t#Unable to malloc X509_NAME *xn");
+  }
+
+  printf("\t#derlen = %d\n", derlen);
+  printf("\t#certlen = %d\n", certlen);
+
+  /* X509_NAME * d2i_X509_NAME(X509_NAME **a,unsigned char **pp,long length); 
+   */
+  xn = d2i_X509_NAME(&xn, &(derout), (long)derlen);
+
+  if (xn != NULL) {
+    X509_NAME_oneline(xn,dnout,256);
+    printf("\t#DNtest == %s\n", dnout);
+  } else {
+    printf("\t#Invalid DER string\n");
+  }
+} /* DEBUGGING OFF */
+#endif
+
+			}
+
+			free(derbytes);
+		}
+	}
+
+	pkey = X509_get_pubkey(x509);
+	if (pkey == NULL) {
+		print_errors(1, "getting public key");
+		return 1;
+	}
+	if (pkey->type != EVP_PKEY_RSA) {
+		print_errors(0, "not an RSA public key");
+		error = 1;
+		goto cleanup;
+	}
+	rsa = pkey->pkey.rsa;
+	
+#if 0
+	if (opt_what & DUMP_CERTIFICATE) {
+		int bytes = BN_num_bytes(rsa->e);
+		printf("\t%srsasigkey=0x%02X", peer_prefix, bytes);
+		BN_print_0(rsa->e);
+		BN_print_0(rsa->n);
+		putchar('\n');
+	}
+#endif
+
+cleanup:
+	EVP_PKEY_free(pkey);
+	return 0;
+}
+
+int read_pkcs12_safebag(PKCS12_SAFEBAG *bag, const char *password)
+{
+	PKCS8_PRIV_KEY_INFO *p8;
+	EVP_PKEY *pkey;
+	X509 *x509;
+	RSA *rsa;
+	int error = 0;
+	
+	switch (M_PKCS12_bag_type(bag)) {
+		case NID_keyBag:
+			p8 = bag->value.keybag;
+			pkey = EVP_PKCS82PKEY(p8);
+			if (!pkey) {
+				print_errors(1, "grabbing private key");
+				return 1;
+			}
+			rsa = EVP_PKEY_get1_RSA(pkey);
+			EVP_PKEY_free(pkey);
+			if (!rsa) {
+				print_errors(1, "getting RSA key");
+				return 1;
+			}
+			error = dump_rsa_private_key(rsa);
+			RSA_free(rsa);
+			break;
+
+		case NID_pkcs8ShroudedKeyBag:
+			p8 = M_PKCS12_decrypt_skey(bag, password, -1);
+			if (!p8) {
+				print_errors(1, "decrypting private key");
+				return 1;
+			}
+			pkey = EVP_PKCS82PKEY(p8);
+			PKCS8_PRIV_KEY_INFO_free(p8);
+			if (!pkey) {
+				print_errors(1, "grabbing private key");
+				return 1;
+			}
+			rsa = EVP_PKEY_get1_RSA(pkey);
+			EVP_PKEY_free(pkey);
+			if (!rsa) {
+				print_errors(1, "getting RSA private key");
+				return 1;
+			}
+			error = dump_rsa_private_key(rsa);
+			RSA_free(rsa);
+			break;
+
+		case NID_certBag:
+			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate){
+				print_errors(0, "not an X.509 certificate");
+				return 1;
+			}
+			/* only dump the key's certificate */
+			if (!PKCS12_get_attr(bag, NID_localKeyID))
+				return 0;
+			x509 = M_PKCS12_certbag2x509(bag);
+			if (!x509) {
+				print_errors(1, "grabbing certificate");
+				return 1;
+			}
+			if (dump_x509_certificate(x509))
+				return 1;
+			X509_free(x509);
+			break;
+
+		default:
+			/* other bag entry */
+	}
+	return error;
+}
+
+int read_pkcs12_file(BIO *bio_in)
+{
+	const char *password = "\0";
+	PKCS12 *p12;
+	STACK /* _OF(PKCS7) */ *asafes = NULL;
+	PKCS7 *p7;
+	int i;
+
+	p12 = d2i_PKCS12_bio (bio_in, NULL);
+	if (!p12) {
+		print_errors(1, "reading PKCS12 file");
+		return 1;
+	}
+	if (!PKCS12_verify_mac(p12, password, 0)) {
+		if (prompt_for_passwords)
+			password = read_password();
+		if (!prompt_for_passwords ||
+		    !PKCS12_verify_mac(p12, password, -1)) {
+			print_errors(1, "verifying MAC: wrong password?");
+			return 1;
+		}
+	}
+
+	/* Unpack PKCS12 file */
+	asafes = M_PKCS12_unpack_authsafes (p12);
+	if (!asafes) {
+		print_errors(1, "unpacking PKCS12 file");
+		return 1;
+	}
+	for (i = 0; i < sk_num(asafes); i++) {
+		int bagnid, j;
+		STACK /* _OK(PKCS12) */ *bags;
+
+		p7 = (PKCS7 *) sk_value(asafes, i);
+		bagnid = OBJ_obj2nid(p7->type);
+		if (bagnid == NID_pkcs7_data)
+			bags = M_PKCS12_unpack_p7data(p7);
+		else if (bagnid == NID_pkcs7_encrypted)
+			bags = M_PKCS12_unpack_p7encdata(p7, password, -1);
+		else
+			continue;
+		if (!bags) {
+			print_errors(1, "unpacking PKCS12 file");
+			return 1;
+		}
+		for (j = 0; j < sk_num(bags); j++) {
+			PKCS12_SAFEBAG *bag =
+				(PKCS12_SAFEBAG *)sk_value(bags, j);
+			if (read_pkcs12_safebag(bag, password))
+				return 1;
+		}
+		sk_pop_free(bags, PKCS12_SAFEBAG_free);
+	}
+	sk_pop_free(asafes, PKCS7_free);
+	return 0;
+}
+
+int read_x509_file(BIO *bio_in, enum input_format input_format)
+{
+	X509 *x509 = NULL;
+	int error;
+
+	if (input_format == FORMAT_PEM)
+		x509 = PEM_read_bio_X509(bio_in, NULL, NULL, NULL);
+	else if (input_format == FORMAT_ASN1)
+		x509 = d2i_X509_bio(bio_in, NULL);
+	if (!x509) {
+		print_errors(1, "reading X509 certificate");
+		return 1;
+	}
+	error = dump_x509_certificate(x509);
+	X509_free(x509);
+
+	return error;
+}
+
+int read_rsa_file(BIO *bio_in, enum input_format input_format)
+{
+	RSA *rsa = NULL;
+	int error;
+
+	if (input_format == FORMAT_PEM)
+		rsa = PEM_read_bio_RSAPrivateKey(bio_in, NULL, NULL, NULL);
+	else if (input_format == FORMAT_ASN1)
+		rsa = d2i_RSAPrivateKey_bio(bio_in, NULL);
+	if (!rsa) {
+                print_errors(1, "reading RSA private key");
+                return 1;
+        }
+	error = dump_rsa_private_key(rsa);
+	RSA_free(rsa);
+	return error;
+}
+
+int main(int argc, char *argv[])
+{
+	enum input_file_type input_file_type = 0;
+	enum input_format input_format = 0;
+	int error = 0, opt;
+
+	prompt_for_passwords = isatty(0) && isatty(1);
+
+	while ((opt = getopt_long(argc, argv, "cklrqd:C:hv",
+	                          long_options, NULL)) != -1) {
+		switch(opt) {
+			case 1:  /* input file type */
+				if (!strcmp(optarg, "pkcs12"))
+					input_file_type = IN_PKCS12;
+				else if (!strcmp(optarg, "x509"))
+					input_file_type = IN_X509;
+				else if (!strcmp(optarg, "rsa"))
+					input_file_type = IN_RSA;
+				else
+					goto synopsis;
+				break;
+
+			case 2:  /* input format */
+				if (!strcmp(optarg, "PEM"))
+					input_format = FORMAT_PEM;
+				else if (!strcmp(optarg, "DER"))
+					input_format = FORMAT_ASN1;
+				else
+					goto synopsis;
+				break;
+
+			case 'c':  /* certificate */
+				opt_what |= DUMP_CERTIFICATE;
+				if (!input_file_type)
+					input_file_type = IN_X509;
+				break;
+
+			case 'k':  /* key */
+				opt_what |= DUMP_KEY;
+				if (!input_file_type)
+					input_file_type = IN_RSA;
+				break;
+
+			case 'l':  /* left */
+				if (!opt_what)
+					opt_what = DUMP_CERTIFICATE;
+				peer_prefix = "left";
+				break;
+
+			case 'r':  /* right */
+				if (!opt_what)
+					opt_what = DUMP_CERTIFICATE;
+				peer_prefix = "right";
+				break;
+
+			case 'C':  /* change directory */
+				if (chdir(optarg) && errno) {
+					perror(optarg);
+					error = 1;
+				}
+				break;
+
+			case 'v':  /* print version and exit */
+				printf("%s " VERSION "\n", argv[0]);
+				return 0;
+
+			case 'q':  /* quiet */
+				opt_quiet = 1;
+				break;
+
+			case 'd':  /* output in DER */
+				der_output = 1;
+				if (!strcmp(optarg, "a")) { 
+					/* ascii */
+					der_binary = 0;
+				} else if (!strcmp(optarg, "b")) {
+					der_binary = 1;
+				} else {
+					goto synopsis;
+				}
+				break;
+
+			default:
+				goto synopsis;
+		}
+	}
+	if (peer_prefix == NULL)
+		peer_prefix = "";
+
+	if (optind+1 != argc || !opt_what)
+		goto synopsis;
+
+	if (!input_file_type)
+		input_file_type = IN_X509;
+	if (!input_format)
+		input_format = FORMAT_PEM;
+
+	if (opt_quiet)
+		dup2(1,2);  /* stderr is stdout (awk hack) */
+
+	ERR_load_crypto_strings();
+	SSLeay_add_all_algorithms();
+	bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
+	
+	while (optind < argc) {
+		BIO *bio_in;
+
+		input_file = argv[optind];
+		bio_in = BIO_new_file(input_file, "rb");
+		if (!bio_in) {
+			perror(input_file);
+			error = 1;
+		} else {
+			if (input_file_type == IN_PKCS12)
+				error |= read_pkcs12_file(bio_in);
+			else if (input_file_type == IN_X509)
+				error |= read_x509_file(bio_in, input_format);
+			else if (input_file_type == IN_RSA)
+				error |= read_rsa_file(bio_in, input_format);
+			BIO_free(bio_in);
+		}
+		optind++;
+	}
+
+	BIO_free(bio_err);
+
+	return error;
+
+synopsis:
+	fprintf(stderr, "SYNOPSIS: %s --cert|--key [--left|--right] "
+	        "options file\n", argv[0]);
+	if (!opt_quiet) {
+		fprintf(stderr, "\t-c --cert\tprint certificate data\n"
+		        "\t-k --key\tprint private RSA key data\n"
+		        "\t-l --left\tleft-side parameters for ipsec.conf\n"
+		        "\t-r --right\tright-side parameters for ipsec.conf\n"
+		        "\t   --type=[x509|rsa|pkcs12]\tselect input file type\n"
+		        "\t   --format=[PEM|DER]\tselect input file format\n"
+		        "\t-C --directory=dir\tchange into dir first\n"
+		        "\t-d [ab]\tprints out the DER\n"
+			
+		        "\t-q --quiet\tsingle line error messages to stdout\n");
+	}
+	return error;
+}
+
diff -BbruN freeswan-1.91.orig/utils/ipsec.conf.5 freeswan-1.91/utils/ipsec.conf.5
--- freeswan-1.91.orig/utils/ipsec.conf.5	Thu Jun 14 15:48:27 2001
+++ freeswan-1.91/utils/ipsec.conf.5	Mon Jun  4 10:47:28 2001
@@ -1,5 +1,5 @@
-.TH IPSEC.CONF 5 "14 June 2001"
-.\" RCSID $Id: ipsec.conf.5,v 1.70 2001/06/14 19:48:27 henry Exp $
+.TH IPSEC.CONF 5 "29 May 2001"
+.\" RCSID $Id: ipsec.conf.5,v 1.68 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec.conf \- IPsec configuration and connections
 .SH DESCRIPTION
@@ -850,8 +850,7 @@
 If the special value
 .B %search
 is used, all connections with
-.BR auto=add ,
-.BR auto=route ,
+.B auto=add
 or
 .B auto=start
 are loaded.
@@ -867,11 +866,6 @@
 If the special value
 .B %search
 is used, all connections with
-.B auto=route
-or
-.B auto=start
-are routed,
-and all connections with
 .B auto=start
 are started.
 .TP
@@ -887,11 +881,9 @@
 .BR no .
 .TP
 .B plutobackgroundload
-obsolete parameter, ignored, nominally specifying whether
-loading and starting of connections should be spun off as a background
-process to avoid startup delays.
-This is now always done.
-Values were
+should loading and starting of connections be spun off as a background
+process to avoid startup delays?
+Values are
 .B yes
 or
 .BR no
diff -BbruN freeswan-1.91.orig/utils/rehashcertdir freeswan-1.91/utils/rehashcertdir
--- freeswan-1.91.orig/utils/rehashcertdir	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/rehashcertdir	Wed May 16 10:57:20 2001
@@ -0,0 +1,38 @@
+#!/bin/sh 
+if [ "$1" = "" ];
+then 
+  echo "Error: No directory to process."
+  echo "Usage: $0 <directory>"
+  echo
+  exit 1
+fi
+
+if [ ! -d $1 ];
+then
+  echo "Error: "$1" is not a directory."
+  echo "Usage: $0 <directory>"
+  echo
+  exit 2
+fi
+
+cd $1
+for ii in *.pem; do
+  if [ "`basename $ii`" = "crl.pem" ];
+  then
+    ln -fs $ii `openssl crl -noout -hash -in crl.pem`.crl.0
+  else
+    ln -fs $ii `openssl x509 -noout -hash -in $ii`.cert.0
+    perl -e "open(IN, \"openssl x509 -in $ii -noout -text \|\"); \
+      @IN = <IN>; \
+      foreach (@IN) { \
+        if (/IP Address:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/) { \
+          system(\"ln -sf $ii `dirname $ii`/ip-\$1.cert.0\"); \
+        } \
+        if (/DNS:([^, ]*).*$/) { \
+          system(\"ln -sf $ii `dirname $ii`/dns-\$1.cert.0\"); \
+        } \
+      };"
+  fi
+done
+
+
diff -BbruN freeswan-1.91.orig/utils/rsakeygen freeswan-1.91/utils/rsakeygen
--- freeswan-1.91.orig/utils/rsakeygen	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/rsakeygen	Wed May 16 13:09:59 2001
@@ -0,0 +1,32 @@
+#!/bin/sh
+# use command line specified directory for rsakeys and publickey files,
+# otherwise use the current directory
+KEYDIR=/usr/local/lib/ipsec
+if [ $# -eq 1 ]
+then 
+  KEYDIR=$1
+fi
+
+# define variables
+KEYFILE=$KEYDIR/rsakeys
+PUBKEY=$KEYDIR/publickey
+IPSEC_SECRETS=/etc/ipsec.secrets
+
+
+# generate rsa keys 
+touch $KEYFILE
+chmod 600 $KEYFILE
+ipsec rsasigkey --random /dev/urandom 1024 > $KEYFILE
+chmod 400 $KEYFILE
+
+# extract public key to write to publickey file
+awk 'NR==3 {print $0}' $KEYFILE | cut -d= -f2 > $PUBKEY
+
+# write the rest part including private key to the ipsec.secrets file
+touch ${IPSEC_SECRETS}
+chmod 600 ${IPSEC_SECRETS}
+echo ": rsa {" > ${IPSEC_SECRETS}
+awk 'NR>3 {print $0}' $KEYFILE >> ${IPSEC_SECRETS}
+echo "	}" >> ${IPSEC_SECRETS}
+chmod 400 ${IPSEC_SECRETS}
+exit 0
diff -BbruN freeswan-1.91.orig/utils/setup freeswan-1.91/utils/setup
--- freeswan-1.91.orig/utils/setup	Wed Jun 13 16:10:07 2001
+++ freeswan-1.91/utils/setup	Mon Jun  4 11:29:01 2001
@@ -1,6 +1,6 @@
 #!/bin/sh
 # IPsec startup and shutdown script
-# Copyright (C) 1998, 1999, 2001  Henry Spencer.
+# Copyright (C) 1998, 1999  Henry Spencer.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: setup,v 1.109 2001/06/13 20:10:07 henry Exp $
+# RCSID $Id: setup,v 1.105 2001/06/01 15:49:14 henry Exp $
 #
 # ipsec         init.d script for starting and stopping
 #               the IPsec security subsystem (KLIPS and Pluto).
@@ -30,10 +30,6 @@
 # description: IPsec provides encrypted and authenticated communications; \
 # KLIPS is the kernel half of it, Pluto is the user-level management daemon.
 
-me='ipsec setup'		# for messages
-
-
-
 if test " $IPSEC_DIR" = " "	# if we were not called by the ipsec command
 then
 	# we must establish a suitable PATH ourselves
@@ -41,6 +37,19 @@
 	export PATH
 fi
 
+me='ipsec setup'		# for messages
+
+# make sure output of (e.g.) ifconfig is in English
+unset LANG LANGUAGE LC_ALL LC_MESSAGES
+
+# verify permissions
+if test " `id -u`" != " 0"
+then
+	echo "permission denied (must be superuser)" |
+		logger -s -p daemon.error -t ipsec_setup
+	exit 1
+fi
+
 # Check that the ipsec command is available.
 found=
 for dir in `echo $PATH | tr ':' ' '`
@@ -60,39 +69,587 @@
 
 # Pick up IPsec configuration (until we have done this, successfully, we
 # do not know where errors should go, hence the explicit "daemon.error"s.)
-# Note the "--export", which exports the variables created.
-eval `ipsec _confread --varprefix IPSEC --export --type config setup`
+eval `ipsec _confread --varprefix IPSEC --type config setup`
 if test " $IPSEC_confreadstatus" != " "
 then
 	echo "$IPSEC_confreadstatus -- \`$1' aborted" |
 		logger -s -p daemon.error -t ipsec_setup
 	exit 1
 fi
-IPSECsyslog=${IPSECsyslog-daemon.error}
-export IPSECsyslog
 
-# misc setup
+# Misc. paths (some of this should perhaps be overrideable from ipsec.conf).
+plutopid=/var/run/pluto.pid
+subsyslock=/var/lock/subsys/ipsec
+info=/var/run/ipsec.info
+sysflags=/proc/sys/net/ipsec
+modules=/proc/modules
+# full rp_filter path is $rpfilter1/interface/$rpfilter2
+rpfilter1=/proc/sys/net/ipv4/conf
+rpfilter2=rp_filter
+ipforward=/proc/sys/net/ipv4/ip_forward
+ipsecversion=/proc/net/ipsec_version
+
+# Misc. configuration (should perhaps be overrideable).
 umask 022
 
 
 
+# some shell functions, to clarify the actual code
+
+# start KLIPS
+startklips() {
+	# load module if necessary
+	if test ! -f $ipsecversion
+	then
+		if test -r $modules		# kernel does have modules
+		then
+			unset MODPATH MODULECONF	# no user overrides!
+			depmod -a >/dev/null 2>&1 && modprobe ipsec
+		fi
+		if test ! -f $ipsecversion
+		then
+			echo "Fatal error, kernel appears to lack KLIPS."
+			exit 1
+		fi
+	fi
+
+	# figure out debugging flags
+	case "$IPSECklipsdebug" in
+	'')	IPSECklipsdebug=none	;;
+	esac
+	echo "KLIPS debug \`$IPSECklipsdebug'" | logonly
+	case "$IPSECklipsdebug" in
+	none)	ipsec klipsdebug --none	;;
+	all)	ipsec klipsdebug --all	;;
+	*)	ipsec klipsdebug --none
+		for d in $IPSECklipsdebug
+		do
+			ipsec klipsdebug --set $d
+		done
+		;;
+	esac
+
+	# figure out misc. kernel config
+	if test -d $sysflags
+	then
+		sysflag "$IPSECfragicmp" "fragicmp" no icmp
+		echo 1 >$sysflags/inbound_policy_check	# no debate
+		sysflag no "no_eroute_pass" no no_eroute_pass	# obsolete parm
+		sysflag no "opportunistic" no opportunistic	# obsolete parm
+		sysflag "$IPSEChidetos" "hidetos" yes tos
+	else
+		echo "Cannot adjust kernel flags, no $sysflags directory!"
+	fi
+
+	# clear tables out in case dregs have been left over
+	ipsec eroute --clear
+	ipsec spi --clear
+
+	# figure out interfaces
+	for i in $IPSECinterfaces
+	do
+		case "$i" in
+		ipsec*=?*)	klipsinterface "$i"	;;
+		%defaultroute)	defaultinterface	;;
+		*)	echo "$me: interface \`$i' not understood, ignored" >&2
+			;;
+		esac
+	done
+
+	# set up default eroute if necessary
+	if test " $IPSECpacketdefault" = " "
+	then
+		case "$IPSECno_eroute_pass" in
+		''|no)	IPSECpacketdefault=drop	;;
+		yes)	IPSECpacketdefault=pass	;;
+		*)	echo "$me: unknown (not yes/no) no_eroute_pass value \`$IPSECno_eroute_pass'" >&2
+			IPSECpacketdefault=drop
+			;;
+		esac
+	fi
+	case "$IPSECpacketdefault" in
+	pass|reject)
+		ipsec eroute --label "packetdefault" --replace --eraf inet \
+			--src 0/0 --dst 0/0 --said "%$IPSECpacketdefault"
+		;;
+	drop)	;;
+	*)	echo "$me: unknown packetdefault value \`$IPSECpacketdefault'" >&2 ;;
+	esac
+}
+
+# set up a system flag based on a variable
+# sysflag value shortname default flagname
+sysflag() {
+	case "$1" in
+	'')	v="$3"	;;
+	*)	v="$1"	;;
+	esac
+	if test ! -f $sysflags/$4
+	then
+		if test " $v" != " $3"
+		then
+			echo "$me: cannot implement $2=$v because" >&2
+			echo "	$sysflags/$4 does not exist" >&2
+			return 1
+		else
+			return 0	# can't set it, but it's default anyway
+		fi
+	fi
+	case "$v" in
+	yes)	echo 1 >$sysflags/$4	;;
+	no)	echo 0 >$sysflags/$4	;;
+	*)	echo "Unknown (not yes/no) $2 value \`$1'"	;;
+	esac
+}
+
+# interfaces=%defaultroute:  put ipsec0 on top of default route's interface
+defaultinterface() {
+	phys=`netstat -nr |
+		awk '$1 == "0.0.0.0" && $3 == "0.0.0.0" { print $NF }'`
+	if test " $phys" = " "
+	then
+		echo "$me: no default route, %defaultroute cannot cope!!!" >&2
+		return			# really should exit, hard to arrange
+	fi
+	if test `echo " $phys" | wc -l` -gt 1
+	then
+		echo "$me: multiple default routes, %defaultroute cannot cope!!!" >&2
+		return			# really should exit, hard to arrange
+	fi
+	next=`netstat -nr |
+		awk '$1 == "0.0.0.0" && $3 == "0.0.0.0" { print $2 }'`
+	klipsinterface "ipsec0=$phys" $next
+}
+
+# set up a Klips interface
+klipsinterface() {
+	# pull apart the interface spec
+	virt=`expr $1 : '\([^=]*\)=.*'`
+	phys=`expr $1 : '[^=]*=\(.*\)'`
+
+	# figure out ifconfig for interface
+	addr=
+	eval `ifconfig $phys |
+		awk '$1 == "inet" && $2 ~ /^addr:/ && $4 ~ /^Mask:/ {
+			gsub(/:/, " ", $0)
+			print "addr=" $3
+			if ($4 == "Bcast")
+				print "type=broadcast"
+			else if ($4 == "P-t-P")
+				print "type=pointopoint"
+			else
+				print "type="
+			print "otheraddr=" $5
+			print "mask=" $7
+		}'`
+	if test " $addr" = " "
+	then
+		echo "$me: unable to determine address of \`$phys'" >&2
+		exit 1
+	fi
+	if test " $type" = " "
+	then
+		echo "$me: \`$phys' is of an unknown type, can't use it" >&2
+		return
+	fi
+	if test " $IPSECoverridemtu" != " "
+	then
+		mtu="mtu $IPSECoverridemtu"
+	else
+		mtu=
+	fi
+	echo "KLIPS $virt on $phys $addr/$mask $type $otheraddr $mtu" | logonly
+
+	# attach the interface and bring it up
+	ipsec tncfg --attach --virtual $virt --physical $phys
+	ifconfig $virt inet $addr $type $otheraddr netmask $mask $mtu
+
+	# if %defaultroute, note the facts
+	if test " $2" != " "
+	then
+		(
+			echo "defaultroutephys=$phys"
+			echo "defaultroutevirt=$virt"
+			echo "defaultrouteaddr=$addr"
+			if test " $2" != " 0.0.0.0"
+			then
+				echo "defaultroutenexthop=$2"
+			fi
+		) >>$info
+	else
+		echo '#dr: no default route' >>$info
+	fi
+
+	# check for advanced-router trouble
+	checkif $virt
+	checkif $phys
+}
+
+# check an interface for problems
+checkif() {
+	rpf=$rpfilter1/$1/$rpfilter2
+	if test -f $rpf
+	then
+		r="`cat $rpf`"
+		if test " $r" != " 0"
+		then
+			echo "WARNING: $1 has route filtering turned on, KLIPS may not work"
+			echo " ($rpf = \`$r', should be 0)"
+		fi
+	fi
+}
+
+# set up manually-keyed connections
+manualconns() {
+	if test " $IPSECmanualstart" != " "
+	then
+		for tu in $IPSECmanualstart
+		do
+			ipsec manual --up $tu
+		done
+	fi
+}
+
+# internal setup for Pluto start
+# sets up vars, so must do its own logging to avoid subprocess
+plutopre() {
+	# searches, if needed
+	if test " $IPSECplutoload" = " %search"
+	then
+		eval `ipsec _confread --varprefix PLUTO --search auto add start background`
+		if test " $PLUTO_confreadstatus" != " "
+		then
+			echo "plutoload: $PLUTO_confreadstatus" | logit
+			echo "unable to determine what conns to add" | logit
+			IPSECplutoload=
+		else
+			IPSECplutoload="$PLUTO_confreadnames"
+		fi
+	fi
+	if test " $IPSECplutostart" = " %search"
+	then
+		eval `ipsec _confread --varprefix PLUTO --search auto start`
+		if test " $PLUTO_confreadstatus" != " "
+		then
+			echo "plutostart: $PLUTO_confreadstatus" | logit
+			echo "unable to determine what conns to start" | logit
+			IPSECplutostart=
+		else
+			IPSECplutostart="$PLUTO_confreadnames"
+		fi
+	fi
+
+	# ensure plutoload > plutoroute > plutostart
+	for s in $IPSECplutostart
+	do
+		found=
+		for lo in $IPSECplutoroute
+		do
+			if test " $lo" = " $s"
+			then
+				found=yes
+			fi
+		done
+		if test ! "$found"
+		then
+			IPSECplutoroute="$IPSECplutoroute $s"
+		fi
+	done
+	for s in $IPSECplutoroute
+	do
+		found=
+		for lo in $IPSECplutoload
+		do
+			if test " $lo" = " $s"
+			then
+				found=yes
+			fi
+		done
+		if test ! "$found"
+		then
+			IPSECplutoload="$IPSECplutoload $s"
+		fi
+	done
+
+	# execute any preliminaries
+	if test " $IPSECprepluto" != " "
+	then
+		$IPSECprepluto 2>&1 | logit
+	fi
+}
+
+# start Pluto daemon
+plutodaemon() {
+	# double-check one little detail
+	if test ! -e /dev/urandom
+	then
+		echo "Cannot start Pluto, system lacks /dev/urandom !!!"
+		exit 1
+	fi
+
+	# figure out options
+	pd=
+	for d in $IPSECplutodebug
+	do
+		pd="$pd --debug-$d"
+	done
+	case "$IPSECuniqueids" in
+	yes)	pd="$pd --uniqueids"	;;
+	no|'')				;;
+	*)	echo "Unknown uniqueids value (not yes/no) \`$IPSECuniqueids'"	;;
+	esac
+
+	# do it
+	if test " $IPSECdumpdir" = " "
+	then
+		ulimit -c 0			# preclude core dumps
+	elif test ! -d "$IPSECdumpdir"
+	then
+		echo "Dumpdir \`$IPSECdumpdir' does not exist, ignored."
+		ulimit -c 0			# preclude core dumps
+	else
+		cd $IPSECdumpdir		# put them where desired
+		ulimit -c unlimited		# and permit them
+	fi
+	echo "Pluto debug \`$IPSECplutodebug'" | logonly
+	ipsec pluto $pd
+}
+
+# Pluto subsystem startup and cleanup, after daemon is running
+plutopost() {
+	# database load
+	if test " $IPSECplutoload" != " "
+	then
+		echo "$IPSECplutoload" | tr ' ' '\n' | column -x -c 100 |
+			tr -s '\t ' '  ' |
+			while read bunch
+			do
+				for tu in $bunch
+				do
+					ipsec auto --add $tu
+				done
+			done
+	fi
+
+	# enable listening
+	ipsec auto --ready
+
+	# execute any cleanup
+	if test " $IPSECpostpluto" != " "
+	then
+		$IPSECpostpluto
+	fi
+
+	# quickly establish routing
+	if test " $IPSECplutoroute" != " "
+	then
+		echo "$IPSECplutoroute" | 
+			tr ' ' '\n' | column -x -c 100 |
+			tr -s '\t ' '  ' |
+			while read bunch
+			do
+				for tu in $bunch
+				do
+					ipsec auto --route $tu
+				done
+			done
+	fi
+}
+
+# Pluto negotiation start (if any)
+plutogo() {
+	# tunnel initiation, which may take a while
+	if test " $IPSECplutostart" != " "
+	then
+		async=
+		p=
+		if test " $IPSECplutowait" = " no"
+		then
+			async="--asynchronous"
+			p=" (asynchronously)"
+		fi
+		for tu in $IPSECplutostart
+		do
+			#echo "Initiating Pluto tunnel \`$tu'$p:"
+			ipsec auto --up $async $tu
+		done
+	fi
+}
+
+# logging control
+logit() {
+	IPSECsyslog=${IPSECsyslog-daemon.error}
+	logger -s -p $IPSECsyslog -t ipsec_setup 2>&1
+}
+logonly() {
+	IPSECsyslog=${IPSECsyslog-daemon.error}
+	logger -p $IPSECsyslog -t ipsec_setup
+}
+
+
+
+# the mainline code
+
+# backward compatibility, defaults.
+if test " $IPSECdump" = " yes" -a " $IPSECdumpdir" = " "
+then
+	IPSECdumpdir=/var/tmp
+fi
+
 # do it
 case "$1" in
-  start|--start|stop|--stop)
-	if test " `id -u`" != " 0"
+  start|--start)
+	# Start things rolling.
+	# First, does it seem to be going already?
+	if test -f $info
 	then
-		echo "permission denied (must be superuser)" |
-			logger -s -p $IPSECsyslog -t ipsec_setup 2>&1
+		echo "FreeS/WAN IPsec apparently already running, start aborted!" | logit
+		exit 1
+	fi
+	# announcement
+	# (Warning, changes to this log message may affect barf.)
+	version="`ipsec --version | awk 'NR == 1 { print $3 }'`"
+	echo "Starting FreeS/WAN IPsec $version..." | logit
+	rm -f $info
+	if test ! -r /dev/random
+	then
+		echo "...unable to start FreeS/WAN IPsec, no /dev/random!" |
+									logit
+		exit 1
+	fi
+	if test ! -r /dev/urandom
+	then
+		echo "...unable to start FreeS/WAN IPsec, no /dev/urandom!" |
+									logit
+		exit 1
+	fi
+	>$info
+	if test ! -r $info
+	then
+		echo "...unable to create $info, aborting start!" | logit
 		exit 1
 	fi
-	tmp=/var/run/ipsec_setup.st
+	startklips 2>&1 | logit
+	if test ! -f $ipsecversion	# hard to test startklips exit status
+	then
+		echo "No KLIPS, cannot continue IPsec startup!"
+		rm -f $info
+		exit 1
+	fi
+	if test -d `dirname $subsyslock`
+	then
+		touch $subsyslock
+	fi
+	manualconns 2>&1 | logit
+	if test " $IPSECpluto" = " no"
+	then
+		pluto=no
+	elif test " $IPSECplutobackgroundload" = " yes"
+	then
+		pluto=back
+	else
+		pluto=fore
+	fi
+	case $pluto in
+	fore|back)
+		plutopre
+		plutodaemon 2>&1 | logit
+		sleep 1				# give it a moment to get going
+		;;
+	esac
+	case $pluto in
+	fore)	plutopost 2>&1 | logit				;;
+	back)	( plutopost ; plutogo ) 2>&1 | logonly &	;;
+	esac
+	fw=`cat $ipforward`
+	if test " $IPSECforwardcontrol" = " yes" -a " $fw" = " 0"
+	then
+		echo "Enabling IP forwarding:" | logonly
+		echo "ipforwardingwas=$fw" >>$info
+		echo 1 >$ipforward
+	fi
+	case $pluto in
+	fore)	plutogo 2>&1 | logit	;;
+	esac
+	echo "...FreeS/WAN IPsec started" | logonly
+
+	echo "Starting background tunnels..." | logit
+	$0 --startbacktunnels
+	;;
+
+  stop|--stop)
+	# Shut things down.
+	if test -r $info
+	then
+		echo "Stopping FreeS/WAN IPsec..." | logit
+		status=0
+		. $info
+	else
+		echo "Stop ordered, but IPsec does not appear to be running!" |
+									logit
+		echo "Doing cleanup anyway..." | logit
+		status=1
+	fi
+	if test " $IPSECforwardcontrol" = " yes" -a " $ipforwardingwas" = " 0"
+	then
+		echo "Disabling IP forwarding:" | logonly
+		echo 0 >$ipforward
+	fi
+	if test ! -f $plutopid
+	then
+		: nothing
+	elif test ! -s $plutopid
+	then
+		echo "Removing empty $plutopid -- pluto still running?" | logit
+		rm -f $plutopid
+	elif kill -0 `cat $plutopid` 2>/dev/null
+	then
+	  (
+		# kill pluto in 30 secs no matter what.
 	(
-		ipsec _realsetup $1
-		echo "$?" >$tmp
-	) 2>&1 | logger -s -p $IPSECsyslog -t ipsec_setup 2>&1
-	st=`cat $tmp`
-	rm -f $tmp
-	exit $st
+			sleep 30
+			echo "30 second timeout expired. Killing Pluto." | logit
+			kill -9 $plutopid &> /dev/null
+		) &> /dev/null &
+		killpid=$!
+		ipsec whack --shutdown | awk '$1 != "002"' | logit
+		sleep 1			# general paranoia
+		# kill the killpid if we still need to.
+		if kill -0 $killpid &> /dev/null ; then
+			kill -9 $killpid &> /dev/null
+		fi
+	  ) 2> /dev/null
+		if test -s $plutopid
+		then
+			echo "Pluto did not go away!  Killing it:" | logit
+			kill `cat $plutopid` 2>&1 | logit
+			sleep 5
+		fi
+		rm -f $plutopid		# harmless if already gone
+	else
+		echo "Removing orphaned $plutopid:" | logit
+		rm -f $plutopid
+	fi
+	for i in `ifconfig | awk '/^ipsec/ { print $1 }'`
+	do
+		ifconfig $i down 2>&1 | logit
+		ipsec tncfg --detach --virtual $i 2>&1 | logit
+	done
+	ipsec klipsdebug --none 2>&1 | logit
+	ipsec eroute --clear 2>&1 | logit
+	ipsec spi --clear 2>&1 | logit
+	i=`lsmod 2>&1 | awk '$1 == "ipsec" { print $1 }'`
+	if test " $i" = " ipsec"
+	then
+		rmmod ipsec 2>&1 | logit
+	fi
+	if test -d `dirname $subsyslock`
+	then
+		rm -f $subsyslock
+	fi
+	rm -f $info
+	echo "...FreeS/WAN IPsec stopped" | logonly
+	exit $status
 	;;
 
   restart|--restart)
@@ -101,8 +658,94 @@
 	;;
 
   status|--status)
-	ipsec _realsetup $1
-	exit
+	if test -f $info
+	then
+		hasinfo=yes
+	fi
+
+	if test -f $subsyslock
+	then
+		haslock=yes
+	fi
+
+	if test -s $plutopid
+	then
+		if ps -p `cat $plutopid` >/dev/null
+		then
+			haspluto=yes
+			plutokind=normal
+		elif ps -C pluto >/dev/null
+		then
+			haspluto=yes
+			plutokind=illicit
+		fi
+	elif ps -C pluto >/dev/null
+	then
+		haspluto=yes
+		plutokind=orphaned
+	fi
+
+	if test -r /proc/net/ipsec_eroute -a \
+		" `wc -l </proc/net/ipsec_eroute`" -gt 0
+	then
+		eroutes=yes
+	fi
+
+	if test -r $ipsecversion
+	then
+		klips=yes
+	elif test -r $modules
+	then
+		klips=maybe
+	else
+		klips=none
+	fi
+               
+	if test "$hasinfo"
+	then
+		echo "started"
+		# might not be a subsystem lock dir, ignore that issue
+		if test "$plutokind" = "normal" -a "$klips" = "yes"
+		then
+			exit 0
+		fi
+		echo "but..."
+		if test ! "$haspluto"
+		then
+			echo "no Pluto running!"
+		else
+			echo "$plutokind Pluto running!"
+		fi
+		case $klips in
+		maybe)  echo "KLIPS module is not loaded!"      ;;
+		none)   echo "no KLIPS in kernel!"              ;;
+		esac
+		if test "$eroutes"
+		then
+		echo "some eroutes exist"
+		fi
+		exit 1
+	else
+		echo "stopped"
+		if test ! "$haslock" -a ! "$haspluto" -a ! "$eroutes"
+		then
+			exit 0
+		fi
+		echo "but..."
+		if test "$haslock"
+		then
+			echo "has subsystem lock!"
+		fi
+		if test "$haspluto"
+		then
+			echo "$plutokind Pluto is running!"
+		fi
+		if test "$eroutes"
+		then
+		echo "some eroutes exist!"
+		fi
+		exit 1
+	fi
 	;;
 
   --version)
@@ -113,6 +756,26 @@
   --help)
 	echo "Usage: $me {--start|--stop|--restart|--status}"
 	exit 0
+	;;
+ 
+  startbacktunnels|--startbacktunnels)
+	(
+	eval `ipsec _confread --varprefix PLUTO --search auto background`
+	if test " $PLUTO_confreadstatus" != " "
+	then
+		echo "$PLUTO_confreadstatus (start search) -- aborting" |
+								logit
+		exit 1
+	fi
+	IPSECplutobackground="$PLUTO_confreadnames"
+
+	(
+	for TUNNEL in $IPSECplutobackground ; 
+	do
+	  ipsec auto --up $TUNNEL 
+	done
+	) &>/dev/null 
+	) &
 	;;
 
   *)
diff -BbruN freeswan-1.91.orig/utils/setup.8 freeswan-1.91/utils/setup.8
--- freeswan-1.91.orig/utils/setup.8	Thu Jun 14 15:45:13 2001
+++ freeswan-1.91/utils/setup.8	Mon Jun  4 10:37:06 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_SETUP 8 "7 June 2001"
-.\" RCSID $Id: setup.8,v 1.31 2001/06/14 19:45:13 henry Exp $
+.TH IPSEC_SETUP 8 "31 May 2001"
+.\" RCSID $Id: setup.8,v 1.29 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec setup \- control IPsec subsystem
 .SH SYNOPSIS
@@ -54,11 +54,9 @@
 .B status
 report the status of the subsystem;
 normally just reports
-.B "IPsec running"
-and
-.BR "pluto pid \fInnn\fP" ,
+.B started
 or
-.BR "IPsec stopped" ,
+.B stopped
 and exits with status 0,
 but will go into more detail (and exit with status 1)
 if something strange is found.
@@ -97,12 +95,12 @@
 .B start
 and
 .B stop
-goes both to standard
+invoke goes both to standard
 output and to
-.IR syslogd (8),
+.IR syslogd (8)
 via
 .IR logger (1).
-Selected additional information is logged only to
+The script itself logs selected information to
 .IR syslogd (8).
 .SH HISTORY
 Written for the FreeS/WAN project
@@ -111,4 +109,8 @@
 .SH BUGS
 Old versions of
 .IR logger (1)
-inject spurious extra newlines onto standard output.
+injected spurious extra newlines onto standard output.
+.PP
+Startup failure is not consistently reported in the exit status.
+.PP
+The normal status report probably should include Pluto's process ID.
diff -BbruN freeswan-1.91.orig/utils/showhostkey freeswan-1.91/utils/showhostkey
--- freeswan-1.91.orig/utils/showhostkey	Mon Jun 11 22:50:03 2001
+++ freeswan-1.91/utils/showhostkey	Mon Jun  4 11:29:24 2001
@@ -1,6 +1,6 @@
 #! /bin/sh
-# show key for this host, in DNS (or other) format
-# Copyright (C) 2000, 2001  Henry Spencer.
+# show key for this host, in DNS format
+# Copyright (C) 2000  Henry Spencer.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
@@ -12,15 +12,14 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: showhostkey,v 1.9 2001/06/12 02:50:03 henry Exp $
+# RCSID $Id: showhostkey,v 1.8 2001/06/01 15:49:14 henry Exp $
 
 me="ipsec showhostkey"
-usage="Usage: $me [--file secrets] [--left] [--right] [--txt gateway] [--id id]"
+usage="Usage: $me [--file secrets] [--left] [--right] [--txt gateway]"
 
 file=/etc/ipsec.secrets
 fmt="dns"
 gw=
-id=
 for dummy
 do
 	case "$1" in
@@ -28,7 +27,6 @@
 	--left)	fmt="left"		;;
 	--right)	fmt="right"	;;
 	--txt)	fmt="txt" ; gw="$2" ; shift	;;
-	--id)	id="$2" ; shift		;;
 	--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
 	--help)	echo "$usage" ; exit 0	;;
 	--)	shift ; break		;;
@@ -65,19 +63,10 @@
 		file = "'"$file"'"
 		fmt = "'"$fmt"'"
 		gw = "'"$gw"'"
-		id = "'"$id"'"
 		comment = ""
-		s = "[ \t]+"
-		os = "[ \t]*"
-		x = "[^ \t]+"
-		suffix = ":" s "RSA" s "{$"
-		if (id == "")
-			pat = "^" suffix
-		else
-			pat = "^(" x s ")*" id "(" s x ")*" os suffix
 		status = 0
 	}
-	$0 ~ pat {
+	/^:[ \t]+RSA[ \t]+{$/ {
 		inkey = 1
 		seenkey = 1
 	}
diff -BbruN freeswan-1.91.orig/utils/showhostkey.8 freeswan-1.91/utils/showhostkey.8
--- freeswan-1.91.orig/utils/showhostkey.8	Mon Jun 11 22:50:03 2001
+++ freeswan-1.91/utils/showhostkey.8	Mon Jun  4 11:29:24 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_SHOWHOSTKEY 8 "11 June 2001"
-.\" RCSID $Id: showhostkey.8,v 1.7 2001/06/12 02:50:03 henry Exp $
+.TH IPSEC_SHOWHOSTKEY 8 "22 May 2001"
+.\" RCSID $Id: showhostkey.8,v 1.6 2001/05/31 21:59:17 henry Exp $
 .SH NAME
 ipsec showhostkey \- show host's authentication key
 .SH SYNOPSIS
@@ -15,9 +15,6 @@
 ] [
 .B \-\-file
 secretfile
-] [
-.B \-\-id
-identity
 ]
 .SH DESCRIPTION
 .I Showhostkey
@@ -62,10 +59,6 @@
       IN TXT  "X-IPsec-Server(10)=10.11.12.13 AQOF8tZ2...+buFuFn/"
 .fi
 .PP
-No name is supplied in the TXT record
-because there are too many possibilities,
-depending on how it will be used.
-.PP
 The
 .B \-\-left
 and
@@ -87,14 +80,6 @@
   leftrsasigkey=0x0103cc2a86fcf440...cf1011abb82d1
 .fi
 .PP
-Normally, the default key for this host is the one extracted.
-The
-.B \-\-id
-option overrides this,
-causing extraction of the key labeled with the specified
-.IR identity ,
-if any.
-.PP
 The
 .B \-\-file
 option overrides the default for where the key information should be
@@ -132,10 +117,6 @@
 currently it is hardwired to
 .BR 10 .
 .PP
-The
-.B \-\-id
-option assumes that the
-.I identity
-appears on the same line as the
-.B ":\ RSA\ {"
-that begins the key proper.
+Assumes there is only one RSA key in
+.IR ipsec.secrets ,
+which is common but not necessarily universal.
diff -BbruN freeswan-1.91.orig/utils/updown.firewall freeswan-1.91/utils/updown.firewall
--- freeswan-1.91.orig/utils/updown.firewall	Wed Dec 31 19:00:00 1969
+++ freeswan-1.91/utils/updown.firewall	Wed May 16 10:57:20 2001
@@ -0,0 +1,166 @@
+#! /bin/sh
+# sample updown script for ipchains
+# Copyright (C) 2000  D. Hugh Redelmeier, Henry Spencer
+# sample updown script for iptables
+# Copyright (C) 2000  Luc Lanthier
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: updown.firewall,v 1.1.2.9 2001/03/27 18:44:16 lanthierl Exp $
+#
+# Modifications: Add ipchains rules specific to Netwinder OfficeServer to
+# let FreeS/WAN work with the firewall. Dacheng Tang
+
+KERNVER=`uname -r | cut -d. -f 1,2`
+
+# check interface version
+case "$PLUTO_VERSION" in
+1.0)    echo "$0: Pluto interface version 1.0 is obsolete." >&2
+        ;;
+1.1)    ;;
+*)      echo "$0: unknown interface version \`$PLUTO_VERSION'" >&2
+        exit 2
+        ;;
+esac
+
+# check parameter(s)
+case "$*" in
+'')     ;;
+*)      echo "$0: parameters unexpected" >&2
+        exit 2
+        ;;
+esac
+
+# utility functions for route manipulation
+# Meddling with this stuff should never be necessary and is most unwise.
+uproute() {
+    route add -net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK \
+      dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP
+      st=$?
+      if test $st -ne 0
+      then
+        # route has already given its own cryptic message
+        echo "$0: \`route $1 $parms' failed" >&2
+      fi
+      return $st
+}
+
+downroute() {
+    route del -net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK \
+      dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP 
+      st=$?
+      if test $st -ne 0
+      then
+        # route has already given its own cryptic message
+        echo "$0: \`route $1 $parms' failed" >&2
+      fi
+      return $st
+
+}
+
+# the big choice
+case "$PLUTO_VERB" in
+prepare-host|prepare-client)
+        # delete possibly-existing route (preliminary to adding a route)
+        oops="`route del -net $PLUTO_PEER_CLIENT_NET \
+                                        netmask $PLUTO_PEER_CLIENT_MASK 2>&1`"
+        status="$?"
+        if test " $oops" = " " -a " $status" != " 0"
+        then
+                oops="silent error in route command, exit status $status"
+        fi
+        case "$oops" in
+        'SIOCDELRT: No such process')
+                # This is what route (currently -- not documented!) gives
+                # for "could not find such a route".
+                status=0
+                ;;
+        esac
+        exit $status
+        ;;
+route-host|route-client)
+        # connection to this host or client being routed
+        uproute
+        ;;
+unroute-host|unroute-client)
+        # connection to this host or client being unrouted
+        downroute
+        ;;
+up-host)
+        # connection to this host coming up
+        ;;
+down-host)
+        # connection to this host going down
+        ;;
+up-client)
+  if [ "$KERNVER" = "2.2" ];
+  then
+	# add an input rule to let KLIPS decapsulated packets pass ipsec0
+	ipchains -A input -i $PLUTO_INTERFACE -j ACCEPT -p all \
+		-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, coming up
+        ipchains -I forward -j ACCEPT -b \
+                -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+                -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+  elif [ "$KERNVER" = "2.4" ];
+  then
+    # add an input rule to let KLIPS decapsulated packets pass ipsec0
+    iptables -A INPUT -i $PLUTO_INTERFACE -j ACCEPT \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, coming up
+    iptables -I FORWARD -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    iptables -I FORWARD -j ACCEPT \
+        -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+    if ( iptables -t nat -L -n &> /dev/null ) ; then
+      iptables -t nat -I POSTROUTING -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    fi
+  fi
+  ;;
+down-client)
+  if [ "$KERNVER" = "2.2" ];
+  then
+	# delete the input rule for the KLIPS decapsulated packets 
+	ipchains -D input -i $PLUTO_INTERFACE -j ACCEPT -p all \
+		-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, going down
+        ipchains -D forward -j ACCEPT -b \
+                -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+                -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+  elif [ "$KERNVER" = "2.4" ];
+  then
+    # delete the input rule for the KLIPS decapsulated packets
+    iptables -D INPUT -i $PLUTO_INTERFACE -j ACCEPT \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, going down
+    iptables -D FORWARD -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    iptables -D FORWARD -j ACCEPT \
+        -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+    if ( iptables -t nat -L -n &> /dev/null ) ; then
+      iptables -t nat -D POSTROUTING -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    fi
+  fi
+  # force a zero error code even the ipchains command(s) failed
+  echo "ok"
+  ;;
+*)      echo "$0: unknown verb \`$PLUTO_VERB' or parameter \`$1'" >&2
+        exit 1
+        ;;
+esac
diff -BbruN freeswan-1.91.orig/version.c freeswan-1.91/version.c
--- freeswan-1.91.orig/version.c	Wed May 30 09:02:20 2001
+++ freeswan-1.91/version.c	Tue Jul  3 04:02:51 2001
@@ -1,2 +1,2 @@
 /* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
-static const char freeswan_version[] = "1.91";
+static const char freeswan_version[] = "FreeSWAN-1.91-pkix1";
