summaryrefslogtreecommitdiff
path: root/src/pluto
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2009-06-23 11:25:24 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2009-06-23 11:25:24 +0000
commit41787e147279ff0695e9d759487266a60b80867b (patch)
tree8f28566c8fd7106c80d2536d2df540dbb4499cc5 /src/pluto
parentc3e7f611ea8273c6b3909cb006ade4903a74aad0 (diff)
downloadvyos-strongswan-41787e147279ff0695e9d759487266a60b80867b.tar.gz
vyos-strongswan-41787e147279ff0695e9d759487266a60b80867b.zip
[svn-upgrade] Integrating new upstream version, strongswan (4.3.2)
Diffstat (limited to 'src/pluto')
-rw-r--r--src/pluto/Makefile.am52
-rw-r--r--src/pluto/Makefile.in239
-rw-r--r--src/pluto/TODO129
-rw-r--r--src/pluto/ac.c1575
-rw-r--r--src/pluto/ac.h56
-rw-r--r--src/pluto/adns.c726
-rw-r--r--src/pluto/adns.h56
-rw-r--r--src/pluto/alg/ike_alg_aes.c68
-rw-r--r--src/pluto/alg/ike_alg_blowfish.c52
-rw-r--r--src/pluto/alg/ike_alg_serpent.c70
-rw-r--r--src/pluto/alg/ike_alg_sha2.c634
-rw-r--r--src/pluto/alg/ike_alg_twofish.c85
-rw-r--r--src/pluto/alg/ike_alginit.c7
-rw-r--r--src/pluto/alg_info.c1539
-rw-r--r--src/pluto/alg_info.h69
-rw-r--r--src/pluto/asn1.c787
-rw-r--r--src/pluto/asn1.h141
-rw-r--r--src/pluto/ca.c923
-rw-r--r--src/pluto/ca.h42
-rw-r--r--src/pluto/certs.c374
-rw-r--r--src/pluto/certs.h63
-rw-r--r--src/pluto/connections.c6574
-rw-r--r--src/pluto/connections.h270
-rw-r--r--src/pluto/constants.c1071
-rw-r--r--src/pluto/constants.h1013
-rw-r--r--src/pluto/cookie.c68
-rw-r--r--src/pluto/cookie.h8
-rw-r--r--src/pluto/crl.c1197
-rw-r--r--src/pluto/crl.h34
-rw-r--r--src/pluto/crypto.c997
-rw-r--r--src/pluto/crypto.h91
-rw-r--r--src/pluto/db_ops.c541
-rw-r--r--src/pluto/db_ops.h36
-rw-r--r--src/pluto/defs.c346
-rw-r--r--src/pluto/defs.h97
-rw-r--r--src/pluto/demux.c3950
-rw-r--r--src/pluto/demux.h64
-rw-r--r--src/pluto/dnskey.c2609
-rw-r--r--src/pluto/dnskey.h70
-rw-r--r--src/pluto/dsa.c476
-rw-r--r--src/pluto/dsa.h32
-rw-r--r--src/pluto/elgamal.c613
-rw-r--r--src/pluto/elgamal.h35
-rw-r--r--src/pluto/fetch.c1293
-rw-r--r--src/pluto/fetch.h28
-rw-r--r--src/pluto/foodgroups.c606
-rw-r--r--src/pluto/foodgroups.h4
-rw-r--r--src/pluto/gcryptfix.c283
-rw-r--r--src/pluto/gcryptfix.h111
-rw-r--r--src/pluto/id.c672
-rw-r--r--src/pluto/id.h34
-rw-r--r--src/pluto/ike_alg.c775
-rw-r--r--src/pluto/ike_alg.h86
-rw-r--r--src/pluto/ipsec_doi.c8810
-rw-r--r--src/pluto/ipsec_doi.h80
-rw-r--r--src/pluto/kameipsec.h46
-rw-r--r--src/pluto/kernel.c4621
-rw-r--r--src/pluto/kernel.h204
-rw-r--r--src/pluto/kernel_alg.c1163
-rw-r--r--src/pluto/kernel_alg.h2
-rw-r--r--src/pluto/kernel_netlink.c1748
-rw-r--r--src/pluto/kernel_netlink.h2
-rw-r--r--src/pluto/kernel_noklips.c60
-rw-r--r--src/pluto/kernel_noklips.h2
-rw-r--r--src/pluto/kernel_pfkey.c1212
-rw-r--r--src/pluto/kernel_pfkey.h2
-rw-r--r--src/pluto/keys.c2249
-rw-r--r--src/pluto/keys.h79
-rw-r--r--src/pluto/lex.c268
-rw-r--r--src/pluto/lex.h20
-rw-r--r--src/pluto/log.c1115
-rw-r--r--src/pluto/log.h104
-rw-r--r--src/pluto/md2.c237
-rw-r--r--src/pluto/md2.h72
-rw-r--r--src/pluto/md5.c385
-rw-r--r--src/pluto/md5.h75
-rw-r--r--src/pluto/modecfg.c1773
-rw-r--r--src/pluto/modecfg.h2
-rw-r--r--src/pluto/mp_defs.c70
-rw-r--r--src/pluto/mp_defs.h36
-rw-r--r--src/pluto/nat_traversal.c1279
-rw-r--r--src/pluto/nat_traversal.h62
-rw-r--r--src/pluto/ocsp.c2396
-rw-r--r--src/pluto/ocsp.h64
-rw-r--r--src/pluto/packet.c1286
-rw-r--r--src/pluto/packet.h312
-rw-r--r--src/pluto/pem.c485
-rw-r--r--src/pluto/pem.h10
-rw-r--r--src/pluto/pgp.c647
-rw-r--r--src/pluto/pgpcert.c496
-rw-r--r--src/pluto/pgpcert.h (renamed from src/pluto/pgp.h)42
-rw-r--r--src/pluto/pkcs1.c676
-rw-r--r--src/pluto/pkcs1.h88
-rw-r--r--src/pluto/pkcs7.c1341
-rw-r--r--src/pluto/pkcs7.h32
-rw-r--r--src/pluto/plutomain.c1125
-rw-r--r--src/pluto/primegen.c593
-rw-r--r--src/pluto/rcv_whack.c1013
-rw-r--r--src/pluto/rcv_whack.h2
-rw-r--r--src/pluto/rnd.c250
-rw-r--r--src/pluto/rnd.h21
-rw-r--r--src/pluto/server.c1434
-rw-r--r--src/pluto/server.h28
-rw-r--r--src/pluto/sha1.c193
-rw-r--r--src/pluto/sha1.h16
-rw-r--r--src/pluto/smallprime.c122
-rw-r--r--src/pluto/smartcard.c2746
-rw-r--r--src/pluto/smartcard.h56
-rw-r--r--src/pluto/spdb.c3779
-rw-r--r--src/pluto/spdb.h84
-rw-r--r--src/pluto/state.c1358
-rw-r--r--src/pluto/state.h276
-rw-r--r--src/pluto/timer.c875
-rw-r--r--src/pluto/timer.h16
-rw-r--r--src/pluto/vendor.c795
-rw-r--r--src/pluto/vendor.h254
-rw-r--r--src/pluto/virtual.c411
-rw-r--r--src/pluto/virtual.h6
-rw-r--r--src/pluto/x509.c3375
-rw-r--r--src/pluto/x509.h137
-rw-r--r--src/pluto/xauth.c74
-rw-r--r--src/pluto/xauth.h18
122 files changed, 37886 insertions, 46595 deletions
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am
index f788bc3d1..01237305b 100644
--- a/src/pluto/Makefile.am
+++ b/src/pluto/Makefile.am
@@ -7,7 +7,6 @@ ipsec_PROGRAMS = pluto _pluto_adns
pluto_SOURCES = \
ac.c ac.h \
alg_info.c alg_info.h \
-asn1.c asn1.h \
ca.c ca.h \
certs.c certs.h \
connections.c connections.h \
@@ -19,11 +18,8 @@ db_ops.c db_ops.h \
defs.c defs.h \
demux.c demux.h \
dnskey.c dnskey.h \
-dsa.c dsa.h \
-elgamal.c elgamal.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
-gcryptfix.c gcryptfix.h \
id.c id.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
@@ -36,23 +32,16 @@ kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
-md2.c md2.h \
-md5.c md5.h \
modecfg.c modecfg.h \
-mp_defs.c mp_defs.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
pem.c pem.h \
-pgp.c pgp.h \
-pkcs1.c pkcs1.h \
+pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \
plutomain.c \
-primegen.c smallprime.c \
rcv_whack.c rcv_whack.h \
-rnd.c rnd.h \
server.c server.h \
-sha1.c sha1.h \
smartcard.c smartcard.h \
spdb.c spdb.h \
state.c state.h \
@@ -61,22 +50,17 @@ vendor.c vendor.h \
virtual.c virtual.h \
xauth.c xauth.h \
x509.c x509.h \
-alg/ike_alg_aes.c alg/ike_alg_blowfish.c alg/ike_alg_twofish.c \
-alg/ike_alg_serpent.c alg/ike_alg_sha2.c alg/ike_alginit.c \
rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
_pluto_adns_SOURCES = adns.c adns.h
-LIBSTRONGSWANDIR=$(top_srcdir)/src/libstrongswan
+LIBSTRONGSWANDIR=$(top_builddir)/src/libstrongswan
LIBFREESWANDIR=$(top_builddir)/src/libfreeswan
-LIBCRYPTODIR=$(top_builddir)/src/libcrypto
-
INCLUDES = \
-I${linuxdir} \
--I$(LIBSTRONGSWANDIR)\
+-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
--I$(top_srcdir)/src/libcrypto \
-I$(top_srcdir)/src/whack
AM_CFLAGS = \
@@ -84,24 +68,23 @@ AM_CFLAGS = \
-DIPSEC_CONFDIR=\"${confdir}\" \
-DIPSEC_PIDDIR=\"${piddir}\" \
-DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \
+-DIPSEC_PLUGINDIR=\"${plugindir}\" \
+-DPLUGINS=\""${pluto_plugins}\"" \
+-DSTRONGSWAN_CONF=\"${strongswan_conf}\" \
-DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES \
-DPLUTO -DKLIPS -DDEBUG
pluto_LDADD = \
-oid.o \
+$(LIBSTRONGSWANDIR)/libstrongswan.la \
$(LIBFREESWANDIR)/libfreeswan.a \
-$(LIBCRYPTODIR)/libcrypto.a \
--lgmp -lresolv -lpthread -ldl
+-lresolv -lpthread $(DLLIB)
_pluto_adns_LDADD = \
$(LIBFREESWANDIR)/libfreeswan.a \
--lresolv -ldl
+-lresolv $(DLLIB)
dist_man_MANS = pluto.8 ipsec.secrets.5
-oid.o : $(LIBSTRONGSWANDIR)/asn1/oid.c $(LIBSTRONGSWANDIR)/asn1/oid.h
- $(COMPILE) -c -o $@ $<
-
# This compile option activates the sending of a strongSwan VID
if USE_VENDORID
AM_CFLAGS += -DVENDORID
@@ -122,23 +105,16 @@ if USE_NAT_TRANSPORT
AM_CFLAGS += -DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
endif
-# This compile option activates dynamic URL fetching using libcurl
-if USE_CURL
- pluto_LDADD += -lcurl
- AM_CFLAGS += -DLIBCURL
-endif
-
-# This compile option activates dynamic LDAP CRL fetching
-if USE_LDAP
- pluto_LDADD += -lldap -llber
- AM_CFLAGS += -DLIBLDAP
-endif
-
# This compile option activates smartcard support
if USE_SMARTCARD
AM_CFLAGS += -DSMARTCARD
endif
+# This compile option activates the integrity test of libstrongswan
+if USE_INTEGRITY_TEST
+ AM_CFLAGS += -DINTEGRITY_TEST
+endif
+
if USE_CAPABILITIES
pluto_LDADD += -lcap
endif
diff --git a/src/pluto/Makefile.in b/src/pluto/Makefile.in
index 457f93d9f..01bda8540 100644
--- a/src/pluto/Makefile.in
+++ b/src/pluto/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -50,21 +50,16 @@ ipsec_PROGRAMS = pluto$(EXEEXT) _pluto_adns$(EXEEXT)
# This compile option activates NAT traversal with IPSec transport mode
@USE_NAT_TRANSPORT_TRUE@am__append_4 = -DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
-# This compile option activates dynamic URL fetching using libcurl
-@USE_CURL_TRUE@am__append_5 = -lcurl
-@USE_CURL_TRUE@am__append_6 = -DLIBCURL
-
-# This compile option activates dynamic LDAP CRL fetching
-@USE_LDAP_TRUE@am__append_7 = -lldap -llber
-@USE_LDAP_TRUE@am__append_8 = -DLIBLDAP
-
# This compile option activates smartcard support
-@USE_SMARTCARD_TRUE@am__append_9 = -DSMARTCARD
-@USE_CAPABILITIES_TRUE@am__append_10 = -lcap
-@USE_THREADS_TRUE@am__append_11 = -DTHREADS
+@USE_SMARTCARD_TRUE@am__append_5 = -DSMARTCARD
+
+# This compile option activates the integrity test of libstrongswan
+@USE_INTEGRITY_TEST_TRUE@am__append_6 = -DINTEGRITY_TEST
+@USE_CAPABILITIES_TRUE@am__append_7 = -lcap
+@USE_THREADS_TRUE@am__append_8 = -DTHREADS
subdir = src/pluto
DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in TODO
+ $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -77,34 +72,28 @@ ipsecPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(ipsec_PROGRAMS)
am__pluto_adns_OBJECTS = adns.$(OBJEXT)
_pluto_adns_OBJECTS = $(am__pluto_adns_OBJECTS)
-_pluto_adns_DEPENDENCIES = $(LIBFREESWANDIR)/libfreeswan.a
-am_pluto_OBJECTS = ac.$(OBJEXT) alg_info.$(OBJEXT) asn1.$(OBJEXT) \
- ca.$(OBJEXT) certs.$(OBJEXT) connections.$(OBJEXT) \
- constants.$(OBJEXT) cookie.$(OBJEXT) crl.$(OBJEXT) \
- crypto.$(OBJEXT) db_ops.$(OBJEXT) defs.$(OBJEXT) \
- demux.$(OBJEXT) dnskey.$(OBJEXT) dsa.$(OBJEXT) \
- elgamal.$(OBJEXT) fetch.$(OBJEXT) foodgroups.$(OBJEXT) \
- gcryptfix.$(OBJEXT) id.$(OBJEXT) ike_alg.$(OBJEXT) \
- ipsec_doi.$(OBJEXT) kernel.$(OBJEXT) kernel_alg.$(OBJEXT) \
- kernel_netlink.$(OBJEXT) kernel_noklips.$(OBJEXT) \
- kernel_pfkey.$(OBJEXT) keys.$(OBJEXT) lex.$(OBJEXT) \
- log.$(OBJEXT) md2.$(OBJEXT) md5.$(OBJEXT) modecfg.$(OBJEXT) \
- mp_defs.$(OBJEXT) nat_traversal.$(OBJEXT) ocsp.$(OBJEXT) \
- packet.$(OBJEXT) pem.$(OBJEXT) pgp.$(OBJEXT) pkcs1.$(OBJEXT) \
- pkcs7.$(OBJEXT) plutomain.$(OBJEXT) primegen.$(OBJEXT) \
- smallprime.$(OBJEXT) rcv_whack.$(OBJEXT) rnd.$(OBJEXT) \
- server.$(OBJEXT) sha1.$(OBJEXT) smartcard.$(OBJEXT) \
- spdb.$(OBJEXT) state.$(OBJEXT) timer.$(OBJEXT) \
- vendor.$(OBJEXT) virtual.$(OBJEXT) xauth.$(OBJEXT) \
- x509.$(OBJEXT) ike_alg_aes.$(OBJEXT) \
- ike_alg_blowfish.$(OBJEXT) ike_alg_twofish.$(OBJEXT) \
- ike_alg_serpent.$(OBJEXT) ike_alg_sha2.$(OBJEXT) \
- ike_alginit.$(OBJEXT)
-pluto_OBJECTS = $(am_pluto_OBJECTS)
am__DEPENDENCIES_1 =
-pluto_DEPENDENCIES = oid.o $(LIBFREESWANDIR)/libfreeswan.a \
- $(LIBCRYPTODIR)/libcrypto.a $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+_pluto_adns_DEPENDENCIES = $(LIBFREESWANDIR)/libfreeswan.a \
+ $(am__DEPENDENCIES_1)
+am_pluto_OBJECTS = ac.$(OBJEXT) alg_info.$(OBJEXT) ca.$(OBJEXT) \
+ certs.$(OBJEXT) connections.$(OBJEXT) constants.$(OBJEXT) \
+ cookie.$(OBJEXT) crl.$(OBJEXT) crypto.$(OBJEXT) \
+ db_ops.$(OBJEXT) defs.$(OBJEXT) demux.$(OBJEXT) \
+ dnskey.$(OBJEXT) fetch.$(OBJEXT) foodgroups.$(OBJEXT) \
+ id.$(OBJEXT) ike_alg.$(OBJEXT) ipsec_doi.$(OBJEXT) \
+ kernel.$(OBJEXT) kernel_alg.$(OBJEXT) kernel_netlink.$(OBJEXT) \
+ kernel_noklips.$(OBJEXT) kernel_pfkey.$(OBJEXT) keys.$(OBJEXT) \
+ lex.$(OBJEXT) log.$(OBJEXT) modecfg.$(OBJEXT) \
+ nat_traversal.$(OBJEXT) ocsp.$(OBJEXT) packet.$(OBJEXT) \
+ pem.$(OBJEXT) pgpcert.$(OBJEXT) pkcs7.$(OBJEXT) \
+ plutomain.$(OBJEXT) rcv_whack.$(OBJEXT) server.$(OBJEXT) \
+ smartcard.$(OBJEXT) spdb.$(OBJEXT) state.$(OBJEXT) \
+ timer.$(OBJEXT) vendor.$(OBJEXT) virtual.$(OBJEXT) \
+ xauth.$(OBJEXT) x509.$(OBJEXT)
+pluto_OBJECTS = $(am_pluto_OBJECTS)
+pluto_DEPENDENCIES = $(LIBSTRONGSWANDIR)/libstrongswan.la \
+ $(LIBFREESWANDIR)/libfreeswan.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -141,6 +130,7 @@ CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
@@ -163,6 +153,9 @@ LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
@@ -174,6 +167,7 @@ MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
@@ -187,6 +181,8 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
RANLIB = @RANLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
@@ -247,6 +243,7 @@ oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
piddir = @piddir@
plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
@@ -258,6 +255,7 @@ srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
xml_CFLAGS = @xml_CFLAGS@
@@ -265,7 +263,6 @@ xml_LIBS = @xml_LIBS@
pluto_SOURCES = \
ac.c ac.h \
alg_info.c alg_info.h \
-asn1.c asn1.h \
ca.c ca.h \
certs.c certs.h \
connections.c connections.h \
@@ -277,11 +274,8 @@ db_ops.c db_ops.h \
defs.c defs.h \
demux.c demux.h \
dnskey.c dnskey.h \
-dsa.c dsa.h \
-elgamal.c elgamal.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
-gcryptfix.c gcryptfix.h \
id.c id.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
@@ -294,23 +288,16 @@ kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
-md2.c md2.h \
-md5.c md5.h \
modecfg.c modecfg.h \
-mp_defs.c mp_defs.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
pem.c pem.h \
-pgp.c pgp.h \
-pkcs1.c pkcs1.h \
+pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \
plutomain.c \
-primegen.c smallprime.c \
rcv_whack.c rcv_whack.h \
-rnd.c rnd.h \
server.c server.h \
-sha1.c sha1.h \
smartcard.c smartcard.h \
spdb.c spdb.h \
state.c state.h \
@@ -319,34 +306,33 @@ vendor.c vendor.h \
virtual.c virtual.h \
xauth.c xauth.h \
x509.c x509.h \
-alg/ike_alg_aes.c alg/ike_alg_blowfish.c alg/ike_alg_twofish.c \
-alg/ike_alg_serpent.c alg/ike_alg_sha2.c alg/ike_alginit.c \
rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
_pluto_adns_SOURCES = adns.c adns.h
-LIBSTRONGSWANDIR = $(top_srcdir)/src/libstrongswan
+LIBSTRONGSWANDIR = $(top_builddir)/src/libstrongswan
LIBFREESWANDIR = $(top_builddir)/src/libfreeswan
-LIBCRYPTODIR = $(top_builddir)/src/libcrypto
INCLUDES = \
-I${linuxdir} \
--I$(LIBSTRONGSWANDIR)\
+-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
--I$(top_srcdir)/src/libcrypto \
-I$(top_srcdir)/src/whack
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_CONFDIR=\"${confdir}\" \
-DIPSEC_PIDDIR=\"${piddir}\" \
-DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \
- -DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES -DPLUTO \
- -DKLIPS -DDEBUG $(am__append_1) $(am__append_2) \
- $(am__append_3) $(am__append_4) $(am__append_6) \
- $(am__append_8) $(am__append_9) $(am__append_11)
-pluto_LDADD = oid.o $(LIBFREESWANDIR)/libfreeswan.a \
- $(LIBCRYPTODIR)/libcrypto.a -lgmp -lresolv -lpthread -ldl \
- $(am__append_5) $(am__append_7) $(am__append_10)
+ -DIPSEC_PLUGINDIR=\"${plugindir}\" \
+ -DPLUGINS=\""${pluto_plugins}\"" \
+ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" -DKERNEL26_SUPPORT \
+ -DKERNEL26_HAS_KAME_DUPLICATES -DPLUTO -DKLIPS -DDEBUG \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_8)
+pluto_LDADD = $(LIBSTRONGSWANDIR)/libstrongswan.la \
+ $(LIBFREESWANDIR)/libfreeswan.a -lresolv -lpthread $(DLLIB) \
+ $(am__append_7)
_pluto_adns_LDADD = \
$(LIBFREESWANDIR)/libfreeswan.a \
--lresolv -ldl
+-lresolv $(DLLIB)
dist_man_MANS = pluto.8 ipsec.secrets.5
all: all-am
@@ -357,8 +343,8 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@@ -426,7 +412,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ac.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adns.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg_info.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ca.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connections.Po@am__quote@
@@ -438,19 +423,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnskey.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elgamal.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/foodgroups.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcryptfix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/id.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg_aes.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg_blowfish.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg_serpent.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg_sha2.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg_twofish.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alginit.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_doi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_alg.Po@am__quote@
@@ -460,24 +436,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keys.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lex.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md2.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modecfg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp_defs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat_traversal.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pgp.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pgpcert.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs7.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plutomain.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/primegen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcv_whack.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rnd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smallprime.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smartcard.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spdb.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Po@am__quote@
@@ -508,90 +476,6 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-ike_alg_aes.o: alg/ike_alg_aes.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_aes.o -MD -MP -MF $(DEPDIR)/ike_alg_aes.Tpo -c -o ike_alg_aes.o `test -f 'alg/ike_alg_aes.c' || echo '$(srcdir)/'`alg/ike_alg_aes.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_aes.Tpo $(DEPDIR)/ike_alg_aes.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_aes.c' object='ike_alg_aes.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_aes.o `test -f 'alg/ike_alg_aes.c' || echo '$(srcdir)/'`alg/ike_alg_aes.c
-
-ike_alg_aes.obj: alg/ike_alg_aes.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_aes.obj -MD -MP -MF $(DEPDIR)/ike_alg_aes.Tpo -c -o ike_alg_aes.obj `if test -f 'alg/ike_alg_aes.c'; then $(CYGPATH_W) 'alg/ike_alg_aes.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_aes.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_aes.Tpo $(DEPDIR)/ike_alg_aes.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_aes.c' object='ike_alg_aes.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_aes.obj `if test -f 'alg/ike_alg_aes.c'; then $(CYGPATH_W) 'alg/ike_alg_aes.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_aes.c'; fi`
-
-ike_alg_blowfish.o: alg/ike_alg_blowfish.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_blowfish.o -MD -MP -MF $(DEPDIR)/ike_alg_blowfish.Tpo -c -o ike_alg_blowfish.o `test -f 'alg/ike_alg_blowfish.c' || echo '$(srcdir)/'`alg/ike_alg_blowfish.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_blowfish.Tpo $(DEPDIR)/ike_alg_blowfish.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_blowfish.c' object='ike_alg_blowfish.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_blowfish.o `test -f 'alg/ike_alg_blowfish.c' || echo '$(srcdir)/'`alg/ike_alg_blowfish.c
-
-ike_alg_blowfish.obj: alg/ike_alg_blowfish.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_blowfish.obj -MD -MP -MF $(DEPDIR)/ike_alg_blowfish.Tpo -c -o ike_alg_blowfish.obj `if test -f 'alg/ike_alg_blowfish.c'; then $(CYGPATH_W) 'alg/ike_alg_blowfish.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_blowfish.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_blowfish.Tpo $(DEPDIR)/ike_alg_blowfish.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_blowfish.c' object='ike_alg_blowfish.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_blowfish.obj `if test -f 'alg/ike_alg_blowfish.c'; then $(CYGPATH_W) 'alg/ike_alg_blowfish.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_blowfish.c'; fi`
-
-ike_alg_twofish.o: alg/ike_alg_twofish.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_twofish.o -MD -MP -MF $(DEPDIR)/ike_alg_twofish.Tpo -c -o ike_alg_twofish.o `test -f 'alg/ike_alg_twofish.c' || echo '$(srcdir)/'`alg/ike_alg_twofish.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_twofish.Tpo $(DEPDIR)/ike_alg_twofish.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_twofish.c' object='ike_alg_twofish.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_twofish.o `test -f 'alg/ike_alg_twofish.c' || echo '$(srcdir)/'`alg/ike_alg_twofish.c
-
-ike_alg_twofish.obj: alg/ike_alg_twofish.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_twofish.obj -MD -MP -MF $(DEPDIR)/ike_alg_twofish.Tpo -c -o ike_alg_twofish.obj `if test -f 'alg/ike_alg_twofish.c'; then $(CYGPATH_W) 'alg/ike_alg_twofish.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_twofish.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_twofish.Tpo $(DEPDIR)/ike_alg_twofish.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_twofish.c' object='ike_alg_twofish.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_twofish.obj `if test -f 'alg/ike_alg_twofish.c'; then $(CYGPATH_W) 'alg/ike_alg_twofish.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_twofish.c'; fi`
-
-ike_alg_serpent.o: alg/ike_alg_serpent.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_serpent.o -MD -MP -MF $(DEPDIR)/ike_alg_serpent.Tpo -c -o ike_alg_serpent.o `test -f 'alg/ike_alg_serpent.c' || echo '$(srcdir)/'`alg/ike_alg_serpent.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_serpent.Tpo $(DEPDIR)/ike_alg_serpent.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_serpent.c' object='ike_alg_serpent.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_serpent.o `test -f 'alg/ike_alg_serpent.c' || echo '$(srcdir)/'`alg/ike_alg_serpent.c
-
-ike_alg_serpent.obj: alg/ike_alg_serpent.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_serpent.obj -MD -MP -MF $(DEPDIR)/ike_alg_serpent.Tpo -c -o ike_alg_serpent.obj `if test -f 'alg/ike_alg_serpent.c'; then $(CYGPATH_W) 'alg/ike_alg_serpent.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_serpent.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_serpent.Tpo $(DEPDIR)/ike_alg_serpent.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_serpent.c' object='ike_alg_serpent.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_serpent.obj `if test -f 'alg/ike_alg_serpent.c'; then $(CYGPATH_W) 'alg/ike_alg_serpent.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_serpent.c'; fi`
-
-ike_alg_sha2.o: alg/ike_alg_sha2.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_sha2.o -MD -MP -MF $(DEPDIR)/ike_alg_sha2.Tpo -c -o ike_alg_sha2.o `test -f 'alg/ike_alg_sha2.c' || echo '$(srcdir)/'`alg/ike_alg_sha2.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_sha2.Tpo $(DEPDIR)/ike_alg_sha2.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_sha2.c' object='ike_alg_sha2.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_sha2.o `test -f 'alg/ike_alg_sha2.c' || echo '$(srcdir)/'`alg/ike_alg_sha2.c
-
-ike_alg_sha2.obj: alg/ike_alg_sha2.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alg_sha2.obj -MD -MP -MF $(DEPDIR)/ike_alg_sha2.Tpo -c -o ike_alg_sha2.obj `if test -f 'alg/ike_alg_sha2.c'; then $(CYGPATH_W) 'alg/ike_alg_sha2.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_sha2.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alg_sha2.Tpo $(DEPDIR)/ike_alg_sha2.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alg_sha2.c' object='ike_alg_sha2.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alg_sha2.obj `if test -f 'alg/ike_alg_sha2.c'; then $(CYGPATH_W) 'alg/ike_alg_sha2.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alg_sha2.c'; fi`
-
-ike_alginit.o: alg/ike_alginit.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alginit.o -MD -MP -MF $(DEPDIR)/ike_alginit.Tpo -c -o ike_alginit.o `test -f 'alg/ike_alginit.c' || echo '$(srcdir)/'`alg/ike_alginit.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alginit.Tpo $(DEPDIR)/ike_alginit.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alginit.c' object='ike_alginit.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alginit.o `test -f 'alg/ike_alginit.c' || echo '$(srcdir)/'`alg/ike_alginit.c
-
-ike_alginit.obj: alg/ike_alginit.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_alginit.obj -MD -MP -MF $(DEPDIR)/ike_alginit.Tpo -c -o ike_alginit.obj `if test -f 'alg/ike_alginit.c'; then $(CYGPATH_W) 'alg/ike_alginit.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alginit.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_alginit.Tpo $(DEPDIR)/ike_alginit.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alg/ike_alginit.c' object='ike_alginit.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_alginit.obj `if test -f 'alg/ike_alginit.c'; then $(CYGPATH_W) 'alg/ike_alginit.c'; else $(CYGPATH_W) '$(srcdir)/alg/ike_alginit.c'; fi`
-
mostlyclean-libtool:
-rm -f *.lo
@@ -608,8 +492,8 @@ install-man5: $(man5_MANS) $(man_MANS)
esac; \
done; \
for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
+ if test -f $$i; then file=$$i; \
+ else file=$(srcdir)/$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
5*) ;; \
@@ -653,8 +537,8 @@ install-man8: $(man8_MANS) $(man_MANS)
esac; \
done; \
for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
+ if test -f $$i; then file=$$i; \
+ else file=$(srcdir)/$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
8*) ;; \
@@ -693,7 +577,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
@@ -871,9 +755,6 @@ uninstall-man: uninstall-man5 uninstall-man8
uninstall-ipsecPROGRAMS uninstall-man uninstall-man5 \
uninstall-man8
-
-oid.o : $(LIBSTRONGSWANDIR)/asn1/oid.c $(LIBSTRONGSWANDIR)/asn1/oid.h
- $(COMPILE) -c -o $@ $<
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/pluto/TODO b/src/pluto/TODO
deleted file mode 100644
index 1c22b2f5c..000000000
--- a/src/pluto/TODO
+++ /dev/null
@@ -1,129 +0,0 @@
-Pluto TODO list
-===============
-RCSID $Id: TODO 3269 2007-10-08 20:03:02Z andreas $
-
-- should all log entries that are for errors say ERROR?
-
-- Add a "plug-in" facility so that others can add features without
- changing the mainline code. This is how X509/LDAP/biometric stuff
- might be added.
-
-- (internal change only) routines for outputting payloads should plug
- "np" into the previous payload so that a payload generating routine
- need not know what the next payload will be. This may be more bother
- than it is worth.
-
-- notifications, in and out
- + delete
- + first contact
- + last contact? (not part of drafts, but would be nice)
-
-- Make DNS usage for asynchronous (non-blocking)
- + looking up KEY and TXT records during negotiation
- + perhaps not for whack command arguments and ipsec.secrets since the
- library code uses gethostbyname
-
-- check that ipsec auto and whack to agree on what is worth reporting
-
-- Should Pluto (rather than ipsec manual) install %passthrough conns?
- That way Pluto would know of them.
-
-- For responding to Road Warriors, how can we decide if the RW has
- gone away? The rekeying event is perhaps too imprecise. Even if
- rekeying event is good enough, how do we know if the route should be
- torn down? Perhaps limiting a Phase 1 ID to one IP address would
- help (limiting a client subnet to one peer already helps). Perhaps
- (in some rate-limited way) we can take an ICMP host unreachable
- as a hint to do some authenticated and reliable probe.
-
-- it is annoying that Pluto and auto have different models for public keys.
- + auto specifies one per connection
- + Pluto allows one to be specified per id
- Two connections with the same id are going to use the same key:
- the one of the last conn to be added!
-
- I think auto ought to be fixed. It is hard for Pluto to warn when
- there is a conflict since the deletion of a connection doesn't
- prompt auto to tell pluto to delete the public key.
-
-- different connections with the same host IP addresses are randomly
- interchangeable until the ID payload is received. At least for the
- Responder case (and eventually for the opportunistic Initiator).
- Worse, all Road Warriors must be considered to have the
- indistinguishable IP addresses. This affects ISAKMP SA negotiation.
- Currently, there is little flexibility in this negotiation, so the
- problem is limited to the specification of acceptable authentication
- method(s). Correct, but more work than seems worthwhile, would be
- to select the conn based on what is proposed.
-
- Warning about such confusion at connection definition time isn't great
- because there is no confusion when explicitly initiated (a particular
- conn is specified). Warning for a Road Warrior conn is possible
- since it cannot be initiated (and has been implemented).
-
-- characterize and ameliorate DOS attacks. Lots of rate limiting.
-
-- look at John Denker's wish list: http://www.quintillion.com/moat/wish.list
-
-- use of random numbers needs to be audited.
-
-- unknown (not just unimplemented) transforms cause a negotiation to
- fail. Only the transform should be rejected.
-
-- we need better policy control. Our present flags need to be
- modulated (forbid, allow, offer, require)
-
-- HS will specify how --copyright and --version should behave
-
-- HS will initiate project-wide terminology replacing ISAKMP SA, IPSEC
- SA, Protection Suite, Phase 1, Main Mode, Phase 2, Quick Mode, ...
- Simplicity and clarity will be a goal.
-
-- interface discovery ought to match what is specified in ipsec.conf.
- This probably means grokking /proc/net/ipsec_tncfg. Documented in
- ipsec_tncfg(5). This won't do for Hugh's debugging setup.
-
-
-Protocol Issues
-===============
-
-Notification and delete payloads seem to be "escape hatches" for the
-protocols. As such, anything implemented using them seems to be
-kludged without being well designed or well situated or well
-constrained in the protocols. Often the precise meaning (if any) or
-usage is under specified. An implementation is allowed to ignore
-them, so they cannot really matter (but they too often do). Their
-specification ought to be scrutinized by a protocol guru.
-
-Any extra payload in last main mode message is not protected (not
-authenticated by hash).
-
-Should notification payloads be interpreted before or after the normal
-payloads (i.e. understood in the context of, executed in the context of).
-
-What is the precise result of an INITIAL_CONNECTION? What is a
-"system" (eg. does Phase 1 Identity count)? What is "earlier" or
-"before" (simultaneous negotiation is possible, with time being only a
-partial order)? Could it be used for FINAL_CONTACT (needed too)?
-
-Blasting out a pile of UDP messages, especially to a particular
-destination, is likely to provoke message loss. The exchanges are
-just that, so they individually are self-throttling. But what about
-multiple exchanges simultaneously? What about notifications (example:
-when shutting down, a flurry of delete notifications are likely).
-Should the RFCs be designed to protect against this problem?
-
-draft-jenkins-ipsec-rekeying-03.txt rekeying is way too complicated.
-Our solution looks sound and simple (we have the Responder install the
-incoming IPSEC SA before sending its first reply). In "2.2.1.4
-Responder Pre-Set-up Security Hole", the draft claims that setting up
-the IPSEC SA early leaves the Responder open to replay attacks. I
-think that this is wrong: the Message Id, since it must not be reused,
-serves to prove that this isn't a replay.
-
-The details for notification messages suggested by
-draft-ietf-ipsec-notifymsg-02.txt are over-complicated, just to make
-them machine-comprehensible. I think this is over-engineering,
-justified only if another level of negotiation is contemplated (ugh!).
-Plain text is probably sufficient for informing humans (I admit that
-there is a problem with I18N).
diff --git a/src/pluto/ac.c b/src/pluto/ac.c
index 6745ff484..3b5df9738 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -11,8 +11,6 @@
* 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: ac.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -25,10 +23,11 @@
#include <freeswan.h>
-#include "constants.h"
-#include "defs.h"
-#include "asn1.h"
+#include <utils.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
#include <asn1/oid.h>
+
#include "ac.h"
#include "x509.h"
#include "crl.h"
@@ -38,971 +37,947 @@
#include "whack.h"
#include "fetch.h"
-/* chained list of X.509 attribute certificates */
-
+/**
+ * Chained list of X.509 attribute certificates
+ */
static x509acert_t *x509acerts = NULL;
-/* chained list of ietfAttributes */
-
+/**
+ * Chained list of ietfAttributes
+ */
static ietfAttrList_t *ietfAttributes = NULL;
-/* ASN.1 definition of ietfAttrSyntax */
-
+/**
+ * ASN.1 definition of ietfAttrSyntax
+ */
static const asn1Object_t ietfAttrSyntaxObjects[] =
{
- { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_BODY }, /* 1 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
- { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
- { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
- ASN1_BODY }, /* 4 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
- { 2, "oid", ASN1_OID, ASN1_OPT |
- ASN1_BODY }, /* 6 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
- { 2, "string", ASN1_UTF8STRING, ASN1_OPT |
- ASN1_BODY }, /* 8 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
- { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */
+ { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_BODY }, /* 1 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
+ { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
+ { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
+ ASN1_BODY }, /* 4 */
+ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
+ { 2, "oid", ASN1_OID, ASN1_OPT |
+ ASN1_BODY }, /* 6 */
+ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
+ { 2, "string", ASN1_UTF8STRING, ASN1_OPT |
+ ASN1_BODY }, /* 8 */
+ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-#define IETF_ATTR_OCTETS 4
-#define IETF_ATTR_OID 6
-#define IETF_ATTR_STRING 8
-#define IETF_ATTR_ROOF 11
-
-/* ASN.1 definition of roleSyntax */
+#define IETF_ATTR_OCTETS 4
+#define IETF_ATTR_OID 6
+#define IETF_ATTR_STRING 8
+/**
+ * ASN.1 definition of roleSyntax
+ */
static const asn1Object_t roleSyntaxObjects[] =
{
- { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_OBJ }, /* 1 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
- { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */
+ { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_OBJ }, /* 1 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
+ { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-#define ROLE_ROOF 4
-
-/* ASN.1 definition of an X509 attribute certificate */
-
+/**
+ * ASN.1 definition of an X509 attribute certificate
+ */
static const asn1Object_t acObjects[] =
{
- { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
- { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
- { 2, "version", ASN1_INTEGER, ASN1_DEF |
- ASN1_BODY }, /* 2 */
- { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
- { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
- { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
- { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
- { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
- ASN1_BODY }, /* 7 */
- { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
- { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
- ASN1_OBJ }, /* 10 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
- { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
- { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/
- { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
- ASN1_BODY }, /* 14 */
- { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/
- { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
- { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
- { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
- ASN1_OBJ }, /* 19 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
- { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
- { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
- { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
- { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
- { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
- ASN1_BODY }, /* 25 */
- { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
- { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
- { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
- { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
- { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
- ASN1_BODY }, /* 31 */
- { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
- { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
- { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
- { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
- { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
- { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
- { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
- { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
- { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
- { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
- { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
- { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
- { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
- { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
- { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
- { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
- { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
- ASN1_BODY }, /* 50 */
- { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
- { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
- { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */
+ { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
+ { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
+ { 2, "version", ASN1_INTEGER, ASN1_DEF |
+ ASN1_BODY }, /* 2 */
+ { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
+ { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
+ { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
+ ASN1_BODY }, /* 7 */
+ { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
+ { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
+ ASN1_OBJ }, /* 10 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
+ { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
+ { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
+ { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
+ ASN1_BODY }, /* 14 */
+ { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
+ { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
+ { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
+ { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
+ ASN1_OBJ }, /* 19 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
+ { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
+ { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
+ { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
+ { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
+ { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
+ ASN1_BODY }, /* 25 */
+ { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
+ { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
+ { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
+ { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
+ { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
+ ASN1_BODY }, /* 31 */
+ { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
+ { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
+ { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
+ { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
+ { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
+ { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
+ { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
+ { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
+ { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
+ { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
+ { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
+ { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
+ { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
+ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
+ { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
+ { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
+ { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
+ { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
+ ASN1_BODY }, /* 50 */
+ { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
+ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
+ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
+ { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-#define AC_OBJ_CERTIFICATE 0
-#define AC_OBJ_CERTIFICATE_INFO 1
-#define AC_OBJ_VERSION 2
-#define AC_OBJ_HOLDER_ISSUER 5
-#define AC_OBJ_HOLDER_SERIAL 6
-#define AC_OBJ_ENTITY_NAME 10
-#define AC_OBJ_ISSUER_NAME 19
-#define AC_OBJ_ISSUER 23
-#define AC_OBJ_SIG_ALG 35
-#define AC_OBJ_SERIAL_NUMBER 36
-#define AC_OBJ_NOT_BEFORE 38
-#define AC_OBJ_NOT_AFTER 39
-#define AC_OBJ_ATTRIBUTE_TYPE 42
-#define AC_OBJ_ATTRIBUTE_VALUE 44
-#define AC_OBJ_EXTN_ID 49
-#define AC_OBJ_CRITICAL 50
-#define AC_OBJ_EXTN_VALUE 51
-#define AC_OBJ_ALGORITHM 53
-#define AC_OBJ_SIGNATURE 54
-#define AC_OBJ_ROOF 55
+#define AC_OBJ_CERTIFICATE 0
+#define AC_OBJ_CERTIFICATE_INFO 1
+#define AC_OBJ_VERSION 2
+#define AC_OBJ_HOLDER_ISSUER 5
+#define AC_OBJ_HOLDER_SERIAL 6
+#define AC_OBJ_ENTITY_NAME 10
+#define AC_OBJ_ISSUER_NAME 19
+#define AC_OBJ_ISSUER 23
+#define AC_OBJ_SIG_ALG 35
+#define AC_OBJ_SERIAL_NUMBER 36
+#define AC_OBJ_NOT_BEFORE 38
+#define AC_OBJ_NOT_AFTER 39
+#define AC_OBJ_ATTRIBUTE_TYPE 42
+#define AC_OBJ_ATTRIBUTE_VALUE 44
+#define AC_OBJ_EXTN_ID 49
+#define AC_OBJ_CRITICAL 50
+#define AC_OBJ_EXTN_VALUE 51
+#define AC_OBJ_ALGORITHM 53
+#define AC_OBJ_SIGNATURE 54
const x509acert_t empty_ac = {
- NULL , /* *next */
- 0 , /* installed */
- { NULL, 0 }, /* certificate */
- { NULL, 0 }, /* certificateInfo */
- 1 , /* version */
- /* holder */
- /* baseCertificateID */
- { NULL, 0 }, /* holderIssuer */
- { NULL, 0 }, /* holderSerial */
- /* entityName */
- { NULL, 0 }, /* generalNames */
- /* v2Form */
- { NULL, 0 }, /* issuerName */
- /* signature */
- OID_UNKNOWN, /* sigAlg */
- { NULL, 0 }, /* serialNumber */
- /* attrCertValidityPeriod */
- 0 , /* notBefore */
- 0 , /* notAfter */
- /* attributes */
- NULL , /* charging */
- NULL , /* groups */
- /* extensions */
- { NULL, 0 }, /* authKeyID */
- { NULL, 0 }, /* authKeySerialNumber */
- FALSE , /* noRevAvail */
- /* signatureAlgorithm */
- OID_UNKNOWN, /* algorithm */
- { NULL, 0 }, /* signature */
+ NULL , /* *next */
+ 0 , /* installed */
+ { NULL, 0 }, /* certificate */
+ { NULL, 0 }, /* certificateInfo */
+ 1 , /* version */
+ /* holder */
+ /* baseCertificateID */
+ { NULL, 0 }, /* holderIssuer */
+ { NULL, 0 }, /* holderSerial */
+ /* entityName */
+ { NULL, 0 }, /* generalNames */
+ /* v2Form */
+ { NULL, 0 }, /* issuerName */
+ /* signature */
+ OID_UNKNOWN, /* sigAlg */
+ { NULL, 0 }, /* serialNumber */
+ /* attrCertValidityPeriod */
+ 0 , /* notBefore */
+ 0 , /* notAfter */
+ /* attributes */
+ NULL , /* charging */
+ NULL , /* groups */
+ /* extensions */
+ { NULL, 0 }, /* authKeyID */
+ { NULL, 0 }, /* authKeySerialNumber */
+ FALSE , /* noRevAvail */
+ /* signatureAlgorithm */
+ OID_UNKNOWN, /* algorithm */
+ { NULL, 0 }, /* signature */
};
-/* compare two ietfAttributes, returns zero if a equals b
+/**
+ * compare two ietfAttributes, returns zero if a equals b
* negative/positive if a is earlier/later in the alphabet than b
*/
-static int
-cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b)
+static int cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b)
{
- int cmp_len, len, cmp_value;
+ int cmp_len, len, cmp_value;
- /* cannot compare OID with STRING or OCTETS attributes */
- if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID)
- return 1;
-
- cmp_len = a->value.len - b->value.len;
- len = (cmp_len < 0)? a->value.len : b->value.len;
- cmp_value = memcmp(a->value.ptr, b->value.ptr, len);
+ /* cannot compare OID with STRING or OCTETS attributes */
+ if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID)
+ return 1;
+
+ cmp_len = a->value.len - b->value.len;
+ len = (cmp_len < 0)? a->value.len : b->value.len;
+ cmp_value = memcmp(a->value.ptr, b->value.ptr, len);
- return (cmp_value == 0)? cmp_len : cmp_value;
+ return (cmp_value == 0)? cmp_len : cmp_value;
}
-/*
+/**
* add an ietfAttribute to the chained list
*/
-static ietfAttr_t*
-add_ietfAttr(ietfAttr_t *attr)
+static ietfAttr_t* add_ietfAttr(ietfAttr_t *attr)
{
- ietfAttrList_t **listp = &ietfAttributes;
- ietfAttrList_t *list = *listp;
- int cmp = -1;
-
- while (list != NULL)
- {
- cmp = cmp_ietfAttr(attr, list->attr);
- if (cmp <= 0)
- break;
- listp = &list->next;
- list = *listp;
- }
-
- if (cmp == 0)
- {
- /* attribute already exists, increase count */
- pfree(attr);
- list->attr->count++;
- return list->attr;
- }
- else
- {
- ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList");
-
- /* new attribute, unshare value */
- attr->value.ptr = clone_bytes(attr->value.ptr, attr->value.len
- , "attr value");
- attr->count = 1;
- time(&attr->installed);
-
- el->attr = attr;
- el->next = list;
- *listp = el;
-
- return attr;
- }
+ ietfAttrList_t **listp = &ietfAttributes;
+ ietfAttrList_t *list = *listp;
+ int cmp = -1;
+
+ while (list != NULL)
+ {
+ cmp = cmp_ietfAttr(attr, list->attr);
+ if (cmp <= 0)
+ break;
+ listp = &list->next;
+ list = *listp;
+ }
+
+ if (cmp == 0)
+ {
+ /* attribute already exists, increase count */
+ free(attr);
+ list->attr->count++;
+ return list->attr;
+ }
+ else
+ {
+ ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
+
+ /* new attribute, unshare value */
+ attr->value = chunk_clone(attr->value);
+ attr->count = 1;
+ time(&attr->installed);
+
+ el->attr = attr;
+ el->next = list;
+ *listp = el;
+
+ return attr;
+ }
}
-/*
+/**
* decodes a comma separated list of group attributes
*/
-void
-decode_groups(char *groups, ietfAttrList_t **listp)
+void decode_groups(char *groups, ietfAttrList_t **listp)
{
- if (groups == NULL)
- return;
+ if (groups == NULL)
+ return;
- while (strlen(groups) > 0)
- {
- char *end;
- char *next = strchr(groups, ',');
+ while (strlen(groups) > 0)
+ {
+ char *end;
+ char *next = strchr(groups, ',');
- if (next == NULL)
- end = next = groups + strlen(groups);
- else
- end = next++;
+ if (next == NULL)
+ end = next = groups + strlen(groups);
+ else
+ end = next++;
- /* eat preceeding whitespace */
- while (groups < end && *groups == ' ')
- groups++;
+ /* eat preceeding whitespace */
+ while (groups < end && *groups == ' ')
+ groups++;
- /* eat trailing whitespace */
- while (end > groups && *(end-1) == ' ')
- end--;
+ /* eat trailing whitespace */
+ while (end > groups && *(end-1) == ' ')
+ end--;
- if (groups < end)
- {
- ietfAttr_t *attr = alloc_thing(ietfAttr_t, "ietfAttr");
- ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList");
+ if (groups < end)
+ {
+ ietfAttr_t *attr = malloc_thing(ietfAttr_t);
+ ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
- attr->kind = IETF_ATTRIBUTE_STRING;
- attr->value.ptr = groups;
- attr->value.len = end - groups;
- attr->count = 0;
+ attr->kind = IETF_ATTRIBUTE_STRING;
+ attr->value.ptr = groups;
+ attr->value.len = end - groups;
+ attr->count = 0;
- el->attr = add_ietfAttr(attr);
- el->next = *listp;
- *listp = el;
- }
+ el->attr = add_ietfAttr(attr);
+ el->next = *listp;
+ *listp = el;
+ }
- groups = next;
- }
+ groups = next;
+ }
}
-static bool
-same_attribute(const ietfAttr_t *a, const ietfAttr_t *b)
+static bool same_attribute(const ietfAttr_t *a, const ietfAttr_t *b)
{
- return (a->kind == b->kind && a->value.len == b->value.len
- && memcmp(a->value.ptr, b->value.ptr, b->value.len) == 0);
+ return (a->kind == b->kind && a->value.len == b->value.len
+ && memeq(a->value.ptr, b->value.ptr, b->value.len));
}
-bool
-group_membership(const ietfAttrList_t *peer_list
- , const char *conn
- , const ietfAttrList_t *conn_list)
+bool group_membership(const ietfAttrList_t *peer_list
+ , const char *conn
+ , const ietfAttrList_t *conn_list)
{
- if (conn_list == NULL)
- return TRUE;
-
- while (peer_list != NULL)
- {
- const ietfAttr_t *peer_attr = peer_list->attr;
- const ietfAttrList_t *list = conn_list;
+ if (conn_list == NULL)
+ return TRUE;
- while (list != NULL)
+ while (peer_list != NULL)
{
- ietfAttr_t *conn_attr = list->attr;
+ const ietfAttr_t *peer_attr = peer_list->attr;
+ const ietfAttrList_t *list = conn_list;
- if (same_attribute(conn_attr, peer_attr))
- {
+ while (list != NULL)
+ {
+ ietfAttr_t *conn_attr = list->attr;
+
+ if (same_attribute(conn_attr, peer_attr))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("%s: peer matches group '%.*s'"
+ , conn
+ , (int)peer_attr->value.len, peer_attr->value.ptr)
+ )
+ return TRUE;
+ }
+ list = list->next;
+ }
+ peer_list = peer_list->next;
+ }
DBG(DBG_CONTROL,
- DBG_log("%s: peer matches group '%.*s'"
- , conn
- , (int)peer_attr->value.len, peer_attr->value.ptr)
+ DBG_log("%s: peer doesn't match any group", conn)
)
- return TRUE;
- }
- list = list->next;
- }
- peer_list = peer_list->next;
- }
- DBG(DBG_CONTROL,
- DBG_log("%s: peer doesn't match any group", conn)
- )
- return FALSE;
+ return FALSE;
}
-
-void
-unshare_ietfAttrList(ietfAttrList_t **listp)
+void unshare_ietfAttrList(ietfAttrList_t **listp)
{
- ietfAttrList_t *list = *listp;
-
- while (list != NULL)
- {
- ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList");
-
- el->attr = list->attr;
- el->attr->count++;
- el->next = NULL;
- *listp = el;
- listp = &el->next;
- list = list->next;
- }
+ ietfAttrList_t *list = *listp;
+
+ while (list != NULL)
+ {
+ ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
+
+ el->attr = list->attr;
+ el->attr->count++;
+ el->next = NULL;
+ *listp = el;
+ listp = &el->next;
+ list = list->next;
+ }
}
-/*
- * parses ietfAttrSyntax
+/**
+ * Parses ietfAttrSyntax
*/
-static ietfAttrList_t*
-parse_ietfAttrSyntax(chunk_t blob, int level0)
+static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
-
- ietfAttrList_t *list = NULL;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ ietfAttrList_t *list = NULL;
- while (objectID < IETF_ATTR_ROOF)
- {
- if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
- return NULL;
+ parser = asn1_parser_create(ietfAttrSyntaxObjects, blob);
+ parser->set_top_level(parser, level0);
- switch (objectID)
+ while (parser->iterate(parser, &objectID, &object))
{
- case IETF_ATTR_OCTETS:
- case IETF_ATTR_OID:
- case IETF_ATTR_STRING:
- {
- ietfAttr_t *attr = alloc_thing(ietfAttr_t, "ietfAttr");
- ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList");
-
- attr->kind = (objectID - IETF_ATTR_OCTETS) / 2;
- attr->value = object;
- attr->count = 0;
-
- el->attr = add_ietfAttr(attr);
- el->next = list;
- list = el;
- }
- break;
- default:
- break;
+ switch (objectID)
+ {
+ case IETF_ATTR_OCTETS:
+ case IETF_ATTR_OID:
+ case IETF_ATTR_STRING:
+ {
+ ietfAttr_t *attr = malloc_thing(ietfAttr_t);
+ ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
+
+ attr->kind = (objectID - IETF_ATTR_OCTETS) / 2;
+ attr->value = object;
+ attr->count = 0;
+
+ el->attr = add_ietfAttr(attr);
+ el->next = list;
+ list = el;
+ }
+ break;
+ default:
+ break;
+ }
}
- objectID++;
- }
- return list;
+ parser->destroy(parser);
+ return list;
}
-/*
- * parses roleSyntax
+
+/**
+ * Parses roleSyntax
*/
-static void
-parse_roleSyntax(chunk_t blob, int level0)
+static void parse_roleSyntax(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ parser = asn1_parser_create(roleSyntaxObjects, blob);
+ parser->set_top_level(parser, level0);
- while (objectID < ROLE_ROOF)
- {
- if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx))
- return;
-
- switch (objectID) {
- default:
- break;
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ switch (objectID)
+ {
+ default:
+ break;
+ }
}
- objectID++;
- }
+ parser->destroy(parser);
}
-/*
+/**
* Parses an X.509 attribute certificate
*/
-bool
-parse_ac(chunk_t blob, x509acert_t *ac)
+bool parse_ac(chunk_t blob, x509acert_t *ac)
{
- asn1_ctx_t ctx;
- bool critical;
- chunk_t object;
- u_int level;
- int objectID = 0;
- int type = OID_UNKNOWN;
- int extn_oid = OID_UNKNOWN;
-
- asn1_init(&ctx, blob, 0, FALSE, DBG_RAW);
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ int type = OID_UNKNOWN;
+ int extn_oid = OID_UNKNOWN;
+ bool success = FALSE;
+ bool critical;
- while (objectID < AC_OBJ_ROOF) {
+ parser = asn1_parser_create(acObjects, blob);
- if (!extract_object(acObjects, &objectID, &object, &level, &ctx))
- return FALSE;
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser)+1;
- /* those objects which will parsed further need the next higher level */
- level++;
+ switch (objectID)
+ {
+ case AC_OBJ_CERTIFICATE:
+ ac->certificate = object;
+ break;
+ case AC_OBJ_CERTIFICATE_INFO:
+ ac->certificateInfo = object;
+ break;
+ case AC_OBJ_VERSION:
+ ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
+ DBG(DBG_PARSING,
+ DBG_log(" v%d", ac->version);
+ )
+ if (ac->version != 2)
+ {
+ plog("v%d attribute certificates are not supported"
+ , ac->version);
+ goto end;
+ }
+ break;
+ case AC_OBJ_HOLDER_ISSUER:
+ ac->holderIssuer = get_directoryName(object, level, FALSE);
+ break;
+ case AC_OBJ_HOLDER_SERIAL:
+ ac->holderSerial = object;
+ break;
+ case AC_OBJ_ENTITY_NAME:
+ ac->entityName = get_directoryName(object, level, TRUE);
+ break;
+ case AC_OBJ_ISSUER_NAME:
+ ac->issuerName = get_directoryName(object, level, FALSE);
+ break;
+ case AC_OBJ_SIG_ALG:
+ ac->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case AC_OBJ_SERIAL_NUMBER:
+ ac->serialNumber = object;
+ break;
+ case AC_OBJ_NOT_BEFORE:
+ ac->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
+ break;
+ case AC_OBJ_NOT_AFTER:
+ ac->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
+ break;
+ case AC_OBJ_ATTRIBUTE_TYPE:
+ type = asn1_known_oid(object);
+ break;
+ case AC_OBJ_ATTRIBUTE_VALUE:
+ {
+ switch (type) {
+ case OID_AUTHENTICATION_INFO:
+ DBG(DBG_PARSING,
+ DBG_log(" need to parse authenticationInfo")
+ )
+ break;
+ case OID_ACCESS_IDENTITY:
+ DBG(DBG_PARSING,
+ DBG_log(" need to parse accessIdentity")
+ )
+ break;
+ case OID_CHARGING_IDENTITY:
+ ac->charging = parse_ietfAttrSyntax(object, level);
+ break;
+ case OID_GROUP:
+ ac->groups = parse_ietfAttrSyntax(object, level);
+ break;
+ case OID_ROLE:
+ parse_roleSyntax(object, level);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case AC_OBJ_EXTN_ID:
+ extn_oid = asn1_known_oid(object);
+ break;
+ case AC_OBJ_CRITICAL:
+ critical = object.len && *object.ptr;
+ DBG(DBG_PARSING,
+ DBG_log(" %s",(critical)?"TRUE":"FALSE");
+ )
+ break;
+ case AC_OBJ_EXTN_VALUE:
+ {
+ switch (extn_oid) {
+ case OID_CRL_DISTRIBUTION_POINTS:
+ DBG(DBG_PARSING,
+ DBG_log(" need to parse crlDistributionPoints")
+ )
+ break;
+ case OID_AUTHORITY_KEY_ID:
+ parse_authorityKeyIdentifier(object, level
+ , &ac->authKeyID, &ac->authKeySerialNumber);
+ break;
+ case OID_TARGET_INFORMATION:
+ DBG(DBG_PARSING,
+ DBG_log(" need to parse targetInformation")
+ )
+ break;
+ case OID_NO_REV_AVAIL:
+ ac->noRevAvail = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case AC_OBJ_ALGORITHM:
+ ac->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case AC_OBJ_SIGNATURE:
+ ac->signature = object;
+ break;
- switch (objectID)
- {
- case AC_OBJ_CERTIFICATE:
- ac->certificate = object;
- break;
- case AC_OBJ_CERTIFICATE_INFO:
- ac->certificateInfo = object;
- break;
- case AC_OBJ_VERSION:
- ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
- DBG(DBG_PARSING,
- DBG_log(" v%d", ac->version);
- )
- if (ac->version != 2)
- {
- plog("v%d attribute certificates are not supported"
- , ac->version);
- return FALSE;
- }
- break;
- case AC_OBJ_HOLDER_ISSUER:
- ac->holderIssuer = get_directoryName(object, level, FALSE);
- break;
- case AC_OBJ_HOLDER_SERIAL:
- ac->holderSerial = object;
- break;
- case AC_OBJ_ENTITY_NAME:
- ac->entityName = get_directoryName(object, level, TRUE);
- break;
- case AC_OBJ_ISSUER_NAME:
- ac->issuerName = get_directoryName(object, level, FALSE);
- break;
- case AC_OBJ_SIG_ALG:
- ac->sigAlg = parse_algorithmIdentifier(object, level, NULL);
- break;
- case AC_OBJ_SERIAL_NUMBER:
- ac->serialNumber = object;
- break;
- case AC_OBJ_NOT_BEFORE:
- ac->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME);
- break;
- case AC_OBJ_NOT_AFTER:
- ac->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME);
- break;
- case AC_OBJ_ATTRIBUTE_TYPE:
- type = known_oid(object);
- break;
- case AC_OBJ_ATTRIBUTE_VALUE:
- {
- switch (type) {
- case OID_AUTHENTICATION_INFO:
- DBG(DBG_PARSING,
- DBG_log(" need to parse authenticationInfo")
- )
- break;
- case OID_ACCESS_IDENTITY:
- DBG(DBG_PARSING,
- DBG_log(" need to parse accessIdentity")
- )
- break;
- case OID_CHARGING_IDENTITY:
- ac->charging = parse_ietfAttrSyntax(object, level);
- break;
- case OID_GROUP:
- ac->groups = parse_ietfAttrSyntax(object, level);
- break;
- case OID_ROLE:
- parse_roleSyntax(object, level);
- break;
- default:
- break;
- }
- }
- break;
- case AC_OBJ_EXTN_ID:
- extn_oid = known_oid(object);
- break;
- case AC_OBJ_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- break;
- case AC_OBJ_EXTN_VALUE:
- {
- switch (extn_oid) {
- case OID_CRL_DISTRIBUTION_POINTS:
- DBG(DBG_PARSING,
- DBG_log(" need to parse crlDistributionPoints")
- )
- break;
- case OID_AUTHORITY_KEY_ID:
- parse_authorityKeyIdentifier(object, level
- , &ac->authKeyID, &ac->authKeySerialNumber);
- break;
- case OID_TARGET_INFORMATION:
- DBG(DBG_PARSING,
- DBG_log(" need to parse targetInformation")
- )
- break;
- case OID_NO_REV_AVAIL:
- ac->noRevAvail = TRUE;
- break;
default:
- break;
+ break;
}
- }
- break;
- case AC_OBJ_ALGORITHM:
- ac->algorithm = parse_algorithmIdentifier(object, level, NULL);
- break;
- case AC_OBJ_SIGNATURE:
- ac->signature = object;
- break;
-
- default:
- break;
}
- objectID++;
- }
- time(&ac->installed);
- return TRUE;
+ success = parser->success(parser);
+ time(&ac->installed);
+
+end:
+ parser->destroy(parser);
+ return success;
}
-/*
- * release an ietfAttribute, free it if count reaches zero
+/**
+ * Release an ietfAttribute, free it if count reaches zero
*/
-static void
-release_ietfAttr(ietfAttr_t* attr)
+static void release_ietfAttr(ietfAttr_t* attr)
{
- if (--attr->count == 0)
- {
- ietfAttrList_t **plist = &ietfAttributes;
- ietfAttrList_t *list = *plist;
-
- while (list->attr != attr)
+ if (--attr->count == 0)
{
- plist = &list->next;
- list = *plist;
+ ietfAttrList_t **plist = &ietfAttributes;
+ ietfAttrList_t *list = *plist;
+
+ while (list->attr != attr)
+ {
+ plist = &list->next;
+ list = *plist;
+ }
+ *plist = list->next;
+
+ free(attr->value.ptr);
+ free(attr);
+ free(list);
}
- *plist = list->next;
-
- pfree(attr->value.ptr);
- pfree(attr);
- pfree(list);
- }
}
-/*
- * free an ietfAttrList
+/**
+ * Free an ietfAttrList
*/
-void
-free_ietfAttrList(ietfAttrList_t* list)
+void free_ietfAttrList(ietfAttrList_t* list)
{
- while (list != NULL)
- {
- ietfAttrList_t *el = list;
-
- release_ietfAttr(el->attr);
- list = list->next;
- pfree(el);
- }
+ while (list != NULL)
+ {
+ ietfAttrList_t *el = list;
+
+ release_ietfAttr(el->attr);
+ list = list->next;
+ free(el);
+ }
}
-/*
- * free a X.509 attribute certificate
+/**
+ * Free a X.509 attribute certificate
*/
-void
-free_acert(x509acert_t *ac)
+void free_acert(x509acert_t *ac)
{
- if (ac != NULL)
- {
- free_ietfAttrList(ac->charging);
- free_ietfAttrList(ac->groups);
- pfreeany(ac->certificate.ptr);
- pfree(ac);
- }
+ if (ac != NULL)
+ {
+ free_ietfAttrList(ac->charging);
+ free_ietfAttrList(ac->groups);
+ free(ac->certificate.ptr);
+ free(ac);
+ }
}
-/*
- * free first X.509 attribute certificate in the chained list
+/**
+ * Free first X.509 attribute certificate in the chained list
*/
-static void
-free_first_acert(void)
+static void free_first_acert(void)
{
- x509acert_t *first = x509acerts;
- x509acerts = first->next;
- free_acert(first);
+ x509acert_t *first = x509acerts;
+ x509acerts = first->next;
+ free_acert(first);
}
-/*
+/**
* Free all attribute certificates in the chained list
*/
-void
-free_acerts(void)
-{
- while (x509acerts != NULL)
- free_first_acert();
+void free_acerts(void)
+{
+ while (x509acerts != NULL)
+ free_first_acert();
}
-/*
- * get a X.509 attribute certificate for a given holder
+/**
+ * Get a X.509 attribute certificate for a given holder
*/
-x509acert_t*
-get_x509acert(chunk_t issuer, chunk_t serial)
+x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial)
{
- x509acert_t *ac = x509acerts;
- x509acert_t *prev_ac = NULL;
+ x509acert_t *ac = x509acerts;
+ x509acert_t *prev_ac = NULL;
- while (ac != NULL)
- {
- if (same_dn(issuer, ac->holderIssuer)
- && same_serial(serial, ac->holderSerial))
+ while (ac != NULL)
{
- if (ac!= x509acerts)
- {
- /* bring the certificate up front */
- prev_ac->next = ac->next;
- ac->next = x509acerts;
- x509acerts = ac;
- }
- return ac;
+ if (same_dn(issuer, ac->holderIssuer)
+ && same_serial(serial, ac->holderSerial))
+ {
+ if (ac!= x509acerts)
+ {
+ /* bring the certificate up front */
+ prev_ac->next = ac->next;
+ ac->next = x509acerts;
+ x509acerts = ac;
+ }
+ return ac;
+ }
+ prev_ac = ac;
+ ac = ac->next;
}
- prev_ac = ac;
- ac = ac->next;
- }
- return NULL;
+ return NULL;
}
-/*
- * add a X.509 attribute certificate to the chained list
+/**
+ * Add a X.509 attribute certificate to the chained list
*/
-static void
-add_acert(x509acert_t *ac)
+static void add_acert(x509acert_t *ac)
{
- x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial);
+ x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial);
- if (old_ac != NULL)
- {
- if (ac->notBefore >old_ac->notBefore)
- {
- /* delete the old attribute cert */
- free_first_acert();
- DBG(DBG_CONTROL,
- DBG_log("attribute cert is newer - existing cert deleted")
- )
- }
- else
+ if (old_ac != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("attribute cert is not newer - existing cert kept");
- )
- free_acert(ac);
- return;
+ if (ac->notBefore >old_ac->notBefore)
+ {
+ /* delete the old attribute cert */
+ free_first_acert();
+ DBG(DBG_CONTROL,
+ DBG_log("attribute cert is newer - existing cert deleted")
+ )
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("attribute cert is not newer - existing cert kept");
+ )
+ free_acert(ac);
+ return;
+ }
}
- }
- plog("attribute cert added");
+ plog("attribute cert added");
- /* insert new attribute cert at the root of the chain */
- ac->next = x509acerts;
- x509acerts = ac;
+ /* insert new attribute cert at the root of the chain */
+ ac->next = x509acerts;
+ x509acerts = ac;
}
-/* verify the validity of an attribute certificate by
+/**
+ * Verify the validity of an attribute certificate by
* checking the notBefore and notAfter dates
*/
-static err_t
-check_ac_validity(const x509acert_t *ac)
+static err_t check_ac_validity(const x509acert_t *ac)
{
- time_t current_time;
-
- time(&current_time);
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" not before : %s", timetoa(&ac->notBefore, TRUE));
- DBG_log(" current time: %s", timetoa(&current_time, TRUE));
- DBG_log(" not after : %s", timetoa(&ac->notAfter, TRUE));
- )
-
- if (current_time < ac->notBefore)
- return "attribute certificate is not valid yet";
- if (current_time > ac->notAfter)
- return "attribute certificate has expired";
- else
- return NULL;
+ time_t current_time;
+
+ time(&current_time);
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log(" not before : %T", &ac->notBefore, TRUE);
+ DBG_log(" current time: %T", &current_time, TRUE);
+ DBG_log(" not after : %T", &ac->notAfter, TRUE);
+ )
+
+ if (current_time < ac->notBefore)
+ return "attribute certificate is not valid yet";
+ if (current_time > ac->notAfter)
+ return "attribute certificate has expired";
+ else
+ return NULL;
}
-/*
+/**
* verifies a X.509 attribute certificate
*/
-bool
-verify_x509acert(x509acert_t *ac, bool strict)
+bool verify_x509acert(x509acert_t *ac, bool strict)
{
- u_char buf[BUF_LEN];
- x509cert_t *aacert;
- err_t ugh = NULL;
- time_t valid_until = ac->notAfter;
-
- DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, ac->entityName);
- DBG_log("holder: '%s'",buf);
- dntoa(buf, BUF_LEN, ac->issuerName);
- DBG_log("issuer: '%s'",buf);
- )
-
- ugh = check_ac_validity(ac);
-
- if (ugh != NULL)
- {
- plog("%s", ugh);
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("attribute certificate is valid")
- )
-
- lock_authcert_list("verify_x509acert");
- aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber
- , ac->authKeyID, AUTH_AA);
- unlock_authcert_list("verify_x509acert");
-
- if (aacert == NULL)
- {
- plog("issuer aacert not found");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("issuer aacert found")
- )
-
- if (!check_signature(ac->certificateInfo, ac->signature
- , ac->algorithm, ac->algorithm, aacert))
- {
- plog("attribute certificate signature is invalid");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("attribute certificate signature is valid");
- )
+ u_char buf[BUF_LEN];
+ x509cert_t *aacert;
+ err_t ugh = NULL;
+ time_t valid_until = ac->notAfter;
- return verify_x509cert(aacert, strict, &valid_until);
+ DBG(DBG_CONTROL,
+ dntoa(buf, BUF_LEN, ac->entityName);
+ DBG_log("holder: '%s'",buf);
+ dntoa(buf, BUF_LEN, ac->issuerName);
+ DBG_log("issuer: '%s'",buf);
+ )
+
+ ugh = check_ac_validity(ac);
+
+ if (ugh != NULL)
+ {
+ plog("%s", ugh);
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("attribute certificate is valid")
+ )
+
+ lock_authcert_list("verify_x509acert");
+ aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber
+ , ac->authKeyID, AUTH_AA);
+ unlock_authcert_list("verify_x509acert");
+
+ if (aacert == NULL)
+ {
+ plog("issuer aacert not found");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("issuer aacert found")
+ )
+
+ if (!x509_check_signature(ac->certificateInfo, ac->signature, ac->algorithm,
+ aacert))
+ {
+ plog("attribute certificate signature is invalid");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("attribute certificate signature is valid");
+ )
+
+ return verify_x509cert(aacert, strict, &valid_until);
}
-/*
+/**
* Loads X.509 attribute certificates
*/
-void
-load_acerts(void)
+void load_acerts(void)
{
- u_char buf[BUF_LEN];
-
- /* change directory to specified path */
- u_char *save_dir = getcwd(buf, BUF_LEN);
-
- if (!chdir(A_CERT_PATH))
- {
- struct dirent **filelist;
- int n;
+ u_char buf[BUF_LEN];
- plog("Changing to directory '%s'",A_CERT_PATH);
- n = scandir(A_CERT_PATH, &filelist, file_select, alphasort);
+ /* change directory to specified path */
+ u_char *save_dir = getcwd(buf, BUF_LEN);
- if (n > 0)
+ if (!chdir(A_CERT_PATH))
{
- while (n--)
- {
- chunk_t blob = empty_chunk;
- bool pgp = FALSE;
+ struct dirent **filelist;
+ int n;
+
+ plog("Changing to directory '%s'",A_CERT_PATH);
+ n = scandir(A_CERT_PATH, &filelist, file_select, alphasort);
- if (load_coded_file(filelist[n]->d_name, NULL, "acert", &blob, &pgp))
+ if (n > 0)
{
- x509acert_t *ac = alloc_thing(x509acert_t, "x509acert");
-
- *ac = empty_ac;
-
- if (parse_ac(blob, ac)
- && verify_x509acert(ac, FALSE))
- add_acert(ac);
- else
- free_acert(ac);
+ while (n--)
+ {
+ chunk_t blob = chunk_empty;
+ bool pgp = FALSE;
+
+ if (load_coded_file(filelist[n]->d_name, NULL, "acert", &blob, &pgp))
+ {
+ x509acert_t *ac = malloc_thing(x509acert_t);
+
+ *ac = empty_ac;
+
+ if (parse_ac(blob, ac)
+ && verify_x509acert(ac, FALSE))
+ add_acert(ac);
+ else
+ free_acert(ac);
+ }
+ free(filelist[n]);
+ }
+ free(filelist);
}
- free(filelist[n]);
- }
- free(filelist);
}
- }
- /* restore directory path */
- ignore_result(chdir(save_dir));
+ /* restore directory path */
+ ignore_result(chdir(save_dir));
}
-/*
+/**
* lists group attributes separated by commas on a single line
*/
-void
-format_groups(const ietfAttrList_t *list, char *buf, int len)
+void format_groups(const ietfAttrList_t *list, char *buf, int len)
{
- bool first_group = TRUE;
-
- while (list != NULL && len > 0)
- {
- ietfAttr_t *attr = list->attr;
+ bool first_group = TRUE;
- if (attr->kind == IETF_ATTRIBUTE_OCTETS
- || attr->kind == IETF_ATTRIBUTE_STRING)
+ while (list != NULL && len > 0)
{
- int written = snprintf(buf, len, "%s%.*s"
- , (first_group)? "" : ", "
- , (int)attr->value.len, attr->value.ptr);
-
- first_group = FALSE;
-
- /* return value of snprintf() up to glibc 2.0.6 */
- if (written < 0)
- break;
-
- buf += written;
- len -= written;
+ ietfAttr_t *attr = list->attr;
+
+ if (attr->kind == IETF_ATTRIBUTE_OCTETS
+ || attr->kind == IETF_ATTRIBUTE_STRING)
+ {
+ int written = snprintf(buf, len, "%s%.*s"
+ , (first_group)? "" : ", "
+ , (int)attr->value.len, attr->value.ptr);
+
+ first_group = FALSE;
+
+ /* return value of snprintf() up to glibc 2.0.6 */
+ if (written < 0)
+ break;
+
+ buf += written;
+ len -= written;
+ }
+ list = list->next;
}
- list = list->next;
- }
}
-/*
+/**
* list all X.509 attribute certificates in the chained list
*/
-void
-list_acerts(bool utc)
+void list_acerts(bool utc)
{
- x509acert_t *ac = x509acerts;
- time_t now;
-
- /* determine the current time */
- time(&now);
+ x509acert_t *ac = x509acerts;
+ time_t now;
- if (ac != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
- whack_log(RC_COMMENT, " ");
- }
+ /* determine the current time */
+ time(&now);
- while (ac != NULL)
- {
- u_char buf[BUF_LEN];
-
- whack_log(RC_COMMENT, "%s",timetoa(&ac->installed, utc));
- if (ac->entityName.ptr != NULL)
+ if (ac != NULL)
{
- dntoa(buf, BUF_LEN, ac->entityName);
- whack_log(RC_COMMENT, " holder: '%s'", buf);
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
+ whack_log(RC_COMMENT, " ");
}
- if (ac->holderIssuer.ptr != NULL)
- {
- dntoa(buf, BUF_LEN, ac->holderIssuer);
- whack_log(RC_COMMENT, " hissuer: '%s'", buf);
- }
- if (ac->holderSerial.ptr != NULL)
- {
- datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " hserial: %s", buf);
- }
- if (ac->groups != NULL)
- {
- format_groups(ac->groups, buf, BUF_LEN);
- whack_log(RC_COMMENT, " groups: %s", buf);
- }
- dntoa(buf, BUF_LEN, ac->issuerName);
- whack_log(RC_COMMENT, " issuer: '%s'", buf);
- datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " serial: %s", buf);
- whack_log(RC_COMMENT, " validity: not before %s %s",
- timetoa(&ac->notBefore, utc),
- (ac->notBefore < now)?"ok":"fatal (not valid yet)");
- whack_log(RC_COMMENT, " not after %s %s",
- timetoa(&ac->notAfter, utc),
- check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE));
- if (ac->authKeyID.ptr != NULL)
- {
- datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
- }
- if (ac->authKeySerialNumber.ptr != NULL)
+
+ while (ac != NULL)
{
- datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
- }
+ u_char buf[BUF_LEN];
+
+ whack_log(RC_COMMENT, "%T", &ac->installed, utc);
+ if (ac->entityName.ptr != NULL)
+ {
+ dntoa(buf, BUF_LEN, ac->entityName);
+ whack_log(RC_COMMENT, " holder: '%s'", buf);
+ }
+ if (ac->holderIssuer.ptr != NULL)
+ {
+ dntoa(buf, BUF_LEN, ac->holderIssuer);
+ whack_log(RC_COMMENT, " hissuer: '%s'", buf);
+ }
+ if (ac->holderSerial.ptr != NULL)
+ {
+ datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " hserial: %s", buf);
+ }
+ if (ac->groups != NULL)
+ {
+ format_groups(ac->groups, buf, BUF_LEN);
+ whack_log(RC_COMMENT, " groups: %s", buf);
+ }
+ dntoa(buf, BUF_LEN, ac->issuerName);
+ whack_log(RC_COMMENT, " issuer: '%s'", buf);
+ datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " serial: %s", buf);
+ whack_log(RC_COMMENT, " validity: not before %T %s",
+ &ac->notBefore, utc,
+ (ac->notBefore < now)?"ok":"fatal (not valid yet)");
+ whack_log(RC_COMMENT, " not after %T %s",
+ &ac->notAfter, utc,
+ check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE));
+ if (ac->authKeyID.ptr != NULL)
+ {
+ datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authkey: %s", buf);
+ }
+ if (ac->authKeySerialNumber.ptr != NULL)
+ {
+ datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " aserial: %s", buf);
+ }
- ac = ac->next;
- }
+ ac = ac->next;
+ }
}
-/*
+/**
* list all group attributes in alphabetical order
*/
-void
-list_groups(bool utc)
+void list_groups(bool utc)
{
- ietfAttrList_t *list = ietfAttributes;
-
- if (list != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of Group Attributes:");
- whack_log(RC_COMMENT, " ");
- }
-
- while (list != NULL)
- {
- ietfAttr_t *attr = list->attr;
-
- whack_log(RC_COMMENT, "%s, count: %d", timetoa(&attr->installed, utc),
- attr->count);
+ ietfAttrList_t *list = ietfAttributes;
- switch (attr->kind)
+ if (list != NULL)
{
- case IETF_ATTRIBUTE_OCTETS:
- case IETF_ATTRIBUTE_STRING:
- whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr);
- break;
- case IETF_ATTRIBUTE_OID:
- whack_log(RC_COMMENT, " OID");
- break;
- default:
- break;
- }
-
- list = list->next;
- }
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of Group Attributes:");
+ whack_log(RC_COMMENT, " ");
+ }
+
+ while (list != NULL)
+ {
+ ietfAttr_t *attr = list->attr;
+
+ whack_log(RC_COMMENT, "%T, count: %d", &attr->installed, utc, attr->count);
+
+ switch (attr->kind)
+ {
+ case IETF_ATTRIBUTE_OCTETS:
+ case IETF_ATTRIBUTE_STRING:
+ whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr);
+ break;
+ case IETF_ATTRIBUTE_OID:
+ whack_log(RC_COMMENT, " OID");
+ break;
+ default:
+ break;
+ }
+
+ list = list->next;
+ }
}
diff --git a/src/pluto/ac.h b/src/pluto/ac.h
index d60ad25af..bee016143 100644
--- a/src/pluto/ac.h
+++ b/src/pluto/ac.h
@@ -1,7 +1,7 @@
/* Support of X.509 attribute certificates
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
* Copyright (C) 2003 Martin Berner, Lukas Suter
-
+
*
* 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,8 +12,6 @@
* 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: ac.h 3253 2007-10-06 21:39:00Z andreas $
*/
#ifndef _AC_H
@@ -22,9 +20,9 @@
/* definition of ietfAttribute kinds */
typedef enum {
- IETF_ATTRIBUTE_OCTETS = 0,
- IETF_ATTRIBUTE_OID = 1,
- IETF_ATTRIBUTE_STRING = 2
+ IETF_ATTRIBUTE_OCTETS = 0,
+ IETF_ATTRIBUTE_OID = 1,
+ IETF_ATTRIBUTE_STRING = 2
} ietfAttribute_t;
/* access structure for an ietfAttribute */
@@ -32,17 +30,17 @@ typedef enum {
typedef struct ietfAttr ietfAttr_t;
struct ietfAttr {
- time_t installed;
- int count;
+ time_t installed;
+ int count;
ietfAttribute_t kind;
- chunk_t value;
+ chunk_t value;
};
typedef struct ietfAttrList ietfAttrList_t;
struct ietfAttrList {
ietfAttrList_t *next;
- ietfAttr_t *attr;
+ ietfAttr_t *attr;
};
@@ -52,31 +50,31 @@ typedef struct x509acert x509acert_t;
struct x509acert {
x509acert_t *next;
- time_t installed;
- chunk_t certificate;
- chunk_t certificateInfo;
- u_int version;
- /* holder */
- /* baseCertificateID */
- chunk_t holderIssuer;
- chunk_t holderSerial;
- chunk_t entityName;
- /* v2Form */
- chunk_t issuerName;
- /* signature */
+ time_t installed;
+ chunk_t certificate;
+ chunk_t certificateInfo;
+ u_int version;
+ /* holder */
+ /* baseCertificateID */
+ chunk_t holderIssuer;
+ chunk_t holderSerial;
+ chunk_t entityName;
+ /* v2Form */
+ chunk_t issuerName;
+ /* signature */
int sigAlg;
- chunk_t serialNumber;
- /* attrCertValidityPeriod */
+ chunk_t serialNumber;
+ /* attrCertValidityPeriod */
time_t notBefore;
time_t notAfter;
- /* attributes */
+ /* attributes */
ietfAttrList_t *charging;
ietfAttrList_t *groups;
- /* extensions */
+ /* extensions */
chunk_t authKeyID;
chunk_t authKeySerialNumber;
- bool noRevAvail;
- /* signatureAlgorithm */
+ bool noRevAvail;
+ /* signatureAlgorithm */
int algorithm;
chunk_t signature;
};
@@ -88,7 +86,7 @@ extern void unshare_ietfAttrList(ietfAttrList_t **listp);
extern void free_ietfAttrList(ietfAttrList_t *list);
extern void decode_groups(char *groups, ietfAttrList_t **listp);
extern bool group_membership(const ietfAttrList_t *my_list
- , const char *conn, const ietfAttrList_t *conn_list);
+ , const char *conn, const ietfAttrList_t *conn_list);
extern bool parse_ac(chunk_t blob, x509acert_t *ac);
extern bool verify_x509acert(x509acert_t *ac, bool strict);
extern x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial);
diff --git a/src/pluto/adns.c b/src/pluto/adns.c
index a721d8837..95e22b96f 100644
--- a/src/pluto/adns.c
+++ b/src/pluto/adns.c
@@ -10,11 +10,9 @@
* 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: adns.c 3252 2007-10-06 21:24:50Z andreas $
*/
-#ifndef USE_LWRES /* whole file! */
+#ifndef USE_LWRES /* whole file! */
/* This program executes as multiple processes. The Master process
* receives queries (struct adns_query messages) from Pluto and distributes
@@ -58,7 +56,7 @@
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#include <netdb.h> /* ??? for h_errno */
+#include <netdb.h> /* ??? for h_errno */
#include <freeswan.h>
@@ -70,11 +68,11 @@
#endif
#include "constants.h"
-#include "adns.h" /* needs <resolv.h> */
+#include "adns.h" /* needs <resolv.h> */
/* shared by all processes */
-static const char *name; /* program name, for messages */
+static const char *name; /* program name, for messages */
static bool debug = FALSE;
@@ -88,43 +86,43 @@ static bool debug = FALSE;
static enum helper_exit_status
read_pipe(int fd, unsigned char *stuff, size_t minlen, size_t maxlen)
{
- size_t n = 0;
- size_t goal = minlen;
+ size_t n = 0;
+ size_t goal = minlen;
- do {
- ssize_t m = read(fd, stuff + n, goal - n);
+ do {
+ ssize_t m = read(fd, stuff + n, goal - n);
- if (m == -1)
- {
- if (errno != EINTR)
- {
- syslog(LOG_ERR, "Input error on pipe: %s", strerror(errno));
- return HES_IO_ERROR_IN;
- }
- }
- else if (m == 0)
- {
- return HES_OK; /* treat empty message as EOF */
- }
- else
- {
- n += m;
- if (n >= sizeof(size_t))
- {
- goal = *(size_t *)(void *)stuff;
- if (goal < minlen || maxlen < goal)
+ if (m == -1)
{
- if (debug)
- fprintf(stderr, "%lu : [%lu, %lu]\n"
- , (unsigned long)goal
- , (unsigned long)minlen, (unsigned long)maxlen);
- return HES_BAD_LEN;
+ if (errno != EINTR)
+ {
+ syslog(LOG_ERR, "Input error on pipe: %s", strerror(errno));
+ return HES_IO_ERROR_IN;
+ }
}
- }
- }
- } while (n < goal);
+ else if (m == 0)
+ {
+ return HES_OK; /* treat empty message as EOF */
+ }
+ else
+ {
+ n += m;
+ if (n >= sizeof(size_t))
+ {
+ goal = *(size_t *)(void *)stuff;
+ if (goal < minlen || maxlen < goal)
+ {
+ if (debug)
+ fprintf(stderr, "%lu : [%lu, %lu]\n"
+ , (unsigned long)goal
+ , (unsigned long)minlen, (unsigned long)maxlen);
+ return HES_BAD_LEN;
+ }
+ }
+ }
+ } while (n < goal);
- return HES_CONTINUE;
+ return HES_CONTINUE;
}
/* Write a variable-length record to a pipe.
@@ -135,27 +133,27 @@ read_pipe(int fd, unsigned char *stuff, size_t minlen, size_t maxlen)
static enum helper_exit_status
write_pipe(int fd, const unsigned char *stuff)
{
- size_t len = *(const size_t *)(const void *)stuff;
- size_t n = 0;
+ size_t len = *(const size_t *)(const void *)stuff;
+ size_t n = 0;
- do {
- ssize_t m = write(fd, stuff + n, len - n);
+ do {
+ ssize_t m = write(fd, stuff + n, len - n);
- if (m == -1)
- {
- /* error, but ignore and retry if EINTR */
- if (errno != EINTR)
- {
- syslog(LOG_ERR, "Output error from master: %s", strerror(errno));
- return HES_IO_ERROR_OUT;
- }
- }
- else
- {
- n += m;
- }
- } while (n != len);
- return HES_CONTINUE;
+ if (m == -1)
+ {
+ /* error, but ignore and retry if EINTR */
+ if (errno != EINTR)
+ {
+ syslog(LOG_ERR, "Output error from master: %s", strerror(errno));
+ return HES_IO_ERROR_OUT;
+ }
+ }
+ else
+ {
+ n += m;
+ }
+ } while (n != len);
+ return HES_CONTINUE;
}
/**************** worker process ****************/
@@ -171,14 +169,14 @@ write_pipe(int fd, const unsigned char *stuff)
*/
#if (__RES) <= 19960801
-# define OLD_RESOLVER 1
+# define OLD_RESOLVER 1
#endif
#ifdef OLD_RESOLVER
# define res_ninit(statp) res_init()
# define res_nquery(statp, dname, class, type, answer, anslen) \
- res_query(dname, class, type, answer, anslen)
+ res_query(dname, class, type, answer, anslen)
# define res_nclose(statp) res_close()
static struct __res_state *statp = &_res;
@@ -193,75 +191,75 @@ static res_state statp = &my_res_state;
static int
worker(int qfd, int afd)
{
- {
- int r = res_ninit(statp);
-
- if (r != 0)
{
- syslog(LOG_ERR, "cannot initialize resolver");
- return HES_RES_INIT;
- }
+ int r = res_ninit(statp);
+
+ if (r != 0)
+ {
+ syslog(LOG_ERR, "cannot initialize resolver");
+ return HES_RES_INIT;
+ }
#ifndef OLD_RESOLVER
- statp->options |= RES_ROTATE;
+ statp->options |= RES_ROTATE;
#endif
- statp->options |= RES_DEBUG;
- }
+ statp->options |= RES_DEBUG;
+ }
- for (;;)
- {
- struct adns_query q;
- struct adns_answer a;
+ for (;;)
+ {
+ struct adns_query q;
+ struct adns_answer a;
- enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q
- , sizeof(q), sizeof(q));
+ enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q
+ , sizeof(q), sizeof(q));
- if (r != HES_CONTINUE)
- return r; /* some kind of exit */
+ if (r != HES_CONTINUE)
+ return r; /* some kind of exit */
- if (q.qmagic != ADNS_Q_MAGIC)
- {
- syslog(LOG_ERR, "error in input from master: bad magic");
- return HES_BAD_MAGIC;
- }
+ if (q.qmagic != ADNS_Q_MAGIC)
+ {
+ syslog(LOG_ERR, "error in input from master: bad magic");
+ return HES_BAD_MAGIC;
+ }
- a.amagic = ADNS_A_MAGIC;
- a.serial = q.serial;
+ a.amagic = ADNS_A_MAGIC;
+ a.serial = q.serial;
- a.result = res_nquery(statp, q.name_buf, C_IN, q.type, a.ans, sizeof(a.ans));
- a.h_errno_val = h_errno;
+ a.result = res_nquery(statp, q.name_buf, C_IN, q.type, a.ans, sizeof(a.ans));
+ a.h_errno_val = h_errno;
- a.len = offsetof(struct adns_answer, ans) + (a.result < 0? 0 : a.result);
+ a.len = offsetof(struct adns_answer, ans) + (a.result < 0? 0 : a.result);
#ifdef DEBUG
- if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type == T_KEY)
- || ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type == T_TXT))
- sleep(30); /* delay the answer */
+ if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type == T_KEY)
+ || ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type == T_TXT))
+ sleep(30); /* delay the answer */
#endif
- /* write answer, possibly a bit at a time */
- r = write_pipe(afd, (const unsigned char *)&a);
+ /* write answer, possibly a bit at a time */
+ r = write_pipe(afd, (const unsigned char *)&a);
- if (r != HES_CONTINUE)
- return r; /* some kind of exit */
- }
+ if (r != HES_CONTINUE)
+ return r; /* some kind of exit */
+ }
}
/**************** master process ****************/
bool eof_from_pluto = FALSE;
-#define PLUTO_QFD 0 /* queries come on stdin */
-#define PLUTO_AFD 1 /* answers go out on stdout */
+#define PLUTO_QFD 0 /* queries come on stdin */
+#define PLUTO_AFD 1 /* answers go out on stdout */
#ifndef MAX_WORKERS
-# define MAX_WORKERS 10 /* number of in-flight queries */
+# define MAX_WORKERS 10 /* number of in-flight queries */
#endif
struct worker_info {
- int qfd; /* query pipe's file descriptor */
- int afd; /* answer pipe's file descriptor */
- pid_t pid;
- bool busy;
- void *continuation; /* of outstanding request */
+ int qfd; /* query pipe's file descriptor */
+ int afd; /* answer pipe's file descriptor */
+ pid_t pid;
+ bool busy;
+ void *continuation; /* of outstanding request */
};
static struct worker_info wi[MAX_WORKERS];
@@ -270,300 +268,300 @@ static struct worker_info *wi_roof = wi;
/* request FIFO */
struct query_list {
- struct query_list *next;
- struct adns_query aq;
+ struct query_list *next;
+ struct adns_query aq;
};
static struct query_list *oldest_query = NULL;
-static struct query_list *newest_query; /* undefined when oldest == NULL */
+static struct query_list *newest_query; /* undefined when oldest == NULL */
static struct query_list *free_queries = NULL;
static bool
spawn_worker(void)
{
- int qfds[2];
- int afds[2];
- pid_t p;
-
- if (pipe(qfds) != 0 || pipe(afds) != 0)
- {
- syslog(LOG_ERR, "pipe(2) failed: %s", strerror(errno));
- exit(HES_PIPE);
- }
-
- wi_roof->qfd = qfds[1]; /* write end of query pipe */
- wi_roof->afd = afds[0]; /* read end of answer pipe */
-
- p = fork();
- if (p == -1)
- {
- /* fork failed: ignore if at least one worker exists */
- if (wi_roof == wi)
+ int qfds[2];
+ int afds[2];
+ pid_t p;
+
+ if (pipe(qfds) != 0 || pipe(afds) != 0)
+ {
+ syslog(LOG_ERR, "pipe(2) failed: %s", strerror(errno));
+ exit(HES_PIPE);
+ }
+
+ wi_roof->qfd = qfds[1]; /* write end of query pipe */
+ wi_roof->afd = afds[0]; /* read end of answer pipe */
+
+ p = fork();
+ if (p == -1)
+ {
+ /* fork failed: ignore if at least one worker exists */
+ if (wi_roof == wi)
+ {
+ syslog(LOG_ERR, "fork(2) error creating first worker: %s", strerror(errno));
+ exit(HES_FORK);
+ }
+ close(qfds[0]);
+ close(qfds[1]);
+ close(afds[0]);
+ close(afds[1]);
+ return FALSE;
+ }
+ else if (p == 0)
{
- syslog(LOG_ERR, "fork(2) error creating first worker: %s", strerror(errno));
- exit(HES_FORK);
+ /* child */
+ struct worker_info *w;
+
+ close(PLUTO_QFD);
+ close(PLUTO_AFD);
+ /* close all master pipes, including ours */
+ for (w = wi; w <= wi_roof; w++)
+ {
+ close(w->qfd);
+ close(w->afd);
+ }
+ exit(worker(qfds[0], afds[1]));
}
- close(qfds[0]);
- close(qfds[1]);
- close(afds[0]);
- close(afds[1]);
- return FALSE;
- }
- else if (p == 0)
- {
- /* child */
- struct worker_info *w;
-
- close(PLUTO_QFD);
- close(PLUTO_AFD);
- /* close all master pipes, including ours */
- for (w = wi; w <= wi_roof; w++)
+ else
{
- close(w->qfd);
- close(w->afd);
+ /* parent */
+ struct worker_info *w = wi_roof++;
+
+ w->pid = p;
+ w->busy = FALSE;
+ close(qfds[0]);
+ close(afds[1]);
+ return TRUE;
}
- exit(worker(qfds[0], afds[1]));
- }
- else
- {
- /* parent */
- struct worker_info *w = wi_roof++;
-
- w->pid = p;
- w->busy = FALSE;
- close(qfds[0]);
- close(afds[1]);
- return TRUE;
- }
}
static void
send_eof(struct worker_info *w)
{
- pid_t p;
- int status;
+ pid_t p;
+ int status;
- close(w->qfd);
- w->qfd = NULL_FD;
+ close(w->qfd);
+ w->qfd = NULL_FD;
- close(w->afd);
- w->afd = NULL_FD;
+ close(w->afd);
+ w->afd = NULL_FD;
- /* reap child */
- p = waitpid(w->pid, &status, 0);
- /* ignore result -- what could we do with it? */
+ /* reap child */
+ p = waitpid(w->pid, &status, 0);
+ /* ignore result -- what could we do with it? */
}
static void
forward_query(struct worker_info *w)
{
- struct query_list *q = oldest_query;
-
- if (q == NULL)
- {
- if (eof_from_pluto)
- send_eof(w);
- }
- else
- {
- enum helper_exit_status r
- = write_pipe(w->qfd, (const unsigned char *) &q->aq);
-
- if (r != HES_CONTINUE)
- exit(r);
-
- w->busy = TRUE;
-
- oldest_query = q->next;
- q->next = free_queries;
- free_queries = q;
- }
+ struct query_list *q = oldest_query;
+
+ if (q == NULL)
+ {
+ if (eof_from_pluto)
+ send_eof(w);
+ }
+ else
+ {
+ enum helper_exit_status r
+ = write_pipe(w->qfd, (const unsigned char *) &q->aq);
+
+ if (r != HES_CONTINUE)
+ exit(r);
+
+ w->busy = TRUE;
+
+ oldest_query = q->next;
+ q->next = free_queries;
+ free_queries = q;
+ }
}
static void
query(void)
{
- struct query_list *q = free_queries;
- enum helper_exit_status r;
+ struct query_list *q = free_queries;
+ enum helper_exit_status r;
- /* find an unused queue entry */
- if (q == NULL)
- {
- q = malloc(sizeof(*q));
+ /* find an unused queue entry */
if (q == NULL)
{
- syslog(LOG_ERR, "malloc(3) failed");
- exit(HES_MALLOC);
+ q = malloc(sizeof(*q));
+ if (q == NULL)
+ {
+ syslog(LOG_ERR, "malloc(3) failed");
+ exit(HES_MALLOC);
+ }
}
- }
- else
- {
- free_queries = q->next;
- }
-
- r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq
- , sizeof(q->aq), sizeof(q->aq));
-
- if (r == HES_OK)
- {
- /* EOF: we're done, except for unanswered queries */
- struct worker_info *w;
-
- eof_from_pluto = TRUE;
- q->next = free_queries;
- free_queries = q;
-
- /* Send bye-bye to unbusy processes.
- * Note that if there are queued queries, there won't be
- * any non-busy workers.
- */
- for (w = wi; w != wi_roof; w++)
- if (!w->busy)
- send_eof(w);
- }
- else if (r != HES_CONTINUE)
- {
- exit(r);
- }
- else if (q->aq.qmagic != ADNS_Q_MAGIC)
- {
- syslog(LOG_ERR, "error in query from Pluto: bad magic");
- exit(HES_BAD_MAGIC);
- }
- else
- {
- struct worker_info *w;
-
- /* got a query */
-
- /* add it to FIFO */
- q->next = NULL;
- if (oldest_query == NULL)
- oldest_query = q;
else
- newest_query->next = q;
- newest_query = q;
+ {
+ free_queries = q->next;
+ }
+
+ r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq
+ , sizeof(q->aq), sizeof(q->aq));
- /* See if any worker available */
- for (w = wi; ; w++)
+ if (r == HES_OK)
{
- if (w == wi_roof)
- {
- /* no free worker */
- if (w == wi + MAX_WORKERS)
- break; /* no more to be created */
- /* make a new one */
- if (!spawn_worker())
- break; /* cannot create one at this time */
- }
- if (!w->busy)
- {
- /* assign first to free worker */
- forward_query(w);
- break;
- }
+ /* EOF: we're done, except for unanswered queries */
+ struct worker_info *w;
+
+ eof_from_pluto = TRUE;
+ q->next = free_queries;
+ free_queries = q;
+
+ /* Send bye-bye to unbusy processes.
+ * Note that if there are queued queries, there won't be
+ * any non-busy workers.
+ */
+ for (w = wi; w != wi_roof; w++)
+ if (!w->busy)
+ send_eof(w);
+ }
+ else if (r != HES_CONTINUE)
+ {
+ exit(r);
+ }
+ else if (q->aq.qmagic != ADNS_Q_MAGIC)
+ {
+ syslog(LOG_ERR, "error in query from Pluto: bad magic");
+ exit(HES_BAD_MAGIC);
+ }
+ else
+ {
+ struct worker_info *w;
+
+ /* got a query */
+
+ /* add it to FIFO */
+ q->next = NULL;
+ if (oldest_query == NULL)
+ oldest_query = q;
+ else
+ newest_query->next = q;
+ newest_query = q;
+
+ /* See if any worker available */
+ for (w = wi; ; w++)
+ {
+ if (w == wi_roof)
+ {
+ /* no free worker */
+ if (w == wi + MAX_WORKERS)
+ break; /* no more to be created */
+ /* make a new one */
+ if (!spawn_worker())
+ break; /* cannot create one at this time */
+ }
+ if (!w->busy)
+ {
+ /* assign first to free worker */
+ forward_query(w);
+ break;
+ }
+ }
}
- }
- return;
+ return;
}
static void
answer(struct worker_info *w)
{
- struct adns_answer a;
- enum helper_exit_status r = read_pipe(w->afd, (unsigned char *)&a
- , offsetof(struct adns_answer, ans), sizeof(a));
-
- if (r == HES_OK)
- {
- /* unexpected EOF */
- syslog(LOG_ERR, "unexpected EOF from worker");
- exit(HES_IO_ERROR_IN);
- }
- else if (r != HES_CONTINUE)
- {
- exit(r);
- }
- else if (a.amagic != ADNS_A_MAGIC)
- {
- syslog(LOG_ERR, "Input from worker error: bad magic");
- exit(HES_BAD_MAGIC);
- }
- else if (a.continuation != w->continuation)
- {
- /* answer doesn't match query */
- syslog(LOG_ERR, "Input from worker error: continuation mismatch");
- exit(HES_SYNC);
- }
- else
- {
- /* pass the answer on to Pluto */
- enum helper_exit_status r
- = write_pipe(PLUTO_AFD, (const unsigned char *) &a);
-
- if (r != HES_CONTINUE)
- exit(r);
- w->busy = FALSE;
- forward_query(w);
- }
+ struct adns_answer a;
+ enum helper_exit_status r = read_pipe(w->afd, (unsigned char *)&a
+ , offsetof(struct adns_answer, ans), sizeof(a));
+
+ if (r == HES_OK)
+ {
+ /* unexpected EOF */
+ syslog(LOG_ERR, "unexpected EOF from worker");
+ exit(HES_IO_ERROR_IN);
+ }
+ else if (r != HES_CONTINUE)
+ {
+ exit(r);
+ }
+ else if (a.amagic != ADNS_A_MAGIC)
+ {
+ syslog(LOG_ERR, "Input from worker error: bad magic");
+ exit(HES_BAD_MAGIC);
+ }
+ else if (a.continuation != w->continuation)
+ {
+ /* answer doesn't match query */
+ syslog(LOG_ERR, "Input from worker error: continuation mismatch");
+ exit(HES_SYNC);
+ }
+ else
+ {
+ /* pass the answer on to Pluto */
+ enum helper_exit_status r
+ = write_pipe(PLUTO_AFD, (const unsigned char *) &a);
+
+ if (r != HES_CONTINUE)
+ exit(r);
+ w->busy = FALSE;
+ forward_query(w);
+ }
}
/* assumption: input limited; accept blocking on output */
static int
master(void)
{
- for (;;)
- {
- fd_set readfds;
- int maxfd = PLUTO_QFD; /* approximate lower bound */
- int ndes = 0;
- struct worker_info *w;
-
- FD_ZERO(&readfds);
- if (!eof_from_pluto)
+ for (;;)
{
- FD_SET(PLUTO_QFD, &readfds);
- ndes++;
- }
- for (w = wi; w != wi_roof; w++)
- {
- if (w->busy)
- {
- FD_SET(w->afd, &readfds);
- ndes++;
- if (maxfd < w->afd)
- maxfd = w->afd;
- }
- }
+ fd_set readfds;
+ int maxfd = PLUTO_QFD; /* approximate lower bound */
+ int ndes = 0;
+ struct worker_info *w;
+
+ FD_ZERO(&readfds);
+ if (!eof_from_pluto)
+ {
+ FD_SET(PLUTO_QFD, &readfds);
+ ndes++;
+ }
+ for (w = wi; w != wi_roof; w++)
+ {
+ if (w->busy)
+ {
+ FD_SET(w->afd, &readfds);
+ ndes++;
+ if (maxfd < w->afd)
+ maxfd = w->afd;
+ }
+ }
- if (ndes == 0)
- return HES_OK; /* done! */
+ if (ndes == 0)
+ return HES_OK; /* done! */
- do {
- ndes = select(maxfd + 1, &readfds, NULL, NULL, NULL);
- } while (ndes == -1 && errno == EINTR);
- if (ndes == -1)
- {
- syslog(LOG_ERR, "select(2) error: %s", strerror(errno));
- exit(HES_IO_ERROR_SELECT);
- }
- else if (ndes > 0)
- {
- if (FD_ISSET(PLUTO_QFD, &readfds))
- {
- query();
- ndes--;
- }
- for (w = wi; ndes > 0 && w != wi_roof; w++)
- {
- if (w->busy && FD_ISSET(w->afd, &readfds))
+ do {
+ ndes = select(maxfd + 1, &readfds, NULL, NULL, NULL);
+ } while (ndes == -1 && errno == EINTR);
+ if (ndes == -1)
+ {
+ syslog(LOG_ERR, "select(2) error: %s", strerror(errno));
+ exit(HES_IO_ERROR_SELECT);
+ }
+ else if (ndes > 0)
{
- answer(w);
- ndes--;
+ if (FD_ISSET(PLUTO_QFD, &readfds))
+ {
+ query();
+ ndes--;
+ }
+ for (w = wi; ndes > 0 && w != wi_roof; w++)
+ {
+ if (w->busy && FD_ISSET(w->afd, &readfds))
+ {
+ answer(w);
+ ndes--;
+ }
+ }
}
- }
}
- }
}
/* Not to be invoked by strangers -- user hostile.
@@ -574,42 +572,42 @@ master(void)
static void
adns_usage(const char *fmt, const char *arg)
{
- const char **sp = ipsec_copyright_notice();
+ const char **sp = ipsec_copyright_notice();
- fprintf(stderr, "INTERNAL TO PLUTO: DO NOT EXECUTE\n");
+ fprintf(stderr, "INTERNAL TO PLUTO: DO NOT EXECUTE\n");
- fprintf(stderr, fmt, arg);
- fprintf(stderr, "\n%s\n", ipsec_version_string());
+ fprintf(stderr, fmt, arg);
+ fprintf(stderr, "\nstrongSwan "VERSION"\n");
- for (; *sp != NULL; sp++)
- fprintf(stderr, "%s\n", *sp);
+ for (; *sp != NULL; sp++)
+ fprintf(stderr, "%s\n", *sp);
- syslog(LOG_ERR, fmt, arg);
- exit(HES_INVOCATION);
+ syslog(LOG_ERR, fmt, arg);
+ exit(HES_INVOCATION);
}
int
main(int argc UNUSED, char **argv)
{
- int i = 1;
+ int i = 1;
- name = argv[0];
+ name = argv[0];
- while (i < argc)
- {
- if (streq(argv[i], "-d"))
+ while (i < argc)
{
- i++;
- debug = TRUE;
- }
- else
- {
- adns_usage("unexpected argument \"%s\"", argv[i]);
- /*NOTREACHED*/
+ if (streq(argv[i], "-d"))
+ {
+ i++;
+ debug = TRUE;
+ }
+ else
+ {
+ adns_usage("unexpected argument \"%s\"", argv[i]);
+ /*NOTREACHED*/
+ }
}
- }
- return master();
+ return master();
}
#endif /* !USE_LWRES */
diff --git a/src/pluto/adns.h b/src/pluto/adns.h
index f2d0b28bd..f564be232 100644
--- a/src/pluto/adns.h
+++ b/src/pluto/adns.h
@@ -10,11 +10,9 @@
* 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: adns.h 3252 2007-10-06 21:24:50Z andreas $
*/
-#ifndef USE_LWRES /* whole file! */
+#ifndef USE_LWRES /* whole file! */
/* The interface in RHL6.x and BIND distribution 8.2.2 are different,
* so we build some of our own :-(
@@ -38,38 +36,38 @@
*/
struct adns_query {
- size_t len;
- unsigned int qmagic;
- unsigned long serial;
- lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
- u_char name_buf[NS_MAXDNAME + 2];
- int type; /* T_KEY or T_TXT */
+ size_t len;
+ unsigned int qmagic;
+ unsigned long serial;
+ lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
+ u_char name_buf[NS_MAXDNAME + 2];
+ int type; /* T_KEY or T_TXT */
};
struct adns_answer {
- size_t len;
- unsigned int amagic;
- unsigned long serial;
- struct adns_continuation *continuation;
- int result;
- int h_errno_val;
- u_char ans[NS_PACKETSZ * 10]; /* very probably bigger than necessary */
+ size_t len;
+ unsigned int amagic;
+ unsigned long serial;
+ struct adns_continuation *continuation;
+ int result;
+ int h_errno_val;
+ u_char ans[NS_PACKETSZ * 10]; /* very probably bigger than necessary */
};
enum helper_exit_status {
- HES_CONTINUE = -1, /* not an exit */
- HES_OK = 0, /* all's well that ends well (perhaps EOF) */
- HES_INVOCATION, /* improper invocation */
- HES_IO_ERROR_SELECT, /* IO error in select() */
- HES_MALLOC, /* malloc failed */
- HES_IO_ERROR_IN, /* error reading pipe */
- HES_IO_ERROR_OUT, /* error reading pipe */
- HES_PIPE, /* pipe(2) failed */
- HES_SYNC, /* answer from worker doesn't match query */
- HES_FORK, /* fork(2) failed */
- HES_RES_INIT, /* resolver initialization failed */
- HES_BAD_LEN, /* implausible .len field */
- HES_BAD_MAGIC, /* .magic field wrong */
+ HES_CONTINUE = -1, /* not an exit */
+ HES_OK = 0, /* all's well that ends well (perhaps EOF) */
+ HES_INVOCATION, /* improper invocation */
+ HES_IO_ERROR_SELECT, /* IO error in select() */
+ HES_MALLOC, /* malloc failed */
+ HES_IO_ERROR_IN, /* error reading pipe */
+ HES_IO_ERROR_OUT, /* error reading pipe */
+ HES_PIPE, /* pipe(2) failed */
+ HES_SYNC, /* answer from worker doesn't match query */
+ HES_FORK, /* fork(2) failed */
+ HES_RES_INIT, /* resolver initialization failed */
+ HES_BAD_LEN, /* implausible .len field */
+ HES_BAD_MAGIC, /* .magic field wrong */
};
#endif /* !USE_LWRES */
diff --git a/src/pluto/alg/ike_alg_aes.c b/src/pluto/alg/ike_alg_aes.c
deleted file mode 100644
index c635af723..000000000
--- a/src/pluto/alg/ike_alg_aes.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "libaes/aes_cbc.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-
-#define AES_CBC_BLOCK_SIZE (128/BITS_PER_BYTE)
-#define AES_KEY_MIN_LEN 128
-#define AES_KEY_DEF_LEN 128
-#define AES_KEY_MAX_LEN 256
-
-static void
-do_aes(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc)
-{
- aes_context aes_ctx;
- char iv_bak[AES_CBC_BLOCK_SIZE];
- char *new_iv = NULL; /* logic will avoid copy to NULL */
-
- aes_set_key(&aes_ctx, key, key_size, 0);
-
- /*
- * my AES cbc does not touch passed IV (optimization for
- * ESP handling), so I must "emulate" des-like IV
- * crunching
- */
- if (!enc)
- memcpy(new_iv=iv_bak, (char*) buf + buf_len - AES_CBC_BLOCK_SIZE
- , AES_CBC_BLOCK_SIZE);
-
- SS_AES_cbc_encrypt(&aes_ctx, buf, buf, buf_len, iv, enc);
-
- if (enc)
- new_iv = (char*) buf + buf_len-AES_CBC_BLOCK_SIZE;
-
- memcpy(iv, new_iv, AES_CBC_BLOCK_SIZE);
-}
-
-struct encrypt_desc algo_aes =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_AES_CBC,
- algo_next: NULL,
- enc_ctxsize: sizeof(aes_context),
- enc_blocksize: AES_CBC_BLOCK_SIZE,
- keyminlen: AES_KEY_MIN_LEN,
- keydeflen: AES_KEY_DEF_LEN,
- keymaxlen: AES_KEY_MAX_LEN,
- do_crypt: do_aes,
-};
-
-int ike_alg_aes_init(void);
-
-int
-ike_alg_aes_init(void)
-{
- int ret = ike_alg_register_enc(&algo_aes);
- return ret;
-}
-/*
-IKE_ALG_INIT_NAME: ike_alg_aes_init
-*/
diff --git a/src/pluto/alg/ike_alg_blowfish.c b/src/pluto/alg/ike_alg_blowfish.c
deleted file mode 100644
index 2bbef051b..000000000
--- a/src/pluto/alg/ike_alg_blowfish.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "libblowfish/blowfish.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-
-#define BLOWFISH_CBC_BLOCK_SIZE 8 /* block size */
-#define BLOWFISH_KEY_MIN_LEN 128
-#define BLOWFISH_KEY_MAX_LEN 448
-
-
-static void
-do_blowfish(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc)
-{
- BF_KEY bf_ctx;
-
- BF_set_key(&bf_ctx, key_size , key);
- BF_cbc_encrypt(buf, buf, buf_len, &bf_ctx, iv, enc);
-}
-
-struct encrypt_desc algo_blowfish =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_BLOWFISH_CBC,
- algo_next: NULL,
- enc_ctxsize: sizeof(BF_KEY),
- enc_blocksize: BLOWFISH_CBC_BLOCK_SIZE,
- keyminlen: BLOWFISH_KEY_MIN_LEN,
- keydeflen: BLOWFISH_KEY_MIN_LEN,
- keymaxlen: BLOWFISH_KEY_MAX_LEN,
- do_crypt: do_blowfish,
-};
-
-int ike_alg_blowfish_init(void);
-
-int
-ike_alg_blowfish_init(void)
-{
- int ret = ike_alg_register_enc(&algo_blowfish);
-
- return ret;
-}
-/*
-IKE_ALG_INIT_NAME: ike_alg_blowfish_init
-*/
diff --git a/src/pluto/alg/ike_alg_serpent.c b/src/pluto/alg/ike_alg_serpent.c
deleted file mode 100644
index fb01caa41..000000000
--- a/src/pluto/alg/ike_alg_serpent.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "libserpent/serpent_cbc.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-
-#define SERPENT_CBC_BLOCK_SIZE (128/BITS_PER_BYTE)
-#define SERPENT_KEY_MIN_LEN 128
-#define SERPENT_KEY_DEF_LEN 128
-#define SERPENT_KEY_MAX_LEN 256
-
-static void
-do_serpent(u_int8_t *buf, size_t buf_size, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc)
-{
- serpent_context serpent_ctx;
- char iv_bak[SERPENT_CBC_BLOCK_SIZE];
- char *new_iv = NULL; /* logic will avoid copy to NULL */
-
-
- serpent_set_key(&serpent_ctx, key, key_size);
- /*
- * my SERPENT cbc does not touch passed IV (optimization for
- * ESP handling), so I must "emulate" des-like IV
- * crunching
- */
- if (!enc)
- memcpy(new_iv=iv_bak,
- (char*) buf + buf_size-SERPENT_CBC_BLOCK_SIZE,
- SERPENT_CBC_BLOCK_SIZE);
-
- serpent_cbc_encrypt(&serpent_ctx, buf, buf, buf_size, iv, enc);
-
- if (enc)
- new_iv = (char*) buf + buf_size-SERPENT_CBC_BLOCK_SIZE;
-
- memcpy(iv, new_iv, SERPENT_CBC_BLOCK_SIZE);
-}
-
-struct encrypt_desc encrypt_desc_serpent =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_SERPENT_CBC,
- algo_next: NULL,
- enc_ctxsize: sizeof(struct serpent_context),
- enc_blocksize: SERPENT_CBC_BLOCK_SIZE,
- keyminlen: SERPENT_KEY_MIN_LEN,
- keydeflen: SERPENT_KEY_DEF_LEN,
- keymaxlen: SERPENT_KEY_MAX_LEN,
- do_crypt: do_serpent,
-};
-
-int ike_alg_serpent_init(void);
-
-int
-ike_alg_serpent_init(void)
-{
- int ret = ike_alg_register_enc(&encrypt_desc_serpent);
-
- return ret;
-}
-/*
-IKE_ALG_INIT_NAME: ike_alg_serpent_init
-*/
diff --git a/src/pluto/alg/ike_alg_sha2.c b/src/pluto/alg/ike_alg_sha2.c
deleted file mode 100644
index 6b7c8438c..000000000
--- a/src/pluto/alg/ike_alg_sha2.c
+++ /dev/null
@@ -1,634 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "libsha2/sha2.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-
-static void
-sha256_hash_final(u_char *hash, sha256_context *ctx)
-{
- sha256_final(ctx);
- memcpy(hash, ctx->sha_out, SHA2_256_DIGEST_SIZE);
-}
-
-static void
-sha384_hash_final(u_char *hash, sha512_context *ctx)
-{
- sha512_final(ctx);
- memcpy(hash, ctx->sha_out, SHA2_384_DIGEST_SIZE);
-}
-
-static void
-sha512_hash_final(u_char *hash, sha512_context *ctx)
-{
- sha512_final(ctx);
- memcpy(hash, ctx->sha_out, SHA2_512_DIGEST_SIZE);
-}
-
-/* SHA-256 hash test vectors
- * from "The Secure Hash Algorithm Validation System (SHAVS)"
- * July 22, 2004, Lawrence E. Bassham III, NIST
- */
-
-static const u_char sha256_short2_msg[] = {
- 0x19
-};
-
-static const u_char sha256_short2_msg_digest[] = {
- 0x68, 0xaa, 0x2e, 0x2e, 0xe5, 0xdf, 0xf9, 0x6e,
- 0x33, 0x55, 0xe6, 0xc7, 0xee, 0x37, 0x3e, 0x3d,
- 0x6a, 0x4e, 0x17, 0xf7, 0x5f, 0x95, 0x18, 0xd8,
- 0x43, 0x70, 0x9c, 0x0c, 0x9b, 0xc3, 0xe3, 0xd4
-};
-
-static const u_char sha256_short4_msg[] = {
- 0xe3, 0xd7, 0x25, 0x70, 0xdc, 0xdd, 0x78, 0x7c,
- 0xe3, 0x88, 0x7a, 0xb2, 0xcd, 0x68, 0x46, 0x52
-};
-
-static const u_char sha256_short4_msg_digest[] = {
- 0x17, 0x5e, 0xe6, 0x9b, 0x02, 0xba, 0x9b, 0x58,
- 0xe2, 0xb0, 0xa5, 0xfd, 0x13, 0x81, 0x9c, 0xea,
- 0x57, 0x3f, 0x39, 0x40, 0xa9, 0x4f, 0x82, 0x51,
- 0x28, 0xcf, 0x42, 0x09, 0xbe, 0xab, 0xb4, 0xe8
-};
-
-static const u_char sha256_long2_msg[] = {
- 0x83, 0x26, 0x75, 0x4e, 0x22, 0x77, 0x37, 0x2f,
- 0x4f, 0xc1, 0x2b, 0x20, 0x52, 0x7a, 0xfe, 0xf0,
- 0x4d, 0x8a, 0x05, 0x69, 0x71, 0xb1, 0x1a, 0xd5,
- 0x71, 0x23, 0xa7, 0xc1, 0x37, 0x76, 0x00, 0x00,
- 0xd7, 0xbe, 0xf6, 0xf3, 0xc1, 0xf7, 0xa9, 0x08,
- 0x3a, 0xa3, 0x9d, 0x81, 0x0d, 0xb3, 0x10, 0x77,
- 0x7d, 0xab, 0x8b, 0x1e, 0x7f, 0x02, 0xb8, 0x4a,
- 0x26, 0xc7, 0x73, 0x32, 0x5f, 0x8b, 0x23, 0x74,
- 0xde, 0x7a, 0x4b, 0x5a, 0x58, 0xcb, 0x5c, 0x5c,
- 0xf3, 0x5b, 0xce, 0xe6, 0xfb, 0x94, 0x6e, 0x5b,
- 0xd6, 0x94, 0xfa, 0x59, 0x3a, 0x8b, 0xeb, 0x3f,
- 0x9d, 0x65, 0x92, 0xec, 0xed, 0xaa, 0x66, 0xca,
- 0x82, 0xa2, 0x9d, 0x0c, 0x51, 0xbc, 0xf9, 0x33,
- 0x62, 0x30, 0xe5, 0xd7, 0x84, 0xe4, 0xc0, 0xa4,
- 0x3f, 0x8d, 0x79, 0xa3, 0x0a, 0x16, 0x5c, 0xba,
- 0xbe, 0x45, 0x2b, 0x77, 0x4b, 0x9c, 0x71, 0x09,
- 0xa9, 0x7d, 0x13, 0x8f, 0x12, 0x92, 0x28, 0x96,
- 0x6f, 0x6c, 0x0a, 0xdc, 0x10, 0x6a, 0xad, 0x5a,
- 0x9f, 0xdd, 0x30, 0x82, 0x57, 0x69, 0xb2, 0xc6,
- 0x71, 0xaf, 0x67, 0x59, 0xdf, 0x28, 0xeb, 0x39,
- 0x3d, 0x54, 0xd6
-};
-
-static const u_char sha256_long2_msg_digest[] = {
- 0x97, 0xdb, 0xca, 0x7d, 0xf4, 0x6d, 0x62, 0xc8,
- 0xa4, 0x22, 0xc9, 0x41, 0xdd, 0x7e, 0x83, 0x5b,
- 0x8a, 0xd3, 0x36, 0x17, 0x63, 0xf7, 0xe9, 0xb2,
- 0xd9, 0x5f, 0x4f, 0x0d, 0xa6, 0xe1, 0xcc, 0xbc
-};
-
-static const hash_testvector_t sha256_hash_testvectors[] = {
- { sizeof(sha256_short2_msg), sha256_short2_msg, sha256_short2_msg_digest },
- { sizeof(sha256_short4_msg), sha256_short4_msg, sha256_short4_msg_digest },
- { sizeof(sha256_long2_msg), sha256_long2_msg, sha256_long2_msg_digest },
- { 0, NULL, NULL }
-};
-
-/* SHA-384 hash test vectors
- * from "The Secure Hash Algorithm Validation System (SHAVS)"
- * July 22, 2004, Lawrence E. Bassham III, NIST
- */
-
-static const u_char sha384_short2_msg[] = {
- 0xb9
-};
-
-static const u_char sha384_short2_msg_digest[] = {
- 0xbc, 0x80, 0x89, 0xa1, 0x90, 0x07, 0xc0, 0xb1,
- 0x41, 0x95, 0xf4, 0xec, 0xc7, 0x40, 0x94, 0xfe,
- 0xc6, 0x4f, 0x01, 0xf9, 0x09, 0x29, 0x28, 0x2c,
- 0x2f, 0xb3, 0x92, 0x88, 0x15, 0x78, 0x20, 0x8a,
- 0xd4, 0x66, 0x82, 0x8b, 0x1c, 0x6c, 0x28, 0x3d,
- 0x27, 0x22, 0xcf, 0x0a, 0xd1, 0xab, 0x69, 0x38
-};
-
-static const u_char sha384_short4_msg[] = {
- 0xa4, 0x1c, 0x49, 0x77, 0x79, 0xc0, 0x37, 0x5f,
- 0xf1, 0x0a, 0x7f, 0x4e, 0x08, 0x59, 0x17, 0x39
-};
-
-static const u_char sha384_short4_msg_digest[] = {
- 0xc9, 0xa6, 0x84, 0x43, 0xa0, 0x05, 0x81, 0x22,
- 0x56, 0xb8, 0xec, 0x76, 0xb0, 0x05, 0x16, 0xf0,
- 0xdb, 0xb7, 0x4f, 0xab, 0x26, 0xd6, 0x65, 0x91,
- 0x3f, 0x19, 0x4b, 0x6f, 0xfb, 0x0e, 0x91, 0xea,
- 0x99, 0x67, 0x56, 0x6b, 0x58, 0x10, 0x9c, 0xbc,
- 0x67, 0x5c, 0xc2, 0x08, 0xe4, 0xc8, 0x23, 0xf7
-};
-
-static const u_char sha384_long2_msg[] = {
- 0x39, 0x96, 0x69, 0xe2, 0x8f, 0x6b, 0x9c, 0x6d,
- 0xbc, 0xbb, 0x69, 0x12, 0xec, 0x10, 0xff, 0xcf,
- 0x74, 0x79, 0x03, 0x49, 0xb7, 0xdc, 0x8f, 0xbe,
- 0x4a, 0x8e, 0x7b, 0x3b, 0x56, 0x21, 0xdb, 0x0f,
- 0x3e, 0x7d, 0xc8, 0x7f, 0x82, 0x32, 0x64, 0xbb,
- 0xe4, 0x0d, 0x18, 0x11, 0xc9, 0xea, 0x20, 0x61,
- 0xe1, 0xc8, 0x4a, 0xd1, 0x0a, 0x23, 0xfa, 0xc1,
- 0x72, 0x7e, 0x72, 0x02, 0xfc, 0x3f, 0x50, 0x42,
- 0xe6, 0xbf, 0x58, 0xcb, 0xa8, 0xa2, 0x74, 0x6e,
- 0x1f, 0x64, 0xf9, 0xb9, 0xea, 0x35, 0x2c, 0x71,
- 0x15, 0x07, 0x05, 0x3c, 0xf4, 0xe5, 0x33, 0x9d,
- 0x52, 0x86, 0x5f, 0x25, 0xcc, 0x22, 0xb5, 0xe8,
- 0x77, 0x84, 0xa1, 0x2f, 0xc9, 0x61, 0xd6, 0x6c,
- 0xb6, 0xe8, 0x95, 0x73, 0x19, 0x9a, 0x2c, 0xe6,
- 0x56, 0x5c, 0xbd, 0xf1, 0x3d, 0xca, 0x40, 0x38,
- 0x32, 0xcf, 0xcb, 0x0e, 0x8b, 0x72, 0x11, 0xe8,
- 0x3a, 0xf3, 0x2a, 0x11, 0xac, 0x17, 0x92, 0x9f,
- 0xf1, 0xc0, 0x73, 0xa5, 0x1c, 0xc0, 0x27, 0xaa,
- 0xed, 0xef, 0xf8, 0x5a, 0xad, 0x7c, 0x2b, 0x7c,
- 0x5a, 0x80, 0x3e, 0x24, 0x04, 0xd9, 0x6d, 0x2a,
- 0x77, 0x35, 0x7b, 0xda, 0x1a, 0x6d, 0xae, 0xed,
- 0x17, 0x15, 0x1c, 0xb9, 0xbc, 0x51, 0x25, 0xa4,
- 0x22, 0xe9, 0x41, 0xde, 0x0c, 0xa0, 0xfc, 0x50,
- 0x11, 0xc2, 0x3e, 0xcf, 0xfe, 0xfd, 0xd0, 0x96,
- 0x76, 0x71, 0x1c, 0xf3, 0xdb, 0x0a, 0x34, 0x40,
- 0x72, 0x0e ,0x16, 0x15, 0xc1, 0xf2, 0x2f, 0xbc,
- 0x3c, 0x72, 0x1d, 0xe5, 0x21, 0xe1, 0xb9, 0x9b,
- 0xa1, 0xbd, 0x55, 0x77, 0x40, 0x86, 0x42, 0x14,
- 0x7e, 0xd0, 0x96
-};
-
-static const u_char sha384_long2_msg_digest[] = {
- 0x4f, 0x44, 0x0d, 0xb1, 0xe6, 0xed, 0xd2, 0x89,
- 0x9f, 0xa3, 0x35, 0xf0, 0x95, 0x15, 0xaa, 0x02,
- 0x5e, 0xe1, 0x77, 0xa7, 0x9f, 0x4b, 0x4a, 0xaf,
- 0x38, 0xe4, 0x2b, 0x5c, 0x4d, 0xe6, 0x60, 0xf5,
- 0xde, 0x8f, 0xb2, 0xa5, 0xb2, 0xfb, 0xd2, 0xa3,
- 0xcb, 0xff, 0xd2, 0x0c, 0xff, 0x12, 0x88, 0xc0
-};
-
-static const hash_testvector_t sha384_hash_testvectors[] = {
- { sizeof(sha384_short2_msg), sha384_short2_msg, sha384_short2_msg_digest },
- { sizeof(sha384_short4_msg), sha384_short4_msg, sha384_short4_msg_digest },
- { sizeof(sha384_long2_msg), sha384_long2_msg, sha384_long2_msg_digest },
- { 0, NULL, NULL }
-};
-
-/* SHA-512 hash test vectors
- * from "The Secure Hash Algorithm Validation System (SHAVS)"
- * July 22, 2004, Lawrence E. Bassham III, NIST
- */
-
-static const u_char sha512_short2_msg[] = {
- 0xd0
-};
-
-static const u_char sha512_short2_msg_digest[] = {
- 0x99, 0x92, 0x20, 0x29, 0x38, 0xe8, 0x82, 0xe7,
- 0x3e, 0x20, 0xf6, 0xb6, 0x9e, 0x68, 0xa0, 0xa7,
- 0x14, 0x90, 0x90, 0x42, 0x3d, 0x93, 0xc8, 0x1b,
- 0xab, 0x3f, 0x21, 0x67, 0x8d, 0x4a, 0xce, 0xee,
- 0xe5, 0x0e, 0x4e, 0x8c, 0xaf, 0xad, 0xa4, 0xc8,
- 0x5a, 0x54, 0xea, 0x83, 0x06, 0x82, 0x6c, 0x4a,
- 0xd6, 0xe7, 0x4c, 0xec, 0xe9, 0x63, 0x1b, 0xfa,
- 0x8a, 0x54, 0x9b, 0x4a, 0xb3, 0xfb, 0xba, 0x15
-};
-
-static const u_char sha512_short4_msg[] = {
- 0x8d, 0x4e, 0x3c, 0x0e, 0x38, 0x89, 0x19, 0x14,
- 0x91, 0x81, 0x6e, 0x9d, 0x98, 0xbf, 0xf0, 0xa0
-};
-
-static const u_char sha512_short4_msg_digest[] = {
- 0xcb, 0x0b, 0x67, 0xa4, 0xb8, 0x71, 0x2c, 0xd7,
- 0x3c, 0x9a, 0xab, 0xc0, 0xb1, 0x99, 0xe9, 0x26,
- 0x9b, 0x20, 0x84, 0x4a, 0xfb, 0x75, 0xac, 0xbd,
- 0xd1, 0xc1, 0x53, 0xc9, 0x82, 0x89, 0x24, 0xc3,
- 0xdd, 0xed, 0xaa, 0xfe, 0x66, 0x9c, 0x5f, 0xdd,
- 0x0b, 0xc6, 0x6f, 0x63, 0x0f, 0x67, 0x73, 0x98,
- 0x82, 0x13, 0xeb, 0x1b, 0x16, 0xf5, 0x17, 0xad,
- 0x0d, 0xe4, 0xb2, 0xf0, 0xc9, 0x5c, 0x90, 0xf8
-};
-
-static const u_char sha512_long2_msg[] = {
- 0xa5, 0x5f, 0x20, 0xc4, 0x11, 0xaa, 0xd1, 0x32,
- 0x80, 0x7a, 0x50, 0x2d, 0x65, 0x82, 0x4e, 0x31,
- 0xa2, 0x30, 0x54, 0x32, 0xaa, 0x3d, 0x06, 0xd3,
- 0xe2, 0x82, 0xa8, 0xd8, 0x4e, 0x0d, 0xe1, 0xde,
- 0x69, 0x74, 0xbf, 0x49, 0x54, 0x69, 0xfc, 0x7f,
- 0x33, 0x8f, 0x80, 0x54, 0xd5, 0x8c, 0x26, 0xc4,
- 0x93, 0x60, 0xc3, 0xe8, 0x7a, 0xf5, 0x65, 0x23,
- 0xac, 0xf6, 0xd8, 0x9d, 0x03, 0xe5, 0x6f, 0xf2,
- 0xf8, 0x68, 0x00, 0x2b, 0xc3, 0xe4, 0x31, 0xed,
- 0xc4, 0x4d, 0xf2, 0xf0, 0x22, 0x3d, 0x4b, 0xb3,
- 0xb2, 0x43, 0x58, 0x6e, 0x1a, 0x7d, 0x92, 0x49,
- 0x36, 0x69, 0x4f, 0xcb, 0xba, 0xf8, 0x8d, 0x95,
- 0x19, 0xe4, 0xeb, 0x50, 0xa6, 0x44, 0xf8, 0xe4,
- 0xf9, 0x5e, 0xb0, 0xea, 0x95, 0xbc, 0x44, 0x65,
- 0xc8, 0x82, 0x1a, 0xac, 0xd2, 0xfe, 0x15, 0xab,
- 0x49, 0x81, 0x16, 0x4b, 0xbb, 0x6d, 0xc3, 0x2f,
- 0x96, 0x90, 0x87, 0xa1, 0x45, 0xb0, 0xd9, 0xcc,
- 0x9c, 0x67, 0xc2, 0x2b, 0x76, 0x32, 0x99, 0x41,
- 0x9c, 0xc4, 0x12, 0x8b, 0xe9, 0xa0, 0x77, 0xb3,
- 0xac, 0xe6, 0x34, 0x06, 0x4e, 0x6d, 0x99, 0x28,
- 0x35, 0x13, 0xdc, 0x06, 0xe7, 0x51, 0x5d, 0x0d,
- 0x73, 0x13, 0x2e, 0x9a, 0x0d, 0xc6, 0xd3, 0xb1,
- 0xf8, 0xb2, 0x46, 0xf1, 0xa9, 0x8a, 0x3f, 0xc7,
- 0x29, 0x41, 0xb1, 0xe3, 0xbb, 0x20, 0x98, 0xe8,
- 0xbf, 0x16, 0xf2, 0x68, 0xd6, 0x4f, 0x0b, 0x0f,
- 0x47, 0x07, 0xfe, 0x1e, 0xa1, 0xa1, 0x79, 0x1b,
- 0xa2, 0xf3, 0xc0, 0xc7, 0x58, 0xe5, 0xf5, 0x51,
- 0x86, 0x3a, 0x96, 0xc9, 0x49, 0xad, 0x47, 0xd7,
- 0xfb, 0x40, 0xd2
-};
-
-static const u_char sha512_long2_msg_digest[] = {
- 0xc6, 0x65, 0xbe, 0xfb, 0x36, 0xda, 0x18, 0x9d,
- 0x78, 0x82, 0x2d, 0x10, 0x52, 0x8c, 0xbf, 0x3b,
- 0x12, 0xb3, 0xee, 0xf7, 0x26, 0x03, 0x99, 0x09,
- 0xc1, 0xa1, 0x6a, 0x27, 0x0d, 0x48, 0x71, 0x93,
- 0x77, 0x96, 0x6b, 0x95, 0x7a, 0x87, 0x8e, 0x72,
- 0x05, 0x84, 0x77, 0x9a, 0x62, 0x82, 0x5c, 0x18,
- 0xda, 0x26, 0x41, 0x5e, 0x49, 0xa7, 0x17, 0x6a,
- 0x89, 0x4e, 0x75, 0x10, 0xfd, 0x14, 0x51, 0xf5
-};
-
-static const hash_testvector_t sha512_hash_testvectors[] = {
- { sizeof(sha512_short2_msg), sha512_short2_msg, sha512_short2_msg_digest },
- { sizeof(sha512_short4_msg), sha512_short4_msg, sha512_short4_msg_digest },
- { sizeof(sha512_long2_msg), sha512_long2_msg, sha512_long2_msg_digest },
- { 0, NULL, NULL }
-};
-
-/* SHA-256, SHA-384, and SHA-512 hmac test vectors
- * from RFC 4231 "Identifiers and Test Vectors for HMAC-SHA-224,
- * HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512"
- * December 2005, M. Nystrom, RSA Security
- */
-
-static const u_char sha2_hmac1_key[] = {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b
-};
-
-static const u_char sha2_hmac1_msg[] = {
- 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
-};
-
-static const u_char sha2_hmac1_256[] = {
- 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
- 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
- 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
- 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
-};
-
-static const u_char sha2_hmac1_384[] = {
- 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
- 0x6b, 0x08, 0x25, 0xf4, 0xab ,0x46, 0x90, 0x7f,
- 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
- 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
- 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
- 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6
-};
-
-static const u_char sha2_hmac1_512[] = {
- 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
- 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
- 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
- 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
- 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
- 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
- 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
- 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54
-};
-
-static const u_char sha2_hmac2_key[] = {
- 0x4a, 0x65, 0x66, 0x65
-};
-
-static const u_char sha2_hmac2_msg[] = {
- 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
- 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
- 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
- 0x69, 0x6e, 0x67, 0x3f
-};
-
-static const u_char sha2_hmac2_256[] = {
- 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
- 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
- 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
- 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
-};
-
-static const u_char sha2_hmac2_384[] = {
- 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
- 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
- 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
- 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
- 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
- 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49
-};
-
-static const u_char sha2_hmac2_512[] = {
- 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
- 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
- 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
- 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
- 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
- 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
- 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
- 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37
-};
-
-static const u_char sha2_hmac3_key[] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa
-};
-
-static const u_char sha2_hmac3_msg[] = {
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd
-};
-
-static const u_char sha2_hmac3_256[] = {
- 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
- 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
- 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
- 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe
-};
-
-static const u_char sha2_hmac3_384[] = {
- 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a,
- 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f,
- 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
- 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b,
- 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9,
- 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27
-};
-
-static const u_char sha2_hmac3_512[] = {
- 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
- 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
- 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
- 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
- 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8,
- 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
- 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26,
- 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb
-};
-
-static const u_char sha2_hmac4_key[] = {
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19
-};
-
-static const u_char sha2_hmac4_msg[] = {
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd
-};
-
-static const u_char sha2_hmac4_256[] = {
- 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
- 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
- 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
- 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b
-};
-
-static const u_char sha2_hmac4_384[] = {
- 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85,
- 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7,
- 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c,
- 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e,
- 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79,
- 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb
-};
-
-static const u_char sha2_hmac4_512[] = {
- 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
- 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
- 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
- 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
- 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4,
- 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63,
- 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d,
- 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd
-};
-
-static const u_char sha2_hmac6_key[] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa
-};
-
-static const u_char sha2_hmac6_msg[] = {
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
- 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
- 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
- 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
- 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
- 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
- 0x20, 0x46, 0x69, 0x72, 0x73, 0x74
-};
-
-static const u_char sha2_hmac6_256[] = {
- 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
- 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
- 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
- 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
-};
-
-static const u_char sha2_hmac6_384[] = {
- 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
- 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
- 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
- 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
- 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
- 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52
-};
-
-static const u_char sha2_hmac6_512[] = {
- 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
- 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
- 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
- 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
- 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
- 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
- 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
- 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98
-};
-
-static const u_char sha2_hmac7_msg[] = {
- 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
- 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
- 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
- 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
- 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
- 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
- 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
- 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
- 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
- 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
- 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
- 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
- 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
- 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
- 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
- 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
- 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
- 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
- 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e
-};
-
-static const u_char sha2_hmac7_256[] = {
- 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
- 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
- 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
- 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2
-};
-
-static const u_char sha2_hmac7_384[] = {
- 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
- 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
- 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
- 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
- 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
- 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e
-};
-
-static const u_char sha2_hmac7_512[] = {
- 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
- 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
- 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
- 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
- 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
- 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
- 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
- 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58
-};
-
-static const hmac_testvector_t sha256_hmac_testvectors[] = {
- { sizeof(sha2_hmac1_key), sha2_hmac1_key, sizeof(sha2_hmac1_msg), sha2_hmac1_msg, sha2_hmac1_256 },
- { sizeof(sha2_hmac2_key), sha2_hmac2_key, sizeof(sha2_hmac2_msg), sha2_hmac2_msg, sha2_hmac2_256 },
- { sizeof(sha2_hmac3_key), sha2_hmac3_key, sizeof(sha2_hmac3_msg), sha2_hmac3_msg, sha2_hmac3_256 },
- { sizeof(sha2_hmac4_key), sha2_hmac4_key, sizeof(sha2_hmac4_msg), sha2_hmac4_msg, sha2_hmac4_256 },
- { sizeof(sha2_hmac6_key), sha2_hmac6_key, sizeof(sha2_hmac6_msg), sha2_hmac6_msg, sha2_hmac6_256 },
- { sizeof(sha2_hmac6_key), sha2_hmac6_key, sizeof(sha2_hmac7_msg), sha2_hmac7_msg, sha2_hmac7_256 },
- { 0, NULL, 0, NULL, NULL }
-};
-
-static const hmac_testvector_t sha384_hmac_testvectors[] = {
- { sizeof(sha2_hmac1_key), sha2_hmac1_key, sizeof(sha2_hmac1_msg), sha2_hmac1_msg, sha2_hmac1_384 },
- { sizeof(sha2_hmac2_key), sha2_hmac2_key, sizeof(sha2_hmac2_msg), sha2_hmac2_msg, sha2_hmac2_384 },
- { sizeof(sha2_hmac3_key), sha2_hmac3_key, sizeof(sha2_hmac3_msg), sha2_hmac3_msg, sha2_hmac3_384 },
- { sizeof(sha2_hmac4_key), sha2_hmac4_key, sizeof(sha2_hmac4_msg), sha2_hmac4_msg, sha2_hmac4_384 },
- { sizeof(sha2_hmac6_key), sha2_hmac6_key, sizeof(sha2_hmac6_msg), sha2_hmac6_msg, sha2_hmac6_384 },
- { sizeof(sha2_hmac6_key), sha2_hmac6_key, sizeof(sha2_hmac7_msg), sha2_hmac7_msg, sha2_hmac7_384 },
- { 0, NULL, 0, NULL, NULL }
-};
-
-static const hmac_testvector_t sha512_hmac_testvectors[] = {
- { sizeof(sha2_hmac1_key), sha2_hmac1_key, sizeof(sha2_hmac1_msg), sha2_hmac1_msg, sha2_hmac1_512 },
- { sizeof(sha2_hmac2_key), sha2_hmac2_key, sizeof(sha2_hmac2_msg), sha2_hmac2_msg, sha2_hmac2_512 },
- { sizeof(sha2_hmac3_key), sha2_hmac3_key, sizeof(sha2_hmac3_msg), sha2_hmac3_msg, sha2_hmac3_512 },
- { sizeof(sha2_hmac4_key), sha2_hmac4_key, sizeof(sha2_hmac4_msg), sha2_hmac4_msg, sha2_hmac4_512 },
- { sizeof(sha2_hmac6_key), sha2_hmac6_key, sizeof(sha2_hmac6_msg), sha2_hmac6_msg, sha2_hmac6_512 },
- { sizeof(sha2_hmac6_key), sha2_hmac6_key, sizeof(sha2_hmac7_msg), sha2_hmac7_msg, sha2_hmac7_512 },
- { 0, NULL, 0, NULL, NULL }
-};
-
-struct hash_desc hash_desc_sha2_256 = {
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA2_256,
- algo_next: NULL,
- hash_ctx_size: sizeof(sha256_context),
- hash_block_size: SHA2_256_BLOCK_SIZE,
- hash_digest_size: SHA2_256_DIGEST_SIZE,
- hash_testvectors: sha256_hash_testvectors,
- hmac_testvectors: sha256_hmac_testvectors,
- hash_init: (void (*)(void *))sha256_init,
- hash_update: (void (*)(void *, const u_char *, size_t ))sha256_write,
- hash_final:(void (*)(u_char *, void *))sha256_hash_final
-};
-
-struct hash_desc hash_desc_sha2_384 = {
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA2_384,
- algo_next: NULL,
- hash_ctx_size: sizeof(sha512_context),
- hash_block_size: SHA2_384_BLOCK_SIZE,
- hash_digest_size: SHA2_384_DIGEST_SIZE,
- hash_testvectors: sha384_hash_testvectors,
- hmac_testvectors: sha384_hmac_testvectors,
- hash_init: (void (*)(void *))sha384_init,
- hash_update: (void (*)(void *, const u_char *, size_t ))sha512_write,
- hash_final:(void (*)(u_char *, void *))sha384_hash_final
-};
-
-struct hash_desc hash_desc_sha2_512 = {
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA2_512,
- algo_next: NULL,
- hash_ctx_size: sizeof(sha512_context),
- hash_block_size: SHA2_512_BLOCK_SIZE,
- hash_digest_size: SHA2_512_DIGEST_SIZE,
- hash_testvectors: sha512_hash_testvectors,
- hmac_testvectors: sha512_hmac_testvectors,
- hash_init: (void (*)(void *))sha512_init,
- hash_update: (void (*)(void *, const u_char *, size_t ))sha512_write,
- hash_final:(void (*)(u_char *, void *))sha512_hash_final
-};
-
-int ike_alg_sha2_init(void);
-
-int
-ike_alg_sha2_init(void)
-{
- int ret
-;
- ret = ike_alg_register_hash(&hash_desc_sha2_256);
- if (ret)
- goto out;
- ret = ike_alg_register_hash(&hash_desc_sha2_384);
- if (ret)
- goto out;
- ret = ike_alg_register_hash(&hash_desc_sha2_512);
-
-out:
- return ret;
-}
-
-/*
-IKE_ALG_INIT_NAME: ike_alg_sha2_init
-*/
diff --git a/src/pluto/alg/ike_alg_twofish.c b/src/pluto/alg/ike_alg_twofish.c
deleted file mode 100644
index 1788bc394..000000000
--- a/src/pluto/alg/ike_alg_twofish.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "libtwofish/twofish_cbc.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-
-#define TWOFISH_CBC_BLOCK_SIZE (128/BITS_PER_BYTE)
-#define TWOFISH_KEY_MIN_LEN 128
-#define TWOFISH_KEY_DEF_LEN 128
-#define TWOFISH_KEY_MAX_LEN 256
-
-static void
-do_twofish(u_int8_t *buf, size_t buf_size, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc)
-{
- twofish_context twofish_ctx;
- char iv_bak[TWOFISH_CBC_BLOCK_SIZE];
- char *new_iv = NULL; /* logic will avoid copy to NULL */
-
- twofish_set_key(&twofish_ctx, key, key_size);
- /*
- * my TWOFISH cbc does not touch passed IV (optimization for
- * ESP handling), so I must "emulate" des-like IV
- * crunching
- */
- if (!enc)
- memcpy(new_iv=iv_bak,
- (char*) buf + buf_size-TWOFISH_CBC_BLOCK_SIZE,
- TWOFISH_CBC_BLOCK_SIZE);
-
- twofish_cbc_encrypt(&twofish_ctx, buf, buf, buf_size, iv, enc);
-
- if (enc)
- new_iv = (char*) buf + buf_size-TWOFISH_CBC_BLOCK_SIZE;
-
- memcpy(iv, new_iv, TWOFISH_CBC_BLOCK_SIZE);
-}
-
-struct encrypt_desc encrypt_desc_twofish =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_TWOFISH_CBC,
- algo_next: NULL,
- enc_ctxsize: sizeof(twofish_context),
- enc_blocksize: TWOFISH_CBC_BLOCK_SIZE,
- keydeflen: TWOFISH_KEY_MIN_LEN,
- keyminlen: TWOFISH_KEY_DEF_LEN,
- keymaxlen: TWOFISH_KEY_MAX_LEN,
- do_crypt: do_twofish,
-};
-
-struct encrypt_desc encrypt_desc_twofish_ssh =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_TWOFISH_CBC_SSH,
- algo_next: NULL,
- enc_ctxsize: sizeof(twofish_context),
- enc_blocksize: TWOFISH_CBC_BLOCK_SIZE,
- keydeflen: TWOFISH_KEY_MIN_LEN,
- keyminlen: TWOFISH_KEY_DEF_LEN,
- keymaxlen: TWOFISH_KEY_MAX_LEN,
- do_crypt: do_twofish,
-};
-
-int ike_alg_twofish_init(void);
-
-int
-ike_alg_twofish_init(void)
-{
- int ret = ike_alg_register_enc(&encrypt_desc_twofish);
-
- if (ike_alg_register_enc(&encrypt_desc_twofish_ssh) < 0)
- plog("ike_alg_twofish_init(): Experimental OAKLEY_TWOFISH_CBC_SSH activation failed");
-
- return ret;
-}
-/*
-IKE_ALG_INIT_NAME: ike_alg_twofish_init
-*/
diff --git a/src/pluto/alg/ike_alginit.c b/src/pluto/alg/ike_alginit.c
deleted file mode 100644
index 8784bf31b..000000000
--- a/src/pluto/alg/ike_alginit.c
+++ /dev/null
@@ -1,7 +0,0 @@
-extern int ike_alg_init(void); int ike_alg_init(void) {
-{ extern int ike_alg_aes_init (void); ike_alg_aes_init();}
-{ extern int ike_alg_blowfish_init (void); ike_alg_blowfish_init();}
-{ extern int ike_alg_serpent_init (void); ike_alg_serpent_init();}
-{ extern int ike_alg_sha2_init (void); ike_alg_sha2_init();}
-{ extern int ike_alg_twofish_init (void); ike_alg_twofish_init();}
-return 0;}
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c
index cd02d2358..a85a18905 100644
--- a/src/pluto/alg_info.c
+++ b/src/pluto/alg_info.c
@@ -1,6 +1,7 @@
/*
* Algorithm info parsing and creation functions
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,8 +12,6 @@
* 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: alg_info.c 3846 2008-04-18 17:01:45Z andreas $
*/
#include <stddef.h>
@@ -27,390 +26,187 @@
#include <ctype.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include <pfkeyv2.h>
+#include <utils.h>
+#include <utils/lexparser.h>
+#include <crypto/diffie_hellman.h>
+#include <crypto/transform.h>
+#include <crypto/proposal/proposal_keywords.h>
+
+
#include "alg_info.h"
#include "constants.h"
-#ifndef NO_PLUTO
#include "defs.h"
#include "log.h"
#include "whack.h"
-#include "sha1.h"
-#include "md5.h"
#include "crypto.h"
#include "kernel_alg.h"
#include "ike_alg.h"
-#else
-/*
- * macros/functions for compilation without pluto (eg: spi for manual conns)
- */
-#include <assert.h>
-#define passert(x) assert(x)
-extern int debug; /* eg: spi.c */
-#define DBG(cond, action) { if (debug) { action ; } }
-#define DBG_log(x, args...) fprintf(stderr, x "\n" , ##args);
-#define RC_LOG_SERIOUS
-#define loglog(x, args...) fprintf(stderr, ##args);
-#define alloc_thing(thing, name) alloc_bytes(sizeof (thing), name)
-void * alloc_bytes(size_t size, const char *name) {
- void *p=malloc(size);
- if (p == NULL)
- fprintf(stderr, "unable to malloc %lu bytes for %s",
- (unsigned long) size, name);
- memset(p, '\0', size);
- return p;
-}
-#define pfreeany(ptr) free(ptr)
-#endif /* NO_PLUTO */
/*
* sadb/ESP aa attrib converters
*/
-int
-alg_info_esp_aa2sadb(int auth)
-{
- int sadb_aalg = 0;
-
- switch(auth) {
- case AUTH_ALGORITHM_HMAC_MD5:
- case AUTH_ALGORITHM_HMAC_SHA1:
- sadb_aalg = auth + 1;
- break;
- case AUTH_ALGORITHM_HMAC_SHA2_256:
- case AUTH_ALGORITHM_HMAC_SHA2_384:
- case AUTH_ALGORITHM_HMAC_SHA2_512:
- case AUTH_ALGORITHM_HMAC_RIPEMD:
- sadb_aalg = auth;
- break;
- default:
- /* loose ... */
- sadb_aalg = auth;
- }
- return sadb_aalg;
-}
-
-int /* __attribute__ ((unused)) */
-alg_info_esp_sadb2aa(int sadb_aalg)
-{
- int auth = 0;
-
- switch(sadb_aalg) {
- case SADB_AALG_MD5HMAC:
- case SADB_AALG_SHA1HMAC:
- auth = sadb_aalg - 1;
- break;
- /* since they are the same ... :) */
- case AUTH_ALGORITHM_HMAC_SHA2_256:
- case AUTH_ALGORITHM_HMAC_SHA2_384:
- case AUTH_ALGORITHM_HMAC_SHA2_512:
- case AUTH_ALGORITHM_HMAC_RIPEMD:
- auth = sadb_aalg;
- break;
- default:
- /* loose ... */
- auth = sadb_aalg;
- }
- return auth;
-}
-
-/*
- * Search enum_name array with in prefixed uppercase
- */
-static int
-enum_search_prefix (enum_names *ed, const char *prefix, const char *str, int strlen)
-{
- char buf[64];
- char *ptr;
- int ret;
- int len = sizeof(buf) - 1; /* reserve space for final \0 */
-
- for (ptr = buf; *prefix; *ptr++ = *prefix++, len--);
- while (strlen-- && len-- && *str) *ptr++ = toupper(*str++);
- *ptr = 0;
-
- DBG(DBG_CRYPT,
- DBG_log("enum_search_prefix () calling enum_search(%p, \"%s\")"
- , ed, buf)
- )
- ret = enum_search(ed, buf);
- return ret;
-}
-
-/*
- * Search enum_name array with in prefixed and postfixed uppercase
- */
-static int
-enum_search_ppfix (enum_names *ed, const char *prefix, const char *postfix, const char *str, int strlen)
-{
- char buf[64];
- char *ptr;
- int ret;
- int len = sizeof(buf) - 1; /* reserve space for final \0 */
-
- for (ptr = buf; *prefix; *ptr++ = *prefix++, len--);
- while (strlen-- && len-- && *str) *ptr++ = toupper(*str++);
- while (len-- && *postfix) *ptr++ = *postfix++;
- *ptr = 0;
-
- DBG(DBG_CRYPT,
- DBG_log("enum_search_ppfixi () calling enum_search(%p, \"%s\")"
- , ed, buf)
- )
- ret = enum_search(ed, buf);
- return ret;
-}
-
-/*
- * Search esp_transformid_names for a match, eg:
- * "3des" <=> "ESP_3DES"
- */
-#define ESP_MAGIC_ID 0x00ffff01
-
-static int
-ealg_getbyname_esp(const char *const str, int len)
+int alg_info_esp_aa2sadb(int auth)
{
- if (!str || !*str)
- return -1;
-
- /* leave special case for eg: "id248" string */
- if (strcmp("id", str) == 0)
- return ESP_MAGIC_ID;
-
- return enum_search_prefix(&esp_transformid_names, "ESP_", str, len);
+ int sadb_aalg = 0;
+
+ switch(auth) {
+ case AUTH_ALGORITHM_HMAC_MD5:
+ case AUTH_ALGORITHM_HMAC_SHA1:
+ sadb_aalg = auth + 1;
+ break;
+ case AUTH_ALGORITHM_HMAC_SHA2_256:
+ case AUTH_ALGORITHM_HMAC_SHA2_384:
+ case AUTH_ALGORITHM_HMAC_SHA2_512:
+ case AUTH_ALGORITHM_HMAC_RIPEMD:
+ sadb_aalg = auth;
+ break;
+ default:
+ /* loose ... */
+ sadb_aalg = auth;
+ }
+ return sadb_aalg;
}
-/*
- * Search auth_alg_names for a match, eg:
- * "md5" <=> "AUTH_ALGORITHM_HMAC_MD5"
- */
-static int
-aalg_getbyname_esp(const char *const str, int len)
+int alg_info_esp_sadb2aa(int sadb_aalg)
{
- int ret;
- unsigned num;
-
- if (!str || !*str)
- return -1;
-
- /* interpret 'SHA' as 'SHA1' */
- if (strncasecmp("SHA", str, len) == 0)
- return AUTH_ALGORITHM_HMAC_SHA1;
-
- /* interpret 'AESXCBC' as 'AES_XCBC_MAC' */
- if (strncasecmp("AESXCBC", str, len) == 0)
- return AUTH_ALGORITHM_AES_XCBC_MAC;
-
- ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_HMAC_", str ,len);
- if (ret >= 0)
- return ret;
-
- ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_", str, len);
- if (ret >= 0)
- return ret;
-
- sscanf(str, "id%d%n", &ret, &num);
- return (ret >= 0 && num != strlen(str))? -1 : ret;
+ int auth = 0;
+
+ switch(sadb_aalg) {
+ case SADB_AALG_MD5HMAC:
+ case SADB_AALG_SHA1HMAC:
+ auth = sadb_aalg - 1;
+ break;
+ /* since they are the same ... :) */
+ case AUTH_ALGORITHM_HMAC_SHA2_256:
+ case AUTH_ALGORITHM_HMAC_SHA2_384:
+ case AUTH_ALGORITHM_HMAC_SHA2_512:
+ case AUTH_ALGORITHM_HMAC_RIPEMD:
+ auth = sadb_aalg;
+ break;
+ default:
+ /* loose ... */
+ auth = sadb_aalg;
+ }
+ return auth;
}
-static int
-modp_getbyname_esp(const char *const str, int len)
+void alg_info_free(struct alg_info *alg_info)
{
- int ret;
-
- if (!str || !*str)
- return -1;
-
- ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len);
- if (ret >= 0)
- return ret;
-
- ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len);
- return ret;
-}
-
-void
-alg_info_free(struct alg_info *alg_info)
-{
- pfreeany(alg_info);
+ free(alg_info);
}
/*
* Raw add routine: only checks for no duplicates
*/
-static void
-__alg_info_esp_add (struct alg_info_esp *alg_info, int ealg_id, unsigned ek_bits, int aalg_id, unsigned ak_bits)
+static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id,
+ unsigned ek_bits, int aalg_id, unsigned ak_bits)
{
- struct esp_info *esp_info=alg_info->esp;
- unsigned cnt = alg_info->alg_info_cnt, i;
+ struct esp_info *esp_info = alg_info->esp;
+ unsigned cnt = alg_info->alg_info_cnt, i;
- /* check for overflows */
- passert(cnt < elemsof(alg_info->esp));
+ /* check for overflows */
+ passert(cnt < countof(alg_info->esp));
- /* dont add duplicates */
- for (i = 0; i < cnt; i++)
- {
- if (esp_info[i].esp_ealg_id == ealg_id
- && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
- && esp_info[i].esp_aalg_id == aalg_id
- && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
- return;
- }
+ /* dont add duplicates */
+ for (i = 0; i < cnt; i++)
+ {
+ if (esp_info[i].esp_ealg_id == ealg_id
+ && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
+ && esp_info[i].esp_aalg_id == aalg_id
+ && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
+ {
+ return;
+ }
+ }
- esp_info[cnt].esp_ealg_id = ealg_id;
- esp_info[cnt].esp_ealg_keylen = ek_bits;
- esp_info[cnt].esp_aalg_id = aalg_id;
- esp_info[cnt].esp_aalg_keylen = ak_bits;
+ esp_info[cnt].esp_ealg_id = ealg_id;
+ esp_info[cnt].esp_ealg_keylen = ek_bits;
+ esp_info[cnt].esp_aalg_id = aalg_id;
+ esp_info[cnt].esp_aalg_keylen = ak_bits;
- /* sadb values */
- esp_info[cnt].encryptalg = ealg_id;
- esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
- alg_info->alg_info_cnt++;
+ /* sadb values */
+ esp_info[cnt].encryptalg = ealg_id;
+ esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
+ alg_info->alg_info_cnt++;
- DBG(DBG_CRYPT,
- DBG_log("__alg_info_esp_add() ealg=%d aalg=%d cnt=%d"
- , ealg_id, aalg_id, alg_info->alg_info_cnt)
- )
+ DBG(DBG_CRYPT,
+ DBG_log("esp alg added: %s_%d/%s, cnt=%d",
+ enum_show(&esp_transformid_names, ealg_id), ek_bits,
+ enum_show(&auth_alg_names, aalg_id),
+ alg_info->alg_info_cnt)
+ )
}
/*
* Add ESP alg info _with_ logic (policy):
*/
-static void
-alg_info_esp_add (struct alg_info *alg_info, int ealg_id, int ek_bits, int aalg_id, int ak_bits)
+static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id,
+ int ek_bits, int aalg_id, int ak_bits)
{
- /* Policy: default to 3DES */
- if (ealg_id == 0)
- ealg_id = ESP_3DES;
-
- if (ealg_id > 0)
- {
-#ifndef NO_PLUTO
- if (aalg_id > 0)
-#else
- /* Allow no auth for manual conns (from spi.c) */
- if (aalg_id >= 0)
-#endif
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- aalg_id, ak_bits);
- else
+ /* Policy: default to 3DES */
+ if (ealg_id == 0)
{
- /* Policy: default to MD5 and SHA1 */
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_HMAC_MD5, ak_bits);
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
+ ealg_id = ESP_3DES;
+ }
+ if (ealg_id > 0)
+ {
+ if (aalg_id > 0)
+ {
+ __alg_info_esp_add((struct alg_info_esp *)alg_info,
+ ealg_id, ek_bits,
+ aalg_id, ak_bits);
+ }
+ else
+ {
+ /* Policy: default to MD5 and SHA1 */
+ __alg_info_esp_add((struct alg_info_esp *)alg_info,
+ ealg_id, ek_bits,
+ AUTH_ALGORITHM_HMAC_MD5, ak_bits);
+ __alg_info_esp_add((struct alg_info_esp *)alg_info,
+ ealg_id, ek_bits,
+ AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
+ }
}
- }
-}
-
-#ifndef NO_PLUTO
-/**************************************
- *
- * IKE alg
- *
- *************************************/
-/*
- * Search oakley_enc_names for a match, eg:
- * "3des_cbc" <=> "OAKLEY_3DES_CBC"
- */
-static int
-ealg_getbyname_ike(const char *const str, int len)
-{
- int ret;
-
- if (!str || !*str)
- return -1;
-
- ret = enum_search_prefix(&oakley_enc_names,"OAKLEY_", str, len);
- if (ret >= 0)
- return ret;
-
- ret = enum_search_ppfix(&oakley_enc_names, "OAKLEY_", "_CBC", str, len);
- return ret;
-}
-
-/*
- * Search oakley_hash_names for a match, eg:
- * "md5" <=> "OAKLEY_MD5"
- */
-static int
-aalg_getbyname_ike(const char *const str, int len)
-{
- int ret;
- unsigned num;
-
- if (!str || !*str)
- return -1;
-
- /* interpret 'SHA1' as 'SHA' */
- if (strncasecmp("SHA1", str, len) == 0)
- return enum_search(&oakley_hash_names, "OAKLEY_SHA");
-
- ret = enum_search_prefix(&oakley_hash_names,"OAKLEY_", str, len);
- if (ret >= 0)
- return ret;
-
- sscanf(str, "id%d%n", &ret, &num);
- return (ret >=0 && num != strlen(str))? -1 : ret;
-}
-
-/*
- * Search oakley_group_names for a match, eg:
- * "modp1024" <=> "OAKLEY_GROUP_MODP1024"
- */
-static int
-modp_getbyname_ike(const char *const str, int len)
-{
- int ret;
-
- if (!str || !*str)
- return -1;
-
- ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len);
- if (ret >= 0)
- return ret;
-
- ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len);
- return ret;
}
-static void
-__alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id, unsigned ek_bits, int aalg_id, unsigned ak_bits, int modp_id)
+static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id,
+ unsigned ek_bits, int aalg_id, unsigned ak_bits,
+ int modp_id)
{
- struct ike_info *ike_info = alg_info->ike;
- unsigned cnt = alg_info->alg_info_cnt;
- unsigned i;
+ struct ike_info *ike_info = alg_info->ike;
+ unsigned cnt = alg_info->alg_info_cnt;
+ unsigned i;
- /* check for overflows */
- passert(cnt < elemsof(alg_info->ike));
+ /* check for overflows */
+ passert(cnt < countof(alg_info->ike));
- /* dont add duplicates */
- for (i = 0;i < cnt; i++)
+ /* dont add duplicates */
+ for (i = 0; i < cnt; i++)
{
- if (ike_info[i].ike_ealg == ealg_id
- && (!ek_bits || ike_info[i].ike_eklen == ek_bits)
- && ike_info[i].ike_halg == aalg_id
- && (!ak_bits || ike_info[i].ike_hklen == ak_bits)
- && ike_info[i].ike_modp==modp_id)
- return;
- }
+ if (ike_info[i].ike_ealg == ealg_id
+ && (!ek_bits || ike_info[i].ike_eklen == ek_bits)
+ && ike_info[i].ike_halg == aalg_id
+ && (!ak_bits || ike_info[i].ike_hklen == ak_bits)
+ && ike_info[i].ike_modp==modp_id)
+ return;
+ }
- ike_info[cnt].ike_ealg = ealg_id;
- ike_info[cnt].ike_eklen = ek_bits;
- ike_info[cnt].ike_halg = aalg_id;
- ike_info[cnt].ike_hklen = ak_bits;
- ike_info[cnt].ike_modp = modp_id;
- alg_info->alg_info_cnt++;
+ ike_info[cnt].ike_ealg = ealg_id;
+ ike_info[cnt].ike_eklen = ek_bits;
+ ike_info[cnt].ike_halg = aalg_id;
+ ike_info[cnt].ike_hklen = ak_bits;
+ ike_info[cnt].ike_modp = modp_id;
+ alg_info->alg_info_cnt++;
- DBG(DBG_CRYPT,
- DBG_log("__alg_info_ike_add() ealg=%d aalg=%d modp_id=%d, cnt=%d"
- , ealg_id, aalg_id, modp_id
- , alg_info->alg_info_cnt)
- )
+ DBG(DBG_CRYPT,
+ DBG_log("ikg alg added: %s_%d/%s/%s, cnt=%d",
+ enum_show(&oakley_enc_names, ealg_id), ek_bits,
+ enum_show(&oakley_hash_names, aalg_id),
+ enum_show(&oakley_group_names, modp_id),
+ alg_info->alg_info_cnt)
+ )
}
/*
@@ -419,792 +215,449 @@ __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id, unsigned ek_bits
*/
static int default_ike_groups[] = {
- OAKLEY_GROUP_MODP1536,
- OAKLEY_GROUP_MODP1024
+ MODP_1536_BIT,
+ MODP_1024_BIT
};
-/*
- * Add IKE alg info _with_ logic (policy):
+/*
+ * Add IKE alg info _with_ logic (policy):
*/
-static void
-alg_info_ike_add (struct alg_info *alg_info, int ealg_id, int ek_bits, int aalg_id, int ak_bits, int modp_id)
+static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
+ int ek_bits, int aalg_id, int ak_bits, int modp_id)
{
- int i = 0;
- int n_groups = elemsof(default_ike_groups);
-
- /* if specified modp_id avoid loop over default_ike_groups */
- if (modp_id)
- {
- n_groups=0;
- goto in_loop;
- }
-
- for (; n_groups--; i++)
- {
- modp_id = default_ike_groups[i];
-in_loop:
- /* Policy: default to 3DES */
- if (ealg_id == 0)
- ealg_id = OAKLEY_3DES_CBC;
+ int i = 0;
+ int n_groups = countof(default_ike_groups);
- if (ealg_id > 0)
+ /* if specified modp_id avoid loop over default_ike_groups */
+ if (modp_id)
{
- if (aalg_id > 0)
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- aalg_id, ak_bits,
- modp_id);
- else
- {
- /* Policy: default to MD5 and SHA */
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- OAKLEY_MD5, ak_bits,
- modp_id);
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- OAKLEY_SHA, ak_bits,
- modp_id);
- }
+ n_groups=0;
+ goto in_loop;
+ }
+
+ for (; n_groups--; i++)
+ {
+ modp_id = default_ike_groups[i];
+in_loop:
+ /* Policy: default to 3DES */
+ if (ealg_id == 0)
+ {
+ ealg_id = OAKLEY_3DES_CBC;
+ }
+ if (ealg_id > 0)
+ {
+ if (aalg_id > 0)
+ {
+ __alg_info_ike_add((struct alg_info_ike *)alg_info,
+ ealg_id, ek_bits,
+ aalg_id, ak_bits,
+ modp_id);
+ }
+ else
+ {
+ /* Policy: default to MD5 and SHA */
+ __alg_info_ike_add((struct alg_info_ike *)alg_info,
+ ealg_id, ek_bits,
+ OAKLEY_MD5, ak_bits,
+ modp_id);
+ __alg_info_ike_add((struct alg_info_ike *)alg_info,
+ ealg_id, ek_bits,
+ OAKLEY_SHA, ak_bits,
+ modp_id);
+ }
+ }
}
- }
-}
-#endif /* NO_PLUTO */
-
-/*
- * Creates a new alg_info by parsing passed string
- */
-enum parser_state_esp {
- ST_INI,
- ST_EA, /* encrypt algo */
- ST_EA_END,
- ST_EK, /* enc. key length */
- ST_EK_END,
- ST_AA, /* auth algo */
- ST_AA_END,
- ST_AK, /* auth. key length */
- ST_AK_END,
- ST_MODP, /* modp spec */
- ST_FLAG_STRICT,
- ST_END,
- ST_EOF,
- ST_ERR
-};
-
-static const char *parser_state_esp_names[] = {
- "ST_INI",
- "ST_EA",
- "ST_EA_END",
- "ST_EK",
- "ST_EK_END",
- "ST_AA",
- "ST_AA_END",
- "ST_AK",
- "ST_AK_END",
- "ST_MOPD",
- "ST_FLAG_STRICT",
- "ST_END",
- "ST_EOF",
- "ST_ERR"
-};
-
-static const char*
-parser_state_name_esp(enum parser_state_esp state)
-{
- return parser_state_esp_names[state];
-}
-
-/* XXX:jjo to implement different parser for ESP and IKE */
-struct parser_context {
- unsigned state, old_state;
- unsigned protoid;
- char ealg_buf[16];
- char aalg_buf[16];
- char modp_buf[16];
- int (*ealg_getbyname)(const char *const str, int len);
- int (*aalg_getbyname)(const char *const str, int len);
- int (*modp_getbyname)(const char *const str, int len);
- char *ealg_str;
- char *aalg_str;
- char *modp_str;
- int eklen;
- int aklen;
- int ch;
- const char *err;
-};
-
-static inline void
-parser_set_state(struct parser_context *p_ctx, enum parser_state_esp state)
-{
- if (state != p_ctx->state)
- {
- p_ctx->old_state = p_ctx->state;
- p_ctx->state = state;
- }
}
-static int
-parser_machine(struct parser_context *p_ctx)
+static status_t alg_info_add(chunk_t alg, unsigned protoid,
+ int *ealg, size_t *ealg_keysize,
+ int *aalg, size_t *aalg_keysize, int *dh_group)
{
- int ch = p_ctx->ch;
-
- /* special 'absolute' cases */
- p_ctx->err = "No error.";
+ const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
- /* chars that end algo strings */
- switch (ch){
- case 0: /* end-of-string */
- case '!': /* flag as strict algo list */
- case ',': /* algo string separator */
- switch (p_ctx->state) {
- case ST_EA:
- case ST_EK:
- case ST_AA:
- case ST_AK:
- case ST_MODP:
- case ST_FLAG_STRICT:
- {
- enum parser_state_esp next_state = 0;
-
- switch (ch) {
- case 0:
- next_state = ST_EOF;
- break;
- case ',':
- next_state = ST_END;
- break;
- case '!':
- next_state = ST_FLAG_STRICT;
- break;
- }
- /* ch? parser_set_state(p_ctx, ST_END) : parser_set_state(p_ctx, ST_EOF) ; */
- parser_set_state(p_ctx, next_state);
- goto out;
- }
- default:
- p_ctx->err = "String ended with invalid char";
- goto err;
- }
- }
-re_eval:
- switch (p_ctx->state) {
- case ST_INI:
- if (isspace(ch))
- break;
- if (isalnum(ch))
- {
- *(p_ctx->ealg_str++) = ch;
- parser_set_state(p_ctx, ST_EA);
- break;
- }
- p_ctx->err = "No alphanum. char initially found";
- goto err;
- case ST_EA:
- if (isalpha(ch) || ch == '_')
- {
- *(p_ctx->ealg_str++) = ch;
- break;
- }
- if (isdigit(ch))
- {
- /* bravely switch to enc keylen */
- *(p_ctx->ealg_str) = 0;
- parser_set_state(p_ctx, ST_EK);
- goto re_eval;
- }
- if (ch == '-')
- {
- *(p_ctx->ealg_str) = 0;
- parser_set_state(p_ctx, ST_EA_END);
- break;
- }
- p_ctx->err = "No valid char found after enc alg string";
- goto err;
- case ST_EA_END:
- if (isdigit(ch))
- {
- /* bravely switch to enc keylen */
- parser_set_state(p_ctx, ST_EK);
- goto re_eval;
- }
- if (isalpha(ch))
- {
- parser_set_state(p_ctx, ST_AA);
- goto re_eval;
- }
- p_ctx->err = "No alphanum char found after enc alg separator";
- goto err;
- case ST_EK:
- if (ch == '-')
- {
- parser_set_state(p_ctx, ST_EK_END);
- break;
- }
- if (isdigit(ch))
- {
- p_ctx->eklen = p_ctx->eklen*10 + ch - '0';
- break;
- }
- p_ctx->err = "Non digit or valid separator found while reading enc keylen";
- goto err;
- case ST_EK_END:
- if (isalpha(ch))
- {
- parser_set_state(p_ctx, ST_AA);
- goto re_eval;
- }
- p_ctx->err = "Non alpha char found after enc keylen end separator";
- goto err;
- case ST_AA:
- if (ch == '-')
- {
- *(p_ctx->aalg_str++) = 0;
- parser_set_state(p_ctx, ST_AA_END);
- break;
- }
- if (isalnum(ch) || ch == '_')
- {
- *(p_ctx->aalg_str++) = ch;
- break;
- }
- p_ctx->err = "Non alphanum or valid separator found in auth string";
- goto err;
- case ST_AA_END:
- if (isdigit(ch))
- {
- parser_set_state(p_ctx, ST_AK);
- goto re_eval;
- }
- /* Only allow modpXXXX string if we have a modp_getbyname method */
- if ((p_ctx->modp_getbyname) && isalpha(ch))
- {
- parser_set_state(p_ctx, ST_MODP);
- goto re_eval;
- }
- p_ctx->err = "Non initial digit found for auth keylen";
- goto err;
- case ST_AK:
- if (ch=='-')
- {
- parser_set_state(p_ctx, ST_AK_END);
- break;
- }
- if (isdigit(ch))
+ if (token == NULL)
{
- p_ctx->aklen = p_ctx->aklen*10 + ch - '0';
- break;
+ return FAILED;
}
- p_ctx->err = "Non digit found for auth keylen";
- goto err;
- case ST_AK_END:
- /* Only allow modpXXXX string if we have a modp_getbyname method */
- if ((p_ctx->modp_getbyname) && isalpha(ch))
+ switch (token->type)
{
- parser_set_state(p_ctx, ST_MODP);
- goto re_eval;
- }
- p_ctx->err = "Non alpha char found after auth keylen";
- goto err;
- case ST_MODP:
- if (isalnum(ch))
- {
- *(p_ctx->modp_str++) = ch;
- break;
- }
- p_ctx->err = "Non alphanum char found after in modp string";
- goto err;
- case ST_FLAG_STRICT:
- if (ch == 0)
- parser_set_state(p_ctx, ST_END);
- p_ctx->err = "Flags character(s) must be at end of whole string";
- goto err;
-
- /* XXX */
- case ST_END:
- case ST_EOF:
- case ST_ERR:
- break;
- /* XXX */
- }
-out:
- return p_ctx->state;
-err:
- parser_set_state(p_ctx, ST_ERR);
- return ST_ERR;
+ case ENCRYPTION_ALGORITHM:
+ if (*ealg != 0)
+ {
+ return FAILED;
+ }
+ *ealg = (protoid == PROTO_ISAKMP) ?
+ oakley_from_encryption_algorithm(token->algorithm) :
+ esp_from_encryption_algorithm(token->algorithm);
+ if (*ealg == 0)
+ {
+ return FAILED;
+ }
+ *ealg_keysize = token->keysize;
+ break;
+ case INTEGRITY_ALGORITHM:
+ if (*aalg != 0)
+ {
+ return FAILED;
+ }
+ *aalg = (protoid == PROTO_ISAKMP) ?
+ oakley_from_integrity_algorithm(token->algorithm) :
+ esp_from_integrity_algorithm(token->algorithm);
+ if (*aalg == 0)
+ {
+ return FAILED;
+ }
+ *aalg_keysize = token->keysize;
+ break;
+ case DIFFIE_HELLMAN_GROUP:
+ if (protoid == PROTO_ISAKMP)
+ {
+ if (*dh_group != 0)
+ {
+ return FAILED;
+ }
+ *dh_group = token->algorithm;
+ }
+ break;
+ default:
+ return FAILED;
+ }
+ return SUCCESS;
}
-/*
- * Must be called for each "new" char, with new
- * character in ctx.ch
- */
-static void
-parser_init(struct parser_context *p_ctx, unsigned protoid)
-{
- memset(p_ctx, 0, sizeof (*p_ctx));
- p_ctx->protoid = protoid; /* XXX: jjo */
- p_ctx->protoid = PROTO_IPSEC_ESP;
- p_ctx->ealg_str = p_ctx->ealg_buf;
- p_ctx->aalg_str = p_ctx->aalg_buf;
- p_ctx->modp_str = p_ctx->modp_buf;
- p_ctx->state = ST_INI;
-
- switch (protoid) {
-#ifndef NO_PLUTO
- case PROTO_ISAKMP:
- p_ctx->ealg_getbyname = ealg_getbyname_ike;
- p_ctx->aalg_getbyname = aalg_getbyname_ike;
- p_ctx->modp_getbyname = modp_getbyname_ike;
- break;
-#endif
- case PROTO_IPSEC_ESP:
- p_ctx->ealg_getbyname = ealg_getbyname_esp;
- p_ctx->aalg_getbyname = aalg_getbyname_esp;
- break;
- }
-}
-static int
-parser_alg_info_add(struct parser_context *p_ctx, struct alg_info *alg_info)
+static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
{
- int ealg_id = 0;
- int aalg_id = 0;
- int modp_id = 0;
-#ifndef NO_PLUTO
- const struct oakley_group_desc *gd;
-#endif
+ char *strict, *single;
+ status_t status = SUCCESS;
- if (*p_ctx->ealg_buf)
- {
- ealg_id = p_ctx->ealg_getbyname(p_ctx->ealg_buf, strlen(p_ctx->ealg_buf));
- if (ealg_id == ESP_MAGIC_ID)
- {
- ealg_id = p_ctx->eklen;
- p_ctx->eklen = 0;
- }
- if (ealg_id < 0)
+ strict = alg_str + strlen(alg_str) - 1;
+ if (*strict == '!')
{
- p_ctx->err = "enc_alg not found";
- return -1;
+ alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
+ *strict = '\0';
}
- DBG(DBG_CRYPT,
- DBG_log("parser_alg_info_add() ealg_getbyname(\"%s\")=%d"
- , p_ctx->ealg_buf
- , ealg_id)
- )
- }
- if (*p_ctx->aalg_buf)
- {
- aalg_id = p_ctx->aalg_getbyname(p_ctx->aalg_buf, strlen(p_ctx->aalg_buf));
- if (aalg_id < 0)
+ while ((single = strsep(&alg_str, ",")))
{
- p_ctx->err = "hash_alg not found";
- return -1;
- }
- DBG(DBG_CRYPT,
- DBG_log("parser_alg_info_add() aalg_getbyname(\"%s\")=%d"
- , p_ctx->aalg_buf
- , aalg_id)
- )
- }
- if (p_ctx->modp_getbyname && *p_ctx->modp_buf)
- {
- modp_id = p_ctx->modp_getbyname(p_ctx->modp_buf, strlen(p_ctx->modp_buf));
- if (modp_id < 0)
- {
- p_ctx->err = "modp group not found";
- return -1;
- }
- DBG(DBG_CRYPT,
- DBG_log("parser_alg_info_add() modp_getbyname(\"%s\")=%d"
- , p_ctx->modp_buf
- , modp_id)
- )
- }
- switch (alg_info->alg_info_protoid) {
- case PROTO_IPSEC_ESP:
- alg_info_esp_add(alg_info,
- ealg_id, p_ctx->eklen,
- aalg_id, p_ctx->aklen);
- break;
-#ifndef NO_PLUTO
- case PROTO_ISAKMP:
- if (modp_id && !(gd = lookup_group(modp_id)))
- {
- p_ctx->err = "found modp group id, but not supported";
- return -1;
- }
- alg_info_ike_add(alg_info,
- ealg_id, p_ctx->eklen,
- aalg_id, p_ctx->aklen,
- modp_id);
- break;
-#endif
- default:
- return -1;
- }
- return 0;
-}
+ chunk_t string = { (u_char *)single, strlen(single) };
+ int ealg = 0;
+ int aalg = 0;
+ int dh_group = 0;
+ size_t ealg_keysize = 0;
+ size_t aalg_keysize = 0;
-static int
-alg_info_parse_str (struct alg_info *alg_info, const char *alg_str, const char **err_p)
-{
- struct parser_context ctx;
- int ret;
- const char *ptr;
- static char err_buf[256];
-
- *err_buf = 0;
- parser_init(&ctx, alg_info->alg_info_protoid);
- if (err_p)
- *err_p = NULL;
+ eat_whitespace(&string);
- /* use default if nul esp string */
- if (!*alg_str)
- {
- switch (alg_info->alg_info_protoid) {
-#ifndef NO_PLUTO
- case PROTO_ISAKMP:
- alg_info_ike_add(alg_info, 0, 0, 0, 0, 0);
- return 0;
-#endif
- case PROTO_IPSEC_ESP:
- alg_info_esp_add(alg_info, 0, 0, 0, 0);
- return 0;
- default:
- /* IMPOSSIBLE */
- passert(alg_info->alg_info_protoid);
- }
- }
+ if (string.len > 0)
+ {
+ chunk_t alg;
+
+ /* get all token, separated by '-' */
+ while (extract_token(&alg, '-', &string))
+ {
+ status |= alg_info_add(alg, alg_info->alg_info_protoid,
+ &ealg, &ealg_keysize,
+ &aalg, &aalg_keysize, &dh_group);
+ }
+ if (string.len)
+ {
+ status |= alg_info_add(string, alg_info->alg_info_protoid,
+ &ealg, &ealg_keysize,
+ &aalg, &aalg_keysize, &dh_group);
+ }
+ }
+ if (status == SUCCESS)
- for (ret = 0, ptr = alg_str; ret < ST_EOF;)
- {
- ctx.ch = *ptr++;
- ret = parser_machine(&ctx);
-
- switch (ret) {
- case ST_FLAG_STRICT:
- alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
- break;
- case ST_END:
- case ST_EOF:
- DBG(DBG_CRYPT,
- DBG_log("alg_info_parse_str() ealg_buf=%s aalg_buf=%s"
- "eklen=%d aklen=%d",
- ctx.ealg_buf, ctx.aalg_buf,
- ctx.eklen, ctx.aklen)
- )
- if (parser_alg_info_add(&ctx, alg_info) < 0)
- {
- snprintf(err_buf, sizeof(err_buf),
- "%s, enc_alg=\"%s\", auth_alg=\"%s\", modp=\"%s\"",
- ctx.err,
- ctx.ealg_buf,
- ctx.aalg_buf,
- ctx.modp_buf);
- goto err;
- }
- /* zero out for next run (ST_END) */
- parser_init(&ctx, alg_info->alg_info_protoid);
- break;
- case ST_ERR:
- snprintf(err_buf, sizeof(err_buf),
- "%s, just after \"%.*s\" (old_state=%s)",
- ctx.err,
- (int)(ptr-alg_str-1), alg_str ,
- parser_state_name_esp(ctx.old_state));
- goto err;
- default:
- if (!ctx.ch)
- break;
+ {
+ switch (alg_info->alg_info_protoid)
+ {
+ case PROTO_IPSEC_ESP:
+ alg_info_esp_add(alg_info, ealg, ealg_keysize,
+ aalg, aalg_keysize);
+ break;
+ case PROTO_ISAKMP:
+ alg_info_ike_add(alg_info, ealg, ealg_keysize,
+ aalg, aalg_keysize,
+ dh_group);
+ break;
+ default:
+ break;
+ }
+ }
}
- }
- return 0;
-err:
- if (err_p)
- *err_p=err_buf;
- return -1;
+ return status;
}
-struct alg_info_esp *
-alg_info_esp_create_from_str (const char *alg_str, const char **err_p)
+struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
{
- struct alg_info_esp *alg_info_esp;
- char esp_buf[256];
- static char err_buf[256];
- char *pfs_name;
- int ret = 0;
- /*
- * alg_info storage should be sized dynamically
- * but this may require 2passes to know
- * transform count in advance.
- */
- alg_info_esp = alloc_thing (struct alg_info_esp, "alg_info_esp");
- if (!alg_info_esp)
- goto out;
-
- pfs_name=index (alg_str, ';');
- if (pfs_name)
- {
- memcpy(esp_buf, alg_str, pfs_name-alg_str);
- esp_buf[pfs_name-alg_str] = 0;
- alg_str = esp_buf;
- pfs_name++;
-
- /* if pfs strings AND first char is not '0' */
- if (*pfs_name && pfs_name[0] != '0')
+ struct alg_info_esp *alg_info_esp;
+ char esp_buf[BUF_LEN];
+ char *pfs_name;
+ status_t status = SUCCESS;
+ /*
+ * alg_info storage should be sized dynamically
+ * but this may require 2passes to know
+ * transform count in advance.
+ */
+ alg_info_esp = malloc_thing (struct alg_info_esp);
+ zero(alg_info_esp);
+
+ pfs_name=index (alg_str, ';');
+ if (pfs_name)
{
- ret = modp_getbyname_esp(pfs_name, strlen(pfs_name));
- if (ret < 0)
- {
- /* Bomb if pfsgroup not found */
- DBG(DBG_CRYPT,
- DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
- , pfs_name)
- )
- if (*err_p)
- {
- snprintf(err_buf, sizeof(err_buf),
- "pfsgroup \"%s\" not found",
- pfs_name);
+ memcpy(esp_buf, alg_str, pfs_name-alg_str);
+ esp_buf[pfs_name-alg_str] = 0;
+ alg_str = esp_buf;
+ pfs_name++;
- *err_p = err_buf;
+ /* if pfs strings AND first char is not '0' */
+ if (*pfs_name && pfs_name[0] != '0')
+ {
+ const proposal_token_t *token;
+
+ token = proposal_get_token(pfs_name, strlen(pfs_name));
+ if (token == NULL || token->type != DIFFIE_HELLMAN_GROUP)
+ {
+ /* Bomb if pfsgroup not found */
+ DBG(DBG_CRYPT,
+ DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
+ , pfs_name)
+ )
+ status = FAILED;
+ goto out;
+ }
+ alg_info_esp->esp_pfsgroup = token->algorithm;
}
- goto out;
- }
- alg_info_esp->esp_pfsgroup = ret;
}
- }
- else
- alg_info_esp->esp_pfsgroup = 0;
-
- alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
- ret = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str, err_p) ;
+ else
+ {
+ alg_info_esp->esp_pfsgroup = 0;
+ }
+ alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
+ status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
+
out:
- if (ret < 0)
- {
- pfreeany(alg_info_esp);
- alg_info_esp = NULL;
- }
- return alg_info_esp;
+ if (status != SUCCESS)
+ {
+ free(alg_info_esp);
+ alg_info_esp = NULL;
+ }
+ return alg_info_esp;
}
-#ifndef NO_PLUTO
-struct alg_info_ike *
-alg_info_ike_create_from_str (const char *alg_str, const char **err_p)
+struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
{
- struct alg_info_ike *alg_info_ike;
- /*
- * alg_info storage should be sized dynamically
- * but this may require 2passes to know
- * transform count in advance.
- */
- alg_info_ike = alloc_thing (struct alg_info_ike, "alg_info_ike");
- alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
-
- if (alg_info_parse_str((struct alg_info *)alg_info_ike,
- alg_str, err_p) < 0)
- {
- pfreeany(alg_info_ike);
- return NULL;
- }
- return alg_info_ike;
+ struct alg_info_ike *alg_info_ike;
+ /*
+ * alg_info storage should be sized dynamically
+ * but this may require 2passes to know
+ * transform count in advance.
+ */
+ alg_info_ike = malloc_thing (struct alg_info_ike);
+ zero(alg_info_ike);
+ alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
+
+ if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) != SUCCESS)
+ {
+ free(alg_info_ike);
+ return NULL;
+ }
+ return alg_info_ike;
}
-#endif
/*
- * alg_info struct can be shared by
- * several connections instances,
- * handle free() with ref_cnts
+ * alg_info struct can be shared by
+ * several connections instances,
+ * handle free() with ref_cnts
*/
void
alg_info_addref(struct alg_info *alg_info)
{
- if (alg_info != NULL)
- {
- alg_info->ref_cnt++;
- DBG(DBG_CRYPT,
- DBG_log("alg_info_addref() alg_info->ref_cnt=%d"
- , alg_info->ref_cnt)
- )
- }
+ if (alg_info != NULL)
+ {
+ alg_info->ref_cnt++;
+ }
}
void
alg_info_delref(struct alg_info **alg_info_p)
{
- struct alg_info *alg_info = *alg_info_p;
+ struct alg_info *alg_info = *alg_info_p;
- if (alg_info != NULL)
- {
- passert(alg_info->ref_cnt != 0);
- alg_info->ref_cnt--;
- DBG(DBG_CRYPT,
- DBG_log("alg_info_delref() alg_info->ref_cnt=%d"
- , alg_info->ref_cnt)
- )
- if (alg_info->ref_cnt == 0)
+ if (alg_info != NULL)
{
- DBG(DBG_CRYPT,
- DBG_log("alg_info_delref() freeing alg_info")
- )
- alg_info_free(alg_info);
+ passert(alg_info->ref_cnt != 0);
+ alg_info->ref_cnt--;
+ if (alg_info->ref_cnt == 0)
+ {
+ alg_info_free(alg_info);
+ }
+ *alg_info_p = NULL;
}
- *alg_info_p = NULL;
- }
}
/* snprint already parsed transform list (alg_info) */
int
alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
{
- char *ptr = buf;
- int np = 0;
- struct esp_info *esp_info;
-#ifndef NO_PLUTO
- struct ike_info *ike_info;
-#endif
- int cnt;
-
- switch (alg_info->alg_info_protoid) {
- case PROTO_IPSEC_ESP:
- {
- struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
+ char *ptr = buf;
+ int np = 0;
+ struct esp_info *esp_info;
+ struct ike_info *ike_info;
+ int cnt;
+
+ switch (alg_info->alg_info_protoid) {
+ case PROTO_IPSEC_ESP:
+ {
+ struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
+
+ ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
+ {
+ np = snprintf(ptr, buflen, "%s",
+ enum_show(&esp_transformid_names, esp_info->esp_ealg_id));
+ ptr += np;
+ buflen -= np;
+ if (esp_info->esp_ealg_keylen)
+ {
+ np = snprintf(ptr, buflen, "_%u", esp_info->esp_ealg_keylen);
+ ptr += np;
+ buflen -= np;
+ }
+ np = snprintf(ptr, buflen, "/%s, ",
+ enum_show(&auth_alg_names, esp_info->esp_aalg_id));
+ ptr += np;
+ buflen -= np;
+ if (buflen < 0)
+ goto out;
+ }
+ if (alg_info_esp->esp_pfsgroup)
+ {
+ np = snprintf(ptr, buflen, "; pfsgroup=%s; ",
+ enum_show(&oakley_group_names, alg_info_esp->esp_pfsgroup));
+ ptr += np;
+ buflen -= np;
+ if (buflen < 0)
+ goto out;
+ }
+ break;
+ }
- ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
- {
- np = snprintf(ptr, buflen, "%d_%03d-%d, "
- , esp_info->esp_ealg_id
- , (int)esp_info->esp_ealg_keylen
- , esp_info->esp_aalg_id);
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- if (alg_info_esp->esp_pfsgroup)
- {
- np = snprintf(ptr, buflen, "; pfsgroup=%d; "
- , alg_info_esp->esp_pfsgroup);
+ case PROTO_ISAKMP:
+ ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
+ {
+ np = snprintf(ptr, buflen, "%s",
+ enum_show(&oakley_enc_names, ike_info->ike_ealg));
+ ptr += np;
+ buflen -= np;
+ if (ike_info->ike_eklen)
+ {
+ np = snprintf(ptr, buflen, "_%u", ike_info->ike_eklen);
+ ptr += np;
+ buflen -= np;
+ }
+ np = snprintf(ptr, buflen, "/%s/%s, ",
+ enum_show(&oakley_hash_names, ike_info->ike_halg),
+ enum_show(&oakley_group_names, ike_info->ike_modp));
+ ptr += np;
+ buflen -= np;
+ if (buflen < 0)
+ goto out;
+ }
+ break;
+ default:
+ np = snprintf(buf, buflen, "INVALID protoid=%d\n"
+ , alg_info->alg_info_protoid);
ptr += np;
buflen -= np;
- if (buflen < 0)
- goto out;
- }
- break;
- }
-#ifndef NO_PLUTO
- case PROTO_ISAKMP:
- ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
- {
- np = snprintf(ptr, buflen, "%d_%03d-%d-%d, "
- , ike_info->ike_ealg
- , (int)ike_info->ike_eklen
- , ike_info->ike_halg
- , ike_info->ike_modp);
- ptr += np;
- buflen -= np;
- if (buflen < 0)
goto out;
- }
- break;
-#endif
- default:
- np = snprintf(buf, buflen, "INVALID protoid=%d\n"
- , alg_info->alg_info_protoid);
- ptr += np;
- buflen -= np;
- goto out;
}
np = snprintf(ptr, buflen, "%s"
- , alg_info->alg_info_flags & ALG_INFO_F_STRICT?
- "strict":"");
+ , alg_info->alg_info_flags & ALG_INFO_F_STRICT?
+ "strict":"");
ptr += np;
buflen -= np;
out:
- if (buflen < 0)
- {
- loglog(RC_LOG_SERIOUS
- , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
- , buflen);
- }
-
- return ptr - buf;
+ if (buflen < 0)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
+ , buflen);
+ }
+
+ return ptr - buf;
}
-#ifndef NO_PLUTO
-int
-alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
+int alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
{
- char *ptr = buf;
+ char *ptr = buf;
- int cnt = alg_info->alg_info_cnt;
- struct esp_info *esp_info = alg_info->esp;
+ int cnt = alg_info->alg_info_cnt;
+ struct esp_info *esp_info = alg_info->esp;
- while (cnt--)
- {
- if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
- && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
+ while (cnt--)
{
- u_int eklen = (esp_info->esp_ealg_keylen)
- ? esp_info->esp_ealg_keylen
- : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
- * BITS_PER_BYTE;
-
- u_int aklen = esp_info->esp_aalg_keylen
- ? esp_info->esp_aalg_keylen
- : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
- * BITS_PER_BYTE;
-
- int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
- esp_info->esp_ealg_id, eklen,
- esp_info->esp_aalg_id, aklen);
- ptr += ret;
- buflen -= ret;
- if (buflen < 0)
- break;
+ if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
+ && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
+ {
+ u_int eklen = (esp_info->esp_ealg_keylen)
+ ? esp_info->esp_ealg_keylen
+ : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
+ * BITS_PER_BYTE;
+
+ u_int aklen = esp_info->esp_aalg_keylen
+ ? esp_info->esp_aalg_keylen
+ : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
+ * BITS_PER_BYTE;
+
+ int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
+ esp_info->esp_ealg_id, eklen,
+ esp_info->esp_aalg_id, aklen);
+ ptr += ret;
+ buflen -= ret;
+ if (buflen < 0)
+ break;
+ }
+ esp_info++;
}
- esp_info++;
- }
- return ptr - buf;
+ return ptr - buf;
}
-int
-alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
+int alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
{
- char *ptr = buf;
-
- int cnt = alg_info->alg_info_cnt;
- struct ike_info *ike_info = alg_info->ike;
+ char *ptr = buf;
- while (cnt--)
- {
- struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ike_info->ike_ealg);
- struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
+ int cnt = alg_info->alg_info_cnt;
+ struct ike_info *ike_info = alg_info->ike;
- if (enc_desc != NULL && hash_desc != NULL
- && lookup_group(ike_info->ike_modp))
+ while (cnt--)
{
+ struct encrypt_desc *enc_desc = ike_alg_get_crypter(ike_info->ike_ealg);
+ struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
+ struct dh_desc *dh_desc = ike_alg_get_dh_group(ike_info->ike_modp);
- u_int eklen = (ike_info->ike_eklen)
- ? ike_info->ike_eklen
- : enc_desc->keydeflen;
-
- u_int aklen = (ike_info->ike_hklen)
- ? ike_info->ike_hklen
- : hash_desc->hash_digest_size * BITS_PER_BYTE;
+ if (enc_desc && hash_desc && dh_desc)
+ {
- int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
- ike_info->ike_ealg, eklen,
- ike_info->ike_halg, aklen,
- ike_info->ike_modp);
- ptr += ret;
- buflen -= ret;
- if (buflen < 0)
- break;
+ u_int eklen = (ike_info->ike_eklen)
+ ? ike_info->ike_eklen
+ : enc_desc->keydeflen;
+
+ u_int aklen = (ike_info->ike_hklen)
+ ? ike_info->ike_hklen
+ : hash_desc->hash_digest_size * BITS_PER_BYTE;
+
+ int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
+ ike_info->ike_ealg, eklen,
+ ike_info->ike_halg, aklen,
+ ike_info->ike_modp);
+ ptr += ret;
+ buflen -= ret;
+ if (buflen < 0)
+ break;
+ }
+ ike_info++;
}
- ike_info++;
- }
- return ptr - buf;
+ return ptr - buf;
}
-#endif /* NO_PLUTO */
+
diff --git a/src/pluto/alg_info.h b/src/pluto/alg_info.h
index cacc2a354..fcf7efca0 100644
--- a/src/pluto/alg_info.h
+++ b/src/pluto/alg_info.h
@@ -10,76 +10,71 @@
* 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: alg_info.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef ALG_INFO_H
#define ALG_INFO_H
struct esp_info {
- u_int8_t transid; /* ESP transform */
- u_int16_t auth; /* AUTH */
- size_t enckeylen; /* keylength for ESP transform */
- size_t authkeylen; /* keylength for AUTH */
- u_int8_t encryptalg; /* normally encryptalg=transid */
- u_int8_t authalg; /* normally authalg=auth+1 */
+ u_int8_t transid; /* ESP transform */
+ u_int16_t auth; /* AUTH */
+ size_t enckeylen; /* keylength for ESP transform */
+ size_t authkeylen; /* keylength for AUTH */
+ u_int8_t encryptalg; /* normally encryptalg=transid */
+ u_int8_t authalg; /* normally authalg=auth+1 */
};
struct ike_info {
- u_int16_t ike_ealg; /* high 16 bit nums for reserved */
- u_int8_t ike_halg;
- size_t ike_eklen;
- size_t ike_hklen;
- u_int16_t ike_modp;
+ u_int16_t ike_ealg; /* high 16 bit nums for reserved */
+ u_int8_t ike_halg;
+ size_t ike_eklen;
+ size_t ike_hklen;
+ u_int16_t ike_modp;
};
#define ALG_INFO_COMMON \
- int alg_info_cnt; \
- int ref_cnt; \
- unsigned alg_info_flags; \
- unsigned alg_info_protoid
+ int alg_info_cnt; \
+ int ref_cnt; \
+ unsigned alg_info_flags; \
+ unsigned alg_info_protoid
struct alg_info {
- ALG_INFO_COMMON;
+ ALG_INFO_COMMON;
};
struct alg_info_esp {
- ALG_INFO_COMMON;
- struct esp_info esp[64];
- int esp_pfsgroup;
+ ALG_INFO_COMMON;
+ struct esp_info esp[64];
+ int esp_pfsgroup;
};
struct alg_info_ike {
- ALG_INFO_COMMON;
- struct ike_info ike[64];
+ ALG_INFO_COMMON;
+ struct ike_info ike[64];
};
#define esp_ealg_id transid
#define esp_aalg_id auth
-#define esp_ealg_keylen enckeylen /* bits */
-#define esp_aalg_keylen authkeylen /* bits */
+#define esp_ealg_keylen enckeylen /* bits */
+#define esp_aalg_keylen authkeylen /* bits */
-/* alg_info_flags bits */
-#define ALG_INFO_F_STRICT 0x01
+/* alg_info_flags bits */
+#define ALG_INFO_F_STRICT 0x01
extern int alg_info_esp_aa2sadb(int auth);
extern int alg_info_esp_sadb2aa(int sadb_aalg);
extern void alg_info_free(struct alg_info *alg_info);
extern void alg_info_addref(struct alg_info *alg_info);
extern void alg_info_delref(struct alg_info **alg_info);
-extern struct alg_info_esp* alg_info_esp_create_from_str(const char *alg_str
- , const char **err_p);
-extern struct alg_info_ike* alg_info_ike_create_from_str(const char *alg_str
- , const char **err_p);
+extern struct alg_info_esp* alg_info_esp_create_from_str(char *alg_str);
+extern struct alg_info_ike* alg_info_ike_create_from_str(char *alg_str);
extern int alg_info_parse(const char *str);
-extern int alg_info_snprint(char *buf, int buflen
- , struct alg_info *alg_info);
+extern int alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info);
extern int alg_info_snprint_esp(char *buf, int buflen
- , struct alg_info_esp *alg_info);
+ , struct alg_info_esp *alg_info);
extern int alg_info_snprint_ike(char *buf, int buflen
- , struct alg_info_ike *alg_info);
+ , struct alg_info_ike *alg_info);
#define ALG_INFO_ESP_FOREACH(ai, ai_esp, i) \
- for (i=(ai)->alg_info_cnt,ai_esp=(ai)->esp; i--; ai_esp++)
+ for (i=(ai)->alg_info_cnt,ai_esp=(ai)->esp; i--; ai_esp++)
#define ALG_INFO_IKE_FOREACH(ai, ai_ike, i) \
- for (i=(ai)->alg_info_cnt,ai_ike=(ai)->ike; i--; ai_ike++)
+ for (i=(ai)->alg_info_cnt,ai_ike=(ai)->ike; i--; ai_ike++)
#endif /* ALG_INFO_H */
diff --git a/src/pluto/asn1.c b/src/pluto/asn1.c
deleted file mode 100644
index 529f597fb..000000000
--- a/src/pluto/asn1.c
+++ /dev/null
@@ -1,787 +0,0 @@
-/* Simple ASN.1 parser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * 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: asn1.c 5041 2009-03-27 08:58:48Z andreas $
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "mp_defs.h"
-#include "asn1.h"
-#include <asn1/oid.h>
-#include "log.h"
-
-/* some common prefabricated ASN.1 constants */
-
-static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 };
-static u_char ASN1_INTEGER_1_str[] = { 0x02, 0x01, 0x01 };
-static u_char ASN1_INTEGER_2_str[] = { 0x02, 0x01, 0x02 };
-
-const chunk_t ASN1_INTEGER_0 = strchunk(ASN1_INTEGER_0_str);
-const chunk_t ASN1_INTEGER_1 = strchunk(ASN1_INTEGER_1_str);
-const chunk_t ASN1_INTEGER_2 = strchunk(ASN1_INTEGER_2_str);
-
-/* some popular algorithmIdentifiers */
-
-static u_char ASN1_md5_id_str[] = {
- 0x30, 0x0C,
- 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
- 0x05, 0x00
-};
-
-static u_char ASN1_sha1_id_str[] = {
- 0x30, 0x09,
- 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A,
- 0x05, 0x00
-};
-
-static u_char ASN1_md5WithRSA_id_str[] = {
- 0x30, 0x0D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04,
- 0x05, 0x00
-};
-
-static u_char ASN1_sha1WithRSA_id_str[] = {
- 0x30, 0x0D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
- 0x05, 0x00
-};
-
-static u_char ASN1_rsaEncryption_id_str[] = {
- 0x30, 0x0D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
- 0x05, 0x00
-};
-
-const chunk_t ASN1_md5_id = strchunk(ASN1_md5_id_str);
-const chunk_t ASN1_sha1_id = strchunk(ASN1_sha1_id_str);
-const chunk_t ASN1_rsaEncryption_id = strchunk(ASN1_rsaEncryption_id_str);
-const chunk_t ASN1_md5WithRSA_id = strchunk(ASN1_md5WithRSA_id_str);
-const chunk_t ASN1_sha1WithRSA_id = strchunk(ASN1_sha1WithRSA_id_str);
-
-/* ASN.1 definition of an algorithmIdentifier */
-
-static const asn1Object_t algorithmIdentifierObjects[] = {
- { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
- { 1, "parameters", ASN1_EOC, ASN1_OPT |
- ASN1_RAW }, /* 2 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */
-};
-
-#define ALGORITHM_ID_ALG 1
-#define ALGORITHM_ID_PARAMETERS 2
-#define ALGORITHM_ID_ROOF 4
-
-/*
- * return the ASN.1 encoded algorithm identifier
- */
-chunk_t
-asn1_algorithmIdentifier(int oid)
-{
- switch (oid)
- {
- case OID_RSA_ENCRYPTION:
- return ASN1_rsaEncryption_id;
- case OID_MD5_WITH_RSA:
- return ASN1_md5WithRSA_id;
- case OID_SHA1_WITH_RSA:
- return ASN1_sha1WithRSA_id;
- case OID_MD5:
- return ASN1_md5_id;
- case OID_SHA1:
- return ASN1_sha1_id;
- default:
- return empty_chunk;
- }
-}
-
-/* If the oid is listed in the oid_names table then the corresponding
- * position in the oid_names table is returned otherwise -1 is returned
- */
-int
-known_oid(chunk_t object)
-{
- int oid = 0;
-
- while (object.len)
- {
- if (oid_names[oid].octet == *object.ptr)
- {
- if (--object.len == 0 || oid_names[oid].down == 0)
- {
- return oid; /* found terminal symbol */
- }
- else
- {
- object.ptr++; oid++; /* advance to next hex octet */
- }
- }
- else
- {
- if (oid_names[oid].next)
- oid = oid_names[oid].next;
- else
- return OID_UNKNOWN;
- }
- }
- return -1;
-}
-
-/*
- * Decodes the length in bytes of an ASN.1 object
- */
-u_int
-asn1_length(chunk_t *blob)
-{
- u_char n;
- size_t len;
-
- /* advance from tag field on to length field */
- blob->ptr++;
- blob->len--;
-
- /* read first octet of length field */
- n = *blob->ptr++;
- blob->len--;
-
- if ((n & 0x80) == 0) /* single length octet */
- return n;
-
- /* composite length, determine number of length octets */
- n &= 0x7f;
-
- if (n > blob->len)
- {
- DBG(DBG_PARSING,
- DBG_log("number of length octets is larger than ASN.1 object")
- )
- return ASN1_INVALID_LENGTH;
- }
-
- if (n > sizeof(len))
- {
- DBG(DBG_PARSING,
- DBG_log("number of length octets is larger than limit of %d octets"
- , (int)sizeof(len))
- )
- return ASN1_INVALID_LENGTH;
- }
-
- len = 0;
-
- while (n-- > 0)
- {
- len = 256*len + *blob->ptr++;
- blob->len--;
- }
- return len;
-}
-
-/*
- * codes ASN.1 lengths up to a size of 16'777'215 bytes
- */
-void
-code_asn1_length(size_t length, chunk_t *code)
-{
- if (length < 128)
- {
- code->ptr[0] = length;
- code->len = 1;
- }
- else if (length < 256)
- {
- code->ptr[0] = 0x81;
- code->ptr[1] = (u_char) length;
- code->len = 2;
- }
- else if (length < 65536)
- {
- code->ptr[0] = 0x82;
- code->ptr[1] = length >> 8;
- code->ptr[2] = length & 0x00ff;
- code->len = 3;
- }
- else
- {
- code->ptr[0] = 0x83;
- code->ptr[1] = length >> 16;
- code->ptr[2] = (length >> 8) & 0x00ff;
- code->ptr[3] = length & 0x0000ff;
- code->len = 4;
- }
-}
-
-/*
- * build an empty asn.1 object with tag and length fields already filled in
- */
-u_char*
-build_asn1_object(chunk_t *object, asn1_t type, size_t datalen)
-{
- u_char length_buf[4];
- chunk_t length = { length_buf, 0 };
- u_char *pos;
-
- /* code the asn.1 length field */
- code_asn1_length(datalen, &length);
-
- /* allocate memory for the asn.1 TLV object */
- object->len = 1 + length.len + datalen;
- object->ptr = alloc_bytes(object->len, "asn1 object");
-
- /* set position pointer at the start of the object */
- pos = object->ptr;
-
- /* copy the asn.1 tag field and advance the pointer */
- *pos++ = type;
-
- /* copy the asn.1 length field and advance the pointer */
- chunkcpy(pos, length);
-
- return pos;
-}
-
-/*
- * build a simple ASN.1 object
- */
-chunk_t
-asn1_simple_object(asn1_t tag, chunk_t content)
-{
- chunk_t object;
-
- u_char *pos = build_asn1_object(&object, tag, content.len);
- chunkcpy(pos, content);
-
- return object;
-}
-
-/* Build an ASN.1 object from a variable number of individual chunks.
- * Depending on the mode, chunks either are moved ('m') or copied ('c').
- */
-chunk_t
-asn1_wrap(asn1_t type, const char *mode, ...)
-{
- chunk_t construct;
- va_list chunks;
- u_char *pos;
- int i;
- int count = strlen(mode);
-
- /* sum up lengths of individual chunks */
- va_start(chunks, mode);
- construct.len = 0;
- for (i = 0; i < count; i++)
- {
- chunk_t ch = va_arg(chunks, chunk_t);
- construct.len += ch.len;
- }
- va_end(chunks);
-
- /* allocate needed memory for construct */
- pos = build_asn1_object(&construct, type, construct.len);
-
- /* copy or move the chunks */
- va_start(chunks, mode);
- for (i = 0; i < count; i++)
- {
- chunk_t ch = va_arg(chunks, chunk_t);
-
- switch (*mode++)
- {
- case 'm':
- mv_chunk(&pos, ch);
- break;
- case 'c':
- default:
- chunkcpy(pos, ch);
- }
- }
- va_end(chunks);
-
- return construct;
-}
-
-/*
- * convert a MP integer into a DER coded ASN.1 object
- */
-chunk_t
-asn1_integer_from_mpz(const mpz_t value)
-{
- size_t bits = mpz_sizeinbase(value, 2); /* size in bits */
- size_t size = 1 + bits / BITS_PER_BYTE; /* size in bytes */
- chunk_t n = mpz_to_n(value, size);
-
- return asn1_wrap(ASN1_INTEGER, "m", n);
-}
-
-/*
- * determines if a character string is of type ASN.1 printableString
- */
-bool
-is_printablestring(chunk_t str)
-{
- const char printablestring_charset[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
- u_int i;
-
- for (i = 0; i < str.len; i++)
- {
- if (strchr(printablestring_charset, str.ptr[i]) == NULL)
- return FALSE;
- }
- return TRUE;
-}
-
-#define TIME_MAX 0x7fffffff
-
-/*
- * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
- */
-time_t
-asn1totime(const chunk_t *utctime, asn1_t type)
-{
- struct tm t;
- time_t tc, tz_offset;
- u_char *eot = NULL;
-
- if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
- {
- tz_offset = 0; /* Zulu time with a zero time zone offset */
- }
- else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
- {
- int tz_hour, tz_min;
-
- sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
- tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
- }
- else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
- {
- int tz_hour, tz_min;
-
- sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
- tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */
- }
- else
- {
- return 0; /* error in time format */
- }
-
- /* parse ASN.1 time string */
- {
- const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
- "%4d%2d%2d%2d%2d";
-
- sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday,
- &t.tm_hour, &t.tm_min);
- }
-
- /* is there a seconds field? */
- if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
- {
- sscanf(eot-2, "%2d", &t.tm_sec);
- }
- else
- {
- t.tm_sec = 0;
- }
-
- /* representation of year */
- if (t.tm_year >= 1900)
- {
- t.tm_year -= 1900;
- }
- else if (t.tm_year >= 100)
- {
- return 0;
- }
- else if (t.tm_year < 50)
- {
- t.tm_year += 100;
- }
-
- /* representation of month 0..11*/
- t.tm_mon--;
-
- /* set daylight saving time to off */
- t.tm_isdst = 0;
-
- /* convert to time_t */
- tc = mktime(&t);
-
- /* if no conversion overflow occurred, compensate timezone */
- return (tc == -1) ? TIME_MAX : (tc - timezone - tz_offset);
-}
-
-/*
- * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
- */
-chunk_t
-timetoasn1(const time_t *time, asn1_t type)
-{
- int offset;
- const char *format;
- char buf[TIMETOA_BUF];
- chunk_t formatted_time;
- struct tm *t = gmtime(time);
-
- if (type == ASN1_GENERALIZEDTIME)
- {
- format = "%04d%02d%02d%02d%02d%02dZ";
- offset = 1900;
- }
- else /* ASN1_UTCTIME */
- {
- format = "%02d%02d%02d%02d%02d%02dZ";
- offset = (t->tm_year < 100)? 0 : -100;
- }
- sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday
- , t->tm_hour, t->tm_min, t->tm_sec);
- formatted_time.ptr = buf;
- formatted_time.len = strlen(buf);
- return asn1_simple_object(type, formatted_time);
-}
-
-
-/*
- * Initializes the internal context of the ASN.1 parser
- */
-void
-asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0,
- bool implicit, u_int cond)
-{
- ctx->blobs[0] = blob;
- ctx->level0 = level0;
- ctx->implicit = implicit;
- ctx->cond = cond;
- memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr));
-}
-
-/*
- * print the value of an ASN.1 simple object
- */
-static void
-debug_asn1_simple_object(chunk_t object, asn1_t type, u_int cond)
-{
- int oid;
-
- switch (type)
- {
- case ASN1_OID:
- oid = known_oid(object);
- if (oid != OID_UNKNOWN)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%s'",oid_names[oid].name);
- )
- return;
- }
- break;
- case ASN1_UTF8STRING:
- case ASN1_IA5STRING:
- case ASN1_PRINTABLESTRING:
- case ASN1_T61STRING:
- case ASN1_VISIBLESTRING:
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", (int)object.len, object.ptr);
- )
- return;
- case ASN1_UTCTIME:
- case ASN1_GENERALIZEDTIME:
- DBG(DBG_PARSING,
- time_t time = asn1totime(&object, type);
- DBG_log(" '%s'", timetoa(&time, TRUE));
- )
- return;
- default:
- break;
- }
- DBG(cond,
- DBG_dump_chunk("", object);
- )
-}
-
-/*
- * Parses and extracts the next ASN.1 object
- */
-bool
-extract_object(asn1Object_t const *objects,
- u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx)
-{
- asn1Object_t obj = objects[*objectID];
- chunk_t *blob;
- chunk_t *blob1;
- u_char *start_ptr;
-
- *object = empty_chunk;
-
- if (obj.flags & ASN1_END) /* end of loop or option found */
- {
- if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0)
- {
- *objectID = ctx->loopAddr[obj.level]; /* another iteration */
- obj = objects[*objectID];
- }
- else
- {
- ctx->loopAddr[obj.level] = 0; /* exit loop or option*/
- return TRUE;
- }
- }
-
- *level = ctx->level0 + obj.level;
- blob = ctx->blobs + obj.level;
- blob1 = blob + 1;
- start_ptr = blob->ptr;
-
- /* handle ASN.1 defaults values */
-
- if ((obj.flags & ASN1_DEF)
- && (blob->len == 0 || *start_ptr != obj.type) )
- {
- /* field is missing */
- DBG(DBG_PARSING,
- DBG_log("L%d - %s:", *level, obj.name);
- )
- if (obj.type & ASN1_CONSTRUCTED)
- {
- (*objectID)++ ; /* skip context-specific tag */
- }
- return TRUE;
- }
-
- /* handle ASN.1 options */
-
- if ((obj.flags & ASN1_OPT)
- && (blob->len == 0 || *start_ptr != obj.type))
- {
- /* advance to end of missing option field */
- do
- (*objectID)++;
- while (!((objects[*objectID].flags & ASN1_END)
- && (objects[*objectID].level == obj.level)));
- return TRUE;
- }
-
- /* an ASN.1 object must possess at least a tag and length field */
-
- if (blob->len < 2)
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s: ASN.1 object smaller than 2 octets",
- *level, obj.name);
- )
- return FALSE;
- }
-
- blob1->len = asn1_length(blob);
-
- if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s: length of ASN.1 object invalid or too large",
- *level, obj.name);
- )
- return FALSE;
- }
-
- blob1->ptr = blob->ptr;
- blob->ptr += blob1->len;
- blob->len -= blob1->len;
-
- /* return raw ASN.1 object without prior type checking */
-
- if (obj.flags & ASN1_RAW)
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s:", *level, obj.name);
- )
- object->ptr = start_ptr;
- object->len = (size_t)(blob->ptr - start_ptr);
- return TRUE;
- }
-
- if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
- *level, obj.name, obj.type, *start_ptr);
- DBG_dump("", start_ptr, (u_int)(blob->ptr - start_ptr));
- )
- return FALSE;
- }
-
- DBG(DBG_PARSING,
- DBG_log("L%d - %s:", ctx->level0+obj.level, obj.name);
- )
-
- /* In case of "SEQUENCE OF" or "SET OF" start a loop */
-
- if (obj.flags & ASN1_LOOP)
- {
- if (blob1->len > 0)
- {
- /* at least one item, start the loop */
- ctx->loopAddr[obj.level] = *objectID + 1;
- }
- else
- {
- /* no items, advance directly to end of loop */
- do
- (*objectID)++;
- while (!((objects[*objectID].flags & ASN1_END)
- && (objects[*objectID].level == obj.level)));
- return TRUE;
- }
- }
-
- if (obj.flags & ASN1_OBJ)
- {
- object->ptr = start_ptr;
- object->len = (size_t)(blob->ptr - start_ptr);
- DBG(ctx->cond,
- DBG_dump_chunk("", *object);
- )
- }
- else if (obj.flags & ASN1_BODY)
- {
- *object = *blob1;
- debug_asn1_simple_object(*object, obj.type, ctx->cond);
- }
- return TRUE;
-}
-
-/*
- * parse an ASN.1 simple type
- */
-bool
-parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level
-, const char* name)
-{
- size_t len;
-
- /* an ASN.1 object must possess at least a tag and length field */
- if (object->len < 2)
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s: ASN.1 object smaller than 2 octets",
- level, name);
- )
- return FALSE;
- }
-
- if (*object->ptr != type)
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
- level, name, type, *object->ptr);
- )
- return FALSE;
- }
-
- len = asn1_length(object);
-
- if (len == ASN1_INVALID_LENGTH || object->len < len)
- {
- DBG(DBG_PARSING,
- DBG_log("L%d - %s: length of ASN.1 object invalid or too large",
- level, name);
- )
- return FALSE;
- }
-
- DBG(DBG_PARSING,
- DBG_log("L%d - %s:", level, name);
- )
- debug_asn1_simple_object(*object, type, DBG_RAW);
- return TRUE;
-}
-
-/*
- * extracts an algorithmIdentifier
- */
-int
-parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
-{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int alg = OID_UNKNOWN;
- int objectID = 0;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < ALGORITHM_ID_ROOF)
- {
- if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx))
- return alg;
-
- switch (objectID)
- {
- case ALGORITHM_ID_ALG:
- alg = known_oid(object);
- break;
- case ALGORITHM_ID_PARAMETERS:
- if (parameters != NULL)
- *parameters = object;
- break;
- default:
- break;
- }
- objectID++;
- }
- return alg;
- }
-
-/*
- * tests if a blob contains a valid ASN.1 set or sequence
- */
-bool
-is_asn1(chunk_t blob)
-{
- u_int len;
- u_char tag = *blob.ptr;
-
- if (tag != ASN1_SEQUENCE && tag != ASN1_SET)
- {
- DBG(DBG_PARSING,
- DBG_log(" file content is not binary ASN.1");
- )
- return FALSE;
- }
-
- len = asn1_length(&blob);
-
- /* exact match */
- if (len == blob.len)
- {
- return TRUE;
- }
-
- /* some websites append a surplus newline character to the blob */
- if (len + 1 == blob.len && *(blob.ptr + len) == '\n')
- {
- return TRUE;
- }
-
- DBG(DBG_PARSING,
- DBG_log(" file size does not match ASN.1 coded length");
- )
- return FALSE;
-}
diff --git a/src/pluto/asn1.h b/src/pluto/asn1.h
deleted file mode 100644
index 730245e4a..000000000
--- a/src/pluto/asn1.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* Simple ASN.1 parser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * 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: asn1.h 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#ifndef _ASN1_H
-#define _ASN1_H
-
-#include <stdarg.h>
-#include <gmp.h>
-
-#include "defs.h"
-
-/* Defines some primitive ASN1 types */
-
-typedef enum {
- ASN1_EOC = 0x00,
- ASN1_BOOLEAN = 0x01,
- ASN1_INTEGER = 0x02,
- ASN1_BIT_STRING = 0x03,
- ASN1_OCTET_STRING = 0x04,
- ASN1_NULL = 0x05,
- ASN1_OID = 0x06,
- ASN1_ENUMERATED = 0x0A,
- ASN1_UTF8STRING = 0x0C,
- ASN1_NUMERICSTRING = 0x12,
- ASN1_PRINTABLESTRING = 0x13,
- ASN1_T61STRING = 0x14,
- ASN1_VIDEOTEXSTRING = 0x15,
- ASN1_IA5STRING = 0x16,
- ASN1_UTCTIME = 0x17,
- ASN1_GENERALIZEDTIME = 0x18,
- ASN1_GRAPHICSTRING = 0x19,
- ASN1_VISIBLESTRING = 0x1A,
- ASN1_GENERALSTRING = 0x1B,
- ASN1_UNIVERSALSTRING = 0x1C,
- ASN1_BMPSTRING = 0x1E,
-
- ASN1_CONSTRUCTED = 0x20,
-
- ASN1_SEQUENCE = 0x30,
-
- ASN1_SET = 0x31,
-
- ASN1_CONTEXT_S_0 = 0x80,
- ASN1_CONTEXT_S_1 = 0x81,
- ASN1_CONTEXT_S_2 = 0x82,
- ASN1_CONTEXT_S_3 = 0x83,
- ASN1_CONTEXT_S_4 = 0x84,
- ASN1_CONTEXT_S_5 = 0x85,
- ASN1_CONTEXT_S_6 = 0x86,
- ASN1_CONTEXT_S_7 = 0x87,
- ASN1_CONTEXT_S_8 = 0x88,
-
- ASN1_CONTEXT_C_0 = 0xA0,
- ASN1_CONTEXT_C_1 = 0xA1,
- ASN1_CONTEXT_C_2 = 0xA2,
- ASN1_CONTEXT_C_3 = 0xA3,
- ASN1_CONTEXT_C_4 = 0xA4,
- ASN1_CONTEXT_C_5 = 0xA5
-} asn1_t;
-
-/* Definition of ASN1 flags */
-
-#define ASN1_NONE 0x00
-#define ASN1_DEF 0x01
-#define ASN1_OPT 0x02
-#define ASN1_LOOP 0x04
-#define ASN1_END 0x08
-#define ASN1_OBJ 0x10
-#define ASN1_BODY 0x20
-#define ASN1_RAW 0x40
-
-#define ASN1_INVALID_LENGTH 0xffffffff
-
-/* definition of an ASN.1 object */
-
-typedef struct {
- u_int level;
- const u_char *name;
- asn1_t type;
- u_char flags;
-} asn1Object_t;
-
-#define ASN1_MAX_LEVEL 10
-
-typedef struct {
- bool implicit;
- u_int cond;
- u_int level0;
- u_int loopAddr[ASN1_MAX_LEVEL+1];
- chunk_t blobs[ASN1_MAX_LEVEL+2];
-} asn1_ctx_t;
-
-/* some common prefabricated ASN.1 constants */
-
-extern const chunk_t ASN1_INTEGER_0;
-extern const chunk_t ASN1_INTEGER_1;
-extern const chunk_t ASN1_INTEGER_2;
-
-/* some popular algorithmIdentifiers */
-extern const chunk_t ASN1_md5_id;
-extern const chunk_t ASN1_sha1_id;
-extern const chunk_t ASN1_rsaEncryption_id;
-extern const chunk_t ASN1_md5WithRSA_id;
-extern const chunk_t ASN1_sha1WithRSA_id;
-
-extern chunk_t asn1_algorithmIdentifier(int oid);
-extern int known_oid(chunk_t object);
-extern u_int asn1_length(chunk_t *blob);
-extern void code_asn1_length(size_t length, chunk_t *code);
-extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen);
-extern chunk_t asn1_integer_from_mpz(const mpz_t value);
-extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
-extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...);
-extern bool is_printablestring(chunk_t str);
-extern time_t asn1totime(const chunk_t *utctime, asn1_t type);
-extern chunk_t timetoasn1(const time_t *time, asn1_t type);
-extern void asn1_init(asn1_ctx_t *ctx, chunk_t blob
- , u_int level0, bool implicit, u_int cond);
-extern bool extract_object(asn1Object_t const *objects
- , u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx);
-extern bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level
- , const char* name);
-extern int parse_algorithmIdentifier(chunk_t blob, int level0
- , chunk_t *parameters);
-extern bool is_asn1(chunk_t blob);
-
-#endif /* _ASN1_H */
-
diff --git a/src/pluto/ca.c b/src/pluto/ca.c
index 816db53a8..4fdb8cfe7 100644
--- a/src/pluto/ca.c
+++ b/src/pluto/ca.c
@@ -10,8 +10,6 @@
* 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: ca.c 4709 2008-11-27 10:20:25Z martin $
*/
#include <stdlib.h>
@@ -23,7 +21,6 @@
#include <sys/types.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "constants.h"
#include "defs.h"
@@ -40,17 +37,17 @@
static x509cert_t *x509authcerts = NULL;
const ca_info_t empty_ca_info = {
- NULL , /* next */
- NULL , /* name */
- UNDEFINED_TIME,
- { NULL, 0 } , /* authName */
- { NULL, 0 } , /* authKeyID */
- { NULL, 0 } , /* authKey SerialNumber */
- NULL , /* ldaphost */
- NULL , /* ldapbase */
- NULL , /* ocspori */
- NULL , /* crluri */
- FALSE /* strictcrlpolicy */
+ NULL , /* next */
+ NULL , /* name */
+ UNDEFINED_TIME,
+ { NULL, 0 } , /* authName */
+ { NULL, 0 } , /* authKeyID */
+ { NULL, 0 } , /* authKey SerialNumber */
+ NULL , /* ldaphost */
+ NULL , /* ldapbase */
+ NULL , /* ocspori */
+ NULL , /* crluri */
+ FALSE /* strictcrlpolicy */
};
/* chained list of X.509 certification authority information records */
@@ -63,52 +60,52 @@ static ca_info_t *ca_infos = NULL;
bool
trusted_ca(chunk_t a, chunk_t b, int *pathlen)
{
- bool match = FALSE;
-
- /* no CA b specified -> any CA a is accepted */
- if (b.ptr == NULL)
- {
- *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN;
- return TRUE;
- }
-
- /* no CA a specified -> trust cannot be established */
- if (a.ptr == NULL)
- {
- *pathlen = MAX_CA_PATH_LEN;
- return FALSE;
- }
+ bool match = FALSE;
+
+ /* no CA b specified -> any CA a is accepted */
+ if (b.ptr == NULL)
+ {
+ *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN;
+ return TRUE;
+ }
+
+ /* no CA a specified -> trust cannot be established */
+ if (a.ptr == NULL)
+ {
+ *pathlen = MAX_CA_PATH_LEN;
+ return FALSE;
+ }
- *pathlen = 0;
+ *pathlen = 0;
- /* CA a equals CA b -> we have a match */
- if (same_dn(a, b))
- return TRUE;
+ /* CA a equals CA b -> we have a match */
+ if (same_dn(a, b))
+ return TRUE;
- /* CA a might be a subordinate CA of b */
- lock_authcert_list("trusted_ca");
+ /* CA a might be a subordinate CA of b */
+ lock_authcert_list("trusted_ca");
- while ((*pathlen)++ < MAX_CA_PATH_LEN)
- {
- x509cert_t *cacert = get_authcert(a, empty_chunk, empty_chunk, AUTH_CA);
+ while ((*pathlen)++ < MAX_CA_PATH_LEN)
+ {
+ x509cert_t *cacert = get_authcert(a, chunk_empty, chunk_empty, AUTH_CA);
- /* cacert not found or self-signed root cacert-> exit */
- if (cacert == NULL || same_dn(cacert->issuer, a))
- break;
+ /* cacert not found or self-signed root cacert-> exit */
+ if (cacert == NULL || same_dn(cacert->issuer, a))
+ break;
- /* does the issuer of CA a match CA b? */
- match = same_dn(cacert->issuer, b);
+ /* does the issuer of CA a match CA b? */
+ match = same_dn(cacert->issuer, b);
- /* we have a match and exit the loop */
- if (match)
- break;
+ /* we have a match and exit the loop */
+ if (match)
+ break;
- /* go one level up in the CA chain */
- a = cacert->issuer;
- }
-
- unlock_authcert_list("trusted_ca");
- return match;
+ /* go one level up in the CA chain */
+ a = cacert->issuer;
+ }
+
+ unlock_authcert_list("trusted_ca");
+ return match;
}
/*
@@ -117,36 +114,36 @@ trusted_ca(chunk_t a, chunk_t b, int *pathlen)
bool
match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen)
{
- /* if no ca is requested than any ca will match */
- if (requested_ca == NULL)
- {
- *our_pathlen = 0;
- return TRUE;
- }
-
- *our_pathlen = MAX_CA_PATH_LEN + 1;
+ /* if no ca is requested than any ca will match */
+ if (requested_ca == NULL)
+ {
+ *our_pathlen = 0;
+ return TRUE;
+ }
- while (requested_ca != NULL)
- {
- int pathlen;
+ *our_pathlen = MAX_CA_PATH_LEN + 1;
- if (trusted_ca(our_ca, requested_ca->name, &pathlen)
- && pathlen < *our_pathlen)
+ while (requested_ca != NULL)
{
- *our_pathlen = pathlen;
+ int pathlen;
+
+ if (trusted_ca(our_ca, requested_ca->name, &pathlen)
+ && pathlen < *our_pathlen)
+ {
+ *our_pathlen = pathlen;
+ }
+ requested_ca = requested_ca->next;
}
- requested_ca = requested_ca->next;
- }
- if (*our_pathlen > MAX_CA_PATH_LEN)
- {
- *our_pathlen = MAX_CA_PATH_LEN;
- return FALSE;
- }
- else
- {
- return TRUE;
- }
+ if (*our_pathlen > MAX_CA_PATH_LEN)
+ {
+ *our_pathlen = MAX_CA_PATH_LEN;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
}
/*
@@ -155,9 +152,9 @@ match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen
static void
free_first_authcert(void)
{
- x509cert_t *first = x509authcerts;
- x509authcerts = first->next;
- free_x509cert(first);
+ x509cert_t *first = x509authcerts;
+ x509authcerts = first->next;
+ free_x509cert(first);
}
/*
@@ -166,12 +163,12 @@ free_first_authcert(void)
void
free_authcerts(void)
{
- lock_authcert_list("free_authcerts");
+ lock_authcert_list("free_authcerts");
- while (x509authcerts != NULL)
- free_first_authcert();
+ while (x509authcerts != NULL)
+ free_first_authcert();
- unlock_authcert_list("free_authcerts");
+ unlock_authcert_list("free_authcerts");
}
/*
@@ -180,29 +177,29 @@ free_authcerts(void)
x509cert_t*
get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags)
{
- x509cert_t *cert = x509authcerts;
- x509cert_t *prev_cert = NULL;
-
- while (cert != NULL)
- {
- if (cert->authority_flags & auth_flags
- && ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
- : (same_dn(subject, cert->subject)
- && same_serial(serial, cert->serialNumber))))
+ x509cert_t *cert = x509authcerts;
+ x509cert_t *prev_cert = NULL;
+
+ while (cert != NULL)
{
- if (cert != x509authcerts)
- {
- /* bring the certificate up front */
- prev_cert->next = cert->next;
- cert->next = x509authcerts;
- x509authcerts = cert;
- }
- return cert;
+ if (cert->authority_flags & auth_flags
+ && ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
+ : (same_dn(subject, cert->subject)
+ && same_serial(serial, cert->serialNumber))))
+ {
+ if (cert != x509authcerts)
+ {
+ /* bring the certificate up front */
+ prev_cert->next = cert->next;
+ cert->next = x509authcerts;
+ x509authcerts = cert;
+ }
+ return cert;
+ }
+ prev_cert = cert;
+ cert = cert->next;
}
- prev_cert = cert;
- cert = cert->next;
- }
- return NULL;
+ return NULL;
}
/*
@@ -211,49 +208,49 @@ get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags)
x509cert_t*
add_authcert(x509cert_t *cert, u_char auth_flags)
{
- x509cert_t *old_cert;
+ x509cert_t *old_cert;
- /* set authority flags */
- cert->authority_flags |= auth_flags;
+ /* set authority flags */
+ cert->authority_flags |= auth_flags;
- lock_authcert_list("add_authcert");
+ lock_authcert_list("add_authcert");
- old_cert = get_authcert(cert->subject, cert->serialNumber
- , cert->subjectKeyID, auth_flags);
+ old_cert = get_authcert(cert->subject, cert->serialNumber
+ , cert->subjectKeyID, auth_flags);
- if (old_cert != NULL)
- {
- if (same_x509cert(cert, old_cert))
- {
- /* cert is already present, just add additional authority flags */
- old_cert->authority_flags |= cert->authority_flags;
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log(" authcert is already present and identical")
- )
- unlock_authcert_list("add_authcert");
-
- free_x509cert(cert);
- return old_cert;
- }
- else
+ if (old_cert != NULL)
{
- /* cert is already present but will be replaced by new cert */
- free_first_authcert();
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log(" existing authcert deleted")
- )
+ if (same_x509cert(cert, old_cert))
+ {
+ /* cert is already present, just add additional authority flags */
+ old_cert->authority_flags |= cert->authority_flags;
+ DBG(DBG_CONTROL | DBG_PARSING ,
+ DBG_log(" authcert is already present and identical")
+ )
+ unlock_authcert_list("add_authcert");
+
+ free_x509cert(cert);
+ return old_cert;
+ }
+ else
+ {
+ /* cert is already present but will be replaced by new cert */
+ free_first_authcert();
+ DBG(DBG_CONTROL | DBG_PARSING ,
+ DBG_log(" existing authcert deleted")
+ )
+ }
}
- }
-
- /* add new authcert to chained list */
- cert->next = x509authcerts;
- x509authcerts = cert;
- share_x509cert(cert); /* set count to one */
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" authcert inserted")
- )
- unlock_authcert_list("add_authcert");
- return cert;
+
+ /* add new authcert to chained list */
+ cert->next = x509authcerts;
+ x509authcerts = cert;
+ share_x509cert(cert); /* set count to one */
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log(" authcert inserted")
+ )
+ unlock_authcert_list("add_authcert");
+ return cert;
}
/*
@@ -262,41 +259,41 @@ add_authcert(x509cert_t *cert, u_char auth_flags)
void
load_authcerts(const char *type, const char *path, u_char auth_flags)
{
- struct dirent **filelist;
- u_char buf[BUF_LEN];
- u_char *save_dir;
- int n;
-
- /* change directory to specified path */
- save_dir = getcwd(buf, BUF_LEN);
-
- if (chdir(path))
- {
- plog("Could not change to directory '%s'", path);
- }
- else
- {
- plog("Changing to directory '%s'", path);
- n = scandir(path, &filelist, file_select, alphasort);
-
- if (n < 0)
- plog(" scandir() error");
- else
- {
- while (n--)
- {
- cert_t cert;
+ struct dirent **filelist;
+ u_char buf[BUF_LEN];
+ u_char *save_dir;
+ int n;
- if (load_cert(filelist[n]->d_name, type, &cert))
- add_authcert(cert.u.x509, auth_flags);
+ /* change directory to specified path */
+ save_dir = getcwd(buf, BUF_LEN);
- free(filelist[n]);
- }
- free(filelist);
+ if (chdir(path))
+ {
+ plog("Could not change to directory '%s'", path);
}
- }
- /* restore directory path */
- ignore_result(chdir(save_dir));
+ else
+ {
+ plog("Changing to directory '%s'", path);
+ n = scandir(path, &filelist, file_select, alphasort);
+
+ if (n < 0)
+ plog(" scandir() error");
+ else
+ {
+ while (n--)
+ {
+ cert_t cert;
+
+ if (load_cert(filelist[n]->d_name, type, &cert))
+ add_authcert(cert.u.x509, auth_flags);
+
+ free(filelist[n]);
+ }
+ free(filelist);
+ }
+ }
+ /* restore directory path */
+ ignore_result(chdir(save_dir));
}
/*
@@ -305,9 +302,9 @@ load_authcerts(const char *type, const char *path, u_char auth_flags)
void
list_authcerts(const char *caption, u_char auth_flags, bool utc)
{
- lock_authcert_list("list_authcerts");
- list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
- unlock_authcert_list("list_authcerts");
+ lock_authcert_list("list_authcerts");
+ list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
+ unlock_authcert_list("list_authcerts");
}
/*
@@ -315,19 +312,19 @@ list_authcerts(const char *caption, u_char auth_flags, bool utc)
*/
static const x509cert_t*
get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid
- , const x509cert_t *cert)
+ , const x509cert_t *cert)
{
- while (cert != NULL)
- {
- if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
- : (same_dn(subject, cert->subject)
- && same_serial(serial, cert->serialNumber)))
+ while (cert != NULL)
{
- return cert;
+ if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
+ : (same_dn(subject, cert->subject)
+ && same_serial(serial, cert->serialNumber)))
+ {
+ return cert;
+ }
+ cert = cert->next;
}
- cert = cert->next;
- }
- return NULL;
+ return NULL;
}
/* establish trust into a candidate authcert by going up the trust chain.
@@ -336,85 +333,85 @@ get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid
bool
trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
{
- int pathlen;
-
- lock_authcert_list("trust_authcert_candidate");
-
- for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
- {
- const x509cert_t *authcert = NULL;
- u_char buf[BUF_LEN];
-
- DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, cert->subject);
- DBG_log("subject: '%s'",buf);
- dntoa(buf, BUF_LEN, cert->issuer);
- DBG_log("issuer: '%s'",buf);
- if (cert->authKeyID.ptr != NULL)
- {
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
- }
- )
+ int pathlen;
- /* search in alternative chain first */
- authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, alt_chain);
+ lock_authcert_list("trust_authcert_candidate");
- if (authcert != NULL)
+ for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
{
- DBG(DBG_CONTROL,
- DBG_log("issuer cacert found in alternative chain")
- )
- }
- else
- {
- /* search in trusted chain */
- authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, AUTH_CA);
+ const x509cert_t *authcert = NULL;
+ u_char buf[BUF_LEN];
- if (authcert != NULL)
- {
DBG(DBG_CONTROL,
- DBG_log("issuer cacert found")
+ dntoa(buf, BUF_LEN, cert->subject);
+ DBG_log("subject: '%s'",buf);
+ dntoa(buf, BUF_LEN, cert->issuer);
+ DBG_log("issuer: '%s'",buf);
+ if (cert->authKeyID.ptr != NULL)
+ {
+ datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ DBG_log("authkey: %s", buf);
+ }
)
- }
- else
- {
- plog("issuer cacert not found");
- unlock_authcert_list("trust_authcert_candidate");
- return FALSE;
- }
- }
- if (!check_signature(cert->tbsCertificate, cert->signature
- , cert->algorithm, cert->algorithm, authcert))
- {
- plog("certificate signature is invalid");
- unlock_authcert_list("trust_authcert_candidate");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate signature is valid")
- )
+ /* search in alternative chain first */
+ authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber
+ , cert->authKeyID, alt_chain);
+
+ if (authcert != NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("issuer cacert found in alternative chain")
+ )
+ }
+ else
+ {
+ /* search in trusted chain */
+ authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
+ , cert->authKeyID, AUTH_CA);
+
+ if (authcert != NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("issuer cacert found")
+ )
+ }
+ else
+ {
+ plog("issuer cacert not found");
+ unlock_authcert_list("trust_authcert_candidate");
+ return FALSE;
+ }
+ }
+
+ if (!x509_check_signature(cert->tbsCertificate, cert->signature,
+ cert->algorithm, authcert))
+ {
+ plog("certificate signature is invalid");
+ unlock_authcert_list("trust_authcert_candidate");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("certificate signature is valid")
+ )
- /* check if cert is a self-signed root ca */
- if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
- {
- DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca")
- )
- unlock_authcert_list("trust_authcert_candidate");
- return TRUE;
+ /* check if cert is a self-signed root ca */
+ if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("reached self-signed root ca")
+ )
+ unlock_authcert_list("trust_authcert_candidate");
+ return TRUE;
+ }
+
+ /* go up one step in the trust chain */
+ cert = authcert;
}
-
- /* go up one step in the trust chain */
- cert = authcert;
- }
- plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
- unlock_authcert_list("trust_authcert_candidate");
- return FALSE;
+ plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ unlock_authcert_list("trust_authcert_candidate");
+ return FALSE;
}
/*
@@ -423,19 +420,19 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
ca_info_t*
get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid)
{
- ca_info_t *ca= ca_infos;
+ ca_info_t *ca= ca_infos;
- while (ca!= NULL)
- {
- if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID)
- : (same_dn(authname, ca->authName)
- && same_serial(serial, ca->authKeySerialNumber)))
+ while (ca!= NULL)
{
- return ca;
+ if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID)
+ : (same_dn(authname, ca->authName)
+ && same_serial(serial, ca->authKeySerialNumber)))
+ {
+ return ca;
+ }
+ ca = ca->next;
}
- ca = ca->next;
- }
- return NULL;
+ return NULL;
}
@@ -445,21 +442,18 @@ get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid)
static void
free_ca_info(ca_info_t* ca_info)
{
- if (ca_info == NULL)
- return;
-
- pfreeany(ca_info->name);
- pfreeany(ca_info->ldaphost);
- pfreeany(ca_info->ldapbase);
- pfreeany(ca_info->ocspuri);
-
- freeanychunk(ca_info->authName);
- freeanychunk(ca_info->authKeyID);
- freeanychunk(ca_info->authKeySerialNumber);
-
- free_generalNames(ca_info->crluri, TRUE);
-
- pfree(ca_info);
+ if (ca_info == NULL)
+ return;
+
+ free(ca_info->name);
+ free(ca_info->ldaphost);
+ free(ca_info->ldapbase);
+ free(ca_info->ocspuri);
+ free(ca_info->authName.ptr);
+ free(ca_info->authKeyID.ptr);
+ free(ca_info->authKeySerialNumber.ptr);
+ free_generalNames(ca_info->crluri, TRUE);
+ free(ca_info);
}
/*
@@ -468,13 +462,13 @@ free_ca_info(ca_info_t* ca_info)
void
free_ca_infos(void)
{
- while (ca_infos != NULL)
- {
- ca_info_t *ca = ca_infos;
+ while (ca_infos != NULL)
+ {
+ ca_info_t *ca = ca_infos;
- ca_infos = ca_infos->next;
- free_ca_info(ca);
- }
+ ca_infos = ca_infos->next;
+ free_ca_info(ca);
+ }
}
/*
@@ -483,28 +477,28 @@ free_ca_infos(void)
bool
find_ca_info_by_name(const char *name, bool delete)
{
- ca_info_t **ca_p = &ca_infos;
- ca_info_t *ca = *ca_p;
+ ca_info_t **ca_p = &ca_infos;
+ ca_info_t *ca = *ca_p;
- while (ca != NULL)
- {
- /* is there already an entry? */
- if (streq(name, ca->name))
+ while (ca != NULL)
{
- if (delete)
- {
- lock_ca_info_list("find_ca_info_by_name");
- *ca_p = ca->next;
- free_ca_info(ca);
- plog("deleting ca description \"%s\"", name);
- unlock_ca_info_list("find_ca_info_by_name");
- }
- return TRUE;
+ /* is there already an entry? */
+ if (streq(name, ca->name))
+ {
+ if (delete)
+ {
+ lock_ca_info_list("find_ca_info_by_name");
+ *ca_p = ca->next;
+ free_ca_info(ca);
+ plog("deleting ca description \"%s\"", name);
+ unlock_ca_info_list("find_ca_info_by_name");
+ }
+ return TRUE;
+ }
+ ca_p = &ca->next;
+ ca = *ca_p;
}
- ca_p = &ca->next;
- ca = *ca_p;
- }
- return FALSE;
+ return FALSE;
}
@@ -514,136 +508,133 @@ find_ca_info_by_name(const char *name, bool delete)
void
add_ca_info(const whack_message_t *msg)
{
- smartcard_t *sc = NULL;
- cert_t cert;
- bool valid_cert = FALSE;
- bool cached_cert = FALSE;
-
- if (find_ca_info_by_name(msg->name, FALSE))
- {
- loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name);
- return;
- }
-
- if (scx_on_smartcard(msg->cacert))
- {
- /* load CA cert from smartcard */
- valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert);
- }
- else
- {
- /* load CA cert from file */
- valid_cert = load_ca_cert(msg->cacert, &cert);
- }
-
- if (valid_cert)
- {
- char buf[BUF_LEN];
- x509cert_t *cacert = cert.u.x509;
- ca_info_t *ca = NULL;
-
- /* does the authname already exist? */
- ca = get_ca_info(cacert->subject, cacert->serialNumber
- , cacert->subjectKeyID);
-
- if (ca != NULL)
- {
- /* ca_info is already present */
- loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
- "ignoring \"%s\"", ca->name, msg->name);
- free_x509cert(cacert);
- return;
- }
+ smartcard_t *sc = NULL;
+ cert_t cert;
+ bool valid_cert = FALSE;
+ bool cached_cert = FALSE;
- plog("added ca description \"%s\"", msg->name);
-
- /* create and initialize new ca_info record */
- ca = alloc_thing(ca_info_t, "ca info");
- *ca = empty_ca_info;
-
- /* name */
- ca->name = clone_str(msg->name, "ca name");
-
- /* authName */
- clonetochunk(ca->authName, cacert->subject.ptr
- , cacert->subject.len, "authName");
- dntoa(buf, BUF_LEN, ca->authName);
- DBG(DBG_CONTROL,
- DBG_log("authname: '%s'", buf)
- )
-
- /* authSerialNumber */
- clonetochunk(ca->authKeySerialNumber, cacert->serialNumber.ptr
- , cacert->serialNumber.len, "authKeySerialNumber");
-
- /* authKeyID */
- if (cacert->subjectKeyID.ptr != NULL)
+ if (find_ca_info_by_name(msg->name, FALSE))
{
- clonetochunk(ca->authKeyID, cacert->subjectKeyID.ptr
- , cacert->subjectKeyID.len, "authKeyID");
- datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':'
- , buf, BUF_LEN);
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log("authkey: %s", buf)
- )
+ loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name);
+ return;
}
- /* ldaphost */
- ca->ldaphost = clone_str(msg->ldaphost, "ldaphost");
-
- /* ldapbase */
- ca->ldapbase = clone_str(msg->ldapbase, "ldapbase");
-
- /* ocspuri */
- if (msg->ocspuri != NULL)
+ if (scx_on_smartcard(msg->cacert))
{
- if (strncasecmp(msg->ocspuri, "http", 4) == 0)
- ca->ocspuri = clone_str(msg->ocspuri, "ocspuri");
- else
- plog(" ignoring ocspuri with unkown protocol");
+ /* load CA cert from smartcard */
+ valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert);
}
-
- /* crluri2*/
- if (msg->crluri2 != NULL)
+ else
{
- generalName_t gn =
- { NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} };
-
- add_distribution_points(&gn, &ca->crluri);
+ /* load CA cert from file */
+ valid_cert = load_ca_cert(msg->cacert, &cert);
}
- /* crluri */
- if (msg->crluri != NULL)
+ if (valid_cert)
{
- generalName_t gn =
- { NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} };
-
- add_distribution_points(&gn, &ca->crluri);
- }
-
- /* strictrlpolicy */
- ca->strictcrlpolicy = msg->whack_strict;
-
- /* insert ca_info record into the chained list */
- lock_ca_info_list("add_ca_info");
-
- ca->next = ca_infos;
- ca_infos = ca;
- ca->installed = time(NULL);
-
- unlock_ca_info_list("add_ca_info");
+ char buf[BUF_LEN];
+ x509cert_t *cacert = cert.u.x509;
+ ca_info_t *ca = NULL;
+
+ /* does the authname already exist? */
+ ca = get_ca_info(cacert->subject, cacert->serialNumber
+ , cacert->subjectKeyID);
+
+ if (ca != NULL)
+ {
+ /* ca_info is already present */
+ loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
+ "ignoring \"%s\"", ca->name, msg->name);
+ free_x509cert(cacert);
+ return;
+ }
+
+ plog("added ca description \"%s\"", msg->name);
+
+ /* create and initialize new ca_info record */
+ ca = malloc_thing(ca_info_t);
+ *ca = empty_ca_info;
+
+ /* name */
+ ca->name = clone_str(msg->name);
+
+ /* authName */
+ ca->authName = chunk_clone(cacert->subject);
+ dntoa(buf, BUF_LEN, ca->authName);
+ DBG(DBG_CONTROL,
+ DBG_log("authname: '%s'", buf)
+ )
- /* add cacert to list of authcerts */
- if (!cached_cert && sc != NULL)
- {
- if (sc->last_cert.type == CERT_X509_SIGNATURE)
- sc->last_cert.u.x509->count--;
- sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA);
- share_cert(sc->last_cert);
+ /* authSerialNumber */
+ ca->authKeySerialNumber = chunk_clone(cacert->serialNumber);
+
+ /* authKeyID */
+ if (cacert->subjectKeyID.ptr != NULL)
+ {
+ ca->authKeyID = chunk_clone(cacert->subjectKeyID);
+ datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':'
+ , buf, BUF_LEN);
+ DBG(DBG_CONTROL | DBG_PARSING ,
+ DBG_log("authkey: %s", buf)
+ )
+ }
+
+ /* ldaphost */
+ ca->ldaphost = clone_str(msg->ldaphost);
+
+ /* ldapbase */
+ ca->ldapbase = clone_str(msg->ldapbase);
+
+ /* ocspuri */
+ if (msg->ocspuri != NULL)
+ {
+ if (strncasecmp(msg->ocspuri, "http", 4) == 0)
+ ca->ocspuri = clone_str(msg->ocspuri);
+ else
+ plog(" ignoring ocspuri with unkown protocol");
+ }
+
+ /* crluri2*/
+ if (msg->crluri2 != NULL)
+ {
+ generalName_t gn =
+ { NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} };
+
+ add_distribution_points(&gn, &ca->crluri);
+ }
+
+ /* crluri */
+ if (msg->crluri != NULL)
+ {
+ generalName_t gn =
+ { NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} };
+
+ add_distribution_points(&gn, &ca->crluri);
+ }
+
+ /* strictrlpolicy */
+ ca->strictcrlpolicy = msg->whack_strict;
+
+ /* insert ca_info record into the chained list */
+ lock_ca_info_list("add_ca_info");
+
+ ca->next = ca_infos;
+ ca_infos = ca;
+ ca->installed = time(NULL);
+
+ unlock_ca_info_list("add_ca_info");
+
+ /* add cacert to list of authcerts */
+ if (!cached_cert && sc != NULL)
+ {
+ if (sc->last_cert.type == CERT_X509_SIGNATURE)
+ sc->last_cert.u.x509->count--;
+ sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA);
+ share_cert(sc->last_cert);
+ }
+ if (sc != NULL)
+ time(&sc->last_load);
}
- if (sc != NULL)
- time(&sc->last_load);
- }
}
/*
@@ -652,51 +643,51 @@ add_ca_info(const whack_message_t *msg)
void
list_ca_infos(bool utc)
{
- ca_info_t *ca = ca_infos;
-
- if (ca != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 CA Information Records:");
- whack_log(RC_COMMENT, " ");
- }
-
- while (ca != NULL)
- {
- u_char buf[BUF_LEN];
-
- /* strictpolicy per CA not supported yet
- *
- whack_log(RC_COMMENT, "%s, \"%s\", strictcrlpolicy: %s"
- , timetoa(&ca->installed, utc), ca->name
- , ca->strictcrlpolicy? "yes":"no");
- */
- whack_log(RC_COMMENT, "%s, \"%s\"", timetoa(&ca->installed, utc), ca->name);
- dntoa(buf, BUF_LEN, ca->authName);
- whack_log(RC_COMMENT, " authname: '%s'", buf);
- if (ca->ldaphost != NULL)
- whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost);
- if (ca->ldapbase != NULL)
- whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase);
- if (ca->ocspuri != NULL)
- whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
-
- list_distribution_points(ca->crluri);
-
- if (ca->authKeyID.ptr != NULL)
+ ca_info_t *ca = ca_infos;
+
+ if (ca != NULL)
{
- datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of X.509 CA Information Records:");
+ whack_log(RC_COMMENT, " ");
}
- if (ca->authKeySerialNumber.ptr != NULL)
+
+ while (ca != NULL)
{
- datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ u_char buf[BUF_LEN];
+
+ /* strictpolicy per CA not supported yet
+ *
+ whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s"
+ , &ca->installed, utc, ca->name
+ , ca->strictcrlpolicy? "yes":"no");
+ */
+ whack_log(RC_COMMENT, "%T, \"%s\"", &ca->installed, utc, ca->name);
+ dntoa(buf, BUF_LEN, ca->authName);
+ whack_log(RC_COMMENT, " authname: '%s'", buf);
+ if (ca->ldaphost != NULL)
+ whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost);
+ if (ca->ldapbase != NULL)
+ whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase);
+ if (ca->ocspuri != NULL)
+ whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
+
+ list_distribution_points(ca->crluri);
+
+ if (ca->authKeyID.ptr != NULL)
+ {
+ datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authkey: %s", buf);
+ }
+ if (ca->authKeySerialNumber.ptr != NULL)
+ {
+ datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " aserial: %s", buf);
+ }
+ ca = ca->next;
}
- ca = ca->next;
- }
}
diff --git a/src/pluto/ca.h b/src/pluto/ca.h
index 13f874284..44d079b4c 100644
--- a/src/pluto/ca.h
+++ b/src/pluto/ca.h
@@ -10,8 +10,6 @@
* 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: ca.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _CA_H
@@ -20,45 +18,45 @@
#include "x509.h"
#include "whack.h"
-#define MAX_CA_PATH_LEN 7
+#define MAX_CA_PATH_LEN 7
/* authority flags */
-#define AUTH_NONE 0x00 /* no authorities */
-#define AUTH_CA 0x01 /* certification authority */
-#define AUTH_AA 0x02 /* authorization authority */
-#define AUTH_OCSP 0x04 /* ocsp signing authority */
+#define AUTH_NONE 0x00 /* no authorities */
+#define AUTH_CA 0x01 /* certification authority */
+#define AUTH_AA 0x02 /* authorization authority */
+#define AUTH_OCSP 0x04 /* ocsp signing authority */
/* CA info structures */
typedef struct ca_info ca_info_t;
struct ca_info {
- ca_info_t *next;
- char *name;
- time_t installed;
- chunk_t authName;
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- char *ldaphost;
- char *ldapbase;
- char *ocspuri;
- generalName_t *crluri;
- bool strictcrlpolicy;
+ ca_info_t *next;
+ char *name;
+ time_t installed;
+ chunk_t authName;
+ chunk_t authKeyID;
+ chunk_t authKeySerialNumber;
+ char *ldaphost;
+ char *ldapbase;
+ char *ocspuri;
+ generalName_t *crluri;
+ bool strictcrlpolicy;
};
extern bool trusted_ca(chunk_t a, chunk_t b, int *pathlen);
extern bool match_requested_ca(generalName_t *requested_ca
- , chunk_t our_ca, int *our_pathlen);
+ , chunk_t our_ca, int *our_pathlen);
extern x509cert_t* get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid
- , u_char auth_flags);
+ , u_char auth_flags);
extern void load_authcerts(const char *type, const char *path
- , u_char auth_flags);
+ , u_char auth_flags);
extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags);
extern void free_authcerts(void);
extern void list_authcerts(const char *caption, u_char auth_flags, bool utc);
extern bool trust_authcert_candidate(const x509cert_t *cert
- , const x509cert_t *alt_chain);
+ , const x509cert_t *alt_chain);
extern ca_info_t* get_ca_info(chunk_t name, chunk_t serial, chunk_t keyid);
extern bool find_ca_info_by_name(const char *name, bool delete);
extern void add_ca_info(const whack_message_t *msg);
diff --git a/src/pluto/certs.c b/src/pluto/certs.c
index 43976a913..ca3019b9b 100644
--- a/src/pluto/certs.c
+++ b/src/pluto/certs.c
@@ -1,5 +1,7 @@
/* Certificate support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +12,6 @@
* 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: certs.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdlib.h>
@@ -19,241 +19,251 @@
#include <string.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include "library.h"
+#include "asn1/asn1.h"
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "asn1.h"
#include "id.h"
-#include "x509.h"
-#include "pgp.h"
#include "pem.h"
#include "certs.h"
-#include "pkcs1.h"
-/*
+/**
* used for initializatin of certs
*/
-const cert_t empty_cert = {CERT_NONE, {NULL}};
+const cert_t cert_empty = {CERT_NONE, {NULL}};
-/*
+/**
* extracts the certificate to be sent to the peer
*/
-chunk_t
-get_mycert(cert_t cert)
+chunk_t cert_get_encoding(cert_t cert)
{
- switch (cert.type)
- {
- case CERT_PGP:
- return cert.u.pgp->certificate;
- case CERT_X509_SIGNATURE:
- return cert.u.x509->certificate;
- default:
- return empty_chunk;
- }
+ switch (cert.type)
+ {
+ case CERT_PGP:
+ return cert.u.pgp->certificate;
+ case CERT_X509_SIGNATURE:
+ return cert.u.x509->certificate;
+ default:
+ return chunk_empty;
+ }
+}
+
+public_key_t* cert_get_public_key(const cert_t cert)
+{
+ switch (cert.type)
+ {
+ case CERT_PGP:
+ return cert.u.pgp->public_key;
+ break;
+ case CERT_X509_SIGNATURE:
+ return cert.u.x509->public_key;
+ break;
+ default:
+ return NULL;
+ }
}
/* load a coded key or certificate file with autodetection
* of binary DER or base64 PEM ASN.1 formats and armored PGP format
*/
-bool
-load_coded_file(const char *filename, prompt_pass_t *pass, const char *type
-, chunk_t *blob, bool *pgp)
+bool load_coded_file(char *filename, prompt_pass_t *pass, const char *type,
+ chunk_t *blob, bool *pgp)
{
- err_t ugh = NULL;
+ err_t ugh = NULL;
+
+ FILE *fd = fopen(filename, "r");
- FILE *fd = fopen(filename, "r");
+ if (fd)
+ {
+ int bytes;
+ fseek(fd, 0, SEEK_END );
+ blob->len = ftell(fd);
+ rewind(fd);
+ blob->ptr = malloc(blob->len);
+ bytes = fread(blob->ptr, 1, blob->len, fd);
+ fclose(fd);
+ plog(" loaded %s file '%s' (%d bytes)", type, filename, bytes);
- if (fd)
- {
- int bytes;
- fseek(fd, 0, SEEK_END );
- blob->len = ftell(fd);
- rewind(fd);
- blob->ptr = alloc_bytes(blob->len, type);
- bytes = fread(blob->ptr, 1, blob->len, fd);
- fclose(fd);
- plog(" loaded %s file '%s' (%d bytes)", type, filename, bytes);
+ *pgp = FALSE;
- *pgp = FALSE;
+ /* try DER format */
+ if (is_asn1(*blob))
+ {
+ DBG(DBG_PARSING,
+ DBG_log(" file coded in DER format");
+ )
+ return TRUE;
+ }
- /* try DER format */
- if (is_asn1(*blob))
- {
- DBG(DBG_PARSING,
- DBG_log(" file coded in DER format");
- )
- return TRUE;
- }
+ /* try PEM format */
+ ugh = pemtobin(blob, pass, filename, pgp);
- /* try PEM format */
- ugh = pemtobin(blob, pass, filename, pgp);
+ if (ugh == NULL)
+ {
+ if (*pgp)
+ {
+ DBG(DBG_PARSING,
+ DBG_log(" file coded in armored PGP format");
+ )
+ return TRUE;
+ }
+ if (is_asn1(*blob))
+ {
+ DBG(DBG_PARSING,
+ DBG_log(" file coded in PEM format");
+ )
+ return TRUE;
+ }
+ ugh = "file coded in unknown format, discarded";
+ }
- if (ugh == NULL)
+ /* a conversion error has occured */
+ plog(" %s", ugh);
+ free(blob->ptr);
+ *blob = chunk_empty;
+ }
+ else
{
- if (*pgp)
- {
- DBG(DBG_PARSING,
- DBG_log(" file coded in armored PGP format");
- )
- return TRUE;
- }
- if (is_asn1(*blob))
- {
- DBG(DBG_PARSING,
- DBG_log(" file coded in PEM format");
- )
- return TRUE;
- }
- ugh = "file coded in unknown format, discarded";
+ plog(" could not open %s file '%s'", type, filename);
}
-
- /* a conversion error has occured */
- plog(" %s", ugh);
- pfree(blob->ptr);
- *blob = empty_chunk;
- }
- else
- {
- plog(" could not open %s file '%s'", type, filename);
- }
- return FALSE;
+ return FALSE;
}
-/*
- * Loads a PKCS#1 or PGP private RSA key file
+/**
+ * Loads a PKCS#1 or PGP privatekey file
*/
-err_t
-load_rsa_private_key(const char* filename, prompt_pass_t *pass
-, RSA_private_key_t *key)
+private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
+ key_type_t type)
{
- err_t ugh = NULL;
- bool pgp = FALSE;
- chunk_t blob = empty_chunk;
+ private_key_t *key = NULL;
+ chunk_t blob = chunk_empty;
+ bool pgp = FALSE;
- const char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
+ char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
- if (load_coded_file(path, pass, "private key", &blob, &pgp))
- {
- if (pgp)
+ if (load_coded_file(path, pass, "private key", &blob, &pgp))
{
- if (!parse_pgp(blob, NULL, key))
- ugh = "syntax error in PGP private key file";
+ if (pgp)
+ {
+ parse_pgp(blob, NULL, &key);
+ }
+ else
+ {
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_BLOB_ASN1_DER, blob, BUILD_END);
+ }
+ if (key == NULL)
+ {
+ plog(" syntax error in %s private key file", pgp ? "PGP":"PKCS#");
+ }
+ free(blob.ptr);
}
else
{
- if (!pkcs1_parse_private_key(blob, key))
- ugh = "syntax error in PKCS#1 private key file";
+ plog(" error loading private key file");
}
- pfree(blob.ptr);
- }
- else
- ugh = "error loading RSA private key file";
-
- return ugh;
+ return key;
}
-/*
+
+/**
* Loads a X.509 or OpenPGP certificate
*/
-bool
-load_cert(const char *filename, const char *label, cert_t *cert)
+bool load_cert(char *filename, const char *label, cert_t *cert)
{
- bool pgp = FALSE;
- chunk_t blob = empty_chunk;
+ bool pgp = FALSE;
+ chunk_t blob = chunk_empty;
- /* initialize cert struct */
- cert->type = CERT_NONE;
- cert->u.x509 = NULL;
+ /* initialize cert struct */
+ cert->type = CERT_NONE;
+ cert->u.x509 = NULL;
- if (load_coded_file(filename, NULL, label, &blob, &pgp))
- {
- if (pgp)
- {
- pgpcert_t *pgpcert = alloc_thing(pgpcert_t, "pgpcert");
- *pgpcert = empty_pgpcert;
- if (parse_pgp(blob, pgpcert, NULL))
- {
- cert->type = CERT_PGP;
- cert->u.pgp = pgpcert;
- return TRUE;
- }
- else
- {
- plog(" error in OpenPGP certificate");
- free_pgpcert(pgpcert);
- return FALSE;
- }
- }
- else
+ if (load_coded_file(filename, NULL, label, &blob, &pgp))
{
- x509cert_t *x509cert = alloc_thing(x509cert_t, "x509cert");
- *x509cert = empty_x509cert;
- if (parse_x509cert(blob, 0, x509cert))
- {
- cert->type = CERT_X509_SIGNATURE;
- cert->u.x509 = x509cert;
- return TRUE;
- }
- else
- {
- plog(" error in X.509 certificate");
- free_x509cert(x509cert);
- return FALSE;
- }
+ if (pgp)
+ {
+ pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
+ *pgpcert = pgpcert_empty;
+ if (parse_pgp(blob, pgpcert, NULL))
+ {
+ cert->type = CERT_PGP;
+ cert->u.pgp = pgpcert;
+ return TRUE;
+ }
+ else
+ {
+ plog(" error in OpenPGP certificate");
+ free_pgpcert(pgpcert);
+ return FALSE;
+ }
+ }
+ else
+ {
+ x509cert_t *x509cert = malloc_thing(x509cert_t);
+ *x509cert = empty_x509cert;
+ if (parse_x509cert(blob, 0, x509cert))
+ {
+ cert->type = CERT_X509_SIGNATURE;
+ cert->u.x509 = x509cert;
+ return TRUE;
+ }
+ else
+ {
+ plog(" error in X.509 certificate");
+ free_x509cert(x509cert);
+ return FALSE;
+ }
+ }
}
- }
- return FALSE;
+ return FALSE;
}
-/*
+/**
* Loads a host certificate
*/
-bool
-load_host_cert(const char *filename, cert_t *cert)
+bool load_host_cert(char *filename, cert_t *cert)
{
- const char *path = concatenate_paths(HOST_CERT_PATH, filename);
+ char *path = concatenate_paths(HOST_CERT_PATH, filename);
- return load_cert(path, "host cert", cert);
+ return load_cert(path, "host cert", cert);
}
-/*
+/**
* Loads a CA certificate
*/
-bool
-load_ca_cert(const char *filename, cert_t *cert)
+bool load_ca_cert(char *filename, cert_t *cert)
{
- const char *path = concatenate_paths(CA_CERT_PATH, filename);
+ char *path = concatenate_paths(CA_CERT_PATH, filename);
- return load_cert(path, "CA cert", cert);
+ return load_cert(path, "CA cert", cert);
}
-/*
+/**
* establish equality of two certificates
*/
-bool
-same_cert(const cert_t *a, const cert_t *b)
+bool same_cert(const cert_t *a, const cert_t *b)
{
- return a->type == b->type && a->u.x509 == b->u.x509;
+ return a->type == b->type && a->u.x509 == b->u.x509;
}
-/* for each link pointing to the certif icate
- " increase the count by one
+/**
+ * for each link pointing to the certificate increase the count by one
*/
-void
-share_cert(cert_t cert)
+void share_cert(cert_t cert)
{
- switch (cert.type)
- {
- case CERT_PGP:
- share_pgpcert(cert.u.pgp);
- break;
- case CERT_X509_SIGNATURE:
- share_x509cert(cert.u.x509);
- break;
- default:
- break;
- }
+ switch (cert.type)
+ {
+ case CERT_PGP:
+ share_pgpcert(cert.u.pgp);
+ break;
+ case CERT_X509_SIGNATURE:
+ share_x509cert(cert.u.x509);
+ break;
+ default:
+ break;
+ }
}
/* release of a certificate decreases the count by one
@@ -263,16 +273,16 @@ void
release_cert(cert_t cert)
{
switch (cert.type)
- {
- case CERT_PGP:
- release_pgpcert(cert.u.pgp);
- break;
- case CERT_X509_SIGNATURE:
- release_x509cert(cert.u.x509);
- break;
- default:
- break;
- }
+ {
+ case CERT_PGP:
+ release_pgpcert(cert.u.pgp);
+ break;
+ case CERT_X509_SIGNATURE:
+ release_x509cert(cert.u.x509);
+ break;
+ default:
+ break;
+ }
}
/*
@@ -281,7 +291,7 @@ release_cert(cert_t cert)
void
list_certs(bool utc)
{
- list_x509_end_certs(utc);
- list_pgp_end_certs(utc);
+ list_x509_end_certs(utc);
+ list_pgp_end_certs(utc);
}
diff --git a/src/pluto/certs.h b/src/pluto/certs.h
index b71c53e15..0810c52fa 100644
--- a/src/pluto/certs.h
+++ b/src/pluto/certs.h
@@ -1,5 +1,7 @@
/* Certificate support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,66 +12,65 @@
* 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: certs.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _CERTS_H
#define _CERTS_H
-#include "pkcs1.h"
+#include <credentials/keys/private_key.h>
+
#include "x509.h"
-#include "pgp.h"
+#include "pgpcert.h"
/* path definitions for private keys, end certs,
* cacerts, attribute certs and crls
*/
#define PRIVATE_KEY_PATH IPSEC_CONFDIR "/ipsec.d/private"
#define HOST_CERT_PATH IPSEC_CONFDIR "/ipsec.d/certs"
-#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts"
-#define A_CERT_PATH IPSEC_CONFDIR "/ipsec.d/acerts"
-#define AA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/aacerts"
-#define OCSP_CERT_PATH IPSEC_CONFDIR "/ipsec.d/ocspcerts"
-#define CRL_PATH IPSEC_CONFDIR "/ipsec.d/crls"
-#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs"
+#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts"
+#define A_CERT_PATH IPSEC_CONFDIR "/ipsec.d/acerts"
+#define AA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/aacerts"
+#define OCSP_CERT_PATH IPSEC_CONFDIR "/ipsec.d/ocspcerts"
+#define CRL_PATH IPSEC_CONFDIR "/ipsec.d/crls"
+#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs"
/* advance warning of imminent expiry of
* cacerts, public keys, and crls
*/
-#define CA_CERT_WARNING_INTERVAL 30 /* days */
-#define OCSP_CERT_WARNING_INTERVAL 30 /* days */
-#define PUBKEY_WARNING_INTERVAL 7 /* days */
-#define CRL_WARNING_INTERVAL 7 /* days */
-#define ACERT_WARNING_INTERVAL 1 /* day */
+#define CA_CERT_WARNING_INTERVAL 30 /* days */
+#define OCSP_CERT_WARNING_INTERVAL 30 /* days */
+#define PUBKEY_WARNING_INTERVAL 7 /* days */
+#define CRL_WARNING_INTERVAL 7 /* days */
+#define ACERT_WARNING_INTERVAL 1 /* day */
/* certificate access structure
* currently X.509 and OpenPGP certificates are supported
*/
typedef struct {
- u_char type;
- union {
- x509cert_t *x509;
- pgpcert_t *pgp;
- } u;
+ u_char type;
+ union {
+ x509cert_t *x509;
+ pgpcert_t *pgp;
+ } u;
} cert_t;
/* used for initialization */
-extern const cert_t empty_cert;
+extern const cert_t cert_empty;
/* do not send certificate requests
* flag set in plutomain.c and used in ipsec_doi.c
*/
extern bool no_cr_send;
-extern err_t load_rsa_private_key(const char* filename, prompt_pass_t *pass
- , RSA_private_key_t *key);
-extern chunk_t get_mycert(cert_t cert);
-extern bool load_coded_file(const char *filename, prompt_pass_t *pass
- , const char *type, chunk_t *blob, bool *pgp);
-extern bool load_cert(const char *filename, const char *label
- , cert_t *cert);
-extern bool load_host_cert(const char *filename, cert_t *cert);
-extern bool load_ca_cert(const char *filename, cert_t *cert);
+extern public_key_t* cert_get_public_key(const cert_t cert);
+extern chunk_t cert_get_encoding(cert_t cert);
+extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
+ key_type_t type);
+extern bool load_coded_file(char *filename, prompt_pass_t *pass,
+ const char *type, chunk_t *blob, bool *pgp);
+extern bool load_cert(char *filename, const char *label, cert_t *cert);
+extern bool load_host_cert(char *filename, cert_t *cert);
+extern bool load_ca_cert(char *filename, cert_t *cert);
extern bool same_cert(const cert_t *a, const cert_t *b);
extern void share_cert(cert_t cert);
extern void release_cert(cert_t cert);
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
index cd118cb34..4deb722f7 100644
--- a/src/pluto/connections.c
+++ b/src/pluto/connections.c
@@ -10,8 +10,6 @@
* 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: connections.c 4924 2009-03-10 21:13:18Z andreas $
*/
#include <string.h>
@@ -25,20 +23,21 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "kameipsec.h"
+#include <credentials/keys/private_key.h>
+
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "x509.h"
#include "ca.h"
#include "crl.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "ac.h"
#include "smartcard.h"
@@ -48,13 +47,13 @@
#include "demux.h"
#include "state.h"
#include "timer.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "server.h"
#include "kernel.h"
#include "log.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "whack.h"
#include "alg_info.h"
#include "ike_alg.h"
@@ -62,7 +61,7 @@
#include "nat_traversal.h"
#include "virtual.h"
-static void flush_pending_by_connection(struct connection *c); /* forward */
+static void flush_pending_by_connection(struct connection *c); /* forward */
static struct connection *connections = NULL;
@@ -77,14 +76,14 @@ static struct connection *connections = NULL;
*/
struct host_pair {
- struct {
- ip_address addr;
- u_int16_t port; /* host order */
- } me, him;
- bool initial_connection_sent;
- struct connection *connections; /* connections with this pair */
- struct pending *pending; /* awaiting Keying Channel */
- struct host_pair *next;
+ struct {
+ ip_address addr;
+ u_int16_t port; /* host order */
+ } me, him;
+ bool initial_connection_sent;
+ struct connection *connections; /* connections with this pair */
+ struct pending *pending; /* awaiting Keying Channel */
+ struct host_pair *next;
};
static struct host_pair *host_pairs = NULL;
@@ -96,45 +95,45 @@ bool
same_peer_ids(const struct connection *c, const struct connection *d
, const struct id *his_id)
{
- return same_id(&c->spd.this.id, &d->spd.this.id)
- && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);
+ return same_id(&c->spd.this.id, &d->spd.this.id)
+ && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);
}
static struct host_pair *
find_host_pair(const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport)
{
- struct host_pair *p, *prev;
-
- /* default hisaddr to an appropriate any */
- if (hisaddr == NULL)
- hisaddr = aftoinfo(addrtypeof(myaddr))->any;
-
- if (nat_traversal_enabled)
- {
- /**
- * port is not relevant in host_pair. with nat_traversal we
- * always use pluto_port (500)
- */
- myport = pluto_port;
- hisport = pluto_port;
- }
-
- for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)
- {
- if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
- && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
+ struct host_pair *p, *prev;
+
+ /* default hisaddr to an appropriate any */
+ if (hisaddr == NULL)
+ hisaddr = aftoinfo(addrtypeof(myaddr))->any;
+
+ if (nat_traversal_enabled)
{
- if (prev != NULL)
- {
- prev->next = p->next; /* remove p from list */
- p->next = host_pairs; /* and stick it on front */
- host_pairs = p;
- }
- break;
+ /**
+ * port is not relevant in host_pair. with nat_traversal we
+ * always use pluto_port (500)
+ */
+ myport = pluto_port;
+ hisport = pluto_port;
}
- }
- return p;
+
+ for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)
+ {
+ if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
+ && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
+ {
+ if (prev != NULL)
+ {
+ prev->next = p->next; /* remove p from list */
+ p->next = host_pairs; /* and stick it on front */
+ host_pairs = p;
+ }
+ break;
+ }
+ }
+ return p;
}
/* find head of list of connections with this pair of hosts */
@@ -142,63 +141,63 @@ static struct connection *
find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport)
{
- struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
-
- if (nat_traversal_enabled && hp && hisaddr)
- {
- struct connection *c;
+ struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
- for (c = hp->connections; c != NULL; c = c->hp_next)
+ if (nat_traversal_enabled && hp && hisaddr)
{
- if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport)
- return c;
+ struct connection *c;
+
+ for (c = hp->connections; c != NULL; c = c->hp_next)
+ {
+ if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport)
+ return c;
+ }
+ return NULL;
}
- return NULL;
- }
- return hp == NULL? NULL : hp->connections;
+ return hp == NULL? NULL : hp->connections;
}
static void
connect_to_host_pair(struct connection *c)
{
- if (oriented(*c))
- {
- struct host_pair *hp;
+ if (oriented(*c))
+ {
+ struct host_pair *hp;
- ip_address his_addr = (c->spd.that.allow_any)
- ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any
- : c->spd.that.host_addr;
+ ip_address his_addr = (c->spd.that.allow_any)
+ ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any
+ : c->spd.that.host_addr;
- hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port
- , &his_addr, c->spd.that.host_port);
+ hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port
+ , &his_addr, c->spd.that.host_port);
- if (hp == NULL)
+ if (hp == NULL)
+ {
+ /* no suitable host_pair -- build one */
+ hp = malloc_thing(struct host_pair);
+ hp->me.addr = c->spd.this.host_addr;
+ hp->him.addr = his_addr;
+ hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port;
+ hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port;
+ hp->initial_connection_sent = FALSE;
+ hp->connections = NULL;
+ hp->pending = NULL;
+ hp->next = host_pairs;
+ host_pairs = hp;
+ }
+ c->host_pair = hp;
+ c->hp_next = hp->connections;
+ hp->connections = c;
+ }
+ else
{
- /* no suitable host_pair -- build one */
- hp = alloc_thing(struct host_pair, "host_pair");
- hp->me.addr = c->spd.this.host_addr;
- hp->him.addr = his_addr;
- hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port;
- hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port;
- hp->initial_connection_sent = FALSE;
- hp->connections = NULL;
- hp->pending = NULL;
- hp->next = host_pairs;
- host_pairs = hp;
+ /* since this connection isn't oriented, we place it
+ * in the unoriented_connections list instead.
+ */
+ c->host_pair = NULL;
+ c->hp_next = unoriented_connections;
+ unoriented_connections = c;
}
- c->host_pair = hp;
- c->hp_next = hp->connections;
- hp->connections = c;
- }
- else
- {
- /* since this connection isn't oriented, we place it
- * in the unoriented_connections list instead.
- */
- c->host_pair = NULL;
- c->hp_next = unoriented_connections;
- unoriented_connections = c;
- }
}
/* find a connection by name.
@@ -209,317 +208,317 @@ connect_to_host_pair(struct connection *c)
struct connection *
con_by_name(const char *nm, bool strict)
{
- struct connection *p, *prev;
+ struct connection *p, *prev;
- for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
- {
- if (p == NULL)
+ for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
{
- if (strict)
- whack_log(RC_UNKNOWN_NAME
- , "no connection named \"%s\"", nm);
- break;
- }
- if (streq(p->name, nm)
- && (!strict || p->kind != CK_INSTANCE))
- {
- if (prev != NULL)
- {
- prev->ac_next = p->ac_next; /* remove p from list */
- p->ac_next = connections; /* and stick it on front */
- connections = p;
- }
- break;
+ if (p == NULL)
+ {
+ if (strict)
+ whack_log(RC_UNKNOWN_NAME
+ , "no connection named \"%s\"", nm);
+ break;
+ }
+ if (streq(p->name, nm)
+ && (!strict || p->kind != CK_INSTANCE))
+ {
+ if (prev != NULL)
+ {
+ prev->ac_next = p->ac_next; /* remove p from list */
+ p->ac_next = connections; /* and stick it on front */
+ connections = p;
+ }
+ break;
+ }
}
- }
- return p;
+ return p;
}
void
release_connection(struct connection *c, bool relations)
{
- if (c->kind == CK_INSTANCE)
- {
- /* This does everything we need.
- * Note that we will be called recursively by delete_connection,
- * but kind will be CK_GOING_AWAY.
- */
- delete_connection(c, relations);
- }
- else
- {
- flush_pending_by_connection(c);
- delete_states_by_connection(c, relations);
- unroute_connection(c);
- }
+ if (c->kind == CK_INSTANCE)
+ {
+ /* This does everything we need.
+ * Note that we will be called recursively by delete_connection,
+ * but kind will be CK_GOING_AWAY.
+ */
+ delete_connection(c, relations);
+ }
+ else
+ {
+ flush_pending_by_connection(c);
+ delete_states_by_connection(c, relations);
+ unroute_connection(c);
+ }
}
/* Delete a connection */
#define list_rm(etype, enext, e, ehead) { \
- etype **ep; \
- for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \
- passert(*ep != NULL); /* we must not come up empty-handed */ \
- *ep = (e)->enext; \
- }
+ etype **ep; \
+ for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \
+ passert(*ep != NULL); /* we must not come up empty-handed */ \
+ *ep = (e)->enext; \
+ }
void
delete_connection(struct connection *c, bool relations)
{
- struct connection *old_cur_connection
- = cur_connection == c? NULL : cur_connection;
+ struct connection *old_cur_connection
+ = cur_connection == c? NULL : cur_connection;
#ifdef DEBUG
- lset_t old_cur_debugging = cur_debugging;
+ lset_t old_cur_debugging = cur_debugging;
#endif
- set_cur_connection(c);
-
- /* Must be careful to avoid circularity:
- * we mark c as going away so it won't get deleted recursively.
- */
- passert(c->kind != CK_GOING_AWAY);
- if (c->kind == CK_INSTANCE)
- {
- plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}"
- , c->name
- , ip_str(&c->spd.that.host_addr)
- , c->newest_isakmp_sa, c->newest_ipsec_sa);
- c->kind = CK_GOING_AWAY;
- }
- else
- {
- plog("deleting connection");
- }
- release_connection(c, relations); /* won't delete c */
-
- if (c->kind == CK_GROUP)
- delete_group(c);
-
- /* free up any logging resources */
- perpeer_logfree(c);
-
- /* find and delete c from connections list */
- list_rm(struct connection, ac_next, c, connections);
- cur_connection = old_cur_connection;
-
- /* find and delete c from the host pair list */
- if (c->host_pair == NULL)
- {
- if (c->ikev1)
- list_rm(struct connection, hp_next, c, unoriented_connections);
- }
- else
- {
- struct host_pair *hp = c->host_pair;
-
- list_rm(struct connection, hp_next, c, hp->connections);
- c->host_pair = NULL; /* redundant, but safe */
-
- /* if there are no more connections with this host_pair
- * and we haven't even made an initial contact, let's delete
- * this guy in case we were created by an attempted DOS attack.
+ set_cur_connection(c);
+
+ /* Must be careful to avoid circularity:
+ * we mark c as going away so it won't get deleted recursively.
*/
- if (hp->connections == NULL
- && !hp->initial_connection_sent)
+ passert(c->kind != CK_GOING_AWAY);
+ if (c->kind == CK_INSTANCE)
+ {
+ plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}"
+ , c->name
+ , ip_str(&c->spd.that.host_addr)
+ , c->newest_isakmp_sa, c->newest_ipsec_sa);
+ c->kind = CK_GOING_AWAY;
+ }
+ else
+ {
+ plog("deleting connection");
+ }
+ release_connection(c, relations); /* won't delete c */
+
+ if (c->kind == CK_GROUP)
+ delete_group(c);
+
+ /* free up any logging resources */
+ perpeer_logfree(c);
+
+ /* find and delete c from connections list */
+ list_rm(struct connection, ac_next, c, connections);
+ cur_connection = old_cur_connection;
+
+ /* find and delete c from the host pair list */
+ if (c->host_pair == NULL)
{
- passert(hp->pending == NULL); /* ??? must deal with this! */
- list_rm(struct host_pair, next, hp, host_pairs);
- pfree(hp);
+ if (c->ikev1)
+ list_rm(struct connection, hp_next, c, unoriented_connections);
}
- }
+ else
+ {
+ struct host_pair *hp = c->host_pair;
- if (c->kind != CK_GOING_AWAY)
- pfreeany(c->spd.that.virt);
+ list_rm(struct connection, hp_next, c, hp->connections);
+ c->host_pair = NULL; /* redundant, but safe */
+ /* if there are no more connections with this host_pair
+ * and we haven't even made an initial contact, let's delete
+ * this guy in case we were created by an attempted DOS attack.
+ */
+ if (hp->connections == NULL
+ && !hp->initial_connection_sent)
+ {
+ passert(hp->pending == NULL); /* ??? must deal with this! */
+ list_rm(struct host_pair, next, hp, host_pairs);
+ free(hp);
+ }
+ }
+ if (c->kind != CK_GOING_AWAY)
+ {
+ free(c->spd.that.virt);
+ }
#ifdef DEBUG
- cur_debugging = old_cur_debugging;
+ cur_debugging = old_cur_debugging;
#endif
- pfreeany(c->name);
- free_id_content(&c->spd.this.id);
- pfreeany(c->spd.this.updown);
- freeanychunk(c->spd.this.ca);
- free_ietfAttrList(c->spd.this.groups);
- free_id_content(&c->spd.that.id);
- pfreeany(c->spd.that.updown);
- freeanychunk(c->spd.that.ca);
- free_ietfAttrList(c->spd.that.groups);
- free_generalNames(c->requested_ca, TRUE);
- gw_delref(&c->gw_info);
-
- lock_certs_and_keys("delete_connection");
- release_cert(c->spd.this.cert);
- scx_release(c->spd.this.sc);
- release_cert(c->spd.that.cert);
- scx_release(c->spd.that.sc);
- unlock_certs_and_keys("delete_connection");
-
- alg_info_delref((struct alg_info **)&c->alg_info_esp);
- alg_info_delref((struct alg_info **)&c->alg_info_ike);
-
- pfree(c);
+ free(c->name);
+ free_id_content(&c->spd.this.id);
+ free(c->spd.this.updown);
+ free(c->spd.this.ca.ptr);
+ free_ietfAttrList(c->spd.this.groups);
+ free_id_content(&c->spd.that.id);
+ free(c->spd.that.updown);
+ free(c->spd.that.ca.ptr);
+ free_ietfAttrList(c->spd.that.groups);
+ free_generalNames(c->requested_ca, TRUE);
+ gw_delref(&c->gw_info);
+
+ lock_certs_and_keys("delete_connection");
+ release_cert(c->spd.this.cert);
+ scx_release(c->spd.this.sc);
+ release_cert(c->spd.that.cert);
+ scx_release(c->spd.that.sc);
+ unlock_certs_and_keys("delete_connection");
+
+ alg_info_delref((struct alg_info **)&c->alg_info_esp);
+ alg_info_delref((struct alg_info **)&c->alg_info_ike);
+
+ free(c);
}
/* Delete connections with the specified name */
void
delete_connections_by_name(const char *name, bool strict)
{
- struct connection *c = con_by_name(name, strict);
+ struct connection *c = con_by_name(name, strict);
- for (; c != NULL; c = con_by_name(name, FALSE))
- delete_connection(c, FALSE);
+ for (; c != NULL; c = con_by_name(name, FALSE))
+ delete_connection(c, FALSE);
}
void
delete_every_connection(void)
{
- while (connections != NULL)
- delete_connection(connections, TRUE);
+ while (connections != NULL)
+ delete_connection(connections, TRUE);
}
void
release_dead_interfaces(void)
{
- struct host_pair *hp;
-
- for (hp = host_pairs; hp != NULL; hp = hp->next)
- {
- struct connection **pp
- , *p;
+ struct host_pair *hp;
- for (pp = &hp->connections; (p = *pp) != NULL; )
+ for (hp = host_pairs; hp != NULL; hp = hp->next)
{
- if (p->interface->change == IFN_DELETE)
- {
- /* this connection's interface is going away */
- enum connection_kind k = p->kind;
-
- release_connection(p, TRUE);
-
- if (k <= CK_PERMANENT)
- {
- /* The connection should have survived release:
- * move it to the unoriented_connections list.
- */
- passert(p == *pp);
-
- p->interface = NULL;
+ struct connection **pp
+ , *p;
- *pp = p->hp_next; /* advance *pp */
- p->host_pair = NULL;
- p->hp_next = unoriented_connections;
- unoriented_connections = p;
- }
- else
+ for (pp = &hp->connections; (p = *pp) != NULL; )
{
- /* The connection should have vanished,
- * but the previous connection remains.
- */
- passert(p != *pp);
+ if (p->interface->change == IFN_DELETE)
+ {
+ /* this connection's interface is going away */
+ enum connection_kind k = p->kind;
+
+ release_connection(p, TRUE);
+
+ if (k <= CK_PERMANENT)
+ {
+ /* The connection should have survived release:
+ * move it to the unoriented_connections list.
+ */
+ passert(p == *pp);
+
+ p->interface = NULL;
+
+ *pp = p->hp_next; /* advance *pp */
+ p->host_pair = NULL;
+ p->hp_next = unoriented_connections;
+ unoriented_connections = p;
+ }
+ else
+ {
+ /* The connection should have vanished,
+ * but the previous connection remains.
+ */
+ passert(p != *pp);
+ }
+ }
+ else
+ {
+ pp = &p->hp_next; /* advance pp */
+ }
}
- }
- else
- {
- pp = &p->hp_next; /* advance pp */
- }
}
- }
}
/* adjust orientations of connections to reflect newly added interfaces */
void
check_orientations(void)
{
- /* try to orient all the unoriented connections */
- {
- struct connection *c = unoriented_connections;
+ /* try to orient all the unoriented connections */
+ {
+ struct connection *c = unoriented_connections;
- unoriented_connections = NULL;
+ unoriented_connections = NULL;
- while (c != NULL)
- {
- struct connection *nxt = c->hp_next;
+ while (c != NULL)
+ {
+ struct connection *nxt = c->hp_next;
- (void)orient(c);
- connect_to_host_pair(c);
- c = nxt;
+ (void)orient(c);
+ connect_to_host_pair(c);
+ c = nxt;
+ }
}
- }
- /* Check that no oriented connection has become double-oriented.
- * In other words, the far side must not match one of our new interfaces.
- */
- {
- struct iface *i;
-
- for (i = interfaces; i != NULL; i = i->next)
+ /* Check that no oriented connection has become double-oriented.
+ * In other words, the far side must not match one of our new interfaces.
+ */
{
- if (i->change == IFN_ADD)
- {
- struct host_pair *hp;
+ struct iface *i;
- for (hp = host_pairs; hp != NULL; hp = hp->next)
+ for (i = interfaces; i != NULL; i = i->next)
{
- if (sameaddr(&hp->him.addr, &i->addr)
- && (!no_klips || hp->him.port == pluto_port))
- {
- /* bad news: the whole chain of connections
- * hanging off this host pair has both sides
- * matching an interface.
- * We'll get rid of them, using orient and
- * connect_to_host_pair. But we'll be lazy
- * and not ditch the host_pair itself (the
- * cost of leaving it is slight and cannot
- * be induced by a foe).
- */
- struct connection *c = hp->connections;
-
- hp->connections = NULL;
- while (c != NULL)
+ if (i->change == IFN_ADD)
{
- struct connection *nxt = c->hp_next;
-
- c->interface = NULL;
- (void)orient(c);
- connect_to_host_pair(c);
- c = nxt;
+ struct host_pair *hp;
+
+ for (hp = host_pairs; hp != NULL; hp = hp->next)
+ {
+ if (sameaddr(&hp->him.addr, &i->addr)
+ && (!no_klips || hp->him.port == pluto_port))
+ {
+ /* bad news: the whole chain of connections
+ * hanging off this host pair has both sides
+ * matching an interface.
+ * We'll get rid of them, using orient and
+ * connect_to_host_pair. But we'll be lazy
+ * and not ditch the host_pair itself (the
+ * cost of leaving it is slight and cannot
+ * be induced by a foe).
+ */
+ struct connection *c = hp->connections;
+
+ hp->connections = NULL;
+ while (c != NULL)
+ {
+ struct connection *nxt = c->hp_next;
+
+ c->interface = NULL;
+ (void)orient(c);
+ connect_to_host_pair(c);
+ c = nxt;
+ }
+ }
+ }
}
- }
}
- }
}
- }
}
static err_t
default_end(struct end *e, ip_address *dflt_nexthop)
{
- err_t ugh = NULL;
- const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr));
-
- if (afi == NULL)
- return "unknown address family in default_end";
-
- /* default ID to IP (but only if not NO_IP -- WildCard) */
- if (e->id.kind == ID_NONE && !isanyaddr(&e->host_addr))
- {
- e->id.kind = afi->id_addr;
- e->id.ip_addr = e->host_addr;
- e->has_id_wildcards = FALSE;
- }
-
- /* default nexthop to other side */
- if (isanyaddr(&e->host_nexthop))
- e->host_nexthop = *dflt_nexthop;
-
- /* default client to subnet containing only self
- * XXX This may mean that the client's address family doesn't match
- * tunnel_addr_family.
- */
- if (!e->has_client)
- ugh = addrtosubnet(&e->host_addr, &e->client);
-
- return ugh;
+ err_t ugh = NULL;
+ const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr));
+
+ if (afi == NULL)
+ return "unknown address family in default_end";
+
+ /* default ID to IP (but only if not NO_IP -- WildCard) */
+ if (e->id.kind == ID_ANY && !isanyaddr(&e->host_addr))
+ {
+ e->id.kind = afi->id_addr;
+ e->id.ip_addr = e->host_addr;
+ e->has_id_wildcards = FALSE;
+ }
+
+ /* default nexthop to other side */
+ if (isanyaddr(&e->host_nexthop))
+ e->host_nexthop = *dflt_nexthop;
+
+ /* default client to subnet containing only self
+ * XXX This may mean that the client's address family doesn't match
+ * tunnel_addr_family.
+ */
+ if (!e->has_client)
+ ugh = addrtosubnet(&e->host_addr, &e->client);
+
+ return ugh;
}
/* Format the topology of a connection end, leaving out defaults.
@@ -535,710 +534,702 @@ format_end(char *buf
, bool is_left
, lset_t policy)
{
- char client[SUBNETTOT_BUF];
- const char *client_sep = "";
- char protoport[sizeof(":255/65535")];
- const char *host = NULL;
- char host_space[ADDRTOT_BUF];
- char host_port[sizeof(":65535")];
- char host_id[BUF_LEN + 2];
- char hop[ADDRTOT_BUF];
- const char *hop_sep = "";
- const char *open_brackets = "";
- const char *close_brackets = "";
-
- if (isanyaddr(&this->host_addr))
- {
- switch (policy & (POLICY_GROUP | POLICY_OPPO))
+ char client[SUBNETTOT_BUF];
+ const char *client_sep = "";
+ char protoport[sizeof(":255/65535")];
+ const char *host = NULL;
+ char host_space[ADDRTOT_BUF];
+ char host_port[sizeof(":65535")];
+ char host_id[BUF_LEN + 2];
+ char hop[ADDRTOT_BUF];
+ const char *hop_sep = "";
+ const char *open_brackets = "";
+ const char *close_brackets = "";
+
+ if (isanyaddr(&this->host_addr))
{
- case POLICY_GROUP:
- host = "%group";
- break;
- case POLICY_OPPO:
- host = "%opportunistic";
- break;
- case POLICY_GROUP | POLICY_OPPO:
- host = "%opportunisticgroup";
- break;
- default:
- host = "%any";
- break;
+ switch (policy & (POLICY_GROUP | POLICY_OPPO))
+ {
+ case POLICY_GROUP:
+ host = "%group";
+ break;
+ case POLICY_OPPO:
+ host = "%opportunistic";
+ break;
+ case POLICY_GROUP | POLICY_OPPO:
+ host = "%opportunisticgroup";
+ break;
+ default:
+ host = "%any";
+ break;
+ }
}
- }
-
- client[0] = '\0';
-
- if (is_virtual_end(this) && isanyaddr(&this->host_addr))
- {
- host = "%virtual";
- }
-
- /* [client===] */
- if (this->has_client)
- {
- ip_address client_net, client_mask;
-
- networkof(&this->client, &client_net);
- maskof(&this->client, &client_mask);
- client_sep = "===";
-
- /* {client_subnet_wildcard} */
- if (this->has_client_wildcard)
- {
- open_brackets = "{";
- close_brackets = "}";
- }
-
- if (isanyaddr(&client_net) && isanyaddr(&client_mask)
- && (policy & (POLICY_GROUP | POLICY_OPPO)))
- client_sep = ""; /* boring case */
- else if (subnetisnone(&this->client))
- strcpy(client, "?");
+
+ client[0] = '\0';
+
+ if (is_virtual_end(this) && isanyaddr(&this->host_addr))
+ {
+ host = "%virtual";
+ }
+
+ /* [client===] */
+ if (this->has_client)
+ {
+ ip_address client_net, client_mask;
+
+ networkof(&this->client, &client_net);
+ maskof(&this->client, &client_mask);
+ client_sep = "===";
+
+ /* {client_subnet_wildcard} */
+ if (this->has_client_wildcard)
+ {
+ open_brackets = "{";
+ close_brackets = "}";
+ }
+
+ if (isanyaddr(&client_net) && isanyaddr(&client_mask)
+ && (policy & (POLICY_GROUP | POLICY_OPPO)))
+ client_sep = ""; /* boring case */
+ else if (subnetisnone(&this->client))
+ strcpy(client, "?");
+ else
+ subnettot(&this->client, 0, client, sizeof(client));
+ }
+ else if (this->modecfg && isanyaddr(&this->host_srcip))
+ {
+ /* we are mode config client */
+ client_sep = "===";
+ strcpy(client, "%modecfg");
+ }
+
+ /* host */
+ if (host == NULL)
+ {
+ addrtot(&this->host_addr, 0, host_space, sizeof(host_space));
+ host = host_space;
+ }
+
+ host_port[0] = '\0';
+ if (this->host_port != IKE_UDP_PORT)
+ snprintf(host_port, sizeof(host_port), ":%u"
+ , this->host_port);
+
+ /* payload portocol and port */
+ protoport[0] = '\0';
+ if (this->has_port_wildcard)
+ snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol);
+ else if (this->port || this->protocol)
+ snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
+ , this->port);
+
+ /* id, if different from host */
+ host_id[0] = '\0';
+ if (this->id.kind == ID_MYID)
+ {
+ strcpy(host_id, "[%myid]");
+ }
+ else if (!(this->id.kind == ID_ANY
+ || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr))))
+ {
+ int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2);
+
+ host_id[0] = '[';
+ strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]");
+ }
+
+ /* [---hop] */
+ hop[0] = '\0';
+ hop_sep = "";
+ if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr))
+ {
+ addrtot(&this->host_nexthop, 0, hop, sizeof(hop));
+ hop_sep = "---";
+ }
+
+ if (is_left)
+ snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
+ , open_brackets, client, close_brackets, client_sep
+ , this->allow_any? "%":""
+ , host, host_port, host_id, protoport
+ , hop_sep, hop);
else
- subnettot(&this->client, 0, client, sizeof(client));
- }
- else if (this->modecfg && isanyaddr(&this->host_srcip))
- {
- /* we are mode config client */
- client_sep = "===";
- strcpy(client, "%modecfg");
- }
-
- /* host */
- if (host == NULL)
- {
- addrtot(&this->host_addr, 0, host_space, sizeof(host_space));
- host = host_space;
- }
-
- host_port[0] = '\0';
- if (this->host_port != IKE_UDP_PORT)
- snprintf(host_port, sizeof(host_port), ":%u"
- , this->host_port);
-
- /* payload portocol and port */
- protoport[0] = '\0';
- if (this->has_port_wildcard)
- snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol);
- else if (this->port || this->protocol)
- snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
- , this->port);
-
- /* id, if different from host */
- host_id[0] = '\0';
- if (this->id.kind == ID_MYID)
- {
- strcpy(host_id, "[%myid]");
- }
- else if (!(this->id.kind == ID_NONE
- || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr))))
- {
- int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2);
-
- host_id[0] = '[';
- strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]");
- }
-
- /* [---hop] */
- hop[0] = '\0';
- hop_sep = "";
- if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr))
- {
- addrtot(&this->host_nexthop, 0, hop, sizeof(hop));
- hop_sep = "---";
- }
-
- if (is_left)
- snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
- , open_brackets, client, close_brackets, client_sep
- , this->allow_any? "%":""
- , host, host_port, host_id, protoport
- , hop_sep, hop);
- else
- snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
- , hop, hop_sep
- , this->allow_any? "%":""
- , host, host_port, host_id, protoport, client_sep
- , open_brackets, client, close_brackets);
- return strlen(buf);
+ snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
+ , hop, hop_sep
+ , this->allow_any? "%":""
+ , host, host_port, host_id, protoport, client_sep
+ , open_brackets, client, close_brackets);
+ return strlen(buf);
}
/* format topology of a connection.
* Two symmetric ends separated by ...
*/
-#define CONNECTION_BUF (2 * (END_BUF - 1) + 4)
+#define CONNECTION_BUF (2 * (END_BUF - 1) + 4)
static size_t
format_connection(char *buf, size_t buf_len
- , const struct connection *c
- , struct spd_route *sr)
+ , const struct connection *c
+ , struct spd_route *sr)
{
- size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
+ size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
- w += snprintf(buf + w, buf_len - w, "...");
- return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
+ w += snprintf(buf + w, buf_len - w, "...");
+ return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
}
static void
unshare_connection_strings(struct connection *c)
{
- c->name = clone_str(c->name, "connection name");
-
- unshare_id_content(&c->spd.this.id);
- c->spd.this.updown = clone_str(c->spd.this.updown, "updown");
- scx_share(c->spd.this.sc);
- share_cert(c->spd.this.cert);
- if (c->spd.this.ca.ptr != NULL)
- clonetochunk(c->spd.this.ca, c->spd.this.ca.ptr, c->spd.this.ca.len, "ca string");
-
- unshare_id_content(&c->spd.that.id);
- c->spd.that.updown = clone_str(c->spd.that.updown, "updown");
- scx_share(c->spd.that.sc);
- share_cert(c->spd.that.cert);
- if (c->spd.that.ca.ptr != NULL)
- clonetochunk(c->spd.that.ca, c->spd.that.ca.ptr, c->spd.that.ca.len, "ca string");
-
- /* increment references to algo's */
- alg_info_addref((struct alg_info *)c->alg_info_esp);
- alg_info_addref((struct alg_info *)c->alg_info_ike);
+ c->name = clone_str(c->name);
+
+ unshare_id_content(&c->spd.this.id);
+ c->spd.this.updown = clone_str(c->spd.this.updown);
+ scx_share(c->spd.this.sc);
+ share_cert(c->spd.this.cert);
+ c->spd.this.ca = chunk_clone(c->spd.this.ca);
+
+ unshare_id_content(&c->spd.that.id);
+ c->spd.that.updown = clone_str(c->spd.that.updown);
+ scx_share(c->spd.that.sc);
+ share_cert(c->spd.that.cert);
+ c->spd.that.ca = chunk_clone(c->spd.that.ca);
+
+ /* increment references to algo's */
+ alg_info_addref((struct alg_info *)c->alg_info_esp);
+ alg_info_addref((struct alg_info *)c->alg_info_ike);
}
-static void
-load_end_certificate(const char *filename, struct end *dst)
+static void load_end_certificate(char *filename, struct end *dst)
{
- time_t valid_until;
- cert_t cert;
- bool valid_cert = FALSE;
- bool cached_cert = FALSE;
+ time_t valid_until;
+ cert_t cert;
+ bool valid_cert = FALSE;
+ bool cached_cert = FALSE;
- /* initialize end certificate */
- dst->cert.type = CERT_NONE;
- dst->cert.u.x509 = NULL;
+ /* initialize end certificate */
+ dst->cert.type = CERT_NONE;
+ dst->cert.u.x509 = NULL;
- /* initialize smartcard info record */
- dst->sc = NULL;
+ /* initialize smartcard info record */
+ dst->sc = NULL;
- if (filename != NULL)
- {
- if (scx_on_smartcard(filename))
+ if (filename != NULL)
{
- /* load cert from smartcard */
- valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert);
- }
- else
- {
- /* load cert from file */
- valid_cert = load_host_cert(filename, &cert);
+ if (scx_on_smartcard(filename))
+ {
+ /* load cert from smartcard */
+ valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert);
+ }
+ else
+ {
+ /* load cert from file */
+ valid_cert = load_host_cert(filename, &cert);
+ }
}
- }
- if (valid_cert)
- {
- err_t ugh = NULL;
-
- switch (cert.type)
+ if (valid_cert)
{
- case CERT_PGP:
- select_pgpcert_id(cert.u.pgp, &dst->id);
-
- if (cached_cert)
- dst->cert = cert;
- else
- {
- valid_until = cert.u.pgp->until;
- add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL);
- dst->cert.type = cert.type;
- dst->cert.u.pgp = add_pgpcert(cert.u.pgp);
- }
- break;
- case CERT_X509_SIGNATURE:
- select_x509cert_id(cert.u.x509, &dst->id);
-
- if (cached_cert)
- dst->cert = cert;
- else
- {
- /* check validity of cert */
- valid_until = cert.u.x509->notAfter;
- ugh = check_validity(cert.u.x509, &valid_until);
- if (ugh != NULL)
+ err_t ugh = NULL;
+
+ switch (cert.type)
{
- plog(" %s", ugh);
- free_x509cert(cert.u.x509);
- break;
- }
+ case CERT_PGP:
+ select_pgpcert_id(cert.u.pgp, &dst->id);
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
- add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL);
- dst->cert.type = cert.type;
- dst->cert.u.x509 = add_x509cert(cert.u.x509);
- }
- /* if no CA is defined, use issuer as default */
- if (dst->ca.ptr == NULL)
- dst->ca = dst->cert.u.x509->issuer;
- break;
- default:
- break;
- }
+ if (cached_cert)
+ dst->cert = cert;
+ else
+ {
+ valid_until = cert.u.pgp->until;
+ add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL);
+ dst->cert.type = cert.type;
+ dst->cert.u.pgp = add_pgpcert(cert.u.pgp);
+ }
+ break;
+ case CERT_X509_SIGNATURE:
+ select_x509cert_id(cert.u.x509, &dst->id);
- /* cache the certificate that was last retrieved from the smartcard */
- if (dst->sc != NULL)
- {
- if (!same_cert(&dst->sc->last_cert, &dst->cert))
- {
- lock_certs_and_keys("load_end_certificates");
- release_cert(dst->sc->last_cert);
- dst->sc->last_cert = dst->cert;
- share_cert(dst->cert);
- unlock_certs_and_keys("load_end_certificates");
- }
- time(&dst->sc->last_load);
+ if (cached_cert)
+ dst->cert = cert;
+ else
+ {
+ /* check validity of cert */
+ valid_until = cert.u.x509->notAfter;
+ ugh = check_validity(cert.u.x509, &valid_until);
+ if (ugh != NULL)
+ {
+ plog(" %s", ugh);
+ free_x509cert(cert.u.x509);
+ break;
+ }
+
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is valid")
+ )
+ add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL);
+ dst->cert.type = cert.type;
+ dst->cert.u.x509 = add_x509cert(cert.u.x509);
+ }
+ /* if no CA is defined, use issuer as default */
+ if (dst->ca.ptr == NULL)
+ dst->ca = dst->cert.u.x509->issuer;
+ break;
+ default:
+ break;
+ }
+
+ /* cache the certificate that was last retrieved from the smartcard */
+ if (dst->sc != NULL)
+ {
+ if (!same_cert(&dst->sc->last_cert, &dst->cert))
+ {
+ lock_certs_and_keys("load_end_certificates");
+ release_cert(dst->sc->last_cert);
+ dst->sc->last_cert = dst->cert;
+ share_cert(dst->cert);
+ unlock_certs_and_keys("load_end_certificates");
+ }
+ time(&dst->sc->last_load);
+ }
}
- }
}
static bool
extract_end(struct end *dst, const whack_end_t *src, const char *which)
{
- bool same_ca = FALSE;
-
- /* decode id, if any */
- if (src->id == NULL)
- {
- dst->id.kind = ID_NONE;
- }
- else
- {
- err_t ugh = atoid(src->id, &dst->id, TRUE);
+ bool same_ca = FALSE;
- if (ugh != NULL)
+ /* decode id, if any */
+ if (src->id == NULL)
{
- loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh);
- dst->id = empty_id; /* ignore bad one */
+ dst->id.kind = ID_ANY;
}
- }
+ else
+ {
+ err_t ugh = atoid(src->id, &dst->id, TRUE);
- dst->ca = empty_chunk;
+ if (ugh != NULL)
+ {
+ loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh);
+ dst->id = empty_id; /* ignore bad one */
+ }
+ }
+
+ dst->ca = chunk_empty;
- /* decode CA distinguished name, if any */
- if (src->ca != NULL)
- {
- if streq(src->ca, "%same")
- same_ca = TRUE;
- else if (!streq(src->ca, "%any"))
+ /* decode CA distinguished name, if any */
+ if (src->ca != NULL)
{
- err_t ugh;
-
- dst->ca.ptr = temporary_cyclic_buffer();
- ugh = atodn(src->ca, &dst->ca);
- if (ugh != NULL)
- {
- plog("bad CA string '%s': %s (ignored)", src->ca, ugh);
- dst->ca = empty_chunk;
- }
+ if streq(src->ca, "%same")
+ same_ca = TRUE;
+ else if (!streq(src->ca, "%any"))
+ {
+ err_t ugh;
+
+ dst->ca.ptr = temporary_cyclic_buffer();
+ ugh = atodn(src->ca, &dst->ca);
+ if (ugh != NULL)
+ {
+ plog("bad CA string '%s': %s (ignored)", src->ca, ugh);
+ dst->ca = chunk_empty;
+ }
+ }
}
- }
-
- /* load local end certificate and extract ID, if any */
- load_end_certificate(src->cert, dst);
-
- /* does id has wildcards? */
- dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
-
- /* decode group attributes, if any */
- decode_groups(src->groups, &dst->groups);
-
- /* the rest is simple copying of corresponding fields */
- dst->host_addr = src->host_addr;
- dst->host_nexthop = src->host_nexthop;
- dst->host_srcip = src->host_srcip;
- dst->has_natip = src->has_natip;
- dst->client = src->client;
- dst->protocol = src->protocol;
- dst->port = src->port;
- dst->has_port_wildcard = src->has_port_wildcard;
- dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand;
- dst->has_client = src->has_client;
- dst->has_client_wildcard = src->has_client_wildcard;
- dst->modecfg = src->modecfg;
- dst->hostaccess = src->hostaccess;
- dst->allow_any = src->allow_any;
- dst->sendcert = src->sendcert;
- dst->updown = src->updown;
- dst->host_port = src->host_port;
-
- /* if host sourceip is defined but no client is present
- * behind the host then set client to sourceip/32
- */
- if (addrbytesptr(&dst->host_srcip, NULL)
- && !isanyaddr(&dst->host_srcip)
- && !dst->has_natip
- && !dst->has_client)
- {
- err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
- if (ugh != NULL)
- plog("could not assign host sourceip to client subnet");
- else
- dst->has_client = TRUE;
- }
- return same_ca;
+ /* load local end certificate and extract ID, if any */
+ load_end_certificate(src->cert, dst);
+
+ /* does id has wildcards? */
+ dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
+
+ /* decode group attributes, if any */
+ decode_groups(src->groups, &dst->groups);
+
+ /* the rest is simple copying of corresponding fields */
+ dst->host_addr = src->host_addr;
+ dst->host_nexthop = src->host_nexthop;
+ dst->host_srcip = src->host_srcip;
+ dst->has_natip = src->has_natip;
+ dst->client = src->client;
+ dst->protocol = src->protocol;
+ dst->port = src->port;
+ dst->has_port_wildcard = src->has_port_wildcard;
+ dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand;
+ dst->has_client = src->has_client;
+ dst->has_client_wildcard = src->has_client_wildcard;
+ dst->modecfg = src->modecfg;
+ dst->hostaccess = src->hostaccess;
+ dst->allow_any = src->allow_any;
+ dst->sendcert = src->sendcert;
+ dst->updown = src->updown;
+ dst->host_port = src->host_port;
+
+ /* if host sourceip is defined but no client is present
+ * behind the host then set client to sourceip/32
+ */
+ if (addrbytesptr(&dst->host_srcip, NULL)
+ && !isanyaddr(&dst->host_srcip)
+ && !dst->has_natip
+ && !dst->has_client)
+ {
+ err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
+
+ if (ugh != NULL)
+ plog("could not assign host sourceip to client subnet");
+ else
+ dst->has_client = TRUE;
+ }
+ return same_ca;
}
static bool
check_connection_end(const whack_end_t *this, const whack_end_t *that
, const whack_message_t *wm)
{
- if (wm->addr_family != addrtypeof(&this->host_addr)
- || wm->addr_family != addrtypeof(&this->host_nexthop)
- || (this->has_client? wm->tunnel_addr_family : wm->addr_family)
- != subnettypeof(&this->client)
- || subnettypeof(&this->client) != subnettypeof(&that->client))
- {
- /* this should have been diagnosed by whack, so we need not be clear
- * !!! overloaded use of RC_CLASH
- */
- loglog(RC_CLASH, "address family inconsistency in connection");
- return FALSE;
- }
+ if (wm->addr_family != addrtypeof(&this->host_addr)
+ || wm->addr_family != addrtypeof(&this->host_nexthop)
+ || (this->has_client? wm->tunnel_addr_family : wm->addr_family)
+ != subnettypeof(&this->client)
+ || subnettypeof(&this->client) != subnettypeof(&that->client))
+ {
+ /* this should have been diagnosed by whack, so we need not be clear
+ * !!! overloaded use of RC_CLASH
+ */
+ loglog(RC_CLASH, "address family inconsistency in connection");
+ return FALSE;
+ }
- if (isanyaddr(&that->host_addr))
- {
- /* other side is wildcard: we must check if other conditions met */
- if (isanyaddr(&this->host_addr))
+ if (isanyaddr(&that->host_addr))
{
- loglog(RC_ORIENT, "connection must specify host IP address for our side");
- return FALSE;
+ /* other side is wildcard: we must check if other conditions met */
+ if (isanyaddr(&this->host_addr))
+ {
+ loglog(RC_ORIENT, "connection must specify host IP address for our side");
+ return FALSE;
+ }
}
- }
- if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client))
- {
- loglog(RC_CLASH,
- "virtual IP must only be used with %%any and without client");
- return FALSE;
- }
+ if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client))
+ {
+ loglog(RC_CLASH,
+ "virtual IP must only be used with %%any and without client");
+ return FALSE;
+ }
- return TRUE; /* happy */
+ return TRUE; /* happy */
}
struct connection *
find_connection_by_reqid(uint32_t reqid)
{
- struct connection *c;
+ struct connection *c;
- reqid &= ~3;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->spd.reqid == reqid)
- return c;
- }
+ reqid &= ~3;
+ for (c = connections; c != NULL; c = c->ac_next)
+ {
+ if (c->spd.reqid == reqid)
+ return c;
+ }
- return NULL;
+ return NULL;
}
static uint32_t
gen_reqid(void)
{
- uint32_t start;
- static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
-
- start = reqid;
- do {
- reqid += 4;
- if (reqid == 0)
- reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4;
- if (!find_connection_by_reqid(reqid))
- return reqid;
- } while (reqid != start);
-
- exit_log("unable to allocate reqid");
- return 0; /* never reached ... */
+ uint32_t start;
+ static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
+
+ start = reqid;
+ do {
+ reqid += 4;
+ if (reqid == 0)
+ reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4;
+ if (!find_connection_by_reqid(reqid))
+ return reqid;
+ } while (reqid != start);
+
+ exit_log("unable to allocate reqid");
+ return 0; /* never reached ... */
}
void
add_connection(const whack_message_t *wm)
{
- if (con_by_name(wm->name, FALSE) != NULL)
- {
- loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
- }
- else if (wm->right.protocol != wm->left.protocol)
- {
- /* this should haven been diagnosed by whack
- * !!! overloaded use of RC_CLASH
- */
- loglog(RC_CLASH, "the protocol must be the same for leftport and rightport");
- }
- else if (check_connection_end(&wm->right, &wm->left, wm)
- && check_connection_end(&wm->left, &wm->right, wm))
- {
- bool same_rightca, same_leftca;
- struct connection *c = alloc_thing(struct connection, "struct connection");
-
- c->name = wm->name;
- c->ikev1 = wm->ikev1;
- c->policy = wm->policy;
-
- if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp)
- loglog(RC_COMMENT
- , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP"
- , c->name);
-
- if (wm->esp)
+ if (con_by_name(wm->name, FALSE) != NULL)
{
- const char *ugh;
-
- DBG(DBG_CONTROL,
- DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")
- )
- c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "", &ugh);
-
- DBG(DBG_CRYPT|DBG_CONTROL,
- static char buf[256]="<NULL>";
-
- if (c->alg_info_esp)
- alg_info_snprint(buf, sizeof(buf)
- ,(struct alg_info *)c->alg_info_esp);
- DBG_log("esp string values: %s", buf);
- )
- if (c->alg_info_esp)
- {
- if (c->alg_info_esp->alg_info_cnt==0)
- loglog(RC_LOG_SERIOUS
- , "got 0 transforms for esp=\"%s\"", wm->esp);
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "esp string error: %s", ugh? ugh : "Unknown");
- }
+ loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
}
-
- if (wm->ike)
+ else if (wm->right.protocol != wm->left.protocol)
{
- const char *ugh;
-
- DBG(DBG_CONTROL,
- DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL")
- )
- c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "", &ugh);
-
- DBG(DBG_CRYPT|DBG_CONTROL,
- static char buf[256]="<NULL>";
-
- if (c->alg_info_ike)
- alg_info_snprint(buf, sizeof(buf)
- , (struct alg_info *)c->alg_info_ike);
- DBG_log("ike string values: %s", buf);
- )
- if (c->alg_info_ike)
- {
- if (c->alg_info_ike->alg_info_cnt==0)
- loglog(RC_LOG_SERIOUS
- , "got 0 transforms for ike=\"%s\"", wm->ike);
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "ike string error: %s", ugh? ugh : "Unknown");
- }
+ /* this should haven been diagnosed by whack
+ * !!! overloaded use of RC_CLASH
+ */
+ loglog(RC_CLASH, "the protocol must be the same for leftport and rightport");
}
-
- c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
- c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
- c->sa_rekey_margin = wm->sa_rekey_margin;
- c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
- c->sa_keying_tries = wm->sa_keying_tries;
+ else if (check_connection_end(&wm->right, &wm->left, wm)
+ && check_connection_end(&wm->left, &wm->right, wm))
+ {
+ bool same_rightca, same_leftca;
+ struct connection *c = malloc_thing(struct connection);
- /* RFC 3706 DPD */
- c->dpd_delay = wm->dpd_delay;
- c->dpd_timeout = wm->dpd_timeout;
- c->dpd_action = wm->dpd_action;
+ zero(c);
+ c->name = wm->name;
+ c->ikev1 = wm->ikev1;
+ c->policy = wm->policy;
- c->addr_family = wm->addr_family;
- c->tunnel_addr_family = wm->tunnel_addr_family;
+ if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp)
+ loglog(RC_COMMENT
+ , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP"
+ , c->name);
- c->requested_ca = NULL;
+ if (wm->esp)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")
+ )
+ c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "");
+
+ DBG(DBG_CRYPT|DBG_CONTROL,
+ static char buf[BUF_LEN]="<NULL>";
+
+ if (c->alg_info_esp)
+ alg_info_snprint(buf, sizeof(buf)
+ ,(struct alg_info *)c->alg_info_esp);
+ DBG_log("esp proposal: %s", buf);
+ )
+ if (c->alg_info_esp)
+ {
+ if (c->alg_info_esp->alg_info_cnt==0)
+ loglog(RC_LOG_SERIOUS
+ , "got 0 transforms for esp=\"%s\"", wm->esp);
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "esp string error");
+ }
+ }
+
+ if (wm->ike)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL")
+ )
+ c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "");
+
+ DBG(DBG_CRYPT|DBG_CONTROL,
+ static char buf[BUF_LEN]="<NULL>";
+
+ if (c->alg_info_ike)
+ alg_info_snprint(buf, sizeof(buf)
+ , (struct alg_info *)c->alg_info_ike);
+ DBG_log("ike proposal: %s", buf);
+ )
+ if (c->alg_info_ike)
+ {
+ if (c->alg_info_ike->alg_info_cnt==0)
+ loglog(RC_LOG_SERIOUS
+ , "got 0 transforms for ike=\"%s\"", wm->ike);
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "ike string error:");
+ }
+ }
+
+ c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
+ c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
+ c->sa_rekey_margin = wm->sa_rekey_margin;
+ c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
+ c->sa_keying_tries = wm->sa_keying_tries;
- same_leftca = extract_end(&c->spd.this, &wm->left, "left");
- same_rightca = extract_end(&c->spd.that, &wm->right, "right");
+ /* RFC 3706 DPD */
+ c->dpd_delay = wm->dpd_delay;
+ c->dpd_timeout = wm->dpd_timeout;
+ c->dpd_action = wm->dpd_action;
- if (same_rightca)
- c->spd.that.ca = c->spd.this.ca;
- else if (same_leftca)
- c->spd.this.ca = c->spd.that.ca;
+ c->addr_family = wm->addr_family;
+ c->tunnel_addr_family = wm->tunnel_addr_family;
- default_end(&c->spd.this, &c->spd.that.host_addr);
- default_end(&c->spd.that, &c->spd.this.host_addr);
+ c->requested_ca = NULL;
- /* force any wildcard host IP address, any wildcard subnet
- * or any wildcard ID to that end
- */
- if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard
- || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards
- || c->spd.this.allow_any)
- {
- struct end t = c->spd.this;
+ same_leftca = extract_end(&c->spd.this, &wm->left, "left");
+ same_rightca = extract_end(&c->spd.that, &wm->right, "right");
- c->spd.this = c->spd.that;
- c->spd.that = t;
- }
+ if (same_rightca)
+ c->spd.that.ca = c->spd.this.ca;
+ else if (same_leftca)
+ c->spd.this.ca = c->spd.that.ca;
- c->spd.next = NULL;
- c->spd.reqid = gen_reqid();
+ default_end(&c->spd.this, &c->spd.that.host_addr);
+ default_end(&c->spd.that, &c->spd.this.host_addr);
- /* set internal fields */
- c->instance_serial = 0;
- c->ac_next = connections;
- connections = c;
- c->interface = NULL;
- c->spd.routing = RT_UNROUTED;
- c->newest_isakmp_sa = SOS_NOBODY;
- c->newest_ipsec_sa = SOS_NOBODY;
- c->spd.eroute_owner = SOS_NOBODY;
-
- if (c->policy & POLICY_GROUP)
- {
- c->kind = CK_GROUP;
- add_group(c);
- }
- else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy))
- || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard
- || c->spd.that.has_id_wildcards || c->spd.that.allow_any)
- {
- /* Opportunistic or Road Warrior or wildcard client subnet
- * or wildcard ID */
- c->kind = CK_TEMPLATE;
- }
- else
- {
- c->kind = CK_PERMANENT;
- }
- set_policy_prio(c); /* must be after kind is set */
+ /* force any wildcard host IP address, any wildcard subnet
+ * or any wildcard ID to that end
+ */
+ if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard
+ || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards
+ || c->spd.this.allow_any)
+ {
+ struct end t = c->spd.this;
+
+ c->spd.this = c->spd.that;
+ c->spd.that = t;
+ }
+
+ c->spd.next = NULL;
+ c->spd.reqid = gen_reqid();
+
+ /* set internal fields */
+ c->instance_serial = 0;
+ c->ac_next = connections;
+ connections = c;
+ c->interface = NULL;
+ c->spd.routing = RT_UNROUTED;
+ c->newest_isakmp_sa = SOS_NOBODY;
+ c->newest_ipsec_sa = SOS_NOBODY;
+ c->spd.eroute_owner = SOS_NOBODY;
+
+ if (c->policy & POLICY_GROUP)
+ {
+ c->kind = CK_GROUP;
+ add_group(c);
+ }
+ else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy))
+ || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard
+ || c->spd.that.has_id_wildcards || c->spd.that.allow_any)
+ {
+ /* Opportunistic or Road Warrior or wildcard client subnet
+ * or wildcard ID */
+ c->kind = CK_TEMPLATE;
+ }
+ else
+ {
+ c->kind = CK_PERMANENT;
+ }
+ set_policy_prio(c); /* must be after kind is set */
#ifdef DEBUG
- c->extra_debugging = wm->debugging;
+ c->extra_debugging = wm->debugging;
#endif
- c->gw_info = NULL;
+ c->gw_info = NULL;
- passert(!(wm->left.virt && wm->right.virt));
- if (wm->left.virt || wm->right.virt)
- {
- passert(isanyaddr(&c->spd.that.host_addr));
- c->spd.that.virt = create_virtual(c,
- wm->left.virt ? wm->left.virt : wm->right.virt);
- if (c->spd.that.virt)
- c->spd.that.has_client = TRUE;
- }
+ passert(!(wm->left.virt && wm->right.virt));
+ if (wm->left.virt || wm->right.virt)
+ {
+ passert(isanyaddr(&c->spd.that.host_addr));
+ c->spd.that.virt = create_virtual(c,
+ wm->left.virt ? wm->left.virt : wm->right.virt);
+ if (c->spd.that.virt)
+ c->spd.that.has_client = TRUE;
+ }
- unshare_connection_strings(c);
- (void)orient(c);
+ unshare_connection_strings(c);
+ (void)orient(c);
- if (c->ikev1)
- connect_to_host_pair(c);
+ if (c->ikev1)
+ connect_to_host_pair(c);
- /* log all about this connection */
- plog("added connection description \"%s\"", c->name);
- DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
-
- (void) format_connection(topo, sizeof(topo), c, &c->spd);
-
- DBG_log("%s", topo);
-
- /* Make sure that address families can be correctly inferred
- * from printed ends.
- */
- passert(c->addr_family == addrtypeof(&c->spd.this.host_addr)
- && c->addr_family == addrtypeof(&c->spd.this.host_nexthop)
- && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family)
- == subnettypeof(&c->spd.this.client)
-
- && c->addr_family == addrtypeof(&c->spd.that.host_addr)
- && c->addr_family == addrtypeof(&c->spd.that.host_nexthop)
- && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family)
- == subnettypeof(&c->spd.that.client));
-
- DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;"
- " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s"
- , (unsigned long) c->sa_ike_life_seconds
- , (unsigned long) c->sa_ipsec_life_seconds
- , (unsigned long) c->sa_rekey_margin
- , (unsigned long) c->sa_rekey_fuzz
- , (unsigned long) c->sa_keying_tries
- , prettypolicy(c->policy));
- );
- }
+ /* log all about this connection */
+ plog("added connection description \"%s\"", c->name);
+ DBG(DBG_CONTROL,
+ char topo[CONNECTION_BUF];
+
+ (void) format_connection(topo, sizeof(topo), c, &c->spd);
+
+ DBG_log("%s", topo);
+
+ /* Make sure that address families can be correctly inferred
+ * from printed ends.
+ */
+ passert(c->addr_family == addrtypeof(&c->spd.this.host_addr)
+ && c->addr_family == addrtypeof(&c->spd.this.host_nexthop)
+ && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family)
+ == subnettypeof(&c->spd.this.client)
+
+ && c->addr_family == addrtypeof(&c->spd.that.host_addr)
+ && c->addr_family == addrtypeof(&c->spd.that.host_nexthop)
+ && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family)
+ == subnettypeof(&c->spd.that.client));
+
+ DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;"
+ " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s"
+ , (unsigned long) c->sa_ike_life_seconds
+ , (unsigned long) c->sa_ipsec_life_seconds
+ , (unsigned long) c->sa_rekey_margin
+ , (unsigned long) c->sa_rekey_fuzz
+ , (unsigned long) c->sa_keying_tries
+ , prettypolicy(c->policy));
+ );
+ }
}
/* Derive a template connection from a group connection and target.
* Similar to instantiate(). Happens at whack --listen.
* Returns name of new connection. May be NULL.
- * Caller is responsible for pfreeing.
+ * Caller is responsible for freeing.
*/
char *
add_group_instance(struct connection *group, const ip_subnet *target)
{
- char namebuf[100]
- , targetbuf[SUBNETTOT_BUF];
- struct connection *t;
- char *name = NULL;
-
- passert(group->kind == CK_GROUP);
- passert(oriented(*group));
-
- /* manufacture a unique name for this template */
- subnettot(target, 0, targetbuf, sizeof(targetbuf));
- snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf);
-
- if (con_by_name(namebuf, FALSE) != NULL)
- {
- loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\""
- , namebuf);
- }
- else
- {
- t = clone_thing(*group, "group instance");
- t->name = namebuf;
- unshare_connection_strings(t);
- name = clone_str(t->name, "group instance name");
- t->spd.that.client = *target;
- t->policy &= ~(POLICY_GROUP | POLICY_GROUTED);
- t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy)
- ? CK_TEMPLATE : CK_INSTANCE;
+ char namebuf[100]
+ , targetbuf[SUBNETTOT_BUF];
+ struct connection *t;
+ char *name = NULL;
- /* reset log file info */
- t->log_file_name = NULL;
- t->log_file = NULL;
- t->log_file_err = FALSE;
+ passert(group->kind == CK_GROUP);
+ passert(oriented(*group));
- t->spd.reqid = gen_reqid();
+ /* manufacture a unique name for this template */
+ subnettot(target, 0, targetbuf, sizeof(targetbuf));
+ snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf);
- if (t->spd.that.virt)
+ if (con_by_name(namebuf, FALSE) != NULL)
{
- DBG_log("virtual_ip not supported in group instance");
- t->spd.that.virt = NULL;
+ loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\""
+ , namebuf);
}
+ else
+ {
+ t = clone_thing(*group);
+ t->name = namebuf;
+ unshare_connection_strings(t);
+ name = clone_str(t->name);
+ t->spd.that.client = *target;
+ t->policy &= ~(POLICY_GROUP | POLICY_GROUTED);
+ t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy)
+ ? CK_TEMPLATE : CK_INSTANCE;
+
+ /* reset log file info */
+ t->log_file_name = NULL;
+ t->log_file = NULL;
+ t->log_file_err = FALSE;
+
+ t->spd.reqid = gen_reqid();
+
+ if (t->spd.that.virt)
+ {
+ DBG_log("virtual_ip not supported in group instance");
+ t->spd.that.virt = NULL;
+ }
- /* add to connections list */
- t->ac_next = connections;
- connections = t;
+ /* add to connections list */
+ t->ac_next = connections;
+ connections = t;
- /* same host_pair as parent: stick after parent on list */
- group->hp_next = t;
+ /* same host_pair as parent: stick after parent on list */
+ group->hp_next = t;
- /* route if group is routed */
- if (group->policy & POLICY_GROUTED)
- {
- if (!trap_connection(t))
- whack_log(RC_ROUTE, "could not route");
+ /* route if group is routed */
+ if (group->policy & POLICY_GROUTED)
+ {
+ if (!trap_connection(t))
+ whack_log(RC_ROUTE, "could not route");
+ }
}
- }
- return name;
+ return name;
}
/* an old target has disappeared for a group: delete instance */
@@ -1246,17 +1237,17 @@ void
remove_group_instance(const struct connection *group USED_BY_DEBUG
, const char *name)
{
- passert(group->kind == CK_GROUP);
- passert(oriented(*group));
+ passert(group->kind == CK_GROUP);
+ passert(oriented(*group));
- delete_connections_by_name(name, FALSE);
+ delete_connections_by_name(name, FALSE);
}
/* Common part of instantiating a Road Warrior or Opportunistic connection.
* his_id can be used to carry over an ID discovered in Phase 1.
* It must not disagree with the one in c, but if that is unspecified,
* the new connection will use his_id.
- * If his_id is NULL, and c.that.id is uninstantiated (ID_NONE), the
+ * If his_id is NULL, and c.that.id is uninstantiated (ID_ANY), the
* new connection will continue to have an uninstantiated that.id.
* Note: instantiation does not affect port numbers.
*
@@ -1267,90 +1258,90 @@ instantiate(struct connection *c, const ip_address *him
, u_int16_t his_port
, const struct id *his_id)
{
- struct connection *d;
- int wildcards;
-
- passert(c->kind == CK_TEMPLATE);
- passert(c->spd.next == NULL);
-
- c->instance_serial++;
- d = clone_thing(*c, "temporary connection");
- d->spd.that.allow_any = FALSE;
-
- if (his_id != NULL)
- {
- passert(match_id(his_id, &d->spd.that.id, &wildcards));
- d->spd.that.id = *his_id;
- d->spd.that.has_id_wildcards = FALSE;
- }
- unshare_connection_strings(d);
- unshare_ietfAttrList(&d->spd.this.groups);
- unshare_ietfAttrList(&d->spd.that.groups);
- d->kind = CK_INSTANCE;
-
- passert(oriented(*d));
- d->spd.that.host_addr = *him;
- setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
-
- if (his_port) d->spd.that.host_port = his_port;
-
- default_end(&d->spd.that, &d->spd.this.host_addr);
-
- /* We cannot guess what our next_hop should be, but if it was
- * explicitly specified as 0.0.0.0, we set it to be him.
- * (whack will not allow nexthop to be elided in RW case.)
- */
- default_end(&d->spd.this, &d->spd.that.host_addr);
- d->spd.next = NULL;
- d->spd.reqid = gen_reqid();
-
- /* set internal fields */
- d->ac_next = connections;
- connections = d;
- d->spd.routing = RT_UNROUTED;
- d->newest_isakmp_sa = SOS_NOBODY;
- d->newest_ipsec_sa = SOS_NOBODY;
- d->spd.eroute_owner = SOS_NOBODY;
-
- /* reset log file info */
- d->log_file_name = NULL;
- d->log_file = NULL;
- d->log_file_err = FALSE;
-
- connect_to_host_pair(d);
-
- return d;
- if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop))
- {
- d->spd.this.host_nexthop = *him;
- }
+ struct connection *d;
+ int wildcards;
+
+ passert(c->kind == CK_TEMPLATE);
+ passert(c->spd.next == NULL);
+
+ c->instance_serial++;
+ d = clone_thing(*c);
+ d->spd.that.allow_any = FALSE;
+
+ if (his_id != NULL)
+ {
+ passert(match_id(his_id, &d->spd.that.id, &wildcards));
+ d->spd.that.id = *his_id;
+ d->spd.that.has_id_wildcards = FALSE;
+ }
+ unshare_connection_strings(d);
+ unshare_ietfAttrList(&d->spd.this.groups);
+ unshare_ietfAttrList(&d->spd.that.groups);
+ d->kind = CK_INSTANCE;
+
+ passert(oriented(*d));
+ d->spd.that.host_addr = *him;
+ setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
+
+ if (his_port) d->spd.that.host_port = his_port;
+
+ default_end(&d->spd.that, &d->spd.this.host_addr);
+
+ /* We cannot guess what our next_hop should be, but if it was
+ * explicitly specified as 0.0.0.0, we set it to be him.
+ * (whack will not allow nexthop to be elided in RW case.)
+ */
+ default_end(&d->spd.this, &d->spd.that.host_addr);
+ d->spd.next = NULL;
+ d->spd.reqid = gen_reqid();
+
+ /* set internal fields */
+ d->ac_next = connections;
+ connections = d;
+ d->spd.routing = RT_UNROUTED;
+ d->newest_isakmp_sa = SOS_NOBODY;
+ d->newest_ipsec_sa = SOS_NOBODY;
+ d->spd.eroute_owner = SOS_NOBODY;
+
+ /* reset log file info */
+ d->log_file_name = NULL;
+ d->log_file = NULL;
+ d->log_file_err = FALSE;
+
+ connect_to_host_pair(d);
+
+ return d;
+ if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop))
+ {
+ d->spd.this.host_nexthop = *him;
+ }
}
struct connection *
rw_instantiate(struct connection *c, const ip_address *him, u_int16_t his_port
, const ip_subnet *his_net, const struct id *his_id)
{
- struct connection *d = instantiate(c, him, his_port, his_id);
-
- if (d && his_net && is_virtual_connection(c))
- {
- d->spd.that.client = *his_net;
- d->spd.that.virt = NULL;
- if (subnetishost(his_net) && addrinsubnet(him, his_net))
- d->spd.that.has_client = FALSE;
- }
-
- if (d->policy & POLICY_OPPO)
- {
- /* This must be before we know the client addresses.
- * Fill in one that is impossible. This prevents anyone else from
- * trying to use this connection to get to a particular client
- */
- d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none;
- }
- DBG(DBG_CONTROL
- , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him)));
- return d;
+ struct connection *d = instantiate(c, him, his_port, his_id);
+
+ if (d && his_net && is_virtual_connection(c))
+ {
+ d->spd.that.client = *his_net;
+ d->spd.that.virt = NULL;
+ if (subnetishost(his_net) && addrinsubnet(him, his_net))
+ d->spd.that.has_client = FALSE;
+ }
+
+ if (d->policy & POLICY_OPPO)
+ {
+ /* This must be before we know the client addresses.
+ * Fill in one that is impossible. This prevents anyone else from
+ * trying to use this connection to get to a particular client
+ */
+ d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none;
+ }
+ DBG(DBG_CONTROL
+ , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him)));
+ return d;
}
struct connection *
@@ -1361,77 +1352,77 @@ oppo_instantiate(struct connection *c
, const ip_address *our_client USED_BY_DEBUG
, const ip_address *peer_client)
{
- struct connection *d = instantiate(c, him, 0, his_id);
+ struct connection *d = instantiate(c, him, 0, his_id);
- passert(d->spd.next == NULL);
+ passert(d->spd.next == NULL);
+
+ /* fill in our client side */
+ if (d->spd.this.has_client)
+ {
+ /* there was a client in the abstract connection
+ * so we demand that the required client is within that subnet.
+ */
+ passert(addrinsubnet(our_client, &d->spd.this.client));
+ happy(addrtosubnet(our_client, &d->spd.this.client));
+ /* opportunistic connections do not use port selectors */
+ setportof(0, &d->spd.this.client.addr);
+ }
+ else
+ {
+ /* there was no client in the abstract connection
+ * so we demand that the required client be the host
+ */
+ passert(sameaddr(our_client, &d->spd.this.host_addr));
+ }
- /* fill in our client side */
- if (d->spd.this.has_client)
- {
- /* there was a client in the abstract connection
- * so we demand that the required client is within that subnet.
+ /* fill in peer's client side.
+ * If the client is the peer, excise the client from the connection.
*/
- passert(addrinsubnet(our_client, &d->spd.this.client));
- happy(addrtosubnet(our_client, &d->spd.this.client));
+ passert((d->policy & POLICY_OPPO)
+ && addrinsubnet(peer_client, &d->spd.that.client));
+ happy(addrtosubnet(peer_client, &d->spd.that.client));
/* opportunistic connections do not use port selectors */
- setportof(0, &d->spd.this.client.addr);
- }
- else
- {
- /* there was no client in the abstract connection
- * so we demand that the required client be the host
+ setportof(0, &d->spd.that.client.addr);
+
+ if (sameaddr(peer_client, &d->spd.that.host_addr))
+ d->spd.that.has_client = FALSE;
+
+ passert(d->gw_info == NULL);
+ gw_addref(gw);
+ d->gw_info = gw;
+
+ /* Adjust routing if something is eclipsing c.
+ * It must be a %hold for us (hard to passert this).
+ * If there was another instance eclipsing, we'd be using it.
+ */
+ if (c->spd.routing == RT_ROUTED_ECLIPSED)
+ d->spd.routing = RT_ROUTED_PROSPECTIVE;
+
+ /* Remember if the template is routed:
+ * if so, this instance applies for initiation
+ * even if it is created for responding.
*/
- passert(sameaddr(our_client, &d->spd.this.host_addr));
- }
-
- /* fill in peer's client side.
- * If the client is the peer, excise the client from the connection.
- */
- passert((d->policy & POLICY_OPPO)
- && addrinsubnet(peer_client, &d->spd.that.client));
- happy(addrtosubnet(peer_client, &d->spd.that.client));
- /* opportunistic connections do not use port selectors */
- setportof(0, &d->spd.that.client.addr);
-
- if (sameaddr(peer_client, &d->spd.that.host_addr))
- d->spd.that.has_client = FALSE;
-
- passert(d->gw_info == NULL);
- gw_addref(gw);
- d->gw_info = gw;
-
- /* Adjust routing if something is eclipsing c.
- * It must be a %hold for us (hard to passert this).
- * If there was another instance eclipsing, we'd be using it.
- */
- if (c->spd.routing == RT_ROUTED_ECLIPSED)
- d->spd.routing = RT_ROUTED_PROSPECTIVE;
-
- /* Remember if the template is routed:
- * if so, this instance applies for initiation
- * even if it is created for responding.
- */
- if (routed(c->spd.routing))
- d->instance_initiation_ok = TRUE;
-
- DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
-
- (void) format_connection(topo, sizeof(topo), d, &d->spd);
- DBG_log("instantiated \"%s\": %s", d->name, topo);
- );
- return d;
+ if (routed(c->spd.routing))
+ d->instance_initiation_ok = TRUE;
+
+ DBG(DBG_CONTROL,
+ char topo[CONNECTION_BUF];
+
+ (void) format_connection(topo, sizeof(topo), d, &d->spd);
+ DBG_log("instantiated \"%s\": %s", d->name, topo);
+ );
+ return d;
}
/* priority formatting */
void
fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
{
- if (pp == BOTTOM_PRIO)
- snprintf(buf, POLICY_PRIO_BUF, "0");
- else
- snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"
- , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);
+ if (pp == BOTTOM_PRIO)
+ snprintf(buf, POLICY_PRIO_BUF, "0");
+ else
+ snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"
+ , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);
}
/* Format any information needed to identify an instance of a connection.
@@ -1442,65 +1433,65 @@ fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
static size_t
fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, char buf[ADDRTOT_BUF])
{
- if (subnetisaddr(client, gw))
- {
- buf[0] = '\0'; /* compact denotation for "self" */
- }
- else
- {
- char *ap;
-
- strcpy(buf, prefix);
- ap = buf + strlen(prefix);
- if (subnetisnone(client))
- strcpy(ap, "?"); /* unknown */
+ if (subnetisaddr(client, gw))
+ {
+ buf[0] = '\0'; /* compact denotation for "self" */
+ }
else
- subnettot(client, 0, ap, SUBNETTOT_BUF);
- }
- return strlen(buf);
+ {
+ char *ap;
+
+ strcpy(buf, prefix);
+ ap = buf + strlen(prefix);
+ if (subnetisnone(client))
+ strcpy(ap, "?"); /* unknown */
+ else
+ subnettot(client, 0, ap, SUBNETTOT_BUF);
+ }
+ return strlen(buf);
}
void
fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
{
- char *p = buf;
+ char *p = buf;
- *p = '\0';
+ *p = '\0';
- if (c->kind == CK_INSTANCE)
- {
- if (c->instance_serial != 0)
+ if (c->kind == CK_INSTANCE)
{
- snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial);
- p += strlen(p);
- }
+ if (c->instance_serial != 0)
+ {
+ snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial);
+ p += strlen(p);
+ }
- if (c->policy & POLICY_OPPO)
- {
- size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p);
+ if (c->policy & POLICY_OPPO)
+ {
+ size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p);
- p += w;
+ p += w;
- strcpy(p, w == 0? " ..." : "=== ...");
- p += strlen(p);
+ strcpy(p, w == 0? " ..." : "=== ...");
+ p += strlen(p);
- addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
- p += strlen(p);
+ addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
+ p += strlen(p);
- (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p);
- }
- else
- {
- *p++ = ' ';
- addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
+ (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p);
+ }
+ else
+ {
+ *p++ = ' ';
+ addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
#
- if (c->spd.that.host_port != pluto_port)
- {
- p += strlen(p);
- sprintf(p, ":%d", c->spd.that.host_port);
- }
+ if (c->spd.that.host_port != pluto_port)
+ {
+ p += strlen(p);
+ sprintf(p, ":%d", c->spd.that.host_port);
+ }
+ }
}
- }
}
/* Find an existing connection for a trapped outbound packet.
@@ -1520,124 +1511,124 @@ fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
*/
struct connection *
find_connection_for_clients(struct spd_route **srp,
- const ip_address *our_client,
- const ip_address *peer_client,
- int transport_proto)
+ const ip_address *our_client,
+ const ip_address *peer_client,
+ int transport_proto)
{
- struct connection *c = connections, *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- struct spd_route *sr;
- struct spd_route *best_sr = NULL;
- int our_port = ntohs(portof(our_client));
- int peer_port = ntohs(portof(peer_client));
-
- passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
+ struct connection *c = connections, *best = NULL;
+ policy_prio_t best_prio = BOTTOM_PRIO;
+ struct spd_route *sr;
+ struct spd_route *best_sr = NULL;
+ int our_port = ntohs(portof(our_client));
+ int peer_port = ntohs(portof(peer_client));
+
+ passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
#ifdef DEBUG
- if (DBGP(DBG_CONTROL))
- {
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
+ if (DBGP(DBG_CONTROL))
+ {
+ char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
- addrtot(our_client, 0, ocb, sizeof(ocb));
- addrtot(peer_client, 0, pcb, sizeof(pcb));
- DBG_log("find_connection: "
- "looking for policy for connection: %s:%d/%d -> %s:%d/%d"
- , ocb, transport_proto, our_port, pcb, transport_proto, peer_port);
- }
+ addrtot(our_client, 0, ocb, sizeof(ocb));
+ addrtot(peer_client, 0, pcb, sizeof(pcb));
+ DBG_log("find_connection: "
+ "looking for policy for connection: %s:%d/%d -> %s:%d/%d"
+ , ocb, transport_proto, our_port, pcb, transport_proto, peer_port);
+ }
#endif /* DEBUG */
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->kind == CK_GROUP)
- continue;
-
- for (sr = &c->spd; best!=c && sr; sr = sr->next)
+ for (c = connections; c != NULL; c = c->ac_next)
{
- if ((routed(sr->routing) || c->instance_initiation_ok)
- && addrinsubnet(our_client, &sr->this.client)
- && addrinsubnet(peer_client, &sr->that.client)
- && addrinsubnet(peer_client, &sr->that.client)
- && (!sr->this.protocol || transport_proto == sr->this.protocol)
- && (!sr->this.port || our_port == sr->this.port)
- && (!sr->that.port || peer_port == sr->that.port))
- {
- char cib[CONN_INST_BUF];
- char cib2[CONN_INST_BUF];
+ if (c->kind == CK_GROUP)
+ continue;
+
+ for (sr = &c->spd; best!=c && sr; sr = sr->next)
+ {
+ if ((routed(sr->routing) || c->instance_initiation_ok)
+ && addrinsubnet(our_client, &sr->this.client)
+ && addrinsubnet(peer_client, &sr->that.client)
+ && addrinsubnet(peer_client, &sr->that.client)
+ && (!sr->this.protocol || transport_proto == sr->this.protocol)
+ && (!sr->this.port || our_port == sr->this.port)
+ && (!sr->that.port || peer_port == sr->that.port))
+ {
+ char cib[CONN_INST_BUF];
+ char cib2[CONN_INST_BUF];
- policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE))
- + 2 * (sr->this.port == our_port)
- + 2 * (sr->that.port == peer_port)
- + (sr->this.protocol == transport_proto);
+ policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE))
+ + 2 * (sr->this.port == our_port)
+ + 2 * (sr->that.port == peer_port)
+ + (sr->this.protocol == transport_proto);
#ifdef DEBUG
- if (DBGP(DBG_CONTROL|DBG_CONTROLMORE))
- {
- char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb));
- subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb));
- DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]"
- , c->name
- , (fmt_conn_instance(c, cib), cib)
- , c_ocb, c_pcb, prio);
- }
+ if (DBGP(DBG_CONTROL|DBG_CONTROLMORE))
+ {
+ char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF];
+
+ subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb));
+ subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb));
+ DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)
+ , c_ocb, c_pcb, prio);
+ }
#endif /* DEBUG */
- if (best == NULL)
- {
- best = c;
- best_sr = sr;
- best_prio = prio;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log("find_connection: "
- "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)"
- , best->name
- , (fmt_conn_instance(best, cib), cib)
- , best_prio
- , best
- , (best->policy_next ? best->policy_next->name : "none")
- , c->name
- , (fmt_conn_instance(c, cib2), cib2)
- , prio
- , c
- , (c->policy_next ? c->policy_next->name : "none")));
-
- if (prio > best_prio)
- {
- best = c;
- best_sr = sr;
- best_prio = prio;
+ if (best == NULL)
+ {
+ best = c;
+ best_sr = sr;
+ best_prio = prio;
+ }
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log("find_connection: "
+ "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)"
+ , best->name
+ , (fmt_conn_instance(best, cib), cib)
+ , best_prio
+ , best
+ , (best->policy_next ? best->policy_next->name : "none")
+ , c->name
+ , (fmt_conn_instance(c, cib2), cib2)
+ , prio
+ , c
+ , (c->policy_next ? c->policy_next->name : "none")));
+
+ if (prio > best_prio)
+ {
+ best = c;
+ best_sr = sr;
+ best_prio = prio;
+ }
+ }
}
- }
}
- }
- if (best!= NULL && NEVER_NEGOTIATE(best->policy))
- best = NULL;
+ if (best!= NULL && NEVER_NEGOTIATE(best->policy))
+ best = NULL;
- if (srp != NULL && best != NULL)
- *srp = best_sr;
+ if (srp != NULL && best != NULL)
+ *srp = best_sr;
#ifdef DEBUG
- if (DBGP(DBG_CONTROL))
- {
- if (best)
+ if (DBGP(DBG_CONTROL))
{
- char cib[CONN_INST_BUF];
- DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s"
- , best->name
- , (fmt_conn_instance(best, cib), cib)
- , best_prio
- , best
- , enum_name(&connection_kind_names, best->kind));
- } else {
- DBG_log("find_connection: concluding with empty");
+ if (best)
+ {
+ char cib[CONN_INST_BUF];
+ DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s"
+ , best->name
+ , (fmt_conn_instance(best, cib), cib)
+ , best_prio
+ , best
+ , enum_name(&connection_kind_names, best->kind));
+ } else {
+ DBG_log("find_connection: concluding with empty");
+ }
}
- }
#endif /* DEBUG */
- return best;
+ return best;
}
/* Find and instantiate a connection for an outgoing Opportunistic connection.
@@ -1664,203 +1655,203 @@ find_connection_for_clients(struct spd_route **srp,
*/
struct connection *
build_outgoing_opportunistic_connection(struct gw_info *gw
- ,const ip_address *our_client
- ,const ip_address *peer_client)
+ ,const ip_address *our_client
+ ,const ip_address *peer_client)
{
- struct iface *p;
- struct connection *best = NULL;
- struct spd_route *sr, *bestsr;
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
-
- addrtot(our_client, 0, ocb, sizeof(ocb));
- addrtot(peer_client, 0, pcb, sizeof(pcb));
-
- passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
-
- /* We don't know his ID yet, so gw id must be an ipaddr */
- passert(gw->key != NULL);
- passert(id_is_ipaddr(&gw->gw_id));
-
- /* for each of our addresses... */
- for (p = interfaces; p != NULL; p = p->next)
- {
- /* go through those connections with our address and NO_IP as hosts
- * We cannot know what port the peer would use, so we assume
- * that it is pluto_port (makes debugging easier).
- */
- struct connection *c = find_host_pair_connections(&p->addr
- , pluto_port, (ip_address *)NULL, pluto_port);
+ struct iface *p;
+ struct connection *best = NULL;
+ struct spd_route *sr, *bestsr;
+ char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
- for (; c != NULL; c = c->hp_next)
+ addrtot(our_client, 0, ocb, sizeof(ocb));
+ addrtot(peer_client, 0, pcb, sizeof(pcb));
+
+ passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
+
+ /* We don't know his ID yet, so gw id must be an ipaddr */
+ passert(gw->key != NULL);
+ passert(id_is_ipaddr(&gw->gw_id));
+
+ /* for each of our addresses... */
+ for (p = interfaces; p != NULL; p = p->next)
{
- DBG(DBG_OPPO,
- DBG_log("checking %s", c->name));
- if (c->kind == CK_GROUP)
- {
- continue;
- }
-
- for (sr = &c->spd; best!=c && sr; sr = sr->next)
- {
- if (routed(sr->routing)
- && addrinsubnet(our_client, &sr->this.client)
- && addrinsubnet(peer_client, &sr->that.client))
+ /* go through those connections with our address and NO_IP as hosts
+ * We cannot know what port the peer would use, so we assume
+ * that it is pluto_port (makes debugging easier).
+ */
+ struct connection *c = find_host_pair_connections(&p->addr
+ , pluto_port, (ip_address *)NULL, pluto_port);
+
+ for (; c != NULL; c = c->hp_next)
{
- if (best == NULL)
- {
- best = c;
- break;
- }
-
- DBG(DBG_OPPO,
- DBG_log("comparing best %s to %s"
- , best->name, c->name));
-
- for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)
- {
- if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)
- || (samesubnet(&bestsr->this.client, &sr->this.client)
- && !subnetinsubnet(&bestsr->that.client
- , &sr->that.client)))
+ DBG(DBG_OPPO,
+ DBG_log("checking %s", c->name));
+ if (c->kind == CK_GROUP)
{
- best = c;
+ continue;
+ }
+
+ for (sr = &c->spd; best!=c && sr; sr = sr->next)
+ {
+ if (routed(sr->routing)
+ && addrinsubnet(our_client, &sr->this.client)
+ && addrinsubnet(peer_client, &sr->that.client))
+ {
+ if (best == NULL)
+ {
+ best = c;
+ break;
+ }
+
+ DBG(DBG_OPPO,
+ DBG_log("comparing best %s to %s"
+ , best->name, c->name));
+
+ for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)
+ {
+ if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)
+ || (samesubnet(&bestsr->this.client, &sr->this.client)
+ && !subnetinsubnet(&bestsr->that.client
+ , &sr->that.client)))
+ {
+ best = c;
+ }
+ }
+ }
}
- }
}
- }
}
- }
- if (best == NULL
- || NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY
- || best->kind != CK_TEMPLATE)
- return NULL;
- else
- return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw
- , our_client, peer_client);
+ if (best == NULL
+ || NEVER_NEGOTIATE(best->policy)
+ || (best->policy & POLICY_OPPO) == LEMPTY
+ || best->kind != CK_TEMPLATE)
+ return NULL;
+ else
+ return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw
+ , our_client, peer_client);
}
bool
orient(struct connection *c)
{
- struct spd_route *sr;
-
- if (!oriented(*c))
- {
- struct iface *p;
+ struct spd_route *sr;
- for (sr = &c->spd; sr; sr = sr->next)
+ if (!oriented(*c))
{
- /* Note: this loop does not stop when it finds a match:
- * it continues checking to catch any ambiguity.
- */
- for (p = interfaces; p != NULL; p = p->next)
- {
- if (p->ike_float)
- continue;
-
- for (;;)
+ struct iface *p;
+
+ for (sr = &c->spd; sr; sr = sr->next)
{
- /* check if this interface matches this end */
- if (sameaddr(&sr->this.host_addr, &p->addr)
- && (!no_klips || sr->this.host_port == pluto_port))
- {
- if (oriented(*c))
+ /* Note: this loop does not stop when it finds a match:
+ * it continues checking to catch any ambiguity.
+ */
+ for (p = interfaces; p != NULL; p = p->next)
{
- if (c->interface == p)
- loglog(RC_LOG_SERIOUS
- , "both sides of \"%s\" are our interface %s!"
- , c->name, p->rname);
- else
- loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"
- , c->name, c->interface->rname, p->rname);
- c->interface = NULL; /* withdraw orientation */
- return FALSE;
+ if (p->ike_float)
+ continue;
+
+ for (;;)
+ {
+ /* check if this interface matches this end */
+ if (sameaddr(&sr->this.host_addr, &p->addr)
+ && (!no_klips || sr->this.host_port == pluto_port))
+ {
+ if (oriented(*c))
+ {
+ if (c->interface == p)
+ loglog(RC_LOG_SERIOUS
+ , "both sides of \"%s\" are our interface %s!"
+ , c->name, p->rname);
+ else
+ loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"
+ , c->name, c->interface->rname, p->rname);
+ c->interface = NULL; /* withdraw orientation */
+ return FALSE;
+ }
+ c->interface = p;
+ }
+
+ /* done with this interface if it doesn't match that end */
+ if (!(sameaddr(&sr->that.host_addr, &p->addr)
+ && (!no_klips || sr->that.host_port == pluto_port)))
+ break;
+
+ /* swap ends and try again.
+ * It is a little tricky to see that this loop will stop.
+ * Only continue if the far side matches.
+ * If both sides match, there is an error-out.
+ */
+ {
+ struct end t = sr->this;
+
+ sr->this = sr->that;
+ sr->that = t;
+ }
+ }
}
- c->interface = p;
- }
-
- /* done with this interface if it doesn't match that end */
- if (!(sameaddr(&sr->that.host_addr, &p->addr)
- && (!no_klips || sr->that.host_port == pluto_port)))
- break;
-
- /* swap ends and try again.
- * It is a little tricky to see that this loop will stop.
- * Only continue if the far side matches.
- * If both sides match, there is an error-out.
- */
- {
- struct end t = sr->this;
-
- sr->this = sr->that;
- sr->that = t;
- }
}
- }
}
- }
- return oriented(*c);
+ return oriented(*c);
}
void
initiate_connection(const char *name, int whackfd)
{
- struct connection *c = con_by_name(name, TRUE);
+ struct connection *c = con_by_name(name, TRUE);
- if (c != NULL && c->ikev1)
- {
- set_cur_connection(c);
- if (!oriented(*c))
- {
- loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection");
- }
- else if (NEVER_NEGOTIATE(c->policy))
- {
- loglog(RC_INITSHUNT
- , "cannot initiate an authby=never connection");
- }
- else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any)
- {
- if (isanyaddr(&c->spd.that.host_addr))
- loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address");
- else
- loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards");
- }
- else
+ if (c != NULL && c->ikev1)
{
- /* do we have to prompt for a PIN code? */
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)
- {
- scx_get_pin(c->spd.this.sc, whackfd);
- }
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid)
- {
- loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
- }
- else
- {
-
- if (c->spd.that.allow_any)
+ set_cur_connection(c);
+ if (!oriented(*c))
+ {
+ loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection");
+ }
+ else if (NEVER_NEGOTIATE(c->policy))
+ {
+ loglog(RC_INITSHUNT
+ , "cannot initiate an authby=never connection");
+ }
+ else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any)
{
- c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port
- , &c->spd.that.id);
+ if (isanyaddr(&c->spd.that.host_addr))
+ loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address");
+ else
+ loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards");
}
+ else
+ {
+ /* do we have to prompt for a PIN code? */
+ if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)
+ {
+ scx_get_pin(c->spd.this.sc, whackfd);
+ }
+ if (c->spd.this.sc != NULL && !c->spd.this.sc->valid)
+ {
+ loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
+ }
+ else
+ {
- /* We will only request an IPsec SA if policy isn't empty
- * (ignoring Main Mode items).
- * This is a fudge, but not yet important.
- * If we are to proceed asynchronously, whackfd will be NULL_FD.
- */
- c->policy |= POLICY_UP;
- ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY);
- whackfd = NULL_FD; /* protect from close */
- }
+ if (c->spd.that.allow_any)
+ {
+ c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port
+ , &c->spd.that.id);
+ }
+
+ /* We will only request an IPsec SA if policy isn't empty
+ * (ignoring Main Mode items).
+ * This is a fudge, but not yet important.
+ * If we are to proceed asynchronously, whackfd will be NULL_FD.
+ */
+ c->policy |= POLICY_UP;
+ ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY);
+ whackfd = NULL_FD; /* protect from close */
+ }
+ }
+ reset_cur_connection();
}
- reset_cur_connection();
- }
- close_any(whackfd);
+ close_any(whackfd);
}
/* (Possibly) Opportunistic Initiation:
@@ -1874,10 +1865,10 @@ initiate_connection(const char *name, int whackfd)
* Most of the code will be restarted if an ADNS request is made
* to discover the gateway. The only difference between the first
* and second entry is whether gateways_from_dns is NULL or not.
- * initiate_opportunistic: initial entrypoint
- * continue_oppo: where we pickup when ADNS result arrives
- * initiate_opportunistic_body: main body shared by above routines
- * cannot_oppo: a helper function to log a diagnostic
+ * initiate_opportunistic: initial entrypoint
+ * continue_oppo: where we pickup when ADNS result arrives
+ * initiate_opportunistic_body: main body shared by above routines
+ * cannot_oppo: a helper function to log a diagnostic
* This structure repeats a lot of code when the ADNS result arrives.
* This seems like a waste, but anything learned the first time through
* may no longer be true!
@@ -1887,174 +1878,174 @@ initiate_connection(const char *name, int whackfd)
*/
enum find_oppo_step {
- fos_start,
- fos_myid_ip_txt,
- fos_myid_hostname_txt,
- fos_myid_ip_key,
- fos_myid_hostname_key,
- fos_our_client,
- fos_our_txt,
+ fos_start,
+ fos_myid_ip_txt,
+ fos_myid_hostname_txt,
+ fos_myid_ip_key,
+ fos_myid_hostname_key,
+ fos_our_client,
+ fos_our_txt,
#ifdef USE_KEYRR
- fos_our_key,
+ fos_our_key,
#endif /* USE_KEYRR */
- fos_his_client,
- fos_done
+ fos_his_client,
+ fos_done
};
#ifdef DEBUG
static const char *const oppo_step_name[] = {
- "fos_start",
- "fos_myid_ip_txt",
- "fos_myid_hostname_txt",
- "fos_myid_ip_key",
- "fos_myid_hostname_key",
- "fos_our_client",
- "fos_our_txt",
+ "fos_start",
+ "fos_myid_ip_txt",
+ "fos_myid_hostname_txt",
+ "fos_myid_ip_key",
+ "fos_myid_hostname_key",
+ "fos_our_client",
+ "fos_our_txt",
#ifdef USE_KEYRR
- "fos_our_key",
+ "fos_our_key",
#endif /* USE_KEYRR */
- "fos_his_client",
- "fos_done"
+ "fos_his_client",
+ "fos_done"
};
#endif /* DEBUG */
struct find_oppo_bundle {
- enum find_oppo_step step;
- err_t want;
- bool failure_ok; /* if true, continue_oppo should not die on DNS failure */
- ip_address our_client; /* not pointer! */
- ip_address peer_client;
- int transport_proto;
- bool held;
- policy_prio_t policy_prio;
- ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */
- int whackfd;
+ enum find_oppo_step step;
+ err_t want;
+ bool failure_ok; /* if true, continue_oppo should not die on DNS failure */
+ ip_address our_client; /* not pointer! */
+ ip_address peer_client;
+ int transport_proto;
+ bool held;
+ policy_prio_t policy_prio;
+ ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */
+ int whackfd;
};
struct find_oppo_continuation {
- struct adns_continuation ac; /* common prefix */
- struct find_oppo_bundle b;
+ struct adns_continuation ac; /* common prefix */
+ struct find_oppo_bundle b;
};
static void
cannot_oppo(struct connection *c
- , struct find_oppo_bundle *b
- , err_t ugh)
+ , struct find_oppo_bundle *b
+ , err_t ugh)
{
- char pcb[ADDRTOT_BUF];
- char ocb[ADDRTOT_BUF];
+ char pcb[ADDRTOT_BUF];
+ char ocb[ADDRTOT_BUF];
- addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- addrtot(&b->our_client, 0, ocb, sizeof(ocb));
+ addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
+ addrtot(&b->our_client, 0, ocb, sizeof(ocb));
- DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s"
- , ocb, pcb, ugh));
+ DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s"
+ , ocb, pcb, ugh));
- whack_log(RC_OPPOFAILURE
- , "Can't Opportunistically initiate for %s to %s: %s"
- , ocb, pcb, ugh);
+ whack_log(RC_OPPOFAILURE
+ , "Can't Opportunistically initiate for %s to %s: %s"
+ , ocb, pcb, ugh);
- if (c != NULL && c->policy_next != NULL)
- {
- /* there is some policy that comes afterwards */
- struct spd_route *shunt_spd;
- struct connection *nc = c->policy_next;
- struct state *st;
+ if (c != NULL && c->policy_next != NULL)
+ {
+ /* there is some policy that comes afterwards */
+ struct spd_route *shunt_spd;
+ struct connection *nc = c->policy_next;
+ struct state *st;
- passert(c->kind == CK_TEMPLATE);
- passert(c->policy_next->kind == CK_PERMANENT);
+ passert(c->kind == CK_TEMPLATE);
+ passert(c->policy_next->kind == CK_PERMANENT);
- DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"
- , ocb, pcb, c->policy_next->name));
+ DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"
+ , ocb, pcb, c->policy_next->name));
- /*
- * okay, here we need add to the "next" policy, which is ought
- * to be an instance.
- * We will add another entry to the spd_route list for the specific
- * situation that we have.
- */
+ /*
+ * okay, here we need add to the "next" policy, which is ought
+ * to be an instance.
+ * We will add another entry to the spd_route list for the specific
+ * situation that we have.
+ */
- shunt_spd = clone_thing(nc->spd, "shunt eroute policy");
+ shunt_spd = clone_thing(nc->spd);
- shunt_spd->next = nc->spd.next;
- nc->spd.next = shunt_spd;
+ shunt_spd->next = nc->spd.next;
+ nc->spd.next = shunt_spd;
- happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));
+ happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));
- if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))
- shunt_spd->that.has_client = FALSE;
+ if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))
+ shunt_spd->that.has_client = FALSE;
- /*
- * override the tunnel destination with the one from the secondaried
- * policy
- */
- shunt_spd->that.host_addr = nc->spd.that.host_addr;
+ /*
+ * override the tunnel destination with the one from the secondaried
+ * policy
+ */
+ shunt_spd->that.host_addr = nc->spd.that.host_addr;
- /* now, lookup the state, and poke it up.
- */
+ /* now, lookup the state, and poke it up.
+ */
- st = state_with_serialno(nc->newest_ipsec_sa);
+ st = state_with_serialno(nc->newest_ipsec_sa);
- /* XXX what to do if the IPSEC SA has died? */
- passert(st != NULL);
+ /* XXX what to do if the IPSEC SA has died? */
+ passert(st != NULL);
- /* link the new connection instance to the state's list of
- * connections
- */
+ /* link the new connection instance to the state's list of
+ * connections
+ */
- DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"
- , nc->newest_ipsec_sa
- , ocb, pcb));
+ DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"
+ , nc->newest_ipsec_sa
+ , ocb, pcb));
#ifdef DEBUG
- if (DBGP(DBG_OPPO | DBG_CONTROLMORE))
- {
- char state_buf[LOG_WIDTH];
- char state_buf2[LOG_WIDTH];
- time_t n = now();
-
- fmt_state(FALSE, st, n
- , state_buf, sizeof(state_buf)
- , state_buf2, sizeof(state_buf2));
- DBG_log("cannot_oppo, failure SA1: %s", state_buf);
- DBG_log("cannot_oppo, failure SA2: %s", state_buf2);
- }
+ if (DBGP(DBG_OPPO | DBG_CONTROLMORE))
+ {
+ char state_buf[LOG_WIDTH];
+ char state_buf2[LOG_WIDTH];
+ time_t n = now();
+
+ fmt_state(FALSE, st, n
+ , state_buf, sizeof(state_buf)
+ , state_buf2, sizeof(state_buf2));
+ DBG_log("cannot_oppo, failure SA1: %s", state_buf);
+ DBG_log("cannot_oppo, failure SA2: %s", state_buf2);
+ }
#endif /* DEBUG */
- if (!route_and_eroute(c, shunt_spd, st))
- {
- whack_log(RC_OPPOFAILURE
- , "failed to instantiate shunt policy %s for %s to %s"
- , c->name
- , ocb, pcb);
+ if (!route_and_eroute(c, shunt_spd, st))
+ {
+ whack_log(RC_OPPOFAILURE
+ , "failed to instantiate shunt policy %s for %s to %s"
+ , c->name
+ , ocb, pcb);
+ }
+ return;
}
- return;
- }
#ifdef KLIPS
- if (b->held)
- {
- /* Replace HOLD with b->failure_shunt.
- * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE.
- */
- if (b->failure_shunt == 0)
+ if (b->held)
{
- DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass"
- , ocb, pcb));
- }
+ /* Replace HOLD with b->failure_shunt.
+ * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE.
+ */
+ if (b->failure_shunt == 0)
+ {
+ DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass"
+ , ocb, pcb));
+ }
- (void) replace_bare_shunt(&b->our_client, &b->peer_client
- , b->policy_prio
- , b->failure_shunt
- , b->failure_shunt != 0
- , b->transport_proto
- , ugh);
- }
+ (void) replace_bare_shunt(&b->our_client, &b->peer_client
+ , b->policy_prio
+ , b->failure_shunt
+ , b->failure_shunt != 0
+ , b->transport_proto
+ , ugh);
+ }
#endif
}
static void initiate_opportunistic_body(struct find_oppo_bundle *b
- , struct adns_continuation *ac, err_t ac_ugh); /* forward */
+ , struct adns_continuation *ac, err_t ac_ugh); /* forward */
void
initiate_opportunistic(const ip_address *our_client
@@ -2063,93 +2054,93 @@ initiate_opportunistic(const ip_address *our_client
, bool held
, int whackfd)
{
- struct find_oppo_bundle b;
-
- b.want = (whackfd == NULL_FD ? "whack" : "acquire");
- b.failure_ok = FALSE;
- b.our_client = *our_client;
- b.peer_client = *peer_client;
- b.transport_proto = transport_proto;
- b.held = held;
- b.policy_prio = BOTTOM_PRIO;
- b.failure_shunt = 0;
- b.whackfd = whackfd;
- b.step = fos_start;
- initiate_opportunistic_body(&b, NULL, NULL);
+ struct find_oppo_bundle b;
+
+ b.want = (whackfd == NULL_FD ? "whack" : "acquire");
+ b.failure_ok = FALSE;
+ b.our_client = *our_client;
+ b.peer_client = *peer_client;
+ b.transport_proto = transport_proto;
+ b.held = held;
+ b.policy_prio = BOTTOM_PRIO;
+ b.failure_shunt = 0;
+ b.whackfd = whackfd;
+ b.step = fos_start;
+ initiate_opportunistic_body(&b, NULL, NULL);
}
static void
continue_oppo(struct adns_continuation *acr, err_t ugh)
{
- struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
- struct connection *c;
- bool was_held = cr->b.held;
- int whackfd = cr->b.whackfd;
+ struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
+ struct connection *c;
+ bool was_held = cr->b.held;
+ int whackfd = cr->b.whackfd;
- /* note: cr->id has no resources; cr->sgw_id is id_none:
- * neither need freeing.
- */
- whack_log_fd = whackfd;
+ /* note: cr->id has no resources; cr->sgw_id is ID_ANY:
+ * neither need freeing.
+ */
+ whack_log_fd = whackfd;
#ifdef KLIPS
- /* Discover and record whether %hold has gone away.
- * This could have happened while we were awaiting DNS.
- * We must check BEFORE any call to cannot_oppo.
- */
- if (was_held)
- cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client
- , cr->b.transport_proto);
+ /* Discover and record whether %hold has gone away.
+ * This could have happened while we were awaiting DNS.
+ * We must check BEFORE any call to cannot_oppo.
+ */
+ if (was_held)
+ cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client
+ , cr->b.transport_proto);
#endif
#ifdef DEBUG
- /* if we're going to ignore the error, at least note it in debugging log */
- if (cr->b.failure_ok && ugh != NULL)
- {
- DBG(DBG_CONTROL | DBG_DNS,
- {
+ /* if we're going to ignore the error, at least note it in debugging log */
+ if (cr->b.failure_ok && ugh != NULL)
+ {
+ DBG(DBG_CONTROL | DBG_DNS,
+ {
+ char ocb[ADDRTOT_BUF];
+ char pcb[ADDRTOT_BUF];
+
+ addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
+ addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
+ DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s"
+ , cr->b.want, ocb, pcb, ugh);
+ });
+ }
+#endif
+
+ if (!cr->b.failure_ok && ugh != NULL)
+ {
+ c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
+ , cr->b.transport_proto);
+ cannot_oppo(c, &cr->b
+ , builddiag("%s: %s", cr->b.want, ugh));
+ }
+ else if (was_held && !cr->b.held)
+ {
+ /* was_held indicates we were started due to a %trap firing
+ * (as opposed to a "whack --oppohere --oppothere").
+ * Since the %hold has gone, we can assume that somebody else
+ * has beaten us to the punch. We can go home. But lets log it.
+ */
char ocb[ADDRTOT_BUF];
char pcb[ADDRTOT_BUF];
addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
- DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s"
- , cr->b.want, ocb, pcb, ugh);
- });
- }
-#endif
- if (!cr->b.failure_ok && ugh != NULL)
- {
- c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
- , cr->b.transport_proto);
- cannot_oppo(c, &cr->b
- , builddiag("%s: %s", cr->b.want, ugh));
- }
- else if (was_held && !cr->b.held)
- {
- /* was_held indicates we were started due to a %trap firing
- * (as opposed to a "whack --oppohere --oppothere").
- * Since the %hold has gone, we can assume that somebody else
- * has beaten us to the punch. We can go home. But lets log it.
- */
- char ocb[ADDRTOT_BUF];
- char pcb[ADDRTOT_BUF];
+ loglog(RC_COMMENT
+ , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s"
+ , ocb, pcb);
+ }
+ else
+ {
+ initiate_opportunistic_body(&cr->b, &cr->ac, ugh);
+ whackfd = NULL_FD; /* was handed off */
+ }
- addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
- addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
-
- loglog(RC_COMMENT
- , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s"
- , ocb, pcb);
- }
- else
- {
- initiate_opportunistic_body(&cr->b, &cr->ac, ugh);
- whackfd = NULL_FD; /* was handed off */
- }
-
- whack_log_fd = NULL_FD;
- close_any(whackfd);
+ whack_log_fd = NULL_FD;
+ close_any(whackfd);
}
#ifdef USE_KEYRR
@@ -2158,110 +2149,112 @@ check_key_recs(enum myid_state try_state
, const struct connection *c
, struct adns_continuation *ac)
{
- /* Check if KEY lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- enum myid_state old_myid_state = myid_state;
- const struct RSA_private_key *our_RSA_pri;
- err_t ugh = NULL;
-
- myid_state = try_state;
-
- if (old_myid_state != myid_state
- && old_myid_state == MYID_SPECIFIED)
- {
- ugh = "%myid was specified while we were guessing";
- }
- else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
+ /* Check if KEY lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
*/
- pubkey_list_t *kr;
+ enum myid_state old_myid_state = myid_state;
+ private_key_t *private;
+ err_t ugh = NULL;
- ugh = "no KEY RR found for us";
- for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
+ myid_state = try_state;
+
+ if (old_myid_state != myid_state && old_myid_state == MYID_SPECIFIED)
{
- ugh = "all our KEY RRs have the wrong public key";
- if (kr->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa))
- {
- ugh = NULL; /* good! */
- break;
- }
+ ugh = "%myid was specified while we were guessing";
+ }
+ else if ((private = get_private_key(c)) == NULL)
+ {
+ ugh = "we don't know our own RSA key";
}
- }
- if (ugh != NULL)
- myid_state = old_myid_state;
- return ugh;
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ pubkey_list_t *kr;
+
+ ugh = "no KEY RR found for us";
+ for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
+ {
+ ugh = "all our KEY RRs have the wrong public key";
+ if (kr->key->alg == PUBKEY_ALG_RSA
+ && private->belongs_to(private, &kr->key->public_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ if (ugh != NULL)
+ myid_state = old_myid_state;
+ return ugh;
}
#endif /* USE_KEYRR */
-static err_t
-check_txt_recs(enum myid_state try_state
-, const struct connection *c
-, struct adns_continuation *ac)
+static err_t check_txt_recs(enum myid_state try_state,
+ const struct connection *c,
+ struct adns_continuation *ac)
{
- /* Check if TXT lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- enum myid_state old_myid_state = myid_state;
- const struct RSA_private_key *our_RSA_pri;
- err_t ugh = NULL;
-
- myid_state = try_state;
-
- if (old_myid_state != myid_state
- && old_myid_state == MYID_SPECIFIED)
- {
- ugh = "%myid was specified while we were guessing";
- }
- else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
+ /* Check if TXT lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
*/
- struct gw_info *gwp;
+ enum myid_state old_myid_state = myid_state;
+ private_key_t *private;
+ err_t ugh = NULL;
+
+ myid_state = try_state;
- ugh = "no TXT RR found for us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ if (old_myid_state != myid_state
+ && old_myid_state == MYID_SPECIFIED)
{
- ugh = "all our TXT RRs have the wrong public key";
- if (gwp->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
- {
- ugh = NULL; /* good! */
- break;
- }
+ ugh = "%myid was specified while we were guessing";
+ }
+ else if ((private = get_private_key(c)) == NULL)
+ {
+ ugh = "we don't know our own RSA key";
}
- }
- if (ugh != NULL)
- myid_state = old_myid_state;
- return ugh;
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ struct gw_info *gwp;
+
+ ugh = "no TXT RR found for us";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ public_key_t *pub_key = gwp->key->public_key;
+
+ ugh = "all our TXT RRs have the wrong public key";
+ if (pub_key->get_type(pub_key) == KEY_RSA &&
+ private->belongs_to(private, pub_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ if (ugh != NULL)
+ {
+ myid_state = old_myid_state;
+ }
+ return ugh;
}
@@ -2271,776 +2264,775 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
, struct adns_continuation *ac
, err_t ac_ugh)
{
- struct connection *c;
- struct spd_route *sr;
+ struct connection *c;
+ struct spd_route *sr;
- /* What connection shall we use?
- * First try for one that explicitly handles the clients.
- */
- DBG(DBG_CONTROL,
- {
- char ours[ADDRTOT_BUF];
- char his[ADDRTOT_BUF];
- int ourport;
- int hisport;
-
- addrtot(&b->our_client, 0, ours, sizeof(ours));
- addrtot(&b->peer_client, 0, his, sizeof(his));
- ourport = ntohs(portof(&b->our_client));
- hisport = ntohs(portof(&b->peer_client));
- DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
- , ours, ourport, his, hisport, b->transport_proto
- , oppo_step_name[b->step], b->want);
- });
- if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client))
- {
- cannot_oppo(NULL, b, "impossible IP address");
- }
- else if ((c = find_connection_for_clients(&sr
- , &b->our_client
- , &b->peer_client
- , b->transport_proto)) == NULL)
- {
- /* No connection explicitly handles the clients and there
- * are no Opportunistic connections -- whine and give up.
- * The failure policy cannot be gotten from a connection; we pick %pass.
- */
- cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair");
- }
- else if (c->kind != CK_TEMPLATE)
- {
- /* We've found a connection that can serve.
- * Do we have to initiate it?
- * Not if there is currently an IPSEC SA.
- * But if there is an IPSEC SA, then KLIPS would not
- * have generated the acquire. So we assume that there isn't one.
- * This may be redundant if a non-opportunistic
- * negotiation is already being attempted.
+ /* What connection shall we use?
+ * First try for one that explicitly handles the clients.
*/
-
- /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
-
- if(c->kind == CK_INSTANCE)
+ DBG(DBG_CONTROL,
+ {
+ char ours[ADDRTOT_BUF];
+ char his[ADDRTOT_BUF];
+ int ourport;
+ int hisport;
+
+ addrtot(&b->our_client, 0, ours, sizeof(ours));
+ addrtot(&b->peer_client, 0, his, sizeof(his));
+ ourport = ntohs(portof(&b->our_client));
+ hisport = ntohs(portof(&b->peer_client));
+ DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
+ , ours, ourport, his, hisport, b->transport_proto
+ , oppo_step_name[b->step], b->want);
+ });
+ if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client))
{
- char cib[CONN_INST_BUF];
- /* there is already an instance being negotiated, no nothing */
- DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it"
- , c->name
- , (fmt_conn_instance(c, cib), cib)));
- /* XXX-mcr - return; */
+ cannot_oppo(NULL, b, "impossible IP address");
}
-
- /* otherwise, there is some kind of static conn that can handle
- * this connection, so we initiate it */
-
-#ifdef KLIPS
- if (b->held)
+ else if ((c = find_connection_for_clients(&sr
+ , &b->our_client
+ , &b->peer_client
+ , b->transport_proto)) == NULL)
{
- /* what should we do on failure? */
- (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client);
+ /* No connection explicitly handles the clients and there
+ * are no Opportunistic connections -- whine and give up.
+ * The failure policy cannot be gotten from a connection; we pick %pass.
+ */
+ cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair");
}
-#endif
- ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
- b->whackfd = NULL_FD; /* protect from close */
- }
- else
- {
- /* We are handling an opportunistic situation.
- * This involves several DNS lookup steps that require suspension.
- * Note: many facts might change while we're suspended.
- * Here be dragons.
- *
- * The first chunk of code handles the result of the previous
- * DNS query (if any). It also selects the kind of the next step.
- * The second chunk initiates the next DNS query (if any).
- */
- enum find_oppo_step next_step = fos_myid_ip_txt;
- err_t ugh = ac_ugh;
- char mycredentialstr[BUF_LEN];
- char cib[CONN_INST_BUF];
-
- DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s"
- , c->name
- , (fmt_conn_instance(c, cib), cib)));
-
-
- idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr));
-
- passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */
-
- /* handle any DNS answer; select next step */
-
- switch (b->step)
+ else if (c->kind != CK_TEMPLATE)
{
- case fos_start:
- /* just starting out: select first query step */
- next_step = fos_myid_ip_txt;
- break;
-
- case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
- ugh = check_txt_recs(MYID_IP, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s"
- , myid_str[MYID_IP]
- , ugh));
- if (!logged_myid_ip_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "can not use our IP (%s:TXT) as identity: %s"
- , myid_str[MYID_IP]
- , ugh);
- logged_myid_ip_txt_warning = TRUE;
- }
-
- next_step = fos_myid_hostname_txt;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_ip_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "using our IP (%s:TXT) as identity!"
- , myid_str[MYID_IP]);
- logged_myid_ip_txt_warning = TRUE;
- }
+ /* We've found a connection that can serve.
+ * Do we have to initiate it?
+ * Not if there is currently an IPSEC SA.
+ * But if there is an IPSEC SA, then KLIPS would not
+ * have generated the acquire. So we assume that there isn't one.
+ * This may be redundant if a non-opportunistic
+ * negotiation is already being attempted.
+ */
- next_step = fos_our_client;
- }
- break;
-
- case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
- ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our hostname as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh));
- if (!logged_myid_fqdn_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "can not use our hostname (%s:TXT) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh);
- logged_myid_fqdn_txt_warning = TRUE;
- }
-#ifdef USE_KEYRR
- next_step = fos_myid_ip_key;
- ugh = NULL; /* failure can be recovered from */
-#endif
- }
- else
- {
- /* we can use our hostname as OE identity for initiation */
- if (!logged_myid_fqdn_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "using our hostname (%s:TXT) as identity!"
- , myid_str[MYID_HOSTNAME]);
- logged_myid_fqdn_txt_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
+ /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
-#ifdef USE_KEYRR
- case fos_myid_ip_key: /* KEY for our default IP address as %myid */
- ugh = check_key_recs(MYID_IP, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s"
- , myid_str[MYID_IP]
- , ugh));
- if (!logged_myid_ip_key_warning)
+ if(c->kind == CK_INSTANCE)
{
- loglog(RC_LOG_SERIOUS
- , "can not use our IP (%s:KEY) as identity: %s"
- , myid_str[MYID_IP]
- , ugh);
- logged_myid_ip_key_warning = TRUE;
+ char cib[CONN_INST_BUF];
+ /* there is already an instance being negotiated, no nothing */
+ DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)));
+ /* XXX-mcr - return; */
}
- next_step = fos_myid_hostname_key;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_ip_key_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "using our IP (%s:KEY) as identity!"
- , myid_str[MYID_IP]);
- logged_myid_ip_key_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
-
- case fos_myid_hostname_key: /* KEY for our hostname as %myid */
- ugh = check_key_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh));
- if (!logged_myid_fqdn_key_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "can not use our hostname (%s:KEY) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh);
- logged_myid_fqdn_key_warning = TRUE;
- }
+ /* otherwise, there is some kind of static conn that can handle
+ * this connection, so we initiate it */
- next_step = fos_myid_hostname_key;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_fqdn_key_warning)
+#ifdef KLIPS
+ if (b->held)
{
- loglog(RC_LOG_SERIOUS
- , "using our hostname (%s:KEY) as identity!"
- , myid_str[MYID_HOSTNAME]);
- logged_myid_fqdn_key_warning = TRUE;
+ /* what should we do on failure? */
+ (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client);
}
- next_step = fos_our_client;
- }
- break;
#endif
-
- case fos_our_client: /* TXT for our client */
- {
- /* Our client is not us: we must check the TXT records.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
+ ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
+ b->whackfd = NULL_FD; /* protect from close */
+ }
+ else
+ {
+ /* We are handling an opportunistic situation.
+ * This involves several DNS lookup steps that require suspension.
+ * Note: many facts might change while we're suspended.
+ * Here be dragons.
+ *
+ * The first chunk of code handles the result of the previous
+ * DNS query (if any). It also selects the kind of the next step.
+ * The second chunk initiates the next DNS query (if any).
*/
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ enum find_oppo_step next_step = fos_myid_ip_txt;
+ err_t ugh = ac_ugh;
+ char mycredentialstr[BUF_LEN];
+ char cib[CONN_INST_BUF];
- next_step = fos_his_client; /* normal situation */
+ DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)));
+
- passert(sr != NULL);
+ idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr));
- if (our_RSA_pri == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (sameaddr(&sr->this.host_addr, &b->our_client))
- {
- /* this wasn't true when we started -- bail */
- ugh = "our IP address changed underfoot";
- }
- else if (!same_id(&ac->sgw_id, &sr->this.id))
- {
- /* this wasn't true when we started -- bail */
- ugh = "our ID changed underfoot";
- }
- else
+ passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */
+
+ /* handle any DNS answer; select next step */
+
+ switch (b->step)
{
- /* Similar to code in quick_inI1_outR1_tail
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR for our client delegates us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- passert(same_id(&gwp->gw_id, &sr->this.id));
-
- ugh = "TXT RR for our client has wrong key";
- /* If there is a key from the TXT record,
- * we count it as a win if we match the key.
- * If there was no key, we have a tentative win:
- * we need to check our KEY record to be sure.
- */
- if (!gwp->gw_key_present)
+ case fos_start:
+ /* just starting out: select first query step */
+ next_step = fos_myid_ip_txt;
+ break;
+
+ case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
+ ugh = check_txt_recs(MYID_IP, c, ac);
+ if (ugh != NULL)
{
- /* Success, but the TXT had no key
- * so we must check our our own KEY records.
- */
- next_step = fos_our_txt;
- ugh = NULL; /* good! */
- break;
+ /* cannot use our IP as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh));
+ if (!logged_myid_ip_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our IP (%s:TXT) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh);
+ logged_myid_ip_txt_warning = TRUE;
+ }
+
+ next_step = fos_myid_hostname_txt;
+ ugh = NULL; /* failure can be recovered from */
}
- if (same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ else
{
- ugh = NULL; /* good! */
- break;
+ /* we can use our IP as OE identity for initiation */
+ if (!logged_myid_ip_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our IP (%s:TXT) as identity!"
+ , myid_str[MYID_IP]);
+ logged_myid_ip_txt_warning = TRUE;
+ }
+
+ next_step = fos_our_client;
}
- }
- }
- }
- break;
-
- case fos_our_txt: /* TXT for us */
- {
- /* Check if TXT lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
-
- next_step = fos_his_client; /* unless we decide to look for KEY RR */
+ break;
- if (our_RSA_pri == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR for us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- passert(same_id(&gwp->gw_id, &sr->this.id));
-
- ugh = "TXT RR for us has wrong key";
- if (gwp->gw_key_present
- && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
+ ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
+ if (ugh != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("initiate on demand found TXT with right public key at: %s"
- , mycredentialstr));
- ugh = NULL;
- break;
- }
- }
+ /* cannot use our hostname as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh));
+ if (!logged_myid_fqdn_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our hostname (%s:TXT) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh);
+ logged_myid_fqdn_txt_warning = TRUE;
+ }
#ifdef USE_KEYRR
- if (ugh != NULL)
- {
- /* if no TXT with right key, try KEY */
- DBG(DBG_CONTROL,
- DBG_log("will try for KEY RR since initiate on demand found %s: %s"
- , ugh, mycredentialstr));
- next_step = fos_our_key;
- ugh = NULL;
- }
+ next_step = fos_myid_ip_key;
+ ugh = NULL; /* failure can be recovered from */
#endif
- }
- }
- break;
+ }
+ else
+ {
+ /* we can use our hostname as OE identity for initiation */
+ if (!logged_myid_fqdn_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our hostname (%s:TXT) as identity!"
+ , myid_str[MYID_HOSTNAME]);
+ logged_myid_fqdn_txt_warning = TRUE;
+ }
+ next_step = fos_our_client;
+ }
+ break;
#ifdef USE_KEYRR
- case fos_our_key: /* KEY for us */
- {
- /* Check if KEY lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ case fos_myid_ip_key: /* KEY for our default IP address as %myid */
+ ugh = check_key_recs(MYID_IP, c, ac);
+ if (ugh != NULL)
+ {
+ /* cannot use our IP as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh));
+ if (!logged_myid_ip_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our IP (%s:KEY) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh);
+ logged_myid_ip_key_warning = TRUE;
+ }
+
+ next_step = fos_myid_hostname_key;
+ ugh = NULL; /* failure can be recovered from */
+ }
+ else
+ {
+ /* we can use our IP as OE identity for initiation */
+ if (!logged_myid_ip_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our IP (%s:KEY) as identity!"
+ , myid_str[MYID_IP]);
+ logged_myid_ip_key_warning = TRUE;
+ }
+ next_step = fos_our_client;
+ }
+ break;
- next_step = fos_his_client; /* always */
+ case fos_myid_hostname_key: /* KEY for our hostname as %myid */
+ ugh = check_key_recs(MYID_HOSTNAME, c, ac);
+ if (ugh != NULL)
+ {
+ /* cannot use our IP as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh));
+ if (!logged_myid_fqdn_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our hostname (%s:KEY) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh);
+ logged_myid_fqdn_key_warning = TRUE;
+ }
+
+ next_step = fos_myid_hostname_key;
+ ugh = NULL; /* failure can be recovered from */
+ }
+ else
+ {
+ /* we can use our IP as OE identity for initiation */
+ if (!logged_myid_fqdn_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our hostname (%s:KEY) as identity!"
+ , myid_str[MYID_HOSTNAME]);
+ logged_myid_fqdn_key_warning = TRUE;
+ }
+ next_step = fos_our_client;
+ }
+ break;
+#endif
- if (our_RSA_pri == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- pubkey_list_t *kr;
-
- ugh = "no KEY RR found for us (and no good TXT RR)";
- for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
- {
- ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)";
- if (kr->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa))
+ case fos_our_client: /* TXT for our client */
{
- /* do this only once a day */
- if (!logged_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html."
- , mycredentialstr);
- logged_txt_warning = TRUE;
- }
- ugh = NULL; /* good! */
- break;
+ /* Our client is not us: we must check the TXT records.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
+ */
+ private_key_t *private = get_private_key(c);
+
+ next_step = fos_his_client; /* normal situation */
+
+ passert(sr != NULL);
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own RSA key";
+ }
+ else if (sameaddr(&sr->this.host_addr, &b->our_client))
+ {
+ /* this wasn't true when we started -- bail */
+ ugh = "our IP address changed underfoot";
+ }
+ else if (!same_id(&ac->sgw_id, &sr->this.id))
+ {
+ /* this wasn't true when we started -- bail */
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in quick_inI1_outR1_tail
+ * for checking the other side.
+ */
+ struct gw_info *gwp;
+
+ ugh = "no TXT RR for our client delegates us";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ passert(same_id(&gwp->gw_id, &sr->this.id));
+
+ ugh = "TXT RR for our client has wrong key";
+ /* If there is a key from the TXT record,
+ * we count it as a win if we match the key.
+ * If there was no key, we have a tentative win:
+ * we need to check our KEY record to be sure.
+ */
+ if (!gwp->gw_key_present)
+ {
+ /* Success, but the TXT had no key
+ * so we must check our our own KEY records.
+ */
+ next_step = fos_our_txt;
+ ugh = NULL; /* good! */
+ break;
+ }
+ if (private->belongs_to(private, gwp->key->public_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
}
- }
- }
- }
- break;
-#endif /* USE_KEYRR */
+ break;
- case fos_his_client: /* TXT for his client */
- {
- /* We've finished last DNS queries: TXT for his client.
- * Using the information, try to instantiate a connection
- * and start negotiating.
- * We now know the peer. The chosing of "c" ignored this,
- * so we will disregard its current value.
- * !!! We need to randomize the entry in gw that we choose.
- */
- next_step = fos_done; /* no more queries */
+ case fos_our_txt: /* TXT for us */
+ {
+ /* Check if TXT lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
+ */
+ private_key_t *private = get_private_key(c);
+
+ next_step = fos_his_client; /* unless we decide to look for KEY RR */
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own RSA key";
+ }
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ struct gw_info *gwp;
+
+ ugh = "no TXT RR for us";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ passert(same_id(&gwp->gw_id, &sr->this.id));
+
+ ugh = "TXT RR for us has wrong key";
+ if (gwp->gw_key_present &&
+ private->belongs_to(private, gwp->key->public_key))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("initiate on demand found TXT with right public key at: %s"
+ , mycredentialstr));
+ ugh = NULL;
+ break;
+ }
+ }
+#ifdef USE_KEYRR
+ if (ugh != NULL)
+ {
+ /* if no TXT with right key, try KEY */
+ DBG(DBG_CONTROL,
+ DBG_log("will try for KEY RR since initiate on demand found %s: %s"
+ , ugh, mycredentialstr));
+ next_step = fos_our_key;
+ ugh = NULL;
+ }
+#endif
+ }
+ }
+ break;
- c = build_outgoing_opportunistic_connection(ac->gateways_from_dns
- , &b->our_client
- , &b->peer_client);
+#ifdef USE_KEYRR
+ case fos_our_key: /* KEY for us */
+ {
+ /* Check if KEY lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
+ */
+ private_key_t *private = get_private_key(c);
+
+ next_step = fos_his_client; /* always */
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own RSA key";
+ }
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ pubkey_list_t *kr;
+
+ ugh = "no KEY RR found for us (and no good TXT RR)";
+ for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
+ {
+ ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)";
+ if (kr->key->alg == PUBKEY_ALG_RSA
+ && private->belongs_to(private, kr->key->public_key))
+ {
+ /* do this only once a day */
+ if (!logged_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html."
+ , mycredentialstr);
+ logged_txt_warning = TRUE;
+ }
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ }
+ break;
+#endif /* USE_KEYRR */
- if (c == NULL)
- {
- /* We cannot seem to instantiate a suitable connection:
- * complain clearly.
- */
- char ocb[ADDRTOT_BUF]
- , pcb[ADDRTOT_BUF]
- , pb[ADDRTOT_BUF];
-
- addrtot(&b->our_client, 0, ocb, sizeof(ocb));
- addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id));
- addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb));
- loglog(RC_OPPOFAILURE
- , "no suitable connection for opportunism"
- " between %s and %s with %s as peer"
- , ocb, pcb, pb);
+ case fos_his_client: /* TXT for his client */
+ {
+ /* We've finished last DNS queries: TXT for his client.
+ * Using the information, try to instantiate a connection
+ * and start negotiating.
+ * We now know the peer. The chosing of "c" ignored this,
+ * so we will disregard its current value.
+ * !!! We need to randomize the entry in gw that we choose.
+ */
+ next_step = fos_done; /* no more queries */
+
+ c = build_outgoing_opportunistic_connection(ac->gateways_from_dns
+ , &b->our_client
+ , &b->peer_client);
+
+ if (c == NULL)
+ {
+ /* We cannot seem to instantiate a suitable connection:
+ * complain clearly.
+ */
+ char ocb[ADDRTOT_BUF]
+ , pcb[ADDRTOT_BUF]
+ , pb[ADDRTOT_BUF];
+
+ addrtot(&b->our_client, 0, ocb, sizeof(ocb));
+ addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
+ passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id));
+ addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb));
+ loglog(RC_OPPOFAILURE
+ , "no suitable connection for opportunism"
+ " between %s and %s with %s as peer"
+ , ocb, pcb, pb);
#ifdef KLIPS
- if (b->held)
- {
- /* Replace HOLD with PASS.
- * The type of replacement *ought* to be
- * specified by policy.
- */
- (void) replace_bare_shunt(&b->our_client, &b->peer_client
- , BOTTOM_PRIO
- , SPI_PASS /* fail into PASS */
- , TRUE, b->transport_proto
- , "no suitable connection");
- }
+ if (b->held)
+ {
+ /* Replace HOLD with PASS.
+ * The type of replacement *ought* to be
+ * specified by policy.
+ */
+ (void) replace_bare_shunt(&b->our_client, &b->peer_client
+ , BOTTOM_PRIO
+ , SPI_PASS /* fail into PASS */
+ , TRUE, b->transport_proto
+ , "no suitable connection");
+ }
#endif
- }
- else
- {
- /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
- passert(c->kind == CK_INSTANCE);
- passert(c->gw_info != NULL);
- passert(HAS_IPSEC_POLICY(c->policy));
- passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing));
+ }
+ else
+ {
+ /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
+ passert(c->kind == CK_INSTANCE);
+ passert(c->gw_info != NULL);
+ passert(HAS_IPSEC_POLICY(c->policy));
+ passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing));
#ifdef KLIPS
- if (b->held)
- {
- /* what should we do on failure? */
- (void) assign_hold(c, &c->spd
- , b->transport_proto
- , &b->our_client, &b->peer_client);
- }
+ if (b->held)
+ {
+ /* what should we do on failure? */
+ (void) assign_hold(c, &c->spd
+ , b->transport_proto
+ , &b->our_client, &b->peer_client);
+ }
#endif
- c->gw_info->key->last_tried_time = now();
- ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
- b->whackfd = NULL_FD; /* protect from close */
- }
- }
- break;
+ c->gw_info->key->last_tried_time = now();
+ ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
+ b->whackfd = NULL_FD; /* protect from close */
+ }
+ }
+ break;
- default:
- bad_case(b->step);
- }
+ default:
+ bad_case(b->step);
+ }
- /* the second chunk: initiate the next DNS query (if any) */
- DBG(DBG_CONTROL,
- {
- char ours[ADDRTOT_BUF];
- char his[ADDRTOT_BUF];
+ /* the second chunk: initiate the next DNS query (if any) */
+ DBG(DBG_CONTROL,
+ {
+ char ours[ADDRTOT_BUF];
+ char his[ADDRTOT_BUF];
- addrtot(&b->our_client, 0, ours, sizeof(ours));
- addrtot(&b->peer_client, 0, his, sizeof(his));
- DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s"
- , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
- });
+ addrtot(&b->our_client, 0, ours, sizeof(ours));
+ addrtot(&b->peer_client, 0, his, sizeof(his));
+ DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s"
+ , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
+ });
- if (ugh != NULL)
- {
- b->policy_prio = c->prio;
- b->failure_shunt = shunt_policy_spi(c, FALSE);
- cannot_oppo(c, b, ugh);
- }
- else if (next_step == fos_done)
- {
- /* nothing to do */
- }
- else
- {
- /* set up the next query */
- struct find_oppo_continuation *cr = alloc_thing(struct find_oppo_continuation
- , "opportunistic continuation");
- struct id id;
-
- b->policy_prio = c->prio;
- b->failure_shunt = shunt_policy_spi(c, FALSE);
- cr->b = *b; /* copy; start hand off of whackfd */
- cr->b.failure_ok = FALSE;
- cr->b.step = next_step;
-
- for (sr = &c->spd
- ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client)
- ; sr = sr->next)
- ;
-
- if (sr == NULL)
- sr = &c->spd;
-
- /* If a %hold shunt has replaced the eroute for this template,
- * record this fact.
- */
- if (b->held
- && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr))
- {
- sr->routing = RT_ROUTED_ECLIPSED;
- eclipse_count++;
- }
-
- /* Switch to issue next query.
- * A case may turn out to be unnecessary. If so, it falls
- * through to the next case.
- * Figuring out what %myid can stand for must be done before
- * our client credentials are looked up: we must know what
- * the client credentials may use to identify us.
- * On the other hand, our own credentials should be looked
- * up after our clients in case our credentials are not
- * needed at all.
- * XXX this is a wasted effort if we don't have credentials
- * BUT they are not needed.
- */
- switch (next_step)
- {
- case fos_myid_ip_txt:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
+ if (ugh != NULL)
{
- cr->b.failure_ok = TRUE;
- cr->b.want = b->want = "TXT record for IP address as %myid";
- ugh = start_adns_query(&myids[MYID_IP]
- , &myids[MYID_IP]
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
+ b->policy_prio = c->prio;
+ b->failure_shunt = shunt_policy_spi(c, FALSE);
+ cannot_oppo(c, b, ugh);
}
- cr->b.step = fos_myid_hostname_txt;
- /* fall through */
-
- case fos_myid_hostname_txt:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
+ else if (next_step == fos_done)
+ {
+ /* nothing to do */
+ }
+ else
{
+ /* set up the next query */
+ struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation);
+ struct id id;
+
+ b->policy_prio = c->prio;
+ b->failure_shunt = shunt_policy_spi(c, FALSE);
+ cr->b = *b; /* copy; start hand off of whackfd */
+ cr->b.failure_ok = FALSE;
+ cr->b.step = next_step;
+
+ for (sr = &c->spd
+ ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client)
+ ; sr = sr->next)
+ ;
+
+ if (sr == NULL)
+ sr = &c->spd;
+
+ /* If a %hold shunt has replaced the eroute for this template,
+ * record this fact.
+ */
+ if (b->held
+ && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr))
+ {
+ sr->routing = RT_ROUTED_ECLIPSED;
+ eclipse_count++;
+ }
+
+ /* Switch to issue next query.
+ * A case may turn out to be unnecessary. If so, it falls
+ * through to the next case.
+ * Figuring out what %myid can stand for must be done before
+ * our client credentials are looked up: we must know what
+ * the client credentials may use to identify us.
+ * On the other hand, our own credentials should be looked
+ * up after our clients in case our credentials are not
+ * needed at all.
+ * XXX this is a wasted effort if we don't have credentials
+ * BUT they are not needed.
+ */
+ switch (next_step)
+ {
+ case fos_myid_ip_txt:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
+ cr->b.failure_ok = TRUE;
+ cr->b.want = b->want = "TXT record for IP address as %myid";
+ ugh = start_adns_query(&myids[MYID_IP]
+ , &myids[MYID_IP]
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
+ cr->b.step = fos_myid_hostname_txt;
+ /* fall through */
+
+ case fos_myid_hostname_txt:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
#ifdef USE_KEYRR
- cr->b.failure_ok = TRUE;
+ cr->b.failure_ok = TRUE;
#else
- cr->b.failure_ok = FALSE;
+ cr->b.failure_ok = FALSE;
#endif
- cr->b.want = b->want = "TXT record for hostname as %myid";
- ugh = start_adns_query(&myids[MYID_HOSTNAME]
- , &myids[MYID_HOSTNAME]
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
- }
+ cr->b.want = b->want = "TXT record for hostname as %myid";
+ ugh = start_adns_query(&myids[MYID_HOSTNAME]
+ , &myids[MYID_HOSTNAME]
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
#ifdef USE_KEYRR
- cr->b.step = fos_myid_ip_key;
- /* fall through */
-
- case fos_myid_ip_key:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = TRUE;
- cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)";
- ugh = start_adns_query(&myids[MYID_IP]
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
- break;
- }
- cr->b.step = fos_myid_hostname_key;
- /* fall through */
-
- case fos_myid_hostname_key:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = FALSE; /* last attempt! */
- cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)";
- ugh = start_adns_query(&myids[MYID_HOSTNAME]
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
- break;
- }
+ cr->b.step = fos_myid_ip_key;
+ /* fall through */
+
+ case fos_myid_ip_key:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
+ cr->b.failure_ok = TRUE;
+ cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)";
+ ugh = start_adns_query(&myids[MYID_IP]
+ , (const struct id *) NULL /* security gateway meaningless */
+ , T_KEY
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
+ cr->b.step = fos_myid_hostname_key;
+ /* fall through */
+
+ case fos_myid_hostname_key:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
+ cr->b.failure_ok = FALSE; /* last attempt! */
+ cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)";
+ ugh = start_adns_query(&myids[MYID_HOSTNAME]
+ , (const struct id *) NULL /* security gateway meaningless */
+ , T_KEY
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
#endif
- cr->b.step = fos_our_client;
- /* fall through */
-
- case fos_our_client: /* TXT for our client */
- if (!sameaddr(&c->spd.this.host_addr, &b->our_client))
- {
- /* Check that at least one TXT(reverse(b->our_client)) is workable.
- * Note: {unshare|free}_id_content not needed for id: ephemeral.
- */
- cr->b.want = b->want = "our client's TXT record";
- iptoid(&b->our_client, &id);
- ugh = start_adns_query(&id
- , &c->spd.this.id /* we are the security gateway */
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
- }
- cr->b.step = fos_our_txt;
- /* fall through */
-
- case fos_our_txt: /* TXT for us */
- cr->b.failure_ok = b->failure_ok = TRUE;
- cr->b.want = b->want = "our TXT record";
- ugh = start_adns_query(&sr->this.id
- , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
+ cr->b.step = fos_our_client;
+ /* fall through */
+
+ case fos_our_client: /* TXT for our client */
+ if (!sameaddr(&c->spd.this.host_addr, &b->our_client))
+ {
+ /* Check that at least one TXT(reverse(b->our_client)) is workable.
+ * Note: {unshare|free}_id_content not needed for id: ephemeral.
+ */
+ cr->b.want = b->want = "our client's TXT record";
+ iptoid(&b->our_client, &id);
+ ugh = start_adns_query(&id
+ , &c->spd.this.id /* we are the security gateway */
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
+ cr->b.step = fos_our_txt;
+ /* fall through */
+
+ case fos_our_txt: /* TXT for us */
+ cr->b.failure_ok = b->failure_ok = TRUE;
+ cr->b.want = b->want = "our TXT record";
+ ugh = start_adns_query(&sr->this.id
+ , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
#ifdef USE_KEYRR
- case fos_our_key: /* KEY for us */
- cr->b.want = b->want = "our KEY record";
- cr->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&sr->this.id
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
- break;
+ case fos_our_key: /* KEY for us */
+ cr->b.want = b->want = "our KEY record";
+ cr->b.failure_ok = b->failure_ok = FALSE;
+ ugh = start_adns_query(&sr->this.id
+ , (const struct id *) NULL /* security gateway meaningless */
+ , T_KEY
+ , continue_oppo
+ , &cr->ac);
+ break;
#endif /* USE_KEYRR */
- case fos_his_client: /* TXT for his client */
- /* note: {unshare|free}_id_content not needed for id: ephemeral */
- cr->b.want = b->want = "target's TXT record";
- cr->b.failure_ok = b->failure_ok = FALSE;
- iptoid(&b->peer_client, &id);
- ugh = start_adns_query(&id
- , (const struct id *) NULL /* security gateway unconstrained */
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
-
- default:
- bad_case(next_step);
- }
+ case fos_his_client: /* TXT for his client */
+ /* note: {unshare|free}_id_content not needed for id: ephemeral */
+ cr->b.want = b->want = "target's TXT record";
+ cr->b.failure_ok = b->failure_ok = FALSE;
+ iptoid(&b->peer_client, &id);
+ ugh = start_adns_query(&id
+ , (const struct id *) NULL /* security gateway unconstrained */
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+
+ default:
+ bad_case(next_step);
+ }
- if (ugh == NULL)
- b->whackfd = NULL_FD; /* complete hand-off */
- else
- cannot_oppo(c, b, ugh);
+ if (ugh == NULL)
+ b->whackfd = NULL_FD; /* complete hand-off */
+ else
+ cannot_oppo(c, b, ugh);
+ }
}
- }
- close_any(b->whackfd);
+ close_any(b->whackfd);
}
void
terminate_connection(const char *nm)
{
- /* Loop because more than one may match (master and instances)
- * But at least one is required (enforced by con_by_name).
- */
- struct connection *c = con_by_name(nm, TRUE);
-
- if (c == NULL || !c->ikev1)
- return;
+ /* Loop because more than one may match (master and instances)
+ * But at least one is required (enforced by con_by_name).
+ */
+ struct connection *c = con_by_name(nm, TRUE);
- do
- {
- struct connection *n = c->ac_next; /* grab this before c might disappear */
+ if (c == NULL || !c->ikev1)
+ return;
- if (streq(c->name, nm)
- && c->kind >= CK_PERMANENT
- && !NEVER_NEGOTIATE(c->policy))
+ do
{
- set_cur_connection(c);
- plog("terminating SAs using this connection");
- c->policy &= ~POLICY_UP;
- flush_pending_by_connection(c);
- delete_states_by_connection(c, FALSE);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, FALSE);
- reset_cur_connection();
- }
- c = n;
- } while (c != NULL);
+ struct connection *n = c->ac_next; /* grab this before c might disappear */
+
+ if (streq(c->name, nm)
+ && c->kind >= CK_PERMANENT
+ && !NEVER_NEGOTIATE(c->policy))
+ {
+ set_cur_connection(c);
+ plog("terminating SAs using this connection");
+ c->policy &= ~POLICY_UP;
+ flush_pending_by_connection(c);
+ delete_states_by_connection(c, FALSE);
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, FALSE);
+ reset_cur_connection();
+ }
+ c = n;
+ } while (c != NULL);
}
/* an ISAKMP SA has been established.
* Note the serial number, and release any connections with
* the same peer ID but different peer IP address.
*/
-bool uniqueIDs = FALSE; /* --uniqueids? */
+bool uniqueIDs = FALSE; /* --uniqueids? */
void
ISAKMP_SA_established(struct connection *c, so_serial_t serial)
{
- c->newest_isakmp_sa = serial;
-
- /* the connection is now oriented so that we are able to determine
- * whether we are a mode config server with a virtual IP to send.
- */
- if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip)
- c->spd.that.modecfg = TRUE;
-
- if (uniqueIDs)
- {
- /* for all connections: if the same Phase 1 IDs are used
- * for a different IP address, unorient that connection.
- */
- struct connection *d;
+ c->newest_isakmp_sa = serial;
- for (d = connections; d != NULL; )
+ /* the connection is now oriented so that we are able to determine
+ * whether we are a mode config server with a virtual IP to send.
+ */
+ if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip)
+ c->spd.that.modecfg = TRUE;
+
+ if (uniqueIDs)
{
- struct connection *next = d->ac_next; /* might move underneath us */
-
- if (d->kind >= CK_PERMANENT
- && same_id(&c->spd.this.id, &d->spd.this.id)
- && same_id(&c->spd.that.id, &d->spd.that.id)
- && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
- {
- release_connection(d, FALSE);
- }
- d = next;
+ /* for all connections: if the same Phase 1 IDs are used
+ * for a different IP address, unorient that connection.
+ */
+ struct connection *d;
+
+ for (d = connections; d != NULL; )
+ {
+ struct connection *next = d->ac_next; /* might move underneath us */
+
+ if (d->kind >= CK_PERMANENT
+ && same_id(&c->spd.this.id, &d->spd.this.id)
+ && same_id(&c->spd.that.id, &d->spd.that.id)
+ && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
+ {
+ release_connection(d, FALSE);
+ }
+ d = next;
+ }
}
- }
}
/* Find the connection to connection c's peer's client with the
@@ -3056,108 +3048,108 @@ ISAKMP_SA_established(struct connection *c, so_serial_t serial)
*/
struct connection *
route_owner(struct connection *c
- , struct spd_route **srp
- , struct connection **erop
- , struct spd_route **esrp)
+ , struct spd_route **srp
+ , struct connection **erop
+ , struct spd_route **esrp)
{
- struct connection *d
- , *best_ro = c
- , *best_ero = c;
- struct spd_route *srd, *src;
- struct spd_route *best_sr, *best_esr;
- enum routing_t best_routing, best_erouting;
-
- passert(oriented(*c));
- best_sr = NULL;
- best_esr = NULL;
- best_routing = c->spd.routing;
- best_erouting = best_routing;
-
- for (d = connections; d != NULL; d = d->ac_next)
- {
- for (srd = &d->spd; srd; srd = srd->next)
+ struct connection *d
+ , *best_ro = c
+ , *best_ero = c;
+ struct spd_route *srd, *src;
+ struct spd_route *best_sr, *best_esr;
+ enum routing_t best_routing, best_erouting;
+
+ passert(oriented(*c));
+ best_sr = NULL;
+ best_esr = NULL;
+ best_routing = c->spd.routing;
+ best_erouting = best_routing;
+
+ for (d = connections; d != NULL; d = d->ac_next)
{
- if (srd->routing == RT_UNROUTED)
- continue;
-
- for (src = &c->spd; src; src=src->next)
- {
- if (!samesubnet(&src->that.client, &srd->that.client))
- continue;
- if (src->that.protocol != srd->that.protocol)
- continue;
- if (src->that.port != srd->that.port)
- continue;
- passert(oriented(*d));
- if (srd->routing > best_routing)
+ for (srd = &d->spd; srd; srd = srd->next)
{
- best_ro = d;
- best_sr = srd;
- best_routing = srd->routing;
- }
+ if (srd->routing == RT_UNROUTED)
+ continue;
- if (!samesubnet(&src->this.client, &srd->this.client))
- continue;
- if (src->this.protocol != srd->this.protocol)
- continue;
- if (src->this.port != srd->this.port)
- continue;
- if (srd->routing > best_erouting)
- {
- best_ero = d;
- best_esr = srd;
- best_erouting = srd->routing;
+ for (src = &c->spd; src; src=src->next)
+ {
+ if (!samesubnet(&src->that.client, &srd->that.client))
+ continue;
+ if (src->that.protocol != srd->that.protocol)
+ continue;
+ if (src->that.port != srd->that.port)
+ continue;
+ passert(oriented(*d));
+ if (srd->routing > best_routing)
+ {
+ best_ro = d;
+ best_sr = srd;
+ best_routing = srd->routing;
+ }
+
+ if (!samesubnet(&src->this.client, &srd->this.client))
+ continue;
+ if (src->this.protocol != srd->this.protocol)
+ continue;
+ if (src->this.port != srd->this.port)
+ continue;
+ if (srd->routing > best_erouting)
+ {
+ best_ero = d;
+ best_esr = srd;
+ best_erouting = srd->routing;
+ }
+ }
}
- }
}
- }
- DBG(DBG_CONTROL,
+ DBG(DBG_CONTROL,
+ {
+ char cib[CONN_INST_BUF];
+ err_t m = builddiag("route owner of \"%s\"%s %s:"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)
+ , enum_name(&routing_story, c->spd.routing));
+
+ if (!routed(best_ro->spd.routing))
+ m = builddiag("%s NULL", m);
+ else if (best_ro == c)
+ m = builddiag("%s self", m);
+ else
+ m = builddiag("%s \"%s\"%s %s", m
+ , best_ro->name
+ , (fmt_conn_instance(best_ro, cib), cib)
+ , enum_name(&routing_story, best_ro->spd.routing));
+
+ if (erop != NULL)
+ {
+ m = builddiag("%s; eroute owner:", m);
+ if (!erouted(best_ero->spd.routing))
+ m = builddiag("%s NULL", m);
+ else if (best_ero == c)
+ m = builddiag("%s self", m);
+ else
+ m = builddiag("%s \"%s\"%s %s", m
+ , best_ero->name
+ , (fmt_conn_instance(best_ero, cib), cib)
+ , enum_name(&routing_story, best_ero->spd.routing));
+ }
+
+ DBG_log("%s", m);
+ });
+
+ if (erop != NULL)
+ *erop = erouted(best_erouting)? best_ero : NULL;
+
+ if (srp != NULL )
{
- char cib[CONN_INST_BUF];
- err_t m = builddiag("route owner of \"%s\"%s %s:"
- , c->name
- , (fmt_conn_instance(c, cib), cib)
- , enum_name(&routing_story, c->spd.routing));
-
- if (!routed(best_ro->spd.routing))
- m = builddiag("%s NULL", m);
- else if (best_ro == c)
- m = builddiag("%s self", m);
- else
- m = builddiag("%s \"%s\"%s %s", m
- , best_ro->name
- , (fmt_conn_instance(best_ro, cib), cib)
- , enum_name(&routing_story, best_ro->spd.routing));
-
- if (erop != NULL)
- {
- m = builddiag("%s; eroute owner:", m);
- if (!erouted(best_ero->spd.routing))
- m = builddiag("%s NULL", m);
- else if (best_ero == c)
- m = builddiag("%s self", m);
- else
- m = builddiag("%s \"%s\"%s %s", m
- , best_ero->name
- , (fmt_conn_instance(best_ero, cib), cib)
- , enum_name(&routing_story, best_ero->spd.routing));
- }
-
- DBG_log("%s", m);
- });
-
- if (erop != NULL)
- *erop = erouted(best_erouting)? best_ero : NULL;
-
- if (srp != NULL )
- {
- *srp = best_sr;
- if (esrp != NULL )
- *esrp = best_esr;
- }
-
- return routed(best_routing)? best_ro : NULL;
+ *srp = best_sr;
+ if (esrp != NULL )
+ *esrp = best_esr;
+ }
+
+ return routed(best_routing)? best_ro : NULL;
}
/* Find a connection that owns the shunt eroute between subnets.
@@ -3167,20 +3159,20 @@ route_owner(struct connection *c
struct connection *
shunt_owner(const ip_subnet *ours, const ip_subnet *his)
{
- struct connection *c;
- struct spd_route *sr;
+ struct connection *c;
+ struct spd_route *sr;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- for (sr = &c->spd; sr; sr = sr->next)
+ for (c = connections; c != NULL; c = c->ac_next)
{
- if (shunt_erouted(sr->routing)
- && samesubnet(ours, &sr->this.client)
- && samesubnet(his, &sr->that.client))
- return c;
+ for (sr = &c->spd; sr; sr = sr->next)
+ {
+ if (shunt_erouted(sr->routing)
+ && samesubnet(ours, &sr->this.client)
+ && samesubnet(his, &sr->that.client))
+ return c;
+ }
}
- }
- return NULL;
+ return NULL;
}
/* Find some connection with this pair of hosts.
@@ -3191,25 +3183,25 @@ struct connection *
find_host_connection(const ip_address *me, u_int16_t my_port
, const ip_address *him, u_int16_t his_port, lset_t policy)
{
- struct connection *c = find_host_pair_connections(me, my_port, him, his_port);
-
- if (policy != LEMPTY)
- {
- lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
+ struct connection *c = find_host_pair_connections(me, my_port, him, his_port);
- /* if we have requirements for the policy,
- * choose the first matching connection.
- */
- while (c != NULL)
+ if (policy != LEMPTY)
{
- if (c->policy & auth_requested)
- {
- break;
- }
- c = c->hp_next;
+ lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
+
+ /* if we have requirements for the policy,
+ * choose the first matching connection.
+ */
+ while (c != NULL)
+ {
+ if (c->policy & auth_requested)
+ {
+ break;
+ }
+ c = c->hp_next;
+ }
}
- }
- return c;
+ return c;
}
/* given an up-until-now satisfactory connection, find the best connection
@@ -3266,187 +3258,197 @@ find_host_connection(const ip_address *me, u_int16_t my_port
*
* In the Initiator case, the particular connection might have been
* specified by whatever provoked Pluto to initiate. For example:
- * whack --initiate connection-name
+ * whack --initiate connection-name
* The advantages of switching connections when we're the Initiator seem
* less important than the disadvantages, so after FreeS/WAN 1.9, we
* don't do this.
*/
-#define PRIO_NO_MATCH_FOUND 2048
+#define PRIO_NO_MATCH_FOUND 2048
struct connection *
refine_host_connection(const struct state *st, const struct id *peer_id
, chunk_t peer_ca)
{
- struct connection *c = st->st_connection;
- struct connection *d;
- struct connection *best_found = NULL;
- u_int16_t auth = st->st_oakley.auth;
- lset_t auth_policy = POLICY_PSK;
- const chunk_t *psk = NULL;
- bool wcpip; /* wildcard Peer IP? */
- int best_prio = PRIO_NO_MATCH_FOUND;
- int wildcards, our_pathlen, peer_pathlen;
-
- if (same_id(&c->spd.that.id, peer_id)
- && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen)
- && peer_pathlen == 0
- && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen)
- && our_pathlen == 0)
- {
- DBG(DBG_CONTROL,
- DBG_log("current connection is a full match"
- " -- no need to look further");
- )
- return c;
- }
-
- switch (auth)
- {
- case OAKLEY_PRESHARED_KEY:
- auth_policy = POLICY_PSK;
- psk = get_preshared_secret(c);
- /* It should be virtually impossible to fail to find PSK:
- * we just used it to decode the current message!
- */
- if (psk == NULL)
- return NULL; /* cannot determine PSK! */
- break;
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- auth_policy = POLICY_XAUTH_PSK;
- psk = get_preshared_secret(c);
- if (psk == NULL)
- return NULL; /* cannot determine PSK! */
- break;
- case OAKLEY_RSA_SIG:
- auth_policy = POLICY_RSASIG;
- break;
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- auth_policy = POLICY_XAUTH_RSASIG;
- break;
- default:
- bad_case(auth);
- }
-
- /* The current connection won't do: search for one that will.
- * First search for one with the same pair of hosts.
- * If that fails, search for a suitable Road Warrior or Opportunistic
- * connection (i.e. wildcard peer IP).
- * We need to match:
- * - peer_id (slightly complicated by instantiation)
- * - if PSK auth, the key must not change (we used it to decode message)
- * - policy-as-used must be acceptable to new connection
- */
- d = c->host_pair->connections;
- for (wcpip = FALSE; ; wcpip = TRUE)
- {
- for (; d != NULL; d = d->hp_next)
+ struct connection *c = st->st_connection;
+ struct connection *d;
+ struct connection *best_found = NULL;
+ u_int16_t auth = st->st_oakley.auth;
+ lset_t auth_policy = POLICY_PSK;
+ const chunk_t *psk = NULL;
+ bool wcpip; /* wildcard Peer IP? */
+ int best_prio = PRIO_NO_MATCH_FOUND;
+ int wildcards, our_pathlen, peer_pathlen;
+
+ if (same_id(&c->spd.that.id, peer_id)
+ && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen)
+ && peer_pathlen == 0
+ && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen)
+ && our_pathlen == 0)
{
- const char *match_name[] = {"no", "ok"};
-
- bool matching_id = match_id(peer_id
- , &d->spd.that.id, &wildcards);
- bool matching_auth = (d->policy & auth_policy) != LEMPTY;
-
- bool matching_trust = trusted_ca(peer_ca
- , d->spd.that.ca, &peer_pathlen);
- bool matching_request = match_requested_ca(c->requested_ca
- , d->spd.this.ca, &our_pathlen);
- bool match = matching_id && matching_auth && matching_trust;
-
- int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards;
-
- prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen;
- prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen;
-
- DBG(DBG_CONTROLMORE,
- DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)"
- , d->name
- , match ? "full":" no"
- , match_name[matching_id]
- , match_name[matching_auth]
- , match_name[matching_trust]
- , match_name[matching_request]
- , match ? prio:PRIO_NO_MATCH_FOUND)
- )
-
- /* do we have a match? */
- if (!match)
- continue;
-
- /* ignore group connections */
- if (d->policy & POLICY_GROUP)
- continue;
-
- if (c->spd.that.host_port != d->spd.that.host_port
- && d->kind == CK_INSTANCE)
- {
- continue;
- }
-
- switch (auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- /* secret must match the one we already used */
- {
- const chunk_t *dpsk = get_preshared_secret(d);
-
- if (dpsk == NULL)
- continue; /* no secret */
+ DBG(DBG_CONTROL,
+ DBG_log("current connection is a full match"
+ " -- no need to look further");
+ )
+ return c;
+ }
- if (psk != dpsk)
- if (psk->len != dpsk->len
- || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
- continue; /* different secret */
+ switch (auth)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ auth_policy = POLICY_PSK;
+ psk = get_preshared_secret(c);
+ /* It should be virtually impossible to fail to find PSK:
+ * we just used it to decode the current message!
+ */
+ if (psk == NULL)
+ {
+ return NULL; /* cannot determine PSK! */
}
break;
-
- case OAKLEY_RSA_SIG:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- /*
- * We must at least be able to find our private key
- .*/
- if (d->spd.this.sc == NULL /* no smartcard */
- && get_RSA_private_key(d) == NULL) /* no private key */
- continue;
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth_policy = POLICY_XAUTH_PSK;
+ psk = get_preshared_secret(c);
+ if (psk == NULL)
+ {
+ return NULL; /* cannot determine PSK! */
+ }
break;
-
- default:
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ auth_policy = POLICY_PUBKEY;
+ break;
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth_policy = POLICY_XAUTH_RSASIG;
+ break;
+ default:
bad_case(auth);
- }
-
- /* d has passed all the tests.
- * We'll go with it if the Peer ID was an exact match.
- */
- if (prio == 0)
- {
- return d;
- }
-
- /* We'll remember it as best_found in case an exact
- * match doesn't come along.
- */
- if (prio < best_prio)
- {
- best_found = d;
- best_prio = prio;
- }
}
- if (wcpip)
- return best_found; /* been around twice already */
- /* Starting second time around.
- * We're willing to settle for a connection that needs Peer IP
- * instantiated: Road Warrior or Opportunistic.
- * Look on list of connections for host pair with wildcard Peer IP
+ /* The current connection won't do: search for one that will.
+ * First search for one with the same pair of hosts.
+ * If that fails, search for a suitable Road Warrior or Opportunistic
+ * connection (i.e. wildcard peer IP).
+ * We need to match:
+ * - peer_id (slightly complicated by instantiation)
+ * - if PSK auth, the key must not change (we used it to decode message)
+ * - policy-as-used must be acceptable to new connection
*/
- d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port
- , (ip_address *)NULL, c->spd.that.host_port);
- }
+ d = c->host_pair->connections;
+ for (wcpip = FALSE; ; wcpip = TRUE)
+ {
+ for (; d != NULL; d = d->hp_next)
+ {
+ const char *match_name[] = {"no", "ok"};
+
+ bool matching_id = match_id(peer_id
+ , &d->spd.that.id, &wildcards);
+ bool matching_auth = (d->policy & auth_policy) != LEMPTY;
+
+ bool matching_trust = trusted_ca(peer_ca
+ , d->spd.that.ca, &peer_pathlen);
+ bool matching_request = match_requested_ca(c->requested_ca
+ , d->spd.this.ca, &our_pathlen);
+ bool match = matching_id && matching_auth && matching_trust;
+
+ int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards;
+
+ prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen;
+ prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen;
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)"
+ , d->name
+ , match ? "full":" no"
+ , match_name[matching_id]
+ , match_name[matching_auth]
+ , match_name[matching_trust]
+ , match_name[matching_request]
+ , match ? prio:PRIO_NO_MATCH_FOUND)
+ )
+
+ /* do we have a match? */
+ if (!match)
+ continue;
+
+ /* ignore group connections */
+ if (d->policy & POLICY_GROUP)
+ continue;
+
+ if (c->spd.that.host_port != d->spd.that.host_port
+ && d->kind == CK_INSTANCE)
+ {
+ continue;
+ }
+
+ switch (auth)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ /* secret must match the one we already used */
+ {
+ const chunk_t *dpsk = get_preshared_secret(d);
+
+ if (dpsk == NULL)
+ continue; /* no secret */
+
+ if (psk != dpsk)
+ if (psk->len != dpsk->len
+ || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
+ continue; /* different secret */
+ }
+ break;
+
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ /*
+ * We must at least be able to find our private key
+ .*/
+ if (d->spd.this.sc == NULL /* no smartcard */
+ && get_private_key(d) == NULL) /* no private key */
+ continue;
+ break;
+
+ default:
+ bad_case(auth);
+ }
+
+ /* d has passed all the tests.
+ * We'll go with it if the Peer ID was an exact match.
+ */
+ if (prio == 0)
+ {
+ return d;
+ }
+
+ /* We'll remember it as best_found in case an exact
+ * match doesn't come along.
+ */
+ if (prio < best_prio)
+ {
+ best_found = d;
+ best_prio = prio;
+ }
+ }
+ if (wcpip)
+ return best_found; /* been around twice already */
+
+ /* Starting second time around.
+ * We're willing to settle for a connection that needs Peer IP
+ * instantiated: Road Warrior or Opportunistic.
+ * Look on list of connections for host pair with wildcard Peer IP
+ */
+ d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port
+ , (ip_address *)NULL, c->spd.that.host_port);
+ }
}
/**
@@ -3456,35 +3458,35 @@ refine_host_connection(const struct state *st, const struct id *peer_id
static bool
is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
{
- struct connection *d;
+ struct connection *d;
- for (d = connections; d != NULL; d = d->ac_next)
- {
- switch (d->kind)
+ for (d = connections; d != NULL; d = d->ac_next)
{
- case CK_PERMANENT:
- case CK_INSTANCE:
- if ((subnetinsubnet(peer_net,&d->spd.that.client) ||
- subnetinsubnet(&d->spd.that.client,peer_net))
- && !same_id(&d->spd.that.id, peer_id))
- {
- char buf[BUF_LEN];
- char client[SUBNETTOT_BUF];
-
- subnettot(peer_net, 0, client, sizeof(client));
- idtoa(&d->spd.that.id, buf, sizeof(buf));
- plog("Virtual IP %s is already used by '%s'", client, buf);
- idtoa(peer_id, buf, sizeof(buf));
- plog("Your ID is '%s'", buf);
- return TRUE; /* already used by another one */
- }
- break;
- case CK_GOING_AWAY:
- default:
- break;
+ switch (d->kind)
+ {
+ case CK_PERMANENT:
+ case CK_INSTANCE:
+ if ((subnetinsubnet(peer_net,&d->spd.that.client) ||
+ subnetinsubnet(&d->spd.that.client,peer_net))
+ && !same_id(&d->spd.that.id, peer_id))
+ {
+ char buf[BUF_LEN];
+ char client[SUBNETTOT_BUF];
+
+ subnettot(peer_net, 0, client, sizeof(client));
+ idtoa(&d->spd.that.id, buf, sizeof(buf));
+ plog("Virtual IP %s is already used by '%s'", client, buf);
+ idtoa(peer_id, buf, sizeof(buf));
+ plog("Your ID is '%s'", buf);
+ return TRUE; /* already used by another one */
+ }
+ break;
+ case CK_GOING_AWAY:
+ default:
+ break;
+ }
}
- }
- return FALSE; /* you can safely use it */
+ return FALSE; /* you can safely use it */
}
/* find_client_connection: given a connection suitable for ISAKMP
@@ -3512,9 +3514,9 @@ is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
* instantiation. They are the IDs that have been authenticated.
*/
-#define PATH_WEIGHT 1
-#define WILD_WEIGHT (MAX_CA_PATH_LEN+1)
-#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
+#define PATH_WEIGHT 1
+#define WILD_WEIGHT (MAX_CA_PATH_LEN+1)
+#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
/* fc_try: a helper function for find_client_connection */
static struct connection *
@@ -3530,121 +3532,121 @@ fc_try(const struct connection *c
, chunk_t peer_ca
, const ietfAttrList_t *peer_list)
{
- struct connection *d;
- struct connection *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
-
- const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
-
- for (d = hp->connections; d != NULL; d = d->hp_next)
- {
- struct spd_route *sr;
+ struct connection *d;
+ struct connection *best = NULL;
+ policy_prio_t best_prio = BOTTOM_PRIO;
+ int wildcards, pathlen;
- if (d->policy & POLICY_GROUP)
- continue;
-
- if (!(same_id(&c->spd.this.id, &d->spd.this.id)
- && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
- && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
- && group_membership(peer_list, d->name, d->spd.that.groups)))
- continue;
-
- /* compare protocol and ports */
- if (d->spd.this.protocol != our_protocol
- || d->spd.this.port != our_port
- || d->spd.that.protocol != peer_protocol
- || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
- continue;
-
- /* non-Opportunistic case:
- * our_client must match.
- *
- * So must peer_client, but the testing is complicated
- * by the fact that the peer might be a wildcard
- * and if so, the default value of that.client
- * won't match the default peer_net. The appropriate test:
- *
- * If d has a peer client, it must match peer_net.
- * If d has no peer client, peer_net must just have peer itself.
- */
+ const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
- for (sr = &d->spd; best != d && sr != NULL; sr = sr->next)
+ for (d = hp->connections; d != NULL; d = d->hp_next)
{
- policy_prio_t prio;
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+ struct spd_route *sr;
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
- subnettot(&sr->this.client, 0, s3, sizeof(s3));
- subnettot(&sr->that.client, 0, d3, sizeof(d3));
- DBG_log(" fc_try trying "
- "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d"
- , c->name, s1, c->spd.this.protocol, c->spd.this.port
- , d1, c->spd.that.protocol, c->spd.that.port
- , d->name, s3, sr->this.protocol, sr->this.port
- , d3, sr->that.protocol, sr->that.port);
- }
-#endif /* DEBUG */
+ if (d->policy & POLICY_GROUP)
+ continue;
- if (!samesubnet(&sr->this.client, our_net))
- continue;
+ if (!(same_id(&c->spd.this.id, &d->spd.this.id)
+ && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
+ && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
+ && group_membership(peer_list, d->name, d->spd.that.groups)))
+ continue;
- if (sr->that.has_client)
- {
- if (sr->that.has_client_wildcard)
- {
- if (!subnetinsubnet(peer_net, &sr->that.client))
+ /* compare protocol and ports */
+ if (d->spd.this.protocol != our_protocol
+ || d->spd.this.port != our_port
+ || d->spd.that.protocol != peer_protocol
+ || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
continue;
- }
- else
+
+ /* non-Opportunistic case:
+ * our_client must match.
+ *
+ * So must peer_client, but the testing is complicated
+ * by the fact that the peer might be a wildcard
+ * and if so, the default value of that.client
+ * won't match the default peer_net. The appropriate test:
+ *
+ * If d has a peer client, it must match peer_net.
+ * If d has no peer client, peer_net must just have peer itself.
+ */
+
+ for (sr = &d->spd; best != d && sr != NULL; sr = sr->next)
{
- if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
- continue;
- if (is_virtual_connection(d)
- && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
- || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
- continue;
+ policy_prio_t prio;
+#ifdef DEBUG
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
+ char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+
+ subnettot(our_net, 0, s1, sizeof(s1));
+ subnettot(peer_net, 0, d1, sizeof(d1));
+ subnettot(&sr->this.client, 0, s3, sizeof(s3));
+ subnettot(&sr->that.client, 0, d3, sizeof(d3));
+ DBG_log(" fc_try trying "
+ "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d"
+ , c->name, s1, c->spd.this.protocol, c->spd.this.port
+ , d1, c->spd.that.protocol, c->spd.that.port
+ , d->name, s3, sr->this.protocol, sr->this.port
+ , d3, sr->that.protocol, sr->that.port);
+ }
+#endif /* DEBUG */
+
+ if (!samesubnet(&sr->this.client, our_net))
+ continue;
+
+ if (sr->that.has_client)
+ {
+ if (sr->that.has_client_wildcard)
+ {
+ if (!subnetinsubnet(peer_net, &sr->that.client))
+ continue;
+ }
+ else
+ {
+ if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
+ continue;
+ if (is_virtual_connection(d)
+ && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
+ || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
+ continue;
+ }
+ }
+ else
+ {
+ if (!peer_net_is_host)
+ continue;
+ }
+
+ /* We've run the gauntlet -- success:
+ * We've got an exact match of subnets.
+ * The connection is feasible, but we continue looking for the best.
+ * The highest priority wins, implementing eroute-like rule.
+ * - a routed connection is preferrred
+ * - given that, the smallest number of ID wildcards are preferred
+ * - given that, the shortest CA pathlength is preferred
+ */
+ prio = PRIO_WEIGHT * routed(sr->routing)
+ + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
+ + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen)
+ + 1;
+ if (prio > best_prio)
+ {
+ best = d;
+ best_prio = prio;
+ }
}
- }
- else
- {
- if (!peer_net_is_host)
- continue;
- }
-
- /* We've run the gauntlet -- success:
- * We've got an exact match of subnets.
- * The connection is feasible, but we continue looking for the best.
- * The highest priority wins, implementing eroute-like rule.
- * - a routed connection is preferrred
- * - given that, the smallest number of ID wildcards are preferred
- * - given that, the shortest CA pathlength is preferred
- */
- prio = PRIO_WEIGHT * routed(sr->routing)
- + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
- + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen)
- + 1;
- if (prio > best_prio)
- {
- best = d;
- best_prio = prio;
- }
}
- }
- if (best != NULL && NEVER_NEGOTIATE(best->policy))
- best = NULL;
+ if (best != NULL && NEVER_NEGOTIATE(best->policy))
+ best = NULL;
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try concluding with %s [%ld]"
- , (best ? best->name : "none"), best_prio)
- )
- return best;
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" fc_try concluding with %s [%ld]"
+ , (best ? best->name : "none"), best_prio)
+ )
+ return best;
}
static struct connection *
@@ -3659,92 +3661,92 @@ fc_try_oppo(const struct connection *c
, chunk_t peer_ca
, const ietfAttrList_t *peer_list)
{
- struct connection *d;
- struct connection *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
+ struct connection *d;
+ struct connection *best = NULL;
+ policy_prio_t best_prio = BOTTOM_PRIO;
+ int wildcards, pathlen;
- for (d = hp->connections; d != NULL; d = d->hp_next)
- {
- struct spd_route *sr;
- policy_prio_t prio;
-
- if (d->policy & POLICY_GROUP)
- continue;
-
- if (!(same_id(&c->spd.this.id, &d->spd.this.id)
- && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
- && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
- && group_membership(peer_list, d->name, d->spd.that.groups)))
- continue;
-
- /* compare protocol and ports */
- if (d->spd.this.protocol != our_protocol
- || d->spd.this.port != our_port
- || d->spd.that.protocol != peer_protocol
- || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
- continue;
-
- /* Opportunistic case:
- * our_net must be inside d->spd.this.client
- * and peer_net must be inside d->spd.that.client
- * Note: this host_pair chain also has shunt
- * eroute conns (clear, drop), but they won't
- * be marked as opportunistic.
- */
- for (sr = &d->spd; sr != NULL; sr = sr->next)
+ for (d = hp->connections; d != NULL; d = d->hp_next)
{
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+ struct spd_route *sr;
+ policy_prio_t prio;
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
- subnettot(&sr->this.client, 0, s3, sizeof(s3));
- subnettot(&sr->that.client, 0, d3, sizeof(d3));
- DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s"
- , c->name, s1, d1, d->name, s3, d3);
- }
+ if (d->policy & POLICY_GROUP)
+ continue;
+
+ if (!(same_id(&c->spd.this.id, &d->spd.this.id)
+ && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
+ && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
+ && group_membership(peer_list, d->name, d->spd.that.groups)))
+ continue;
+
+ /* compare protocol and ports */
+ if (d->spd.this.protocol != our_protocol
+ || d->spd.this.port != our_port
+ || d->spd.that.protocol != peer_protocol
+ || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
+ continue;
+
+ /* Opportunistic case:
+ * our_net must be inside d->spd.this.client
+ * and peer_net must be inside d->spd.that.client
+ * Note: this host_pair chain also has shunt
+ * eroute conns (clear, drop), but they won't
+ * be marked as opportunistic.
+ */
+ for (sr = &d->spd; sr != NULL; sr = sr->next)
+ {
+#ifdef DEBUG
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
+ char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+
+ subnettot(our_net, 0, s1, sizeof(s1));
+ subnettot(peer_net, 0, d1, sizeof(d1));
+ subnettot(&sr->this.client, 0, s3, sizeof(s3));
+ subnettot(&sr->that.client, 0, d3, sizeof(d3));
+ DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s"
+ , c->name, s1, d1, d->name, s3, d3);
+ }
#endif /* DEBUG */
- if (!subnetinsubnet(our_net, &sr->this.client)
- || !subnetinsubnet(peer_net, &sr->that.client))
- continue;
-
- /* The connection is feasible, but we continue looking for the best.
- * The highest priority wins, implementing eroute-like rule.
- * - our smallest client subnet is preferred (longest mask)
- * - given that, his smallest client subnet is preferred
- * - given that, a routed connection is preferrred
- * - given that, the smallest number of ID wildcards are preferred
- * - given that, the shortest CA pathlength is preferred
- */
- prio = PRIO_WEIGHT * (d->prio + routed(sr->routing))
- + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
- + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen);
- if (prio > best_prio)
- {
- best = d;
- best_prio = prio;
- }
+ if (!subnetinsubnet(our_net, &sr->this.client)
+ || !subnetinsubnet(peer_net, &sr->that.client))
+ continue;
+
+ /* The connection is feasible, but we continue looking for the best.
+ * The highest priority wins, implementing eroute-like rule.
+ * - our smallest client subnet is preferred (longest mask)
+ * - given that, his smallest client subnet is preferred
+ * - given that, a routed connection is preferrred
+ * - given that, the smallest number of ID wildcards are preferred
+ * - given that, the shortest CA pathlength is preferred
+ */
+ prio = PRIO_WEIGHT * (d->prio + routed(sr->routing))
+ + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
+ + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen);
+ if (prio > best_prio)
+ {
+ best = d;
+ best_prio = prio;
+ }
+ }
+ }
+
+ /* if the best wasn't opportunistic, we fail: it must be a shunt */
+ if (best != NULL
+ && (NEVER_NEGOTIATE(best->policy)
+ || (best->policy & POLICY_OPPO) == LEMPTY))
+ {
+ best = NULL;
}
- }
-
- /* if the best wasn't opportunistic, we fail: it must be a shunt */
- if (best != NULL
- && (NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY))
- {
- best = NULL;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try_oppo concluding with %s [%ld]"
- , (best ? best->name : "none"), best_prio)
- )
- return best;
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" fc_try_oppo concluding with %s [%ld]"
+ , (best ? best->name : "none"), best_prio)
+ )
+ return best;
}
@@ -3754,28 +3756,28 @@ fc_try_oppo(const struct connection *c
chunk_t
get_peer_ca_and_groups(struct connection *c, const ietfAttrList_t **peer_list)
{
- struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
-
- *peer_list = NULL;
+ struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
- if (p1st != NULL
- && p1st->st_peer_pubkey != NULL
- && p1st->st_peer_pubkey->issuer.ptr != NULL)
- {
- x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
- , p1st->st_peer_pubkey->serial);;
+ *peer_list = NULL;
- if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
- *peer_list = ac->groups;
- else
+ if (p1st != NULL
+ && p1st->st_peer_pubkey != NULL
+ && p1st->st_peer_pubkey->issuer.ptr != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("no valid attribute cert found")
- )
+ x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
+ , p1st->st_peer_pubkey->serial);;
+
+ if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
+ *peer_list = ac->groups;
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("no valid attribute cert found")
+ )
+ }
+ return p1st->st_peer_pubkey->issuer;
}
- return p1st->st_peer_pubkey->issuer;
- }
- return empty_chunk;
+ return chunk_empty;
}
struct connection *
@@ -3784,325 +3786,325 @@ find_client_connection(struct connection *c
, const u_int8_t our_protocol, const u_int16_t our_port
, const u_int8_t peer_protocol, const u_int16_t peer_port)
{
- struct connection *d;
- struct spd_route *sr;
+ struct connection *d;
+ struct spd_route *sr;
- const ietfAttrList_t *peer_list = NULL;
- chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
+ const ietfAttrList_t *peer_list = NULL;
+ chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
-
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
-
- DBG_log("find_client_connection starting with %s"
- , (c ? c->name : "(none)"));
- DBG_log(" looking for %s:%d/%d -> %s:%d/%d"
- , s1, our_protocol, our_port
- , d1, peer_protocol, peer_port);
- }
-#endif /* DEBUG */
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- /* give priority to current connection
- * but even greater priority to a routed concrete connection
- */
- {
- struct connection *unrouted = NULL;
- int srnum = -1;
+ subnettot(our_net, 0, s1, sizeof(s1));
+ subnettot(peer_net, 0, d1, sizeof(d1));
+
+ DBG_log("find_client_connection starting with %s"
+ , (c ? c->name : "(none)"));
+ DBG_log(" looking for %s:%d/%d -> %s:%d/%d"
+ , s1, our_protocol, our_port
+ , d1, peer_protocol, peer_port);
+ }
+#endif /* DEBUG */
- for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next)
+ /* give priority to current connection
+ * but even greater priority to a routed concrete connection
+ */
{
- srnum++;
+ struct connection *unrouted = NULL;
+ int srnum = -1;
+
+ for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next)
+ {
+ srnum++;
#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
-
- subnettot(&sr->this.client, 0, s2, sizeof(s2));
- subnettot(&sr->that.client, 0, d2, sizeof(d2));
- DBG_log(" concrete checking against sr#%d %s -> %s"
- , srnum, s2, d2);
- }
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
+
+ subnettot(&sr->this.client, 0, s2, sizeof(s2));
+ subnettot(&sr->that.client, 0, d2, sizeof(d2));
+ DBG_log(" concrete checking against sr#%d %s -> %s"
+ , srnum, s2, d2);
+ }
#endif /* DEBUG */
- if (samesubnet(&sr->this.client, our_net)
- && samesubnet(&sr->that.client, peer_net)
- && sr->this.protocol == our_protocol
- && sr->this.port == our_port
- && sr->that.protocol == peer_protocol
- && sr->that.port == peer_port
- && group_membership(peer_list, c->name, sr->that.groups))
- {
- passert(oriented(*c));
- if (routed(sr->routing))
- return c;
-
- unrouted = c;
- }
- }
+ if (samesubnet(&sr->this.client, our_net)
+ && samesubnet(&sr->that.client, peer_net)
+ && sr->this.protocol == our_protocol
+ && sr->this.port == our_port
+ && sr->that.protocol == peer_protocol
+ && sr->that.port == peer_port
+ && group_membership(peer_list, c->name, sr->that.groups))
+ {
+ passert(oriented(*c));
+ if (routed(sr->routing))
+ return c;
- /* exact match? */
- d = fc_try(c, c->host_pair, NULL, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
+ unrouted = c;
+ }
+ }
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try %s gives %s"
- , c->name
- , (d ? d->name : "none"))
- )
+ /* exact match? */
+ d = fc_try(c, c->host_pair, NULL, our_net, peer_net
+ , our_protocol, our_port, peer_protocol, peer_port
+ , peer_ca, peer_list);
- if (d == NULL)
- d = unrouted;
- }
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" fc_try %s gives %s"
+ , c->name
+ , (d ? d->name : "none"))
+ )
- if (d == NULL)
- {
- /* look for an abstract connection to match */
- struct spd_route *sr;
- struct host_pair *hp = NULL;
+ if (d == NULL)
+ d = unrouted;
+ }
- for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next)
+ if (d == NULL)
{
- hp = find_host_pair(&sr->this.host_addr
- , sr->this.host_port
- , NULL
- , sr->that.host_port);
+ /* look for an abstract connection to match */
+ struct spd_route *sr;
+ struct host_pair *hp = NULL;
+
+ for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next)
+ {
+ hp = find_host_pair(&sr->this.host_addr
+ , sr->this.host_port
+ , NULL
+ , sr->that.host_port);
#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
- subnettot(&sr->this.client, 0, s2, sizeof(s2));
- subnettot(&sr->that.client, 0, d2, sizeof(d2));
+ subnettot(&sr->this.client, 0, s2, sizeof(s2));
+ subnettot(&sr->that.client, 0, d2, sizeof(d2));
- DBG_log(" checking hostpair %s -> %s is %s"
- , s2, d2
- , (hp ? "found" : "not found"));
- }
+ DBG_log(" checking hostpair %s -> %s is %s"
+ , s2, d2
+ , (hp ? "found" : "not found"));
+ }
#endif /* DEBUG */
- }
+ }
- if (hp != NULL)
- {
- /* RW match with actual peer_id or abstract peer_id? */
- d = fc_try(c, hp, NULL, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
-
- if (d == NULL
- && subnetishost(our_net)
- && subnetishost(peer_net))
- {
- /* Opportunistic match?
- * Always use abstract peer_id.
- * Note that later instantiation will result in the same peer_id.
- */
- d = fc_try_oppo(c, hp, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
- }
+ if (hp != NULL)
+ {
+ /* RW match with actual peer_id or abstract peer_id? */
+ d = fc_try(c, hp, NULL, our_net, peer_net
+ , our_protocol, our_port, peer_protocol, peer_port
+ , peer_ca, peer_list);
+
+ if (d == NULL
+ && subnetishost(our_net)
+ && subnetishost(peer_net))
+ {
+ /* Opportunistic match?
+ * Always use abstract peer_id.
+ * Note that later instantiation will result in the same peer_id.
+ */
+ d = fc_try_oppo(c, hp, our_net, peer_net
+ , our_protocol, our_port, peer_protocol, peer_port
+ , peer_ca, peer_list);
+ }
+ }
}
- }
- DBG(DBG_CONTROLMORE,
- DBG_log(" concluding with d = %s"
- , (d ? d->name : "none"))
- )
- return d;
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" concluding with d = %s"
+ , (d ? d->name : "none"))
+ )
+ return d;
}
int
connection_compare(const struct connection *ca
, const struct connection *cb)
{
- int ret;
-
- /* DBG_log("comparing %s to %s", ca->name, cb->name); */
-
- ret = strcasecmp(ca->name, cb->name);
- if (ret != 0)
- return ret;
-
- ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
- if (ret != 0)
- return ret;
-
- /* same name, and same type */
- switch (ca->kind)
- {
- case CK_INSTANCE:
- return ca->instance_serial < cb->instance_serial ? -1
- : ca->instance_serial > cb->instance_serial ? 1
- : 0;
-
- default:
- return ca->prio < cb->prio ? -1
- : ca->prio > cb->prio ? 1
- : 0;
- }
+ int ret;
+
+ /* DBG_log("comparing %s to %s", ca->name, cb->name); */
+
+ ret = strcasecmp(ca->name, cb->name);
+ if (ret != 0)
+ return ret;
+
+ ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
+ if (ret != 0)
+ return ret;
+
+ /* same name, and same type */
+ switch (ca->kind)
+ {
+ case CK_INSTANCE:
+ return ca->instance_serial < cb->instance_serial ? -1
+ : ca->instance_serial > cb->instance_serial ? 1
+ : 0;
+
+ default:
+ return ca->prio < cb->prio ? -1
+ : ca->prio > cb->prio ? 1
+ : 0;
+ }
}
static int
connection_compare_qsort(const void *a, const void *b)
{
- return connection_compare(*(const struct connection *const *)a
- , *(const struct connection *const *)b);
+ return connection_compare(*(const struct connection *const *)a
+ , *(const struct connection *const *)b);
}
void
show_connections_status(bool all, const char *name)
{
- struct connection *c;
- int count, i;
- struct connection **array;
-
- /* make an array of connections, and sort it */
- count = 0;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->ikev1 && (name == NULL || streq(c->name, name)))
- count++;
- }
- array = alloc_bytes(sizeof(struct connection *)*count, "connection array");
-
- count=0;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->ikev1 && (name == NULL || streq(c->name, name)))
- array[count++]=c;
- }
-
- /* sort it! */
- qsort(array, count, sizeof(struct connection *), connection_compare_qsort);
-
- for (i = 0; i < count; i++)
- {
- const char *ifn;
- char instance[1 + 10 + 1];
- char prio[POLICY_PRIO_BUF];
-
- c = array[i];
-
- ifn = oriented(*c)? c->interface->rname : "";
-
- instance[0] = '\0';
- if (c->kind == CK_INSTANCE && c->instance_serial != 0)
- snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial);
-
- /* show topology */
+ struct connection *c;
+ int count, i;
+ struct connection **array;
+
+ /* make an array of connections, and sort it */
+ count = 0;
+ for (c = connections; c != NULL; c = c->ac_next)
{
- char topo[CONNECTION_BUF];
- struct spd_route *sr = &c->spd;
- int num=0;
-
- while (sr != NULL)
- {
- (void) format_connection(topo, sizeof(topo), c, sr);
- whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
- , c->name, instance, topo
- , enum_name(&routing_story, sr->routing)
- , sr->eroute_owner);
- sr = sr->next;
- num++;
- }
+ if (c->ikev1 && (name == NULL || streq(c->name, name)))
+ count++;
}
+ array = malloc(sizeof(struct connection *)*count);
- if (all)
+ count=0;
+ for (c = connections; c != NULL; c = c->ac_next)
{
- /* show CAs if defined */
- if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL)
- {
- char this_ca[BUF_LEN], that_ca[BUF_LEN];
-
- dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any");
- dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any");
-
- whack_log(RC_COMMENT
- , "\"%s\"%s: CAs: '%s'...'%s'"
- , c->name
- , instance
- , this_ca
- , that_ca);
- }
-
- /* show group attributes if defined */
- if (c->spd.that.groups != NULL)
- {
- char buf[BUF_LEN];
-
- format_groups(c->spd.that.groups, buf, BUF_LEN);
- whack_log(RC_COMMENT
- , "\"%s\"%s: groups: %s"
- , c->name
- , instance
- , buf);
- }
-
- whack_log(RC_COMMENT
- , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;"
- " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu"
- , c->name
- , instance
- , (unsigned long) c->sa_ike_life_seconds
- , (unsigned long) c->sa_ipsec_life_seconds
- , (unsigned long) c->sa_rekey_margin
- , (unsigned long) c->sa_rekey_fuzz
- , (unsigned long) c->sa_keying_tries);
-
- /* show DPD parameters if defined */
-
- if (c->dpd_action != DPD_ACTION_NONE)
- whack_log(RC_COMMENT
- , "\"%s\"%s: dpd_action: %s;"
- " dpd_delay: %lus; dpd_timeout: %lus;"
- , c->name
- , instance
- , enum_show(&dpd_action_names, c->dpd_action)
- , (unsigned long) c->dpd_delay
- , (unsigned long) c->dpd_timeout);
-
- if (c->policy_next)
- {
- whack_log(RC_COMMENT
- , "\"%s\"%s: policy_next: %s"
- , c->name, instance, c->policy_next->name);
- }
-
- /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */
- fmt_policy_prio(c->prio, prio);
- whack_log(RC_COMMENT
- , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; "
- , c->name
- , instance
- , prettypolicy(c->policy)
- , c->spd.this.key_from_DNS_on_demand? "+lKOD" : ""
- , c->spd.that.key_from_DNS_on_demand? "+rKOD" : ""
- , prio
- , ifn);
+ if (c->ikev1 && (name == NULL || streq(c->name, name)))
+ array[count++]=c;
}
- whack_log(RC_COMMENT
- , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; "
- , c->name
- , instance
- , c->newest_isakmp_sa
- , c->newest_ipsec_sa);
-
- if (all)
+ /* sort it! */
+ qsort(array, count, sizeof(struct connection *), connection_compare_qsort);
+
+ for (i = 0; i < count; i++)
{
- ike_alg_show_connection(c, instance);
- kernel_alg_show_connection(c, instance);
+ const char *ifn;
+ char instance[1 + 10 + 1];
+ char prio[POLICY_PRIO_BUF];
+
+ c = array[i];
+
+ ifn = oriented(*c)? c->interface->rname : "";
+
+ instance[0] = '\0';
+ if (c->kind == CK_INSTANCE && c->instance_serial != 0)
+ snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial);
+
+ /* show topology */
+ {
+ char topo[CONNECTION_BUF];
+ struct spd_route *sr = &c->spd;
+ int num=0;
+
+ while (sr != NULL)
+ {
+ (void) format_connection(topo, sizeof(topo), c, sr);
+ whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
+ , c->name, instance, topo
+ , enum_name(&routing_story, sr->routing)
+ , sr->eroute_owner);
+ sr = sr->next;
+ num++;
+ }
+ }
+
+ if (all)
+ {
+ /* show CAs if defined */
+ if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL)
+ {
+ char this_ca[BUF_LEN], that_ca[BUF_LEN];
+
+ dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any");
+ dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any");
+
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: CAs: '%s'...'%s'"
+ , c->name
+ , instance
+ , this_ca
+ , that_ca);
+ }
+
+ /* show group attributes if defined */
+ if (c->spd.that.groups != NULL)
+ {
+ char buf[BUF_LEN];
+
+ format_groups(c->spd.that.groups, buf, BUF_LEN);
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: groups: %s"
+ , c->name
+ , instance
+ , buf);
+ }
+
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;"
+ " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu"
+ , c->name
+ , instance
+ , (unsigned long) c->sa_ike_life_seconds
+ , (unsigned long) c->sa_ipsec_life_seconds
+ , (unsigned long) c->sa_rekey_margin
+ , (unsigned long) c->sa_rekey_fuzz
+ , (unsigned long) c->sa_keying_tries);
+
+ /* show DPD parameters if defined */
+
+ if (c->dpd_action != DPD_ACTION_NONE)
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: dpd_action: %N;"
+ " dpd_delay: %lus; dpd_timeout: %lus;"
+ , c->name
+ , instance
+ , dpd_action_names, c->dpd_action
+ , (unsigned long) c->dpd_delay
+ , (unsigned long) c->dpd_timeout);
+
+ if (c->policy_next)
+ {
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: policy_next: %s"
+ , c->name, instance, c->policy_next->name);
+ }
+
+ /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */
+ fmt_policy_prio(c->prio, prio);
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; "
+ , c->name
+ , instance
+ , prettypolicy(c->policy)
+ , c->spd.this.key_from_DNS_on_demand? "+lKOD" : ""
+ , c->spd.that.key_from_DNS_on_demand? "+rKOD" : ""
+ , prio
+ , ifn);
+ }
+
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; "
+ , c->name
+ , instance
+ , c->newest_isakmp_sa
+ , c->newest_ipsec_sa);
+
+ if (all)
+ {
+ ike_alg_show_connection(c, instance);
+ kernel_alg_show_connection(c, instance);
+ }
}
- }
- if (count > 0)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
+ if (count > 0)
+ whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
- pfree(array);
+ free(array);
}
/* struct pending, the structure representing Quick Mode
@@ -4111,14 +4113,14 @@ show_connections_status(bool all, const char *name)
*/
struct pending {
- int whack_sock;
- struct state *isakmp_sa;
- struct connection *connection;
- lset_t policy;
- unsigned long try;
- so_serial_t replacing;
-
- struct pending *next;
+ int whack_sock;
+ struct state *isakmp_sa;
+ struct connection *connection;
+ lset_t policy;
+ unsigned long try;
+ so_serial_t replacing;
+
+ struct pending *next;
};
/* queue a Quick Mode negotiation pending completion of a suitable Main Mode */
@@ -4130,36 +4132,36 @@ add_pending(int whack_sock
, unsigned long try
, so_serial_t replacing)
{
- bool already_queued = FALSE;
- struct pending *p = c->host_pair->pending;
+ bool already_queued = FALSE;
+ struct pending *p = c->host_pair->pending;
- while (p != NULL)
- {
- if (streq(c->name, p->connection->name))
+ while (p != NULL)
{
- already_queued = TRUE;
- break;
+ if (streq(c->name, p->connection->name))
+ {
+ already_queued = TRUE;
+ break;
+ }
+ p = p->next;
}
- p = p->next;
- }
- DBG(DBG_CONTROL,
- DBG_log("Queuing pending Quick Mode with %s \"%s\"%s"
- , ip_str(&c->spd.that.host_addr)
- , c->name
- , already_queued? " already done" : "")
- )
- if (already_queued)
- return;
-
- p = alloc_thing(struct pending, "struct pending");
- p->whack_sock = whack_sock;
- p->isakmp_sa = isakmp_sa;
- p->connection = c;
- p->policy = policy;
- p->try = try;
- p->replacing = replacing;
- p->next = c->host_pair->pending;
- c->host_pair->pending = p;
+ DBG(DBG_CONTROL,
+ DBG_log("Queuing pending Quick Mode with %s \"%s\"%s"
+ , ip_str(&c->spd.that.host_addr)
+ , c->name
+ , already_queued? " already done" : "")
+ )
+ if (already_queued)
+ return;
+
+ p = malloc_thing(struct pending);
+ p->whack_sock = whack_sock;
+ p->isakmp_sa = isakmp_sa;
+ p->connection = c;
+ p->policy = policy;
+ p->try = try;
+ p->replacing = replacing;
+ p->next = c->host_pair->pending;
+ c->host_pair->pending = p;
}
/* Release all the whacks awaiting the completion of this state.
@@ -4169,157 +4171,157 @@ add_pending(int whack_sock
void
release_pending_whacks(struct state *st, err_t story)
{
- struct pending *p;
- struct stat stst;
+ struct pending *p;
+ struct stat stst;
- if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0)
- zero(&stst); /* resulting st_dev/st_ino ought to be distinct */
+ if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0)
+ zero(&stst); /* resulting st_dev/st_ino ought to be distinct */
- release_whack(st);
+ release_whack(st);
- for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == st && p->whack_sock != NULL_FD)
+ for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next)
{
- struct stat pst;
+ if (p->isakmp_sa == st && p->whack_sock != NULL_FD)
+ {
+ struct stat pst;
- if (fstat(p->whack_sock, &pst) == 0
- && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino))
- {
- passert(whack_log_fd == NULL_FD);
- whack_log_fd = p->whack_sock;
- whack_log(RC_COMMENT
- , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA"
- , story);
- whack_log_fd = NULL_FD;
- }
- close(p->whack_sock);
- p->whack_sock = NULL_FD;
+ if (fstat(p->whack_sock, &pst) == 0
+ && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino))
+ {
+ passert(whack_log_fd == NULL_FD);
+ whack_log_fd = p->whack_sock;
+ whack_log(RC_COMMENT
+ , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA"
+ , story);
+ whack_log_fd = NULL_FD;
+ }
+ close(p->whack_sock);
+ p->whack_sock = NULL_FD;
+ }
}
- }
}
static void
delete_pending(struct pending **pp)
{
- struct pending *p = *pp;
+ struct pending *p = *pp;
- *pp = p->next;
- if (p->connection != NULL)
- connection_discard(p->connection);
- close_any(p->whack_sock);
- pfree(p);
+ *pp = p->next;
+ if (p->connection != NULL)
+ connection_discard(p->connection);
+ close_any(p->whack_sock);
+ free(p);
}
void
unpend(struct state *st)
{
- struct pending **pp
- , *p;
+ struct pending **pp
+ , *p;
- for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
- {
- if (p->isakmp_sa == st)
- {
- DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\""
- , ip_str(&p->connection->spd.that.host_addr)
- , p->connection->name));
- (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
- , p->try, p->replacing);
- p->whack_sock = NULL_FD; /* ownership transferred */
- p->connection = NULL; /* ownership transferred */
- delete_pending(pp);
- }
- else
+ for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
{
- pp = &p->next;
+ if (p->isakmp_sa == st)
+ {
+ DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\""
+ , ip_str(&p->connection->spd.that.host_addr)
+ , p->connection->name));
+ (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
+ , p->try, p->replacing);
+ p->whack_sock = NULL_FD; /* ownership transferred */
+ p->connection = NULL; /* ownership transferred */
+ delete_pending(pp);
+ }
+ else
+ {
+ pp = &p->next;
+ }
}
- }
}
/* a Main Mode negotiation has been replaced; update any pending */
void
update_pending(struct state *os, struct state *ns)
{
- struct pending *p;
+ struct pending *p;
- for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == os)
- p->isakmp_sa = ns;
- if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port)
+ for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next)
{
- p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port;
- p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port;
+ if (p->isakmp_sa == os)
+ p->isakmp_sa = ns;
+ if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port)
+ {
+ p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port;
+ p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port;
+ }
}
- }
}
/* a Main Mode negotiation has failed; discard any pending */
void
flush_pending_by_state(struct state *st)
{
- struct host_pair *hp = st->st_connection->host_pair;
-
- if (hp != NULL)
- {
- struct pending **pp
- , *p;
+ struct host_pair *hp = st->st_connection->host_pair;
- for (pp = &hp->pending; (p = *pp) != NULL; )
+ if (hp != NULL)
{
- if (p->isakmp_sa == st)
- delete_pending(pp);
- else
- pp = &p->next;
+ struct pending **pp
+ , *p;
+
+ for (pp = &hp->pending; (p = *pp) != NULL; )
+ {
+ if (p->isakmp_sa == st)
+ delete_pending(pp);
+ else
+ pp = &p->next;
+ }
}
- }
}
/* a connection has been deleted; discard any related pending */
static void
flush_pending_by_connection(struct connection *c)
{
- if (c->host_pair != NULL)
- {
- struct pending **pp
- , *p;
-
- for (pp = &c->host_pair->pending; (p = *pp) != NULL; )
+ if (c->host_pair != NULL)
{
- if (p->connection == c)
- {
- p->connection = NULL; /* prevent delete_pending from releasing */
- delete_pending(pp);
- }
- else
- {
- pp = &p->next;
- }
+ struct pending **pp
+ , *p;
+
+ for (pp = &c->host_pair->pending; (p = *pp) != NULL; )
+ {
+ if (p->connection == c)
+ {
+ p->connection = NULL; /* prevent delete_pending from releasing */
+ delete_pending(pp);
+ }
+ else
+ {
+ pp = &p->next;
+ }
+ }
}
- }
}
void
show_pending_phase2(const struct host_pair *hp, const struct state *st)
{
- const struct pending *p;
+ const struct pending *p;
- for (p = hp->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == st)
+ for (p = hp->pending; p != NULL; p = p->next)
{
- /* connection-name state-number [replacing state-number] */
- char cip[CONN_INST_BUF];
-
- fmt_conn_instance(p->connection, cip);
- whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu"
- , p->isakmp_sa->st_serialno
- , p->connection->name
- , cip
- , p->replacing);
+ if (p->isakmp_sa == st)
+ {
+ /* connection-name state-number [replacing state-number] */
+ char cip[CONN_INST_BUF];
+
+ fmt_conn_instance(p->connection, cip);
+ whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu"
+ , p->isakmp_sa->st_serialno
+ , p->connection->name
+ , cip
+ , p->replacing);
+ }
}
- }
}
/* Delete a connection if it is an instance and it is no longer in use.
@@ -4329,18 +4331,18 @@ show_pending_phase2(const struct host_pair *hp, const struct state *st)
void
connection_discard(struct connection *c)
{
- if (c->kind == CK_INSTANCE)
- {
- /* see if it is being used by a pending */
- struct pending *p;
+ if (c->kind == CK_INSTANCE)
+ {
+ /* see if it is being used by a pending */
+ struct pending *p;
- for (p = c->host_pair->pending; p != NULL; p = p->next)
- if (p->connection == c)
- return; /* in use, so we're done */
+ for (p = c->host_pair->pending; p != NULL; p = p->next)
+ if (p->connection == c)
+ return; /* in use, so we're done */
- if (!states_use_connection(c))
- delete_connection(c, FALSE);
- }
+ if (!states_use_connection(c))
+ delete_connection(c, FALSE);
+ }
}
@@ -4354,32 +4356,32 @@ long eclipse_count = 0;
struct connection *
eclipsed(struct connection *c, struct spd_route **esrp)
{
- struct connection *ue;
- struct spd_route *sr1 = &c->spd;
+ struct connection *ue;
+ struct spd_route *sr1 = &c->spd;
- ue = NULL;
+ ue = NULL;
- while (sr1 != NULL && ue != NULL)
- {
- for (ue = connections; ue != NULL; ue = ue->ac_next)
+ while (sr1 != NULL && ue != NULL)
{
- struct spd_route *srue = &ue->spd;
-
- while (srue != NULL
- && srue->routing == RT_ROUTED_ECLIPSED
- && !(samesubnet(&sr1->this.client, &srue->this.client)
- && samesubnet(&sr1->that.client, &srue->that.client)))
- {
- srue = srue->next;
- }
- if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED)
- {
- *esrp = srue;
- break;
- }
+ for (ue = connections; ue != NULL; ue = ue->ac_next)
+ {
+ struct spd_route *srue = &ue->spd;
+
+ while (srue != NULL
+ && srue->routing == RT_ROUTED_ECLIPSED
+ && !(samesubnet(&sr1->this.client, &srue->this.client)
+ && samesubnet(&sr1->that.client, &srue->that.client)))
+ {
+ srue = srue->next;
+ }
+ if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED)
+ {
+ *esrp = srue;
+ break;
+ }
+ }
}
- }
- return ue;
+ return ue;
}
/*
diff --git a/src/pluto/connections.h b/src/pluto/connections.h
index b11565296..16cbbfd72 100644
--- a/src/pluto/connections.h
+++ b/src/pluto/connections.h
@@ -10,8 +10,6 @@
* 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: connections.h 4024 2008-05-29 07:49:47Z andreas $
*/
#ifndef _CONNECTIONS_H
@@ -118,135 +116,135 @@
* - display format: n,m
*/
typedef unsigned long policy_prio_t;
-#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */
+#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */
#define set_policy_prio(c) { (c)->prio = \
- ((policy_prio_t)(c)->spd.this.client.maskbits << 16) \
- | ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \
- | (policy_prio_t)1; }
-#define POLICY_PRIO_BUF (3+1+3+1)
+ ((policy_prio_t)(c)->spd.this.client.maskbits << 16) \
+ | ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \
+ | (policy_prio_t)1; }
+#define POLICY_PRIO_BUF (3+1+3+1)
extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
struct virtual_t;
struct end {
- struct id id;
- ip_address
- host_addr,
- host_nexthop,
- host_srcip;
- ip_subnet client;
-
- bool key_from_DNS_on_demand;
- bool has_client;
- bool has_client_wildcard;
- bool has_port_wildcard;
- bool has_id_wildcards;
- bool has_natip;
- char *updown;
- u_int16_t host_port; /* host order */
- u_int16_t port; /* host order */
- u_int8_t protocol;
- cert_t cert; /* end certificate */
- chunk_t ca; /* CA distinguished name */
- struct ietfAttrList *groups;/* access control groups */
- smartcard_t *sc; /* smartcard reader and key info */
- struct virtual_t *virt;
- bool modecfg; /* this end: request local address from server */
- /* that end: give local addresses to clients */
- bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */
- /* rules if client behind host is a subnet */
- bool allow_any; /* IP address is subject to change */
- certpolicy_t sendcert; /* whether or not to send the certificate */
+ struct id id;
+ ip_address
+ host_addr,
+ host_nexthop,
+ host_srcip;
+ ip_subnet client;
+
+ bool key_from_DNS_on_demand;
+ bool has_client;
+ bool has_client_wildcard;
+ bool has_port_wildcard;
+ bool has_id_wildcards;
+ bool has_natip;
+ char *updown;
+ u_int16_t host_port; /* host order */
+ u_int16_t port; /* host order */
+ u_int8_t protocol;
+ cert_t cert; /* end certificate */
+ chunk_t ca; /* CA distinguished name */
+ struct ietfAttrList *groups;/* access control groups */
+ smartcard_t *sc; /* smartcard reader and key info */
+ struct virtual_t *virt;
+ bool modecfg; /* this end: request local address from server */
+ /* that end: give local addresses to clients */
+ bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */
+ /* rules if client behind host is a subnet */
+ bool allow_any; /* IP address is subject to change */
+ certpolicy_t sendcert; /* whether or not to send the certificate */
};
struct spd_route {
- struct spd_route *next;
- struct end this;
- struct end that;
- so_serial_t eroute_owner;
- enum routing_t routing; /* level of routing in place */
- uint32_t reqid;
+ struct spd_route *next;
+ struct end this;
+ struct end that;
+ so_serial_t eroute_owner;
+ enum routing_t routing; /* level of routing in place */
+ uint32_t reqid;
};
struct connection {
- char *name;
- bool ikev1;
+ char *name;
+ bool ikev1;
- lset_t policy;
- time_t sa_ike_life_seconds;
- time_t sa_ipsec_life_seconds;
- time_t sa_rekey_margin;
- unsigned long sa_rekey_fuzz;
- unsigned long sa_keying_tries;
+ lset_t policy;
+ time_t sa_ike_life_seconds;
+ time_t sa_ipsec_life_seconds;
+ time_t sa_rekey_margin;
+ unsigned long sa_rekey_fuzz;
+ unsigned long sa_keying_tries;
- /* RFC 3706 DPD */
- time_t dpd_delay;
- time_t dpd_timeout;
- dpd_action_t dpd_action;
+ /* RFC 3706 DPD */
+ time_t dpd_delay;
+ time_t dpd_timeout;
+ dpd_action_t dpd_action;
- char *log_file_name; /* name of log file */
- FILE *log_file; /* possibly open FILE */
- TAILQ_ENTRY(connection) log_link; /* linked list of open conns */
- bool log_file_err; /* only bitch once */
+ char *log_file_name; /* name of log file */
+ FILE *log_file; /* possibly open FILE */
+ TAILQ_ENTRY(connection) log_link; /* linked list of open conns */
+ bool log_file_err; /* only bitch once */
- struct spd_route spd;
+ struct spd_route spd;
- /* internal fields: */
+ /* internal fields: */
- unsigned long instance_serial;
- policy_prio_t prio;
- bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */
- enum connection_kind kind;
- const struct iface *interface; /* filled in iff oriented */
+ unsigned long instance_serial;
+ policy_prio_t prio;
+ bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */
+ enum connection_kind kind;
+ const struct iface *interface; /* filled in iff oriented */
- so_serial_t /* state object serial number */
- newest_isakmp_sa,
- newest_ipsec_sa;
+ so_serial_t /* state object serial number */
+ newest_isakmp_sa,
+ newest_ipsec_sa;
#ifdef DEBUG
- lset_t extra_debugging;
+ lset_t extra_debugging;
#endif
- /* note: if the client is the gateway, the following must be equal */
- sa_family_t addr_family; /* between gateways */
- sa_family_t tunnel_addr_family; /* between clients */
+ /* note: if the client is the gateway, the following must be equal */
+ sa_family_t addr_family; /* between gateways */
+ sa_family_t tunnel_addr_family; /* between clients */
- struct connection *policy_next; /* if multiple policies,
- next one to apply */
+ struct connection *policy_next; /* if multiple policies,
+ next one to apply */
- struct gw_info *gw_info;
- struct alg_info_esp *alg_info_esp;
- struct alg_info_ike *alg_info_ike;
+ struct gw_info *gw_info;
+ struct alg_info_esp *alg_info_esp;
+ struct alg_info_ike *alg_info_ike;
- struct host_pair *host_pair;
- struct connection *hp_next; /* host pair list link */
+ struct host_pair *host_pair;
+ struct connection *hp_next; /* host pair list link */
- struct connection *ac_next; /* all connections list link */
+ struct connection *ac_next; /* all connections list link */
- generalName_t *requested_ca; /* collected certificate requests */
- bool got_certrequest;
+ generalName_t *requested_ca; /* collected certificate requests */
+ bool got_certrequest;
};
#define oriented(c) ((c).interface != NULL)
extern bool orient(struct connection *c);
extern bool same_peer_ids(const struct connection *c
- , const struct connection *d, const struct id *his_id);
+ , const struct connection *d, const struct id *his_id);
/* Format the topology of a connection end, leaving out defaults.
* Largest left end looks like: client === host : port [ host_id ] --- hop
* Note: if that==NULL, skip nexthop
*/
-#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10)
+#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10)
extern size_t format_end(char *buf, size_t buf_len
- , const struct end *this, const struct end *that
- , bool is_left, lset_t policy);
+ , const struct end *this, const struct end *that
+ , bool is_left, lset_t policy);
extern void add_connection(const whack_message_t *wm);
extern void initiate_connection(const char *name, int whackfd);
extern void initiate_opportunistic(const ip_address *our_client
- , const ip_address *peer_client, int transport_proto, bool held, int whackfd);
+ , const ip_address *peer_client, int transport_proto, bool held, int whackfd);
extern void terminate_connection(const char *nm);
extern void release_connection(struct connection *c, bool relations);
extern void delete_connection(struct connection *c, bool relations);
@@ -257,87 +255,87 @@ extern void remove_group_instance(const struct connection *group, const char *na
extern void release_dead_interfaces(void);
extern void check_orientations(void);
extern struct connection *route_owner(struct connection *c
- , struct spd_route **srp
- , struct connection **erop
- , struct spd_route **esrp);
+ , struct spd_route **srp
+ , struct connection **erop
+ , struct spd_route **esrp);
extern struct connection *shunt_owner(const ip_subnet *ours
- , const ip_subnet *his);
+ , const ip_subnet *his);
-extern bool uniqueIDs; /* --uniqueids? */
+extern bool uniqueIDs; /* --uniqueids? */
extern void ISAKMP_SA_established(struct connection *c, so_serial_t serial);
#define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \
- && (id_is_ipaddr(&(c)->spd.that.id)? \
- sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE))
+ && (id_is_ipaddr(&(c)->spd.that.id)? \
+ sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE))
-struct state; /* forward declaration of tag (defined in state.h) */
+struct state; /* forward declaration of tag (defined in state.h) */
extern struct connection
- *con_by_name(const char *nm, bool strict),
- *find_host_connection(const ip_address *me, u_int16_t my_port
- , const ip_address *him, u_int16_t his_port, lset_t policy),
- *refine_host_connection(const struct state *st, const struct id *id
- , chunk_t peer_ca),
- *find_client_connection(struct connection *c
- , const ip_subnet *our_net
- , const ip_subnet *peer_net
- , const u_int8_t our_protocol
- , const u_int16_t out_port
- , const u_int8_t peer_protocol
- , const u_int16_t peer_port),
- *find_connection_by_reqid(uint32_t reqid);
+ *con_by_name(const char *nm, bool strict),
+ *find_host_connection(const ip_address *me, u_int16_t my_port
+ , const ip_address *him, u_int16_t his_port, lset_t policy),
+ *refine_host_connection(const struct state *st, const struct id *id
+ , chunk_t peer_ca),
+ *find_client_connection(struct connection *c
+ , const ip_subnet *our_net
+ , const ip_subnet *peer_net
+ , const u_int8_t our_protocol
+ , const u_int16_t out_port
+ , const u_int8_t peer_protocol
+ , const u_int16_t peer_port),
+ *find_connection_by_reqid(uint32_t reqid);
extern struct connection *
find_connection_for_clients(struct spd_route **srp
- , const ip_address *our_client
- , const ip_address *peer_client
- , int transport_proto);
+ , const ip_address *our_client
+ , const ip_address *peer_client
+ , int transport_proto);
extern chunk_t get_peer_ca_and_groups(struct connection *c
- , const ietfAttrList_t **peer_list);
-
+ , const ietfAttrList_t **peer_list);
+
/* instantiating routines
* Note: connection_discard() is in state.h because all its work
* is looking through state objects.
*/
-struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
-struct alg_info; /* forward declaration of tag (defined in alg_info.h) */
+struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
+struct alg_info; /* forward declaration of tag (defined in alg_info.h) */
extern struct connection *rw_instantiate(struct connection *c
- , const ip_address *him
- , u_int16_t his_port
- , const ip_subnet *his_net
- , const struct id *his_id);
+ , const ip_address *him
+ , u_int16_t his_port
+ , const ip_subnet *his_net
+ , const struct id *his_id);
extern struct connection *oppo_instantiate(struct connection *c
- , const ip_address *him
- , const struct id *his_id
- , struct gw_info *gw
- , const ip_address *our_client
- , const ip_address *peer_client);
+ , const ip_address *him
+ , const struct id *his_id
+ , struct gw_info *gw
+ , const ip_address *our_client
+ , const ip_address *peer_client);
extern struct connection
*build_outgoing_opportunistic_connection(struct gw_info *gw
- , const ip_address *our_client
- , const ip_address *peer_client);
+ , const ip_address *our_client
+ , const ip_address *peer_client);
/* worst case: "[" serial "] " myclient "=== ..." peer "===" hisclient '\0' */
#define CONN_INST_BUF \
- (2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1)
+ (2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1)
extern void fmt_conn_instance(const struct connection *c
- , char buf[CONN_INST_BUF]);
+ , char buf[CONN_INST_BUF]);
/* operations on "pending", the structure representing Quick Mode
* negotiations delayed until a Keying Channel has been negotiated.
*/
-struct pending; /* forward declaration (opaque outside connections.c) */
+struct pending; /* forward declaration (opaque outside connections.c) */
extern void add_pending(int whack_sock
- , struct state *isakmp_sa
- , struct connection *c
- , lset_t policy
- , unsigned long try
- , so_serial_t replacing);
+ , struct state *isakmp_sa
+ , struct connection *c
+ , lset_t policy
+ , unsigned long try
+ , so_serial_t replacing);
extern void release_pending_whacks(struct state *st, err_t story);
extern void unpend(struct state *st);
@@ -360,9 +358,9 @@ extern struct connection *eclipsed(struct connection *c, struct spd_route **);
extern void show_connections_status(bool all, const char *name);
extern int connection_compare(const struct connection *ca
- , const struct connection *cb);
+ , const struct connection *cb);
extern void update_host_pair(const char *why, struct connection *c
- , const ip_address *myaddr, u_int16_t myport
- , const ip_address *hisaddr, u_int16_t hisport);
+ , const ip_address *myaddr, u_int16_t myport
+ , const ip_address *hisaddr, u_int16_t hisport);
#endif /* _CONNECTIONS_H */
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
index 50a75c0aa..adcd77131 100644
--- a/src/pluto/constants.c
+++ b/src/pluto/constants.c
@@ -1,5 +1,6 @@
/* tables of names for values defined in constants.h
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
+ * Copyright (C) 1998-2002 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +11,6 @@
* 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: constants.c 4612 2008-11-11 06:37:37Z andreas $
*/
/*
@@ -25,7 +24,6 @@
#include <netinet/in.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "constants.h"
#include "defs.h"
@@ -36,42 +34,36 @@
const char compile_time_interop_options[] = ""
#ifdef THREADS
- " THREADS"
-#endif
-#ifdef LIBCURL
- " LIBCURL"
-#endif
-#ifdef LIBLDAP
- " LIBLDAP"
+ " THREADS"
#endif
#ifdef SMARTCARD
- " SMARTCARD"
+ " SMARTCARD"
#endif
#ifdef VENDORID
- " VENDORID"
+ " VENDORID"
#endif
#ifdef CISCO_QUIRKS
- " CISCO_QUIRKS"
+ " CISCO_QUIRKS"
#endif
#ifdef USE_KEYRR
- " KEYRR"
+ " KEYRR"
#endif
- ;
+ ;
/* version */
static const char *const version_name[] = {
- "ISAKMP Version 1.0",
+ "ISAKMP Version 1.0",
};
enum_names version_names =
- { ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
- ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
- version_name, NULL };
+ { ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
+ ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
+ version_name, NULL };
/* RFC 2459 CRL reason codes */
-static const char *const crl_reason_name[] = {
+ENUM(crl_reason_names, REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL,
"unspecified",
"key compromise",
"ca compromise",
@@ -81,26 +73,20 @@ static const char *const crl_reason_name[] = {
"certificate hold",
"reason #7",
"remove from crl"
- };
-
-enum_names crl_reason_names =
- { REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL, crl_reason_name, NULL};
+);
/* RFC 3706 Dead Peer Detection */
-static const char *const dpd_action_name[] = {
+ENUM(dpd_action_names, DPD_ACTION_NONE, DPD_ACTION_RESTART,
"none",
"clear",
"hold",
"restart"
- };
-
-enum_names dpd_action_names =
- { DPD_ACTION_NONE, DPD_ACTION_RESTART, dpd_action_name, NULL};
-
+);
+
/* Timer events */
-static const char *const timer_event_name[] = {
+ENUM(timer_event_names, EVENT_NULL, EVENT_LOG_DAILY,
"EVENT_NULL",
"EVENT_REINIT_SECRET",
"EVENT_SHUNT_SCAN",
@@ -113,16 +99,13 @@ static const char *const timer_event_name[] = {
"EVENT_DPD",
"EVENT_DPD_TIMEOUT",
"EVENT_LOG_DAILY"
- };
-
-enum_names timer_event_names =
- { EVENT_NULL, EVENT_LOG_DAILY, timer_event_name, NULL };
+);
/* Domain of Interpretation */
static const char *const doi_name[] = {
- "ISAKMP_DOI_ISAKMP",
- "ISAKMP_DOI_IPSEC",
+ "ISAKMP_DOI_ISAKMP",
+ "ISAKMP_DOI_IPSEC",
};
enum_names doi_names = { ISAKMP_DOI_ISAKMP, ISAKMP_DOI_IPSEC, doi_name, NULL };
@@ -155,7 +138,7 @@ const char *const debug_bit_names[] = {
"impair-bust-mr2",
NULL
- };
+};
#endif
/* State of exchanges */
@@ -197,78 +180,78 @@ static const char *const state_name[] = {
"STATE_MODE_CFG_R4",
"STATE_IKE_ROOF"
- };
+};
enum_names state_names =
- { STATE_MAIN_R0, STATE_IKE_ROOF-1, state_name, NULL };
+ { STATE_MAIN_R0, STATE_IKE_ROOF-1, state_name, NULL };
/* story for state */
const char *const state_story[] = {
- "expecting MI1", /* STATE_MAIN_R0 */
- "sent MI1, expecting MR1", /* STATE_MAIN_I1 */
- "sent MR1, expecting MI2", /* STATE_MAIN_R1 */
- "sent MI2, expecting MR2", /* STATE_MAIN_I2 */
- "sent MR2, expecting MI3", /* STATE_MAIN_R2 */
- "sent MI3, expecting MR3", /* STATE_MAIN_I3 */
- "sent MR3, ISAKMP SA established", /* STATE_MAIN_R3 */
- "ISAKMP SA established", /* STATE_MAIN_I4 */
-
- "expecting QI1", /* STATE_QUICK_R0 */
- "sent QI1, expecting QR1", /* STATE_QUICK_I1 */
- "sent QR1, inbound IPsec SA installed, expecting QI2", /* STATE_QUICK_R1 */
- "sent QI2, IPsec SA established", /* STATE_QUICK_I2 */
- "IPsec SA established", /* STATE_QUICK_R2 */
-
- "got Informational Message in clear", /* STATE_INFO */
- "got encrypted Informational Message", /* STATE_INFO_PROTECTED */
-
- "expecting XAUTH request", /* STATE_XAUTH_I0 */
- "sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */
- "sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
- "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */
- "sent XAUTH ack, established", /* STATE_XAUTH_I2 */
- "received XAUTH ack, established", /* STATE_XAUTH_R3 */
-
- "expecting ModeCfg request", /* STATE_MODE_CFG_R0 */
+ "expecting MI1", /* STATE_MAIN_R0 */
+ "sent MI1, expecting MR1", /* STATE_MAIN_I1 */
+ "sent MR1, expecting MI2", /* STATE_MAIN_R1 */
+ "sent MI2, expecting MR2", /* STATE_MAIN_I2 */
+ "sent MR2, expecting MI3", /* STATE_MAIN_R2 */
+ "sent MI3, expecting MR3", /* STATE_MAIN_I3 */
+ "sent MR3, ISAKMP SA established", /* STATE_MAIN_R3 */
+ "ISAKMP SA established", /* STATE_MAIN_I4 */
+
+ "expecting QI1", /* STATE_QUICK_R0 */
+ "sent QI1, expecting QR1", /* STATE_QUICK_I1 */
+ "sent QR1, inbound IPsec SA installed, expecting QI2", /* STATE_QUICK_R1 */
+ "sent QI2, IPsec SA established", /* STATE_QUICK_I2 */
+ "IPsec SA established", /* STATE_QUICK_R2 */
+
+ "got Informational Message in clear", /* STATE_INFO */
+ "got encrypted Informational Message", /* STATE_INFO_PROTECTED */
+
+ "expecting XAUTH request", /* STATE_XAUTH_I0 */
+ "sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */
+ "sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
+ "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */
+ "sent XAUTH ack, established", /* STATE_XAUTH_I2 */
+ "received XAUTH ack, established", /* STATE_XAUTH_R3 */
+
+ "expecting ModeCfg request", /* STATE_MODE_CFG_R0 */
"sent ModeCfg request, expecting reply", /* STATE_MODE_CFG_I1 */
- "sent ModeCfg reply, established", /* STATE_MODE_CFG_R1 */
- "received ModeCfg reply, established", /* STATE_MODE_CFG_I2 */
+ "sent ModeCfg reply, established", /* STATE_MODE_CFG_R1 */
+ "received ModeCfg reply, established", /* STATE_MODE_CFG_I2 */
- "expecting ModeCfg set", /* STATE_MODE_CFG_I0 */
- "sent ModeCfg set, expecting ack", /* STATE_MODE_CFG_R3 */
- "sent ModeCfg ack, established", /* STATE_MODE_CFG_I3 */
- "received ModeCfg ack, established", /* STATE_MODE_CFG_R4 */
- };
+ "expecting ModeCfg set", /* STATE_MODE_CFG_I0 */
+ "sent ModeCfg set, expecting ack", /* STATE_MODE_CFG_R3 */
+ "sent ModeCfg ack, established", /* STATE_MODE_CFG_I3 */
+ "received ModeCfg ack, established", /* STATE_MODE_CFG_R4 */
+};
/* kind of struct connection */
static const char *const connection_kind_name[] = {
- "CK_GROUP", /* policy group: instantiates to template */
- "CK_TEMPLATE", /* abstract connection, with wildcard */
- "CK_PERMANENT", /* normal connection */
- "CK_INSTANCE", /* instance of template, created for a particular attempt */
- "CK_GOING_AWAY" /* instance being deleted -- don't delete again */
+ "CK_GROUP", /* policy group: instantiates to template */
+ "CK_TEMPLATE", /* abstract connection, with wildcard */
+ "CK_PERMANENT", /* normal connection */
+ "CK_INSTANCE", /* instance of template, created for a particular attempt */
+ "CK_GOING_AWAY" /* instance being deleted -- don't delete again */
};
enum_names connection_kind_names =
- { CK_GROUP, CK_GOING_AWAY, connection_kind_name, NULL };
+ { CK_GROUP, CK_GOING_AWAY, connection_kind_name, NULL };
/* routing status names */
static const char *const routing_story_strings[] = {
- "unrouted", /* RT_UNROUTED: unrouted */
- "unrouted HOLD", /* RT_UNROUTED_HOLD: unrouted, but HOLD shunt installed */
- "eroute eclipsed", /* RT_ROUTED_ECLIPSED: RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */
- "prospective erouted", /* RT_ROUTED_PROSPECTIVE: routed, and prospective shunt installed */
- "erouted HOLD", /* RT_ROUTED_HOLD: routed, and HOLD shunt installed */
- "fail erouted", /* RT_ROUTED_FAILURE: routed, and failure-context shunt eroute installed */
- "erouted", /* RT_ROUTED_TUNNEL: routed, and erouted to an IPSEC SA group */
- "keyed, unrouted", /* RT_UNROUTED_KEYED: was routed+keyed, but it got turned into an outer policy */
- };
+ "unrouted", /* RT_UNROUTED: unrouted */
+ "unrouted HOLD", /* RT_UNROUTED_HOLD: unrouted, but HOLD shunt installed */
+ "eroute eclipsed", /* RT_ROUTED_ECLIPSED: RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */
+ "prospective erouted", /* RT_ROUTED_PROSPECTIVE: routed, and prospective shunt installed */
+ "erouted HOLD", /* RT_ROUTED_HOLD: routed, and HOLD shunt installed */
+ "fail erouted", /* RT_ROUTED_FAILURE: routed, and failure-context shunt eroute installed */
+ "erouted", /* RT_ROUTED_TUNNEL: routed, and erouted to an IPSEC SA group */
+ "keyed, unrouted", /* RT_UNROUTED_KEYED: was routed+keyed, but it got turned into an outer policy */
+};
enum_names routing_story =
- { RT_UNROUTED, RT_ROUTED_TUNNEL, routing_story_strings, NULL};
+ { RT_UNROUTED, RT_ROUTED_TUNNEL, routing_story_strings, NULL};
/* Payload types (RFC 2408 "ISAKMP" section 3.1) */
@@ -296,16 +279,18 @@ const char *const payload_name[] = {
"ISAKMP_NEXT_NAT-D",
"ISAKMP_NEXT_NAT-OA",
NULL
- };
+};
-const char *const payload_name_nat_d[] = { "ISAKMP_NEXT_NAT-D",
- "ISAKMP_NEXT_NAT-OA", NULL };
+const char *const payload_name_nat_d[] = {
+ "ISAKMP_NEXT_NAT-D",
+ "ISAKMP_NEXT_NAT-OA", NULL
+};
static enum_names payload_names_nat_d =
{ ISAKMP_NEXT_NATD_DRAFTS, ISAKMP_NEXT_NATOA_DRAFTS, payload_name_nat_d, NULL };
-
+
enum_names payload_names =
- { ISAKMP_NEXT_NONE, ISAKMP_NEXT_NATOA_RFC, payload_name, &payload_names_nat_d };
+ { ISAKMP_NEXT_NONE, ISAKMP_NEXT_NATOA_RFC, payload_name, &payload_names_nat_d };
/* Exchange types (note: two discontinuous ranges) */
@@ -317,26 +302,26 @@ static const char *const exchange_name[] = {
"ISAKMP_XCHG_AGGR",
"ISAKMP_XCHG_INFO",
"ISAKMP_XCHG_MODE_CFG",
- };
+};
static const char *const exchange_name2[] = {
"ISAKMP_XCHG_QUICK",
"ISAKMP_XCHG_NGRP",
"ISAKMP_XCHG_ACK_INFO",
- };
+};
static enum_names exchange_desc2 =
- { ISAKMP_XCHG_QUICK, ISAKMP_XCHG_ACK_INFO, exchange_name2, NULL };
+ { ISAKMP_XCHG_QUICK, ISAKMP_XCHG_ACK_INFO, exchange_name2, NULL };
enum_names exchange_names =
- { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, exchange_name, &exchange_desc2 };
+ { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, exchange_name, &exchange_desc2 };
/* Flag BITS */
const char *const flag_bit_names[] = {
"ISAKMP_FLAG_ENCRYPTION",
"ISAKMP_FLAG_COMMIT",
NULL
- };
+};
/* Situation BITS definition for IPsec DOI */
@@ -345,7 +330,7 @@ const char *const sit_bit_names[] = {
"SIT_SECRECY",
"SIT_INTEGRITY",
NULL
- };
+};
/* Protocol IDs (RFC 2407 "IPsec DOI" section 4.4.1) */
@@ -354,78 +339,74 @@ static const char *const protocol_name[] = {
"PROTO_IPSEC_AH",
"PROTO_IPSEC_ESP",
"PROTO_IPCOMP",
- };
+};
enum_names protocol_names =
- { PROTO_ISAKMP, PROTO_IPCOMP, protocol_name, NULL };
+ { PROTO_ISAKMP, PROTO_IPCOMP, protocol_name, NULL };
/* IPsec ISAKMP transform values */
static const char *const isakmp_transform_name[] = {
"KEY_IKE",
- };
+};
enum_names isakmp_transformid_names =
- { KEY_IKE, KEY_IKE, isakmp_transform_name, NULL };
+ { KEY_IKE, KEY_IKE, isakmp_transform_name, NULL };
/* IPsec AH transform values */
static const char *const ah_transform_name[] = {
- "AH_MD5",
- "AH_SHA",
- "AH_DES",
- "AH_SHA2_256",
- "AH_SHA2_384",
- "AH_SHA2_512",
- "AH_RIPEMD",
- "AH_AES_XCBC_MAC",
- "AH_RSA"
- };
+ "HMAC_MD5",
+ "HMAC_SHA1",
+ "DES_MAC",
+ "HMAC_SHA2_256",
+ "HMAC_SHA2_384",
+ "HMAC_SHA2_512",
+ "HMAC_RIPEMD",
+ "AES_XCBC_96",
+ "SIG_RSA"
+};
enum_names ah_transformid_names =
- { AH_MD5, AH_RSA, ah_transform_name, NULL };
+ { AH_MD5, AH_RSA, ah_transform_name, NULL };
/* IPsec ESP transform values */
static const char *const esp_transform_name[] = {
- "ESP_DES_IV64",
- "ESP_DES",
- "ESP_3DES",
- "ESP_RC5",
- "ESP_IDEA",
- "ESP_CAST",
- "ESP_BLOWFISH",
- "ESP_3IDEA",
- "ESP_DES_IV32",
- "ESP_RC4",
- "ESP_NULL",
- "ESP_AES",
- "ESP_AES-CTR",
- "ESP_AES-CCM_8",
- "ESP_AES-CCM_12",
- "ESP_AES-CCM_16",
- "ESP_UNASSIGNED_17",
- "ESP_AES_GCM_8",
- "ESP_AES_GCM_12",
- "ESP_AES_GCM_16",
- "ESP_SEED_CBC",
- "ESP_CAMELLIA"
- };
+ "DES_IV64",
+ "DES_CBC",
+ "3DES_CBC",
+ "RC5_CBC",
+ "IDEA_CBC",
+ "CAST_CBC",
+ "BLOWFISH_CBC",
+ "3IDEA",
+ "DES_IV32",
+ "RC4",
+ "NULL",
+ "AES_CBC",
+ "AES_CTR",
+ "AES_CCM_8",
+ "AES_CCM_12",
+ "AES_CCM_16",
+ "UNASSIGNED_17",
+ "AES_GCM_8",
+ "AES_GCM_12",
+ "AES_GCM_16",
+ "SEED_CBC",
+ "CAMELLIA_CBC"
+};
-/*
- * ipsec drafts suggest "high" ESP ids values for testing,
- * assign generic ESP_ID<num> if not officially defined
- */
static const char *const esp_transform_name_high[] = {
- "ESP_SERPENT",
- "ESP_TWOFISH"
- };
+ "SERPENT_CBC",
+ "TWOFISH_CBC"
+};
enum_names esp_transformid_names_high =
- { ESP_SERPENT, ESP_TWOFISH, esp_transform_name_high, NULL };
+ { ESP_SERPENT, ESP_TWOFISH, esp_transform_name_high, NULL };
enum_names esp_transformid_names =
- { ESP_DES_IV64, ESP_CAMELLIA, esp_transform_name, &esp_transformid_names_high };
+ { ESP_DES_IV64, ESP_CAMELLIA, esp_transform_name, &esp_transformid_names_high };
/* IPCOMP transform values */
@@ -434,10 +415,10 @@ static const char *const ipcomp_transform_name[] = {
"IPCOMP_DEFLAT",
"IPCOMP_LZS",
"IPCOMP_LZJH",
- };
+};
enum_names ipcomp_transformid_names =
- { IPCOMP_OUI, IPCOMP_LZJH, ipcomp_transform_name, NULL };
+ { IPCOMP_OUI, IPCOMP_LZJH, ipcomp_transform_name, NULL };
/* Identification type values */
@@ -453,10 +434,10 @@ static const char *const ident_name[] = {
"ID_DER_ASN1_DN",
"ID_DER_ASN1_GN",
"ID_KEY_ID",
- };
+};
enum_names ident_names =
- { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL };
+ { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL };
/* Certificate type values */
@@ -472,21 +453,18 @@ static const char *const cert_type_name[] = {
"CERT_ARL",
"CERT_SPKI",
"CERT_X509_ATTRIBUTE",
- };
+};
enum_names cert_type_names =
- { CERT_NONE, CERT_X509_ATTRIBUTE, cert_type_name, NULL };
+ { CERT_NONE, CERT_X509_ATTRIBUTE, cert_type_name, NULL };
/* Certificate policy names */
-static const char *const cert_policy_name[] = {
+ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
"ALWAYS_SEND",
"SEND_IF_ASKED",
"NEVER_SEND",
- };
-
-enum_names cert_policy_names =
- { CERT_ALWAYS_SEND, CERT_NEVER_SEND, cert_policy_name, NULL };
+);
/* Goal BITs for establishing an SA
* Note: we drop the POLICY_ prefix so that logs are more concise.
@@ -494,7 +472,7 @@ enum_names cert_policy_names =
const char *const sa_policy_bit_names[] = {
"PSK",
- "RSASIG",
+ "PUBKEY",
"ENCRYPT",
"AUTHENTICATE",
"COMPRESS",
@@ -517,24 +495,23 @@ const char *const sa_policy_bit_names[] = {
"DONTREAUTH",
"BEET",
"MOBIKE",
- "ECDSA",
"PROXY",
NULL
- };
+};
const char *const policy_shunt_names[4] = {
"TRAP",
"PASS",
"DROP",
"REJECT",
- };
+};
const char *const policy_fail_names[4] = {
"NONE",
"PASS",
"DROP",
"REJECT",
- };
+};
/* Oakley transform attributes
* oakley_attr_bit_names does double duty: it is used for enum names
@@ -560,7 +537,7 @@ const char *const oakley_attr_bit_names[] = {
"OAKLEY_GROUP_ORDER",
"OAKLEY_BLOCK_SIZE",
NULL
- };
+};
static const char *const oakley_var_attr_name[] = {
"OAKLEY_GROUP_PRIME (variable length)",
@@ -574,36 +551,36 @@ static const char *const oakley_var_attr_name[] = {
NULL,
NULL,
"OAKLEY_GROUP_ORDER (variable length)",
- };
+};
static enum_names oakley_attr_desc_tv = {
- OAKLEY_ENCRYPTION_ALGORITHM + ISAKMP_ATTR_AF_TV,
- OAKLEY_GROUP_ORDER + ISAKMP_ATTR_AF_TV, oakley_attr_bit_names, NULL };
+ OAKLEY_ENCRYPTION_ALGORITHM + ISAKMP_ATTR_AF_TV,
+ OAKLEY_GROUP_ORDER + ISAKMP_ATTR_AF_TV, oakley_attr_bit_names, NULL };
enum_names oakley_attr_names = {
- OAKLEY_GROUP_PRIME, OAKLEY_GROUP_ORDER,
- oakley_var_attr_name, &oakley_attr_desc_tv };
+ OAKLEY_GROUP_PRIME, OAKLEY_GROUP_ORDER,
+ oakley_var_attr_name, &oakley_attr_desc_tv };
/* for each Oakley attribute, which enum_names describes its values? */
enum_names *oakley_attr_val_descs[] = {
- NULL, /* (none) */
- &oakley_enc_names, /* OAKLEY_ENCRYPTION_ALGORITHM */
- &oakley_hash_names, /* OAKLEY_HASH_ALGORITHM */
- &oakley_auth_names, /* OAKLEY_AUTHENTICATION_METHOD */
- &oakley_group_names, /* OAKLEY_GROUP_DESCRIPTION */
+ NULL, /* (none) */
+ &oakley_enc_names, /* OAKLEY_ENCRYPTION_ALGORITHM */
+ &oakley_hash_names, /* OAKLEY_HASH_ALGORITHM */
+ &oakley_auth_names, /* OAKLEY_AUTHENTICATION_METHOD */
+ &oakley_group_names, /* OAKLEY_GROUP_DESCRIPTION */
&oakley_group_type_names,/* OAKLEY_GROUP_TYPE */
- NULL, /* OAKLEY_GROUP_PRIME */
- NULL, /* OAKLEY_GROUP_GENERATOR_ONE */
- NULL, /* OAKLEY_GROUP_GENERATOR_TWO */
- NULL, /* OAKLEY_GROUP_CURVE_A */
- NULL, /* OAKLEY_GROUP_CURVE_B */
- &oakley_lifetime_names, /* OAKLEY_LIFE_TYPE */
- NULL, /* OAKLEY_LIFE_DURATION */
- &oakley_prf_names, /* OAKLEY_PRF */
- NULL, /* OAKLEY_KEY_LENGTH */
- NULL, /* OAKLEY_FIELD_SIZE */
- NULL, /* OAKLEY_GROUP_ORDER */
- };
+ NULL, /* OAKLEY_GROUP_PRIME */
+ NULL, /* OAKLEY_GROUP_GENERATOR_ONE */
+ NULL, /* OAKLEY_GROUP_GENERATOR_TWO */
+ NULL, /* OAKLEY_GROUP_CURVE_A */
+ NULL, /* OAKLEY_GROUP_CURVE_B */
+ &oakley_lifetime_names, /* OAKLEY_LIFE_TYPE */
+ NULL, /* OAKLEY_LIFE_DURATION */
+ &oakley_prf_names, /* OAKLEY_PRF */
+ NULL, /* OAKLEY_KEY_LENGTH */
+ NULL, /* OAKLEY_FIELD_SIZE */
+ NULL, /* OAKLEY_GROUP_ORDER */
+};
/* IPsec DOI attributes (RFC 2407 "IPsec DOI" section 4.5) */
@@ -617,7 +594,7 @@ static const char *const ipsec_attr_name[] = {
"KEY_ROUNDS",
"COMPRESS_DICT_SIZE",
"COMPRESS_PRIVATE_ALG",
- };
+};
static const char *const ipsec_var_attr_name[] = {
"SA_LIFE_DURATION (variable length)",
@@ -628,40 +605,40 @@ static const char *const ipsec_var_attr_name[] = {
NULL,
NULL,
"COMPRESS_PRIVATE_ALG (variable length)",
- };
+};
static enum_names ipsec_attr_desc_tv = {
- SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV,
- COMPRESS_PRIVATE_ALG + ISAKMP_ATTR_AF_TV,
- ipsec_attr_name, NULL };
+ SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV,
+ COMPRESS_PRIVATE_ALG + ISAKMP_ATTR_AF_TV,
+ ipsec_attr_name, NULL };
enum_names ipsec_attr_names = {
- SA_LIFE_DURATION, COMPRESS_PRIVATE_ALG,
- ipsec_var_attr_name, &ipsec_attr_desc_tv };
+ SA_LIFE_DURATION, COMPRESS_PRIVATE_ALG,
+ ipsec_var_attr_name, &ipsec_attr_desc_tv };
/* for each IPsec attribute, which enum_names describes its values? */
enum_names *ipsec_attr_val_descs[] = {
- NULL, /* (none) */
- &sa_lifetime_names, /* SA_LIFE_TYPE */
- NULL, /* SA_LIFE_DURATION */
- &oakley_group_names, /* GROUP_DESCRIPTION */
- &enc_mode_names, /* ENCAPSULATION_MODE */
- &auth_alg_names, /* AUTH_ALGORITHM */
- NULL, /* KEY_LENGTH */
- NULL, /* KEY_ROUNDS */
- NULL, /* COMPRESS_DICT_SIZE */
- NULL, /* COMPRESS_PRIVATE_ALG */
- };
+ NULL, /* (none) */
+ &sa_lifetime_names, /* SA_LIFE_TYPE */
+ NULL, /* SA_LIFE_DURATION */
+ &oakley_group_names, /* GROUP_DESCRIPTION */
+ &enc_mode_names, /* ENCAPSULATION_MODE */
+ &auth_alg_names, /* AUTH_ALGORITHM */
+ NULL, /* KEY_LENGTH */
+ NULL, /* KEY_ROUNDS */
+ NULL, /* COMPRESS_DICT_SIZE */
+ NULL, /* COMPRESS_PRIVATE_ALG */
+};
/* SA Lifetime Type attribute */
static const char *const sa_lifetime_name[] = {
"SA_LIFE_TYPE_SECONDS",
"SA_LIFE_TYPE_KBYTES",
- };
+};
enum_names sa_lifetime_names =
- { SA_LIFE_TYPE_SECONDS, SA_LIFE_TYPE_KBYTES, sa_lifetime_name, NULL };
+ { SA_LIFE_TYPE_SECONDS, SA_LIFE_TYPE_KBYTES, sa_lifetime_name, NULL };
/* Encapsulation Mode attribute */
@@ -670,55 +647,55 @@ static const char *const enc_mode_name[] = {
"ENCAPSULATION_MODE_TRANSPORT",
"ENCAPSULATION_MODE_UDP_TUNNEL",
"ENCAPSULATION_MODE_UDP_TRANSPORT",
- };
+};
static const char *const enc_udp_mode_name[] = {
- "ENCAPSULATION_MODE_UDP_TUNNEL",
- "ENCAPSULATION_MODE_UDP_TRANSPORT",
- };
+ "ENCAPSULATION_MODE_UDP_TUNNEL",
+ "ENCAPSULATION_MODE_UDP_TRANSPORT",
+ };
static enum_names enc_udp_mode_names =
- { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, enc_udp_mode_name, NULL };
+ { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, enc_udp_mode_name, NULL };
enum_names enc_mode_names =
- { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, enc_mode_name, &enc_udp_mode_names };
+ { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, enc_mode_name, &enc_udp_mode_names };
/* Auth Algorithm attribute */
static const char *const auth_alg_name[] = {
- "AUTH_ALGORITHM_HMAC_MD5",
- "AUTH_ALGORITHM_HMAC_SHA1",
- "AUTH_ALGORITHM_DES_MAC",
- "AUTH_ALGORITHM_KPDK",
- "AUTH_ALGORITHM_HMAC_SHA2_256",
- "AUTH_ALGORITHM_HMAC_SHA2_384",
- "AUTH_ALGORITHM_HMAC_SHA2_512",
- "AUTH_ALGORITHM_HMAC_RIPEMD",
- "AUTH_ALGORITHM_AES_XCBC_MAC",
- "AUTH_ALGORITHM_SIG_RSA"
- };
+ "HMAC_MD5",
+ "HMAC_SHA1",
+ "DES_MAC",
+ "KPDK",
+ "HMAC_SHA2_256",
+ "HMAC_SHA2_384",
+ "HMAC_SHA2_512",
+ "HMAC_RIPEMD",
+ "AES_XCBC_96",
+ "SIG_RSA"
+};
static const char *const extended_auth_alg_name[] = {
- "AUTH_ALGORITHM_NULL"
- };
+ "NULL"
+ };
enum_names extended_auth_alg_names =
- { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_NULL, extended_auth_alg_name, NULL };
+ { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_NULL, extended_auth_alg_name, NULL };
enum_names auth_alg_names =
- { AUTH_ALGORITHM_HMAC_MD5, AUTH_ALGORITHM_SIG_RSA, auth_alg_name
- , &extended_auth_alg_names };
+ { AUTH_ALGORITHM_HMAC_MD5, AUTH_ALGORITHM_SIG_RSA, auth_alg_name
+ , &extended_auth_alg_names };
/* From draft-beaulieu-ike-xauth */
static const char *const xauth_type_name[] = {
- "Generic",
- "RADIUS-CHAP",
- "OTP",
- "S/KEY",
+ "Generic",
+ "RADIUS-CHAP",
+ "OTP",
+ "S/KEY",
};
enum_names xauth_type_names =
- { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, xauth_type_name, NULL};
+ { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, xauth_type_name, NULL};
/* From draft-beaulieu-ike-xauth */
static const char *const xauth_attr_tv_name[] = {
@@ -730,11 +707,11 @@ static const char *const xauth_attr_tv_name[] = {
NULL,
NULL,
"XAUTH_STATUS",
- };
+};
enum_names xauth_attr_tv_names = {
- XAUTH_TYPE + ISAKMP_ATTR_AF_TV,
- XAUTH_STATUS + ISAKMP_ATTR_AF_TV, xauth_attr_tv_name, NULL };
+ XAUTH_TYPE + ISAKMP_ATTR_AF_TV,
+ XAUTH_STATUS + ISAKMP_ATTR_AF_TV, xauth_attr_tv_name, NULL };
static const char *const unity_attr_name[] = {
"UNITY_BANNER",
@@ -751,8 +728,15 @@ static const char *const unity_attr_name[] = {
};
enum_names unity_attr_names =
- { UNITY_BANNER , UNITY_DDNS_HOSTNAME, unity_attr_name , &xauth_attr_tv_names };
+ { UNITY_BANNER , UNITY_DDNS_HOSTNAME, unity_attr_name , &xauth_attr_tv_names };
+static const char *const microsoft_attr_name[] = {
+ "INTERNAL_IP4_SERVER",
+ "INTERNAL_IP6_SERVER",
+};
+
+enum_names microsoft_attr_names =
+ { INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, microsoft_attr_name , &unity_attr_names };
static const char *const xauth_attr_name[] = {
"XAUTH_USER_NAME",
@@ -764,10 +748,10 @@ static const char *const xauth_attr_name[] = {
"XAUTH_STATUS (wrong TLV syntax, should be TV)",
"XAUTH_NEXT_PIN",
"XAUTH_ANSWER",
- };
+};
enum_names xauth_attr_names =
- { XAUTH_USER_NAME , XAUTH_ANSWER, xauth_attr_name , &unity_attr_names };
+ { XAUTH_USER_NAME , XAUTH_ANSWER, xauth_attr_name , &microsoft_attr_names };
static const char *const modecfg_attr_name[] = {
"INTERNAL_IP4_ADDRESS",
@@ -785,97 +769,104 @@ static const char *const modecfg_attr_name[] = {
"INTERNAL_IP4_SUBNET",
"SUPPORTED_ATTRIBUTES",
"INTERNAL_IP6_SUBNET",
- };
+};
enum_names modecfg_attr_names =
- { INTERNAL_IP4_ADDRESS, INTERNAL_IP6_SUBNET, modecfg_attr_name , &xauth_attr_names };
+ { INTERNAL_IP4_ADDRESS, INTERNAL_IP6_SUBNET, modecfg_attr_name , &xauth_attr_names };
/* Oakley Lifetime Type attribute */
static const char *const oakley_lifetime_name[] = {
"OAKLEY_LIFE_SECONDS",
"OAKLEY_LIFE_KILOBYTES",
- };
+};
enum_names oakley_lifetime_names =
- { OAKLEY_LIFE_SECONDS, OAKLEY_LIFE_KILOBYTES, oakley_lifetime_name, NULL };
+ { OAKLEY_LIFE_SECONDS, OAKLEY_LIFE_KILOBYTES, oakley_lifetime_name, NULL };
/* Oakley PRF attribute (none defined) */
enum_names oakley_prf_names =
- { 1, 0, NULL, NULL };
+ { 1, 0, NULL, NULL };
/* Oakley Encryption Algorithm attribute */
static const char *const oakley_enc_name[] = {
- "OAKLEY_DES_CBC",
- "OAKLEY_IDEA_CBC",
- "OAKLEY_BLOWFISH_CBC",
- "OAKLEY_RC5_R16_B64_CBC",
- "OAKLEY_3DES_CBC",
- "OAKLEY_CAST_CBC",
- "OAKLEY_AES_CBC",
- };
+ "DES_CBC",
+ "IDEA_CBC",
+ "BLOWFISH_CBC",
+ "RC5_R16_B64_CBC",
+ "3DES_CBC",
+ "CAST_CBC",
+ "AES_CBC",
+ "CAMELLIA_CBC"
+};
#ifdef NO_EXTRA_IKE
enum_names oakley_enc_names =
- { OAKLEY_DES_CBC, OAKLEY_AES_CBC, oakley_enc_name, NULL };
+ { OAKLEY_DES_CBC, OAKLEY_CAMELLIA_CBC, oakley_enc_name, NULL };
#else
static const char *const oakley_enc_name_draft_aes_cbc_02[] = {
- "OAKLEY_MARS_CBC" /* 65001 */,
- "OAKLEY_RC6_CBC" /* 65002 */,
- "OAKLEY_ID_65003" /* 65003 */,
- "OAKLEY_SERPENT_CBC" /* 65004 */,
- "OAKLEY_TWOFISH_CBC" /* 65005 */,
+ "MARS_CBC" /* 65001 */,
+ "RC6_CBC" /* 65002 */,
+ "ID_65003" /* 65003 */,
+ "SERPENT_CBC" /* 65004 */,
+ "TWOFISH_CBC" /* 65005 */,
};
+
static const char *const oakley_enc_name_ssh[] = {
- "OAKLEY_TWOFISH_CBC_SSH",
+ "TWOFISH_CBC_SSH",
};
+
enum_names oakley_enc_names_ssh =
- { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, oakley_enc_name_ssh
- , NULL };
+ { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, oakley_enc_name_ssh
+ , NULL };
enum_names oakley_enc_names_draft_aes_cbc_02 =
- { OAKLEY_MARS_CBC, OAKLEY_TWOFISH_CBC, oakley_enc_name_draft_aes_cbc_02
- , &oakley_enc_names_ssh };
+ { OAKLEY_MARS_CBC, OAKLEY_TWOFISH_CBC, oakley_enc_name_draft_aes_cbc_02
+ , &oakley_enc_names_ssh };
enum_names oakley_enc_names =
- { OAKLEY_DES_CBC, OAKLEY_AES_CBC, oakley_enc_name
- , &oakley_enc_names_draft_aes_cbc_02 };
+ { OAKLEY_DES_CBC, OAKLEY_CAMELLIA_CBC, oakley_enc_name
+ , &oakley_enc_names_draft_aes_cbc_02 };
#endif
/* Oakley Hash Algorithm attribute */
static const char *const oakley_hash_name[] = {
- "OAKLEY_MD5",
- "OAKLEY_SHA",
- "OAKLEY_TIGER",
- "OAKLEY_SHA2_256",
- "OAKLEY_SHA2_384",
- "OAKLEY_SHA2_512",
- };
+ "HMAC_MD5",
+ "HMAC_SHA1",
+ "HMAC_TIGER",
+ "HMAC_SHA2_256",
+ "HMAC_SHA2_384",
+ "HMAC_SHA2_512",
+};
enum_names oakley_hash_names =
- { OAKLEY_MD5, OAKLEY_SHA2_512, oakley_hash_name, NULL };
+ { OAKLEY_MD5, OAKLEY_SHA2_512, oakley_hash_name, NULL };
/* Oakley Authentication Method attribute */
static const char *const oakley_auth_name1[] = {
- "OAKLEY_PRESHARED_KEY",
- "OAKLEY_DSS_SIG",
- "OAKLEY_RSA_SIG",
- "OAKLEY_RSA_ENC",
- "OAKLEY_RSA_ENC_REV",
- "OAKLEY_ELGAMAL_ENC",
- "OAKLEY_ELGAMAL_ENC_REV",
- };
+ "pre-shared key",
+ "DSS signature",
+ "RSA signature",
+ "RSA encryption",
+ "RSA encryption revised",
+ "ElGamal encryption",
+ "ELGamal encryption revised",
+ "ECDSA signature",
+ "ECDSA-256 signature",
+ "ECDSA-384 signature",
+ "ECDSA-521-signature",
+};
static const char *const oakley_auth_name2[] = {
"HybridInitRSA",
"HybridRespRSA",
"HybridInitDSS",
"HybridRespDSS",
- };
+};
static const char *const oakley_auth_name3[] = {
"XAUTHInitPreShared",
@@ -888,44 +879,64 @@ static const char *const oakley_auth_name3[] = {
"XAUTHRespRSAEncryption",
"XAUTHInitRSARevisedEncryption",
"XAUTHRespRSARevisedEncryption",
- };
+};
static enum_names oakley_auth_names1 =
- { OAKLEY_PRESHARED_KEY, OAKLEY_ELGAMAL_ENC_REV
- , oakley_auth_name1, NULL };
+ { OAKLEY_PRESHARED_KEY, OAKLEY_ECDSA_521
+ , oakley_auth_name1, NULL };
static enum_names oakley_auth_names2 =
- { HybridInitRSA, HybridRespDSS
- , oakley_auth_name2, &oakley_auth_names1 };
+ { HybridInitRSA, HybridRespDSS
+ , oakley_auth_name2, &oakley_auth_names1 };
enum_names oakley_auth_names =
- { XAUTHInitPreShared, XAUTHRespRSARevisedEncryption
- , oakley_auth_name3, &oakley_auth_names2 };
+ { XAUTHInitPreShared, XAUTHRespRSARevisedEncryption
+ , oakley_auth_name3, &oakley_auth_names2 };
/* Oakley Group Description attribute */
static const char *const oakley_group_name[] = {
- "OAKLEY_GROUP_MODP768",
- "OAKLEY_GROUP_MODP1024",
- "OAKLEY_GROUP_GP155",
- "OAKLEY_GROUP_GP185",
- "OAKLEY_GROUP_MODP1536",
- };
+ "MODP_768",
+ "MODP_1024",
+ "GP_155",
+ "GP_185",
+ "MODP_1536",
+};
static const char *const oakley_group_name_rfc3526[] = {
- "OAKLEY_GROUP_MODP2048",
- "OAKLEY_GROUP_MODP3072",
- "OAKLEY_GROUP_MODP4096",
- "OAKLEY_GROUP_MODP6144",
- "OAKLEY_GROUP_MODP8192"
+ "MODP_2048",
+ "MODP_3072",
+ "MODP_4096",
+ "MODP_6144",
+ "MODP_8192"
+};
+
+static const char *const oakley_group_name_rfc4753[] = {
+ "ECP_256",
+ "ECP_384",
+ "ECP_521"
+};
+
+static const char *const oakley_group_name_rfc5114[] = {
+ "ECP_192",
+ "ECP_224"
};
+
+enum_names oakley_group_names_rfc5114 =
+ { ECP_192_BIT, ECP_224_BIT,
+ oakley_group_name_rfc5114, NULL };
+
+enum_names oakley_group_names_rfc4753 =
+ { ECP_256_BIT, ECP_521_BIT,
+ oakley_group_name_rfc4753, &oakley_group_names_rfc5114 };
+
enum_names oakley_group_names_rfc3526 =
- { OAKLEY_GROUP_MODP2048, OAKLEY_GROUP_MODP8192,
- oakley_group_name_rfc3526, NULL };
+ { MODP_2048_BIT, MODP_8192_BIT,
+ oakley_group_name_rfc3526, &oakley_group_names_rfc4753 };
enum_names oakley_group_names =
- { OAKLEY_GROUP_MODP768, OAKLEY_GROUP_MODP1536,
- oakley_group_name, &oakley_group_names_rfc3526 };
+ { MODP_768_BIT, MODP_1536_BIT,
+ oakley_group_name, &oakley_group_names_rfc3526 };
/* Oakley Group Type attribute */
@@ -933,10 +944,10 @@ static const char *const oakley_group_type_name[] = {
"OAKLEY_GROUP_TYPE_MODP",
"OAKLEY_GROUP_TYPE_ECP",
"OAKLEY_GROUP_TYPE_EC2N",
- };
+};
enum_names oakley_group_type_names =
- { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, oakley_group_type_name, NULL };
+ { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, oakley_group_type_name, NULL };
/* Notify messages -- error types */
@@ -971,38 +982,38 @@ static const char *const notification_name[] = {
"CERTIFICATE_UNAVAILABLE",
"UNSUPPORTED_EXCHANGE_TYPE",
"UNEQUAL_PAYLOAD_LENGTHS",
- };
+};
static const char *const notification_status_name[] = {
"CONNECTED",
- };
+};
static const char *const ipsec_notification_name[] = {
"IPSEC_RESPONDER_LIFETIME",
"IPSEC_REPLAY_STATUS",
"IPSEC_INITIAL_CONTACT",
- };
+};
static const char *const notification_dpd_name[] = {
- "R_U_THERE",
- "R_U_THERE_ACK",
+ "R_U_THERE",
+ "R_U_THERE_ACK",
};
enum_names notification_dpd_names =
- { R_U_THERE, R_U_THERE_ACK,
- notification_dpd_name, NULL };
+ { R_U_THERE, R_U_THERE_ACK,
+ notification_dpd_name, NULL };
enum_names ipsec_notification_names =
- { IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT,
- ipsec_notification_name, &notification_dpd_names };
+ { IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT,
+ ipsec_notification_name, &notification_dpd_names };
enum_names notification_status_names =
- { CONNECTED, CONNECTED,
- notification_status_name, &ipsec_notification_names };
+ { CONNECTED, CONNECTED,
+ notification_status_name, &ipsec_notification_names };
enum_names notification_names =
- { INVALID_PAYLOAD_TYPE, UNEQUAL_PAYLOAD_LENGTHS,
- notification_name, &notification_status_names };
+ { INVALID_PAYLOAD_TYPE, UNEQUAL_PAYLOAD_LENGTHS,
+ notification_name, &notification_status_names };
/* MODECFG
* From draft-dukes-ike-mode-cfg
@@ -1014,20 +1025,20 @@ const char *const attr_msg_type_name[] = {
"ISAKMP_CFG_SET",
"ISAKMP_CFG_ACK",
NULL
- };
+};
enum_names attr_msg_type_names =
- { 0 , ISAKMP_CFG_ACK, attr_msg_type_name , NULL };
+ { 0 , ISAKMP_CFG_ACK, attr_msg_type_name , NULL };
/* socket address family info */
static const char *const af_inet_name[] = {
"AF_INET",
- };
+};
static const char *const af_inet6_name[] = {
"AF_INET6",
- };
+};
static enum_names af_names6 = { AF_INET6, AF_INET6, af_inet6_name, NULL };
@@ -1045,7 +1056,7 @@ const struct af_info af_inet4_info = {
32,
ID_IPV4_ADDR, ID_IPV4_ADDR_SUBNET, ID_IPV4_ADDR_RANGE,
&ipv4_any, &ipv4_wildcard, &ipv4_all,
- };
+};
const struct af_info af_inet6_info = {
AF_INET6,
@@ -1055,29 +1066,28 @@ const struct af_info af_inet6_info = {
128,
ID_IPV6_ADDR, ID_IPV6_ADDR_SUBNET, ID_IPV6_ADDR_RANGE,
&ipv6_any, &ipv6_wildcard, &ipv6_all,
- };
+};
const struct af_info *
aftoinfo(int af)
{
- switch (af)
- {
- case AF_INET:
- return &af_inet4_info;
- case AF_INET6:
- return &af_inet6_info;
- default:
- return NULL;
- }
+ switch (af)
+ {
+ case AF_INET:
+ return &af_inet4_info;
+ case AF_INET6:
+ return &af_inet6_info;
+ default:
+ return NULL;
+ }
}
-bool
-subnetisnone(const ip_subnet *sn)
+bool subnetisnone(const ip_subnet *sn)
{
- ip_address base;
+ ip_address base;
- networkof(sn, &base);
- return isanyaddr(&base) && subnetishost(sn);
+ networkof(sn, &base);
+ return isanyaddr(&base) && subnetishost(sn);
}
/* BIND enumerated types */
@@ -1085,62 +1095,62 @@ subnetisnone(const ip_subnet *sn)
#include <arpa/nameser.h>
static const char *const rr_type_name[] = {
- "T_A", /* 1 host address */
- "T_NS", /* 2 authoritative server */
- "T_MD", /* 3 mail destination */
- "T_MF", /* 4 mail forwarder */
- "T_CNAME", /* 5 canonical name */
- "T_SOA", /* 6 start of authority zone */
- "T_MB", /* 7 mailbox domain name */
- "T_MG", /* 8 mail group member */
- "T_MR", /* 9 mail rename name */
- "T_NULL", /* 10 null resource record */
- "T_WKS", /* 11 well known service */
- "T_PTR", /* 12 domain name pointer */
- "T_HINFO", /* 13 host information */
- "T_MINFO", /* 14 mailbox information */
- "T_MX", /* 15 mail routing information */
- "T_TXT", /* 16 text strings */
- "T_RP", /* 17 responsible person */
- "T_AFSDB", /* 18 AFS cell database */
- "T_X25", /* 19 X_25 calling address */
- "T_ISDN", /* 20 ISDN calling address */
- "T_RT", /* 21 router */
- "T_NSAP", /* 22 NSAP address */
- "T_NSAP_PTR", /* 23 reverse NSAP lookup (deprecated) */
- "T_SIG", /* 24 security signature */
- "T_KEY", /* 25 security key */
- "T_PX", /* 26 X.400 mail mapping */
- "T_GPOS", /* 27 geographical position (withdrawn) */
- "T_AAAA", /* 28 IP6 Address */
- "T_LOC", /* 29 Location Information */
- "T_NXT", /* 30 Next Valid Name in Zone */
- "T_EID", /* 31 Endpoint identifier */
- "T_NIMLOC", /* 32 Nimrod locator */
- "T_SRV", /* 33 Server selection */
- "T_ATMA", /* 34 ATM Address */
- "T_NAPTR", /* 35 Naming Authority PoinTeR */
+ "T_A", /* 1 host address */
+ "T_NS", /* 2 authoritative server */
+ "T_MD", /* 3 mail destination */
+ "T_MF", /* 4 mail forwarder */
+ "T_CNAME", /* 5 canonical name */
+ "T_SOA", /* 6 start of authority zone */
+ "T_MB", /* 7 mailbox domain name */
+ "T_MG", /* 8 mail group member */
+ "T_MR", /* 9 mail rename name */
+ "T_NULL", /* 10 null resource record */
+ "T_WKS", /* 11 well known service */
+ "T_PTR", /* 12 domain name pointer */
+ "T_HINFO", /* 13 host information */
+ "T_MINFO", /* 14 mailbox information */
+ "T_MX", /* 15 mail routing information */
+ "T_TXT", /* 16 text strings */
+ "T_RP", /* 17 responsible person */
+ "T_AFSDB", /* 18 AFS cell database */
+ "T_X25", /* 19 X_25 calling address */
+ "T_ISDN", /* 20 ISDN calling address */
+ "T_RT", /* 21 router */
+ "T_NSAP", /* 22 NSAP address */
+ "T_NSAP_PTR", /* 23 reverse NSAP lookup (deprecated) */
+ "T_SIG", /* 24 security signature */
+ "T_KEY", /* 25 security key */
+ "T_PX", /* 26 X.400 mail mapping */
+ "T_GPOS", /* 27 geographical position (withdrawn) */
+ "T_AAAA", /* 28 IP6 Address */
+ "T_LOC", /* 29 Location Information */
+ "T_NXT", /* 30 Next Valid Name in Zone */
+ "T_EID", /* 31 Endpoint identifier */
+ "T_NIMLOC", /* 32 Nimrod locator */
+ "T_SRV", /* 33 Server selection */
+ "T_ATMA", /* 34 ATM Address */
+ "T_NAPTR", /* 35 Naming Authority PoinTeR */
NULL
- };
+};
enum_names rr_type_names = { T_A, T_NAPTR, rr_type_name, NULL };
/* Query type values which do not appear in resource records */
static const char *const rr_qtype_name[] = {
- "T_IXFR", /* 251 incremental zone transfer */
- "T_AXFR", /* 252 transfer zone of authority */
- "T_MAILB", /* 253 transfer mailbox records */
- "T_MAILA", /* 254 transfer mail agent records */
- "T_ANY", /* 255 wildcard match */
+ "T_IXFR", /* 251 incremental zone transfer */
+ "T_AXFR", /* 252 transfer zone of authority */
+ "T_MAILB", /* 253 transfer mailbox records */
+ "T_MAILA", /* 254 transfer mail agent records */
+ "T_ANY", /* 255 wildcard match */
NULL
- };
+};
enum_names rr_qtype_names = { T_IXFR, T_ANY, rr_qtype_name, &rr_type_names };
static const char *const rr_class_name[] = {
- "C_IN", /* 1 the arpa internet */
+ "C_IN", /* 1 the arpa internet */
NULL
- };
+};
enum_names rr_class_names = { C_IN, C_IN, rr_class_name, NULL };
@@ -1149,34 +1159,33 @@ enum_names rr_class_names = { C_IN, C_IN, rr_class_name, NULL };
*
*/
const char *const natt_type_bitnames[] = {
- "draft-ietf-ipsec-nat-t-ike-00/01", /* 0 */
- "draft-ietf-ipsec-nat-t-ike-02/03",
- "RFC 3947",
- "3", /* 3 */
- "4", "5", "6", "7",
- "8", "9", "10", "11",
- "12", "13", "14", "15",
- "16", "17", "18", "19",
- "20", "21", "22", "23",
- "24", "25", "26", "27",
- "28", "29",
- "nat is behind me",
- "nat is behind peer"
+ "draft-ietf-ipsec-nat-t-ike-00/01", /* 0 */
+ "draft-ietf-ipsec-nat-t-ike-02/03",
+ "RFC 3947",
+ "3", /* 3 */
+ "4", "5", "6", "7",
+ "8", "9", "10", "11",
+ "12", "13", "14", "15",
+ "16", "17", "18", "19",
+ "20", "21", "22", "23",
+ "24", "25", "26", "27",
+ "28", "29",
+ "nat is behind me",
+ "nat is behind peer"
};
/* look up enum names in an enum_names */
-const char *
-enum_name(enum_names *ed, unsigned long val)
+const char* enum_name(enum_names *ed, unsigned long val)
{
- enum_names *p;
-
- for (p = ed; p != NULL; p = p->en_next_range)
- {
- if (p->en_first <= val && val <= p->en_last)
- return p->en_names[val - p->en_first];
- }
- return NULL;
+ enum_names *p;
+
+ for (p = ed; p != NULL; p = p->en_next_range)
+ {
+ if (p->en_first <= val && val <= p->en_last)
+ return p->en_names[val - p->en_first];
+ }
+ return NULL;
}
/* find or construct a string to describe an enum value
@@ -1185,16 +1194,16 @@ enum_name(enum_names *ed, unsigned long val)
const char *
enum_show(enum_names *ed, unsigned long val)
{
- const char *p = enum_name(ed, val);
+ const char *p = enum_name(ed, val);
- if (p == NULL)
- {
- static char buf[12]; /* only one! I hope that it is big enough */
+ if (p == NULL)
+ {
+ static char buf[12]; /* only one! I hope that it is big enough */
- snprintf(buf, sizeof(buf), "%lu??", val);
- p = buf;
- }
- return p;
+ snprintf(buf, sizeof(buf), "%lu??", val);
+ p = buf;
+ }
+ return p;
}
@@ -1203,123 +1212,126 @@ static char bitnamesbuf[200]; /* only one! I hope that it is big enough! */
int
enum_search(enum_names *ed, const char *str)
{
- enum_names *p;
- const char *ptr;
- unsigned en;
+ enum_names *p;
+ const char *ptr;
+ unsigned en;
- for (p = ed; p != NULL; p = p->en_next_range)
- for (en = p->en_first; en <= p->en_last ;en++)
+ for (p = ed; p != NULL; p = p->en_next_range)
{
- ptr = p->en_names[en - p->en_first];
- if (ptr == 0) continue;
- /* if (strncmp(ptr, str, strlen(ptr))==0) */
- if (strcmp(ptr, str) == 0)
- return en;
+ for (en = p->en_first; en <= p->en_last ;en++)
+ {
+ ptr = p->en_names[en - p->en_first];
+ if (ptr == 0)
+ {
+ continue;
+ }
+ if (streq(ptr, str))
+ {
+ return en;
+ }
+ }
}
- return -1;
+ return -1;
}
/* construct a string to name the bits on in a set
* Result may be in STATIC buffer!
* Note: prettypolicy depends on internal details.
*/
-const char *
-bitnamesof(const char *const table[], lset_t val)
+const char* bitnamesof(const char *const table[], lset_t val)
{
- char *p = bitnamesbuf;
- lset_t bit;
- const char *const *tp;
+ char *p = bitnamesbuf;
+ lset_t bit;
+ const char *const *tp;
- if (val == 0)
- return "none";
+ if (val == 0)
+ return "none";
- for (tp = table, bit = 01; val != 0; bit <<= 1)
- {
- if (val & bit)
+ for (tp = table, bit = 01; val != 0; bit <<= 1)
{
- const char *n = *tp;
- size_t nl;
-
- if (n == NULL || *n == '\0')
- {
- /* no name for this bit, so use hex */
- static char flagbuf[sizeof("0x80000000")];
-
- snprintf(flagbuf, sizeof(flagbuf), "0x%llx", bit);
- n = flagbuf;
- }
-
- nl = strlen(n);
-
- if (p != bitnamesbuf && p < bitnamesbuf+sizeof(bitnamesbuf) - 1)
- *p++ = '+';
-
- if (bitnamesbuf+sizeof(bitnamesbuf) - p > (ptrdiff_t)nl)
- {
- strcpy(p, n);
- p += nl;
- }
- val -= bit;
+ if (val & bit)
+ {
+ const char *n = *tp;
+ size_t nl;
+
+ if (n == NULL || *n == '\0')
+ {
+ /* no name for this bit, so use hex */
+ static char flagbuf[sizeof("0x80000000")];
+
+ snprintf(flagbuf, sizeof(flagbuf), "0x%llx", bit);
+ n = flagbuf;
+ }
+
+ nl = strlen(n);
+
+ if (p != bitnamesbuf && p < bitnamesbuf+sizeof(bitnamesbuf) - 1)
+ *p++ = '+';
+
+ if (bitnamesbuf+sizeof(bitnamesbuf) - p > (ptrdiff_t)nl)
+ {
+ strcpy(p, n);
+ p += nl;
+ }
+ val -= bit;
+ }
+ if (*tp != NULL)
+ tp++; /* move on, but not past end */
}
- if (*tp != NULL)
- tp++; /* move on, but not past end */
- }
- *p = '\0';
- return bitnamesbuf;
+ *p = '\0';
+ return bitnamesbuf;
}
/* print a policy: like bitnamesof, but it also does the non-bitfields.
* Suppress the shunt and fail fields if 0.
*/
-const char *
-prettypolicy(lset_t policy)
+const char* prettypolicy(lset_t policy)
{
- const char *bn = bitnamesof(sa_policy_bit_names
- , policy & ~(POLICY_SHUNT_MASK | POLICY_FAIL_MASK));
- size_t len;
- lset_t shunt = (policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT;
- lset_t fail = (policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT;
-
- if (bn != bitnamesbuf)
- bitnamesbuf[0] = '\0';
- len = strlen(bitnamesbuf);
- if (shunt != 0)
- {
- snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+%s"
- , policy_shunt_names[shunt]);
- len += strlen(bitnamesbuf + len);
- }
- if (fail != 0)
- {
- snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+failure%s"
- , policy_fail_names[fail]);
- len += strlen(bitnamesbuf + len);
- }
- if (NEVER_NEGOTIATE(policy))
- {
- snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+NEVER_NEGOTIATE");
- len += strlen(bitnamesbuf + len);
- }
- return bitnamesbuf;
+ const char *bn = bitnamesof(sa_policy_bit_names
+ , policy & ~(POLICY_SHUNT_MASK | POLICY_FAIL_MASK));
+ size_t len;
+ lset_t shunt = (policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT;
+ lset_t fail = (policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT;
+
+ if (bn != bitnamesbuf)
+ bitnamesbuf[0] = '\0';
+ len = strlen(bitnamesbuf);
+ if (shunt != 0)
+ {
+ snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+%s"
+ , policy_shunt_names[shunt]);
+ len += strlen(bitnamesbuf + len);
+ }
+ if (fail != 0)
+ {
+ snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+failure%s"
+ , policy_fail_names[fail]);
+ len += strlen(bitnamesbuf + len);
+ }
+ if (NEVER_NEGOTIATE(policy))
+ {
+ snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+NEVER_NEGOTIATE");
+ len += strlen(bitnamesbuf + len);
+ }
+ return bitnamesbuf;
}
/* test a set by seeing if all bits have names */
-bool
-testset(const char *const table[], lset_t val)
+bool testset(const char *const table[], lset_t val)
{
- lset_t bit;
- const char *const *tp;
-
- for (tp = table, bit = 01; val != 0; bit <<= 1, tp++)
- {
- const char *n = *tp;
-
- if (n == NULL || ((val & bit) && *n == '\0'))
- return FALSE;
- val &= ~bit;
- }
- return TRUE;
+ lset_t bit;
+ const char *const *tp;
+
+ for (tp = table, bit = 01; val != 0; bit <<= 1, tp++)
+ {
+ const char *n = *tp;
+
+ if (n == NULL || ((val & bit) && *n == '\0'))
+ return FALSE;
+ val &= ~bit;
+ }
+ return TRUE;
}
@@ -1328,40 +1340,43 @@ const char sparse_end[] = "end of sparse names";
/* look up enum names in a sparse_names */
const char *sparse_name(sparse_names sd, unsigned long val)
{
- const struct sparse_name *p;
+ const struct sparse_name *p;
- for (p = sd; p->name != sparse_end; p++)
- if (p->val == val)
- return p->name;
- return NULL;
+ for (p = sd; p->name != sparse_end; p++)
+ if (p->val == val)
+ return p->name;
+ return NULL;
}
/* find or construct a string to describe an sparse value
* Result may be in STATIC buffer!
*/
-const char *
-sparse_val_show(sparse_names sd, unsigned long val)
+const char* sparse_val_show(sparse_names sd, unsigned long val)
{
- const char *p = sparse_name(sd, val);
+ const char *p = sparse_name(sd, val);
- if (p == NULL)
- {
- static char buf[12]; /* only one! I hope that it is big enough */
+ if (p == NULL)
+ {
+ static char buf[12]; /* only one! I hope that it is big enough */
- snprintf(buf, sizeof(buf), "%lu??", val);
- p = buf;
- }
- return p;
+ snprintf(buf, sizeof(buf), "%lu??", val);
+ p = buf;
+ }
+ return p;
}
void init_constants(void)
{
- happy(anyaddr(AF_INET, &ipv4_any));
- happy(anyaddr(AF_INET6, &ipv6_any));
+ happy(anyaddr(AF_INET, &ipv4_any));
+ happy(anyaddr(AF_INET6, &ipv6_any));
- happy(addrtosubnet(&ipv4_any, &ipv4_wildcard));
- happy(addrtosubnet(&ipv6_any, &ipv6_wildcard));
+ happy(addrtosubnet(&ipv4_any, &ipv4_wildcard));
+ happy(addrtosubnet(&ipv6_any, &ipv6_wildcard));
- happy(initsubnet(&ipv4_any, 0, '0', &ipv4_all));
- happy(initsubnet(&ipv6_any, 0, '0', &ipv6_all));
+ happy(initsubnet(&ipv4_any, 0, '0', &ipv4_all));
+ happy(initsubnet(&ipv6_any, 0, '0', &ipv6_all));
}
+
+u_char secret_of_the_day[HASH_SIZE_SHA1];
+
+
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index 409dd1d61..5fe936e08 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -1,4 +1,3 @@
-
/* manifest constants
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
@@ -12,13 +11,15 @@
* 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: constants.h 4612 2008-11-11 06:37:37Z andreas $
*/
#ifndef _CONSTANTS_H
#define _CONSTANTS_H
+#include <utils.h>
+#include <utils/identification.h>
+#include <crypto/hashers/hasher.h>
+
extern const char compile_time_interop_options[];
extern void init_constants(void);
@@ -28,8 +29,6 @@ extern void init_constants(void);
* Any changes here should be reflected there.
*/
-#define elemsof(array) (sizeof(array) / sizeof(*(array))) /* number of elements in an array */
-
/* Many routines return only success or failure, but wish to describe
* the failure in a message. We use the convention that they return
* a NULL on success and a pointer to constant string on failure.
@@ -39,19 +38,10 @@ extern void init_constants(void);
* <freeswan.h> defines err_t for this return type.
*/
-typedef int bool;
-#define FALSE 0
-#define TRUE 1
-
-#define NULL_FD (-1) /* NULL file descriptor */
+#define NULL_FD (-1) /* NULL file descriptor */
#define dup_any(fd) ((fd) == NULL_FD? NULL_FD : dup(fd))
#define close_any(fd) { if ((fd) != NULL_FD) { close(fd); (fd) = NULL_FD; } }
-#define BITS_PER_BYTE 8
-
-#define streq(a, b) (strcmp((a), (b)) == 0) /* clearer shorthand */
-#define strcaseeq(a, b) (strcasecmp((a), (b)) == 0) /* clearer shorthand */
-
/* set type with room for at least 64 elements for ALG opts (was 32 in stock FS) */
typedef unsigned long long lset_t;
@@ -71,8 +61,8 @@ typedef unsigned long long lset_t;
# define DEFAULT_CTLBASE IPSEC_PIDDIR "/pluto"
#endif
-#define CTL_SUFFIX ".ctl" /* for UNIX domain socket pathname */
-#define LOCK_SUFFIX ".pid" /* for pluto's lock */
+#define CTL_SUFFIX ".ctl" /* for UNIX domain socket pathname */
+#define LOCK_SUFFIX ".pid" /* for pluto's lock */
#define INFO_SUFFIX ".info" /* for UNIX domain socket for apps */
/* Routines to check and display values.
@@ -86,10 +76,10 @@ typedef unsigned long long lset_t;
*/
struct enum_names {
- unsigned long en_first; /* first value in range */
- unsigned long en_last; /* last value in range (inclusive) */
- const char *const *en_names;
- const struct enum_names *en_next_range; /* descriptor of next range */
+ unsigned long en_first; /* first value in range */
+ unsigned long en_last; /* last value in range (inclusive) */
+ const char *const *en_names;
+ const struct enum_names *en_next_range; /* descriptor of next range */
};
typedef const struct enum_names enum_names;
@@ -108,8 +98,8 @@ extern const char *bitnamesof(const char *const table[], lset_t val);
* Often appropriate for enums defined by others.
*/
struct sparse_name {
- unsigned long val;
- const char *const name;
+ unsigned long val;
+ const char *const name;
};
typedef const struct sparse_name sparse_names[];
@@ -119,264 +109,172 @@ extern const char sparse_end[];
#define FULL_INET_ADDRESS_SIZE 6
-/* Group parameters from draft-ietf-ike-01.txt section 6 */
-
-#define MODP_GENERATOR "2"
-
-#define MODP768_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \
- "E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF"
-
-#define MODP1024_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \
- "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \
- "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 " \
- "FFFFFFFF FFFFFFFF"
-
-#define MODP1536_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \
- "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \
- "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D " \
- "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F " \
- "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D " \
- "670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF "
-
-/* draft-ietf-ipsec-ike-modp-groups-03.txt */
-#define MODP2048_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
- "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
- "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
- "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
- "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
- "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
- "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
- "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
- "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF"
-
-#define MODP3072_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
- "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
- "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
- "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
- "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
- "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
- "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
- "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
- "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
- "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
- "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
- "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
- "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
- "43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF"
-
-#define MODP4096_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
- "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
- "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
- "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
- "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
- "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
- "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
- "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
- "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
- "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
- "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
- "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
- "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
- "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \
- "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \
- "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \
- "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \
- "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \
- "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" \
- "FFFFFFFF FFFFFFFF"
-
-/* copy&pasted from rfc3526: */
-#define MODP6144_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" \
- "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" \
- "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" \
- "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" \
- "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" \
- "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
- "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" \
- "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" \
- "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" \
- "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" \
- "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" \
- "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
- "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" \
- "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" \
- "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" \
- "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" \
- "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" \
- "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \
- "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406" \
- "AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918" \
- "DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151" \
- "2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03" \
- "F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F" \
- "BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \
- "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B" \
- "B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632" \
- "387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E" \
- "6DCC4024 FFFFFFFF FFFFFFFF"
-
-/* copy&pasted from rfc3526: */
-#define MODP8192_MODULUS \
- "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
- "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
- "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
- "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
- "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
- "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
- "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
- "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
- "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
- "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
- "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
- "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
- "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
- "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
- "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
- "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \
- "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \
- "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \
- "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \
- "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \
- "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \
- "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" \
- "F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" \
- "179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" \
- "DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" \
- "5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" \
- "D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" \
- "23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \
- "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" \
- "06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" \
- "DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" \
- "12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" \
- "38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" \
- "741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" \
- "3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" \
- "22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" \
- "4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" \
- "062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" \
- "4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" \
- "B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" \
- "4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" \
- "9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" \
- "60C980DD 98EDD3DF FFFFFFFF FFFFFFFF"
-#define LOCALSECRETSIZE (512 / BITS_PER_BYTE)
-
/* limits on nonce sizes. See RFC2409 "The internet key exchange (IKE)" 5 */
-#define MINIMUM_NONCE_SIZE 8 /* bytes */
-#define DEFAULT_NONCE_SIZE 16 /* bytes */
-#define MAXIMUM_NONCE_SIZE 256 /* bytes */
+#define MINIMUM_NONCE_SIZE 8 /* bytes */
+#define DEFAULT_NONCE_SIZE 16 /* bytes */
+#define MAXIMUM_NONCE_SIZE 256 /* bytes */
#define COOKIE_SIZE 8
#define MAX_ISAKMP_SPI_SIZE 16
-#define MD2_DIGEST_SIZE (128 / BITS_PER_BYTE)
-#define MD5_DIGEST_SIZE (128 / BITS_PER_BYTE)
-#define SHA1_DIGEST_SIZE (160 / BITS_PER_BYTE)
-#define SHA2_256_DIGEST_SIZE (256 / BITS_PER_BYTE)
-#define SHA2_384_DIGEST_SIZE (384 / BITS_PER_BYTE)
-#define SHA2_512_DIGEST_SIZE (512 / BITS_PER_BYTE)
-
-#define MD5_BLOCK_SIZE (512 / BITS_PER_BYTE)
-#define SHA1_BLOCK_SIZE (512 / BITS_PER_BYTE)
-#define SHA2_256_BLOCK_SIZE (512 / BITS_PER_BYTE)
-#define SHA2_384_BLOCK_SIZE (1024 / BITS_PER_BYTE)
-#define SHA2_512_BLOCK_SIZE (1024 / BITS_PER_BYTE)
-
-#define DES_CBC_BLOCK_SIZE (64 / BITS_PER_BYTE)
-
-#define DSS_QBITS 160 /* bits in DSS's "q" (FIPS 186-1) */
+#define DES_CBC_BLOCK_SIZE (64 / BITS_PER_BYTE)
/* Maximum is required for SHA2_512 */
-#define MAX_DIGEST_LEN SHA2_512_DIGEST_SIZE
-#define MAX_HASH_BLOCK_SIZE SHA2_512_BLOCK_SIZE
+#define MAX_DIGEST_LEN HASH_SIZE_SHA512
/* RFC 2404 "HMAC-SHA-1-96" section 3 */
-#define HMAC_SHA1_KEY_LEN SHA1_DIGEST_SIZE
+#define HMAC_SHA1_KEY_LEN HASH_SIZE_SHA1
/* RFC 2403 "HMAC-MD5-96" section 3 */
-#define HMAC_MD5_KEY_LEN MD5_DIGEST_SIZE
+#define HMAC_MD5_KEY_LEN HASH_SIZE_MD5
-#define IKE_UDP_PORT 500
+#define IKE_UDP_PORT 500
+
+/* IPsec AH transform values
+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3
+ * and in http://www.iana.org/assignments/isakmp-registry
+ */
+enum ipsec_authentication_algo {
+ AH_NONE = 0,
+ AH_MD5 = 2,
+ AH_SHA = 3,
+ AH_DES = 4,
+ AH_SHA2_256 = 5,
+ AH_SHA2_384 = 6,
+ AH_SHA2_512 = 7,
+ AH_RIPEMD = 8,
+ AH_AES_XCBC_MAC = 9,
+ AH_RSA = 10
+};
+
+extern enum_names ah_transformid_names;
+
+/* IPsec ESP transform values
+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4
+ * and from http://www.iana.org/assignments/isakmp-registry
+ */
+
+enum ipsec_cipher_algo {
+ ESP_NONE = 0,
+ ESP_DES_IV64 = 1,
+ ESP_DES = 2,
+ ESP_3DES = 3,
+ ESP_RC5 = 4,
+ ESP_IDEA = 5,
+ ESP_CAST = 6,
+ ESP_BLOWFISH = 7,
+ ESP_3IDEA = 8,
+ ESP_DES_IV32 = 9,
+ ESP_RC4 = 10,
+ ESP_NULL = 11,
+ ESP_AES = 12,
+ ESP_AES_CTR = 13,
+ ESP_AES_CCM_8 = 14,
+ ESP_AES_CCM_12 = 15,
+ ESP_AES_CCM_16 = 16,
+ ESP_UNASSIGNED_17 = 17,
+ ESP_AES_GCM_8 = 18,
+ ESP_AES_GCM_12 = 19,
+ ESP_AES_GCM_16 = 20,
+ ESP_SEED_CBC = 21,
+ ESP_CAMELLIA = 22,
+ ESP_SERPENT = 252,
+ ESP_TWOFISH = 253
+};
+
+extern enum_names esp_transformid_names;
+
+/* IPCOMP transform values
+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5
+ */
+
+enum ipsec_comp_algo {
+ IPSCOMP_NONE = 0,
+ IPCOMP_OUI = 1,
+ IPCOMP_DEFLATE = 2,
+ IPCOMP_LZS = 3,
+ IPCOMP_LZJH = 4
+};
+
+extern enum_names ipcomp_transformid_names;
+
+/* Certificate type values
+ * RFC 2408 ISAKMP, chapter 3.9
+ */
+enum ipsec_cert_type {
+ CERT_NONE= 0,
+ CERT_PKCS7_WRAPPED_X509= 1,
+ CERT_PGP= 2,
+ CERT_DNS_SIGNED_KEY= 3,
+ CERT_X509_SIGNATURE= 4,
+ CERT_X509_KEY_EXCHANGE= 5,
+ CERT_KERBEROS_TOKENS= 6,
+ CERT_CRL= 7,
+ CERT_ARL= 8,
+ CERT_SPKI= 9,
+ CERT_X509_ATTRIBUTE= 10,
+ CERT_RAW_RSA_KEY= 11
+};
/* RFC 2560 OCSP - certificate status */
typedef enum {
- CERT_GOOD = 0,
- CERT_REVOKED = 1,
- CERT_UNKNOWN = 2,
- CERT_UNDEFINED = 3
+ CERT_GOOD = 0,
+ CERT_REVOKED = 1,
+ CERT_UNKNOWN = 2,
+ CERT_UNDEFINED = 3
} cert_status_t;
/* RFC 2459 CRL reason codes */
-extern enum_names crl_reason_names;
+extern enum_name_t *crl_reason_names;
typedef enum {
- REASON_UNSPECIFIED = 0,
- REASON_KEY_COMPROMISE = 1,
- REASON_CA_COMPROMISE = 2,
- REASON_AFFILIATION_CHANGED = 3,
- REASON_SUPERSEDED = 4,
- REASON_CESSATION_OF_OPERATON = 5,
- REASON_CERTIFICATE_HOLD = 6,
- REASON_REMOVE_FROM_CRL = 8
+ REASON_UNSPECIFIED = 0,
+ REASON_KEY_COMPROMISE = 1,
+ REASON_CA_COMPROMISE = 2,
+ REASON_AFFILIATION_CHANGED = 3,
+ REASON_SUPERSEDED = 4,
+ REASON_CESSATION_OF_OPERATON = 5,
+ REASON_CERTIFICATE_HOLD = 6,
+ REASON_REMOVE_FROM_CRL = 8
} crl_reason_t;
/* RFC 3706 Dead Peer Detection */
-extern enum_names dpd_action_names;
+extern enum_name_t *dpd_action_names;
typedef enum {
- DPD_ACTION_NONE = 0,
- DPD_ACTION_CLEAR = 1,
- DPD_ACTION_HOLD = 2,
- DPD_ACTION_RESTART = 3,
- DPD_ACTION_UNKNOWN = 4
+ DPD_ACTION_NONE = 0,
+ DPD_ACTION_CLEAR = 1,
+ DPD_ACTION_HOLD = 2,
+ DPD_ACTION_RESTART = 3,
+ DPD_ACTION_UNKNOWN = 4
} dpd_action_t;
/* Timer events */
-extern enum_names timer_event_names;
+extern enum_name_t *timer_event_names;
enum event_type {
- EVENT_NULL, /* non-event */
- EVENT_REINIT_SECRET, /* Refresh cookie secret */
+ EVENT_NULL, /* non-event */
+ EVENT_REINIT_SECRET, /* Refresh cookie secret */
#ifdef KLIPS
- EVENT_SHUNT_SCAN, /* scan shunt eroutes known to kernel */
+ EVENT_SHUNT_SCAN, /* scan shunt eroutes known to kernel */
#endif
- EVENT_SO_DISCARD, /* discard unfinished state object */
- EVENT_RETRANSMIT, /* Retransmit packet */
- EVENT_SA_REPLACE, /* SA replacement event */
- EVENT_SA_REPLACE_IF_USED, /* SA replacement event */
- EVENT_SA_EXPIRE, /* SA expiration event */
- EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */
- EVENT_DPD, /* dead peer detection */
- EVENT_DPD_TIMEOUT, /* dead peer detection timeout */
- EVENT_LOG_DAILY /* reset certain log events/stats */
+ EVENT_SO_DISCARD, /* discard unfinished state object */
+ EVENT_RETRANSMIT, /* Retransmit packet */
+ EVENT_SA_REPLACE, /* SA replacement event */
+ EVENT_SA_REPLACE_IF_USED, /* SA replacement event */
+ EVENT_SA_EXPIRE, /* SA expiration event */
+ EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */
+ EVENT_DPD, /* dead peer detection */
+ EVENT_DPD_TIMEOUT, /* dead peer detection timeout */
+ EVENT_LOG_DAILY /* reset certain log events/stats */
};
-#define EVENT_REINIT_SECRET_DELAY 3600 /* 1 hour */
-#define EVENT_RETRANSMIT_DELAY_0 10 /* 10 seconds */
+#define EVENT_REINIT_SECRET_DELAY 3600 /* 1 hour */
+#define EVENT_RETRANSMIT_DELAY_0 10 /* 10 seconds */
/* Misc. stuff */
@@ -429,29 +327,29 @@ extern enum_names doi_names;
extern const char *const debug_bit_names[];
#endif
-#define DBG_RAW LELEM(0) /* raw packet I/O */
-#define DBG_CRYPT LELEM(1) /* encryption/decryption of messages */
-#define DBG_PARSING LELEM(2) /* show decoding of messages */
-#define DBG_EMITTING LELEM(3) /* show encoding of messages */
-#define DBG_CONTROL LELEM(4) /* control flow within Pluto */
-#define DBG_LIFECYCLE LELEM(5) /* SA lifecycle */
-#define DBG_KLIPS LELEM(6) /* messages to KLIPS */
-#define DBG_DNS LELEM(7) /* DNS activity */
-#define DBG_NATT LELEM(8) /* NAT-T */
-#define DBG_OPPO LELEM(9) /* opportunism */
-#define DBG_CONTROLMORE LELEM(10) /* more detailed debugging */
+#define DBG_RAW LELEM(0) /* raw packet I/O */
+#define DBG_CRYPT LELEM(1) /* encryption/decryption of messages */
+#define DBG_PARSING LELEM(2) /* show decoding of messages */
+#define DBG_EMITTING LELEM(3) /* show encoding of messages */
+#define DBG_CONTROL LELEM(4) /* control flow within Pluto */
+#define DBG_LIFECYCLE LELEM(5) /* SA lifecycle */
+#define DBG_KLIPS LELEM(6) /* messages to KLIPS */
+#define DBG_DNS LELEM(7) /* DNS activity */
+#define DBG_NATT LELEM(8) /* NAT-T */
+#define DBG_OPPO LELEM(9) /* opportunism */
+#define DBG_CONTROLMORE LELEM(10) /* more detailed debugging */
-#define DBG_PRIVATE LELEM(11) /* private information: DANGER! */
+#define DBG_PRIVATE LELEM(11) /* private information: DANGER! */
-#define IMPAIR0 12 /* first bit for IMPAIR_* */
+#define IMPAIR0 12 /* first bit for IMPAIR_* */
-#define IMPAIR_DELAY_ADNS_KEY_ANSWER LELEM(IMPAIR0+0) /* sleep before answering */
-#define IMPAIR_DELAY_ADNS_TXT_ANSWER LELEM(IMPAIR0+1) /* sleep before answering */
-#define IMPAIR_BUST_MI2 LELEM(IMPAIR0+2) /* make MI2 really large */
-#define IMPAIR_BUST_MR2 LELEM(IMPAIR0+3) /* make MI2 really large */
+#define IMPAIR_DELAY_ADNS_KEY_ANSWER LELEM(IMPAIR0+0) /* sleep before answering */
+#define IMPAIR_DELAY_ADNS_TXT_ANSWER LELEM(IMPAIR0+1) /* sleep before answering */
+#define IMPAIR_BUST_MI2 LELEM(IMPAIR0+2) /* make MI2 really large */
+#define IMPAIR_BUST_MR2 LELEM(IMPAIR0+3) /* make MI2 really large */
-#define DBG_NONE 0 /* no options on, including impairments */
-#define DBG_ALL LRANGES(DBG_RAW, DBG_CONTROLMORE) /* all logging options on EXCEPT DBG_PRIVATE */
+#define DBG_NONE 0 /* no options on, including impairments */
+#define DBG_ALL LRANGES(DBG_RAW, DBG_CONTROLMORE) /* all logging options on EXCEPT DBG_PRIVATE */
/* State of exchanges
*
@@ -484,86 +382,86 @@ extern enum_names state_names;
extern const char *const state_story[];
enum state_kind {
- STATE_UNDEFINED, /* 0 -- most likely accident */
+ STATE_UNDEFINED, /* 0 -- most likely accident */
- /* Opportunism states: see "Opportunistic Encryption" 2.2 */
+ /* Opportunism states: see "Opportunistic Encryption" 2.2 */
- OPPO_ACQUIRE, /* got an ACQUIRE message for this pair */
- OPPO_GW_DISCOVERED, /* got TXT specifying gateway */
+ OPPO_ACQUIRE, /* got an ACQUIRE message for this pair */
+ OPPO_GW_DISCOVERED, /* got TXT specifying gateway */
- /* IKE states */
+ /* IKE states */
- STATE_MAIN_R0,
- STATE_MAIN_I1,
- STATE_MAIN_R1,
- STATE_MAIN_I2,
- STATE_MAIN_R2,
- STATE_MAIN_I3,
- STATE_MAIN_R3,
- STATE_MAIN_I4,
+ STATE_MAIN_R0,
+ STATE_MAIN_I1,
+ STATE_MAIN_R1,
+ STATE_MAIN_I2,
+ STATE_MAIN_R2,
+ STATE_MAIN_I3,
+ STATE_MAIN_R3,
+ STATE_MAIN_I4,
- STATE_QUICK_R0,
- STATE_QUICK_I1,
- STATE_QUICK_R1,
- STATE_QUICK_I2,
- STATE_QUICK_R2,
+ STATE_QUICK_R0,
+ STATE_QUICK_I1,
+ STATE_QUICK_R1,
+ STATE_QUICK_I2,
+ STATE_QUICK_R2,
- STATE_INFO,
- STATE_INFO_PROTECTED,
+ STATE_INFO,
+ STATE_INFO_PROTECTED,
- /* XAUTH states */
+ /* XAUTH states */
- STATE_XAUTH_I0, /* initiator state (client) */
- STATE_XAUTH_R1, /* responder state (server) */
- STATE_XAUTH_I1,
- STATE_XAUTH_R2,
- STATE_XAUTH_I2,
- STATE_XAUTH_R3,
+ STATE_XAUTH_I0, /* initiator state (client) */
+ STATE_XAUTH_R1, /* responder state (server) */
+ STATE_XAUTH_I1,
+ STATE_XAUTH_R2,
+ STATE_XAUTH_I2,
+ STATE_XAUTH_R3,
- /* Mode Config pull states */
+ /* Mode Config pull states */
- STATE_MODE_CFG_R0, /* responder state (server) */
- STATE_MODE_CFG_I1, /* initiator state (client) */
- STATE_MODE_CFG_R1,
- STATE_MODE_CFG_I2,
+ STATE_MODE_CFG_R0, /* responder state (server) */
+ STATE_MODE_CFG_I1, /* initiator state (client) */
+ STATE_MODE_CFG_R1,
+ STATE_MODE_CFG_I2,
- /* Mode Config push states */
+ /* Mode Config push states */
- STATE_MODE_CFG_I0, /* initiator state (client) */
- STATE_MODE_CFG_R3, /* responder state (server) */
- STATE_MODE_CFG_I3,
- STATE_MODE_CFG_R4,
+ STATE_MODE_CFG_I0, /* initiator state (client) */
+ STATE_MODE_CFG_R3, /* responder state (server) */
+ STATE_MODE_CFG_I3,
+ STATE_MODE_CFG_R4,
- STATE_IKE_ROOF
+ STATE_IKE_ROOF
};
-#define STATE_IKE_FLOOR STATE_MAIN_R0
+#define STATE_IKE_FLOOR STATE_MAIN_R0
-#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \
- | LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4))
+#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \
+ | LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4))
#define ISAKMP_SA_ESTABLISHED_STATES ( \
- LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
- | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
- | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
- | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \
- | LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4))
+ LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
+ | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
+ | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
+ | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \
+ | LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4))
#define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \
- || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \
- || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4))
+ || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \
+ || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4))
#define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
#define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s))
#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
- (s) == STATE_MAIN_R3 \
- || (s) == STATE_MAIN_I4 \
- || (s) == STATE_XAUTH_I2 \
- || (s) == STATE_XAUTH_R3 \
- || (s) == STATE_MODE_CFG_R1 \
- || (s) == STATE_MODE_CFG_I2 \
- || (s) == STATE_MODE_CFG_I3 \
- || (s) == STATE_MODE_CFG_R4)
+ (s) == STATE_MAIN_R3 \
+ || (s) == STATE_MAIN_I4 \
+ || (s) == STATE_XAUTH_I2 \
+ || (s) == STATE_XAUTH_R3 \
+ || (s) == STATE_MODE_CFG_R1 \
+ || (s) == STATE_MODE_CFG_I2 \
+ || (s) == STATE_MODE_CFG_I3 \
+ || (s) == STATE_MODE_CFG_R4)
#define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2)
#define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1)
@@ -575,11 +473,11 @@ enum state_kind {
extern enum_names connection_kind_names;
enum connection_kind {
- CK_GROUP, /* policy group: instantiates to template */
- CK_TEMPLATE, /* abstract connection, with wildcard */
- CK_PERMANENT, /* normal connection */
- CK_INSTANCE, /* instance of template, created for a particular attempt */
- CK_GOING_AWAY /* instance being deleted -- don't delete again */
+ CK_GROUP, /* policy group: instantiates to template */
+ CK_TEMPLATE, /* abstract connection, with wildcard */
+ CK_PERMANENT, /* normal connection */
+ CK_INSTANCE, /* instance of template, created for a particular attempt */
+ CK_GOING_AWAY /* instance being deleted -- don't delete again */
};
@@ -593,14 +491,14 @@ extern enum_names routing_story;
/* note that this is assumed to be ordered! */
enum routing_t {
- RT_UNROUTED, /* unrouted */
- RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */
- RT_ROUTED_ECLIPSED, /* RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */
- RT_ROUTED_PROSPECTIVE, /* routed, and prospective shunt installed */
- RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */
- RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */
- RT_ROUTED_TUNNEL, /* routed, and erouted to an IPSEC SA group */
- RT_UNROUTED_KEYED /* keyed, but not routed, on purpose */
+ RT_UNROUTED, /* unrouted */
+ RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */
+ RT_ROUTED_ECLIPSED, /* RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */
+ RT_ROUTED_PROSPECTIVE, /* routed, and prospective shunt installed */
+ RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */
+ RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */
+ RT_ROUTED_TUNNEL, /* routed, and erouted to an IPSEC SA group */
+ RT_UNROUTED_KEYED /* keyed, but not routed, on purpose */
};
#define routed(rs) ((rs) > RT_UNROUTED_HOLD)
@@ -618,25 +516,25 @@ enum routing_t {
extern enum_names payload_names;
extern const char *const payload_name[];
-#define ISAKMP_NEXT_NONE 0 /* No other payload following */
-#define ISAKMP_NEXT_SA 1 /* Security Association */
-#define ISAKMP_NEXT_P 2 /* Proposal */
-#define ISAKMP_NEXT_T 3 /* Transform */
-#define ISAKMP_NEXT_KE 4 /* Key Exchange */
-#define ISAKMP_NEXT_ID 5 /* Identification */
-#define ISAKMP_NEXT_CERT 6 /* Certificate */
-#define ISAKMP_NEXT_CR 7 /* Certificate Request */
-#define ISAKMP_NEXT_HASH 8 /* Hash */
-#define ISAKMP_NEXT_SIG 9 /* Signature */
-#define ISAKMP_NEXT_NONCE 10 /* Nonce */
-#define ISAKMP_NEXT_N 11 /* Notification */
-#define ISAKMP_NEXT_D 12 /* Delete */
-#define ISAKMP_NEXT_VID 13 /* Vendor ID */
+#define ISAKMP_NEXT_NONE 0 /* No other payload following */
+#define ISAKMP_NEXT_SA 1 /* Security Association */
+#define ISAKMP_NEXT_P 2 /* Proposal */
+#define ISAKMP_NEXT_T 3 /* Transform */
+#define ISAKMP_NEXT_KE 4 /* Key Exchange */
+#define ISAKMP_NEXT_ID 5 /* Identification */
+#define ISAKMP_NEXT_CERT 6 /* Certificate */
+#define ISAKMP_NEXT_CR 7 /* Certificate Request */
+#define ISAKMP_NEXT_HASH 8 /* Hash */
+#define ISAKMP_NEXT_SIG 9 /* Signature */
+#define ISAKMP_NEXT_NONCE 10 /* Nonce */
+#define ISAKMP_NEXT_N 11 /* Notification */
+#define ISAKMP_NEXT_D 12 /* Delete */
+#define ISAKMP_NEXT_VID 13 /* Vendor ID */
#define ISAKMP_NEXT_ATTR 14 /* Mode config Attribute */
-#define ISAKMP_NEXT_NATD_RFC 20 /* NAT-Traversal: NAT-D (rfc) */
-#define ISAKMP_NEXT_NATOA_RFC 21 /* NAT-Traversal: NAT-OA (rfc) */
-#define ISAKMP_NEXT_ROOF 22 /* roof on payload types */
+#define ISAKMP_NEXT_NATD_RFC 20 /* NAT-Traversal: NAT-D (rfc) */
+#define ISAKMP_NEXT_NATOA_RFC 21 /* NAT-Traversal: NAT-OA (rfc) */
+#define ISAKMP_NEXT_ROOF 22 /* roof on payload types */
#define ISAKMP_NEXT_NATD_DRAFTS 130 /* NAT-Traversal: NAT-D (drafts) */
#define ISAKMP_NEXT_NATOA_DRAFTS 131 /* NAT-Traversal: NAT-OA (drafts) */
@@ -687,18 +585,24 @@ extern enum_names modecfg_attr_names;
extern enum_names xauth_attr_names;
-/* ISAKMP mode config attributes specific to the Unity vendor Id */
-#define UNITY_BANNER 28672
-#define UNITY_SAVE_PASSWD 28673
-#define UNITY_DEF_DOMAIN 28674
-#define UNITY_SPLITDNS_NAME 28675
-#define UNITY_SPLIT_INCLUDE 28676
-#define UNITY_NATT_PORT 28677
-#define UNITY_LOCAL_LAN 28678
-#define UNITY_PFS 28679
-#define UNITY_FW_TYPE 28680
-#define UNITY_BACKUP_SERVERS 28681
-#define UNITY_DDNS_HOSTNAME 28682
+/* ISAKMP mode config attributes specific to Microsoft */
+#define INTERNAL_IP4_SERVER 23456
+#define INTERNAL_IP6_SERVER 23457
+
+extern enum_names microsoft_attr_names;
+
+/* ISAKMP mode config attributes specific to the Unity vendor ID */
+#define UNITY_BANNER 28672
+#define UNITY_SAVE_PASSWD 28673
+#define UNITY_DEF_DOMAIN 28674
+#define UNITY_SPLITDNS_NAME 28675
+#define UNITY_SPLIT_INCLUDE 28676
+#define UNITY_NATT_PORT 28677
+#define UNITY_LOCAL_LAN 28678
+#define UNITY_PFS 28679
+#define UNITY_FW_TYPE 28680
+#define UNITY_BACKUP_SERVERS 28681
+#define UNITY_DDNS_HOSTNAME 28682
#define UNITY_BASE UNITY_BANNER
@@ -711,8 +615,8 @@ extern enum_names unity_attr_names;
#define XAUTH_TYPE_SKEY 3
/* Values for XAUTH_STATUS */
-#define XAUTH_STATUS_FAIL 0
-#define XAUTH_STATUS_OK 1
+#define XAUTH_STATUS_FAIL 0
+#define XAUTH_STATUS_OK 1
extern enum_names xauth_type_names;
@@ -732,19 +636,19 @@ extern enum_names exchange_names;
#define ISAKMP_XCHG_NONE 0
#define ISAKMP_XCHG_BASE 1
-#define ISAKMP_XCHG_IDPROT 2 /* ID Protection */
-#define ISAKMP_XCHG_AO 3 /* Authentication Only */
-#define ISAKMP_XCHG_AGGR 4 /* Aggressive */
-#define ISAKMP_XCHG_INFO 5 /* Informational */
-#define ISAKMP_XCHG_MODE_CFG 6 /* Mode Config */
+#define ISAKMP_XCHG_IDPROT 2 /* ID Protection */
+#define ISAKMP_XCHG_AO 3 /* Authentication Only */
+#define ISAKMP_XCHG_AGGR 4 /* Aggressive */
+#define ISAKMP_XCHG_INFO 5 /* Informational */
+#define ISAKMP_XCHG_MODE_CFG 6 /* Mode Config */
/* Extra exchange types, defined by Oakley
* RFC2409 "The Internet Key Exchange (IKE)", near end of Appendix A
*/
-#define ISAKMP_XCHG_QUICK 32 /* Oakley Quick Mode */
-#define ISAKMP_XCHG_NGRP 33 /* Oakley New Group Mode */
+#define ISAKMP_XCHG_QUICK 32 /* Oakley Quick Mode */
+#define ISAKMP_XCHG_NGRP 33 /* Oakley New Group Mode */
/* added in draft-ietf-ipsec-ike-01.txt, near end of Appendix A */
-#define ISAKMP_XCHG_ACK_INFO 34 /* Oakley Acknowledged Informational */
+#define ISAKMP_XCHG_ACK_INFO 34 /* Oakley Acknowledged Informational */
/* Flag bits */
@@ -774,20 +678,14 @@ extern enum_names protocol_names;
/* warning: trans_show uses enum_show, so same static buffer is used */
#define trans_show(p, t) \
- ((p)==PROTO_IPSEC_AH ? enum_show(&ah_transformid_names, (t)) \
- : (p)==PROTO_IPSEC_ESP ? enum_show(&esp_transformid_names, (t)) \
- : (p)==PROTO_IPCOMP ? enum_show(&ipcomp_transformid_names, (t)) \
- : "??")
-
-/* many transform values are moved to freeswan/ipsec_policy.h */
-
-extern enum_names isakmp_transformid_names;
+ ((p)==PROTO_IPSEC_AH ? enum_show(&ah_transformid_names, (t)) \
+ : (p)==PROTO_IPSEC_ESP ? enum_show(&esp_transformid_names, (t)) \
+ : (p)==PROTO_IPCOMP ? enum_show(&ipcomp_transformid_names, (t)) \
+ : "??")
#define KEY_IKE 1
-extern enum_names ah_transformid_names;
-extern enum_names esp_transformid_names;
-extern enum_names ipcomp_transformid_names;
+extern enum_names isakmp_transformid_names;
/* the following are from RFC 2393/draft-shacham-ippcp-rfc2393bis-05.txt 3.3 */
typedef u_int16_t cpi_t;
@@ -801,15 +699,16 @@ typedef u_int16_t cpi_t;
extern enum_names ident_names;
extern enum_names cert_type_names;
-extern enum_names cert_policy_names;
+
+extern enum_name_t *cert_policy_names;
typedef enum certpolicy {
- CERT_ALWAYS_SEND = 0, /* the default */
- CERT_SEND_IF_ASKED = 1,
- CERT_NEVER_SEND = 2,
+ CERT_ALWAYS_SEND = 0,
+ CERT_SEND_IF_ASKED = 1,
+ CERT_NEVER_SEND = 2,
- CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */
- CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */
+ CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */
+ CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */
} certpolicy_t;
/* Policies for establishing an SA
@@ -825,36 +724,36 @@ extern const char *prettypolicy(lset_t policy);
/* ISAKMP auth techniques (none means never negotiate) */
#define POLICY_PSK LELEM(0)
-#define POLICY_RSASIG LELEM(1)
+#define POLICY_PUBKEY LELEM(1)
-#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */
-#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_RSASIG | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG)
-#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */
+#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */
+#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_PUBKEY | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG)
+#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */
/* Quick Mode (IPSEC) attributes */
-#define POLICY_ENCRYPT LELEM(2) /* must be first of IPSEC policies */
-#define POLICY_AUTHENTICATE LELEM(3) /* must be second */
-#define POLICY_COMPRESS LELEM(4) /* must be third */
+#define POLICY_ENCRYPT LELEM(2) /* must be first of IPSEC policies */
+#define POLICY_AUTHENTICATE LELEM(3) /* must be second */
+#define POLICY_COMPRESS LELEM(4) /* must be third */
#define POLICY_TUNNEL LELEM(5)
#define POLICY_PFS LELEM(6)
-#define POLICY_DISABLEARRIVALCHECK LELEM(7) /* supress tunnel egress address checking */
+#define POLICY_DISABLEARRIVALCHECK LELEM(7) /* supress tunnel egress address checking */
-#define POLICY_IPSEC_SHIFT 2 /* log2(POLICY_ENCRYPT) */
-#define POLICY_IPSEC_MASK LRANGES(POLICY_ENCRYPT, POLICY_DISABLEARRIVALCHECK)
+#define POLICY_IPSEC_SHIFT 2 /* log2(POLICY_ENCRYPT) */
+#define POLICY_IPSEC_MASK LRANGES(POLICY_ENCRYPT, POLICY_DISABLEARRIVALCHECK)
/* shunt attributes: what to do when routed without tunnel (2 bits) */
-#define POLICY_SHUNT_SHIFT 8 /* log2(POLICY_SHUNT_PASS) */
-#define POLICY_SHUNT_MASK (03ul << POLICY_SHUNT_SHIFT)
+#define POLICY_SHUNT_SHIFT 8 /* log2(POLICY_SHUNT_PASS) */
+#define POLICY_SHUNT_MASK (03ul << POLICY_SHUNT_SHIFT)
-#define POLICY_SHUNT_TRAP (0ul << POLICY_SHUNT_SHIFT) /* default: negotiate */
-#define POLICY_SHUNT_PASS (1ul << POLICY_SHUNT_SHIFT)
-#define POLICY_SHUNT_DROP (2ul << POLICY_SHUNT_SHIFT)
-#define POLICY_SHUNT_REJECT (3ul << POLICY_SHUNT_SHIFT)
+#define POLICY_SHUNT_TRAP (0ul << POLICY_SHUNT_SHIFT) /* default: negotiate */
+#define POLICY_SHUNT_PASS (1ul << POLICY_SHUNT_SHIFT)
+#define POLICY_SHUNT_DROP (2ul << POLICY_SHUNT_SHIFT)
+#define POLICY_SHUNT_REJECT (3ul << POLICY_SHUNT_SHIFT)
/* fail attributes: what to do with failed negotiation (2 bits) */
-#define POLICY_FAIL_SHIFT 10 /* log2(POLICY_FAIL_PASS) */
-#define POLICY_FAIL_MASK (03ul << POLICY_FAIL_SHIFT)
+#define POLICY_FAIL_SHIFT 10 /* log2(POLICY_FAIL_PASS) */
+#define POLICY_FAIL_MASK (03ul << POLICY_FAIL_SHIFT)
#define POLICY_FAIL_NONE (0ul << POLICY_FAIL_SHIFT) /* default */
#define POLICY_FAIL_PASS (1ul << POLICY_FAIL_SHIFT)
@@ -864,21 +763,20 @@ extern const char *prettypolicy(lset_t policy);
/* connection policy
* Other policies could vary per state object. These live in connection.
*/
-#define POLICY_DONT_REKEY LELEM(12) /* don't rekey state either Phase */
-#define POLICY_OPPO LELEM(13) /* is this opportunistic? */
-#define POLICY_GROUP LELEM(14) /* is this a group template? */
-#define POLICY_GROUTED LELEM(15) /* do we want this group routed? */
-#define POLICY_UP LELEM(16) /* do we want this up? */
-#define POLICY_MODECFG_PUSH LELEM(17) /* is modecfg pushed by server? */
-#define POLICY_XAUTH_PSK LELEM(18) /* do we support XAUTH????PreShared? */
-#define POLICY_XAUTH_RSASIG LELEM(19) /* do we support XAUTH????RSA? */
-#define POLICY_XAUTH_SERVER LELEM(20) /* are we an XAUTH server? */
-#define POLICY_DONT_REAUTH LELEM(21) /* don't reauthenticate on rekeying, IKEv2 only */
-#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
-#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
-#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
-#define POLICY_ECDSASIG LELEM(25) /* ECDSA signature (IKEv2) */
-#define POLICY_PROXY LELEM(26) /* proxy transport mode (MIPv6) */
+#define POLICY_DONT_REKEY LELEM(12) /* don't rekey state either Phase */
+#define POLICY_OPPO LELEM(13) /* is this opportunistic? */
+#define POLICY_GROUP LELEM(14) /* is this a group template? */
+#define POLICY_GROUTED LELEM(15) /* do we want this group routed? */
+#define POLICY_UP LELEM(16) /* do we want this up? */
+#define POLICY_MODECFG_PUSH LELEM(17) /* is modecfg pushed by server? */
+#define POLICY_XAUTH_PSK LELEM(18) /* do we support XAUTH????PreShared? */
+#define POLICY_XAUTH_RSASIG LELEM(19) /* do we support XAUTH????RSA? */
+#define POLICY_XAUTH_SERVER LELEM(20) /* are we an XAUTH server? */
+#define POLICY_DONT_REAUTH LELEM(21) /* don't reauthenticate on rekeying, IKEv2 only */
+#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
+#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
+#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
+#define POLICY_PROXY LELEM(25) /* proxy transport mode (MIPv6) */
/* Any IPsec policy? If not, a connection description
* is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
@@ -903,17 +801,17 @@ extern const char *const oakley_attr_bit_names[];
#define OAKLEY_AUTHENTICATION_METHOD 3
#define OAKLEY_GROUP_DESCRIPTION 4
#define OAKLEY_GROUP_TYPE 5
-#define OAKLEY_GROUP_PRIME 6 /* B/V */
-#define OAKLEY_GROUP_GENERATOR_ONE 7 /* B/V */
-#define OAKLEY_GROUP_GENERATOR_TWO 8 /* B/V */
-#define OAKLEY_GROUP_CURVE_A 9 /* B/V */
-#define OAKLEY_GROUP_CURVE_B 10 /* B/V */
+#define OAKLEY_GROUP_PRIME 6 /* B/V */
+#define OAKLEY_GROUP_GENERATOR_ONE 7 /* B/V */
+#define OAKLEY_GROUP_GENERATOR_TWO 8 /* B/V */
+#define OAKLEY_GROUP_CURVE_A 9 /* B/V */
+#define OAKLEY_GROUP_CURVE_B 10 /* B/V */
#define OAKLEY_LIFE_TYPE 11
-#define OAKLEY_LIFE_DURATION 12 /* B/V */
+#define OAKLEY_LIFE_DURATION 12 /* B/V */
#define OAKLEY_PRF 13
#define OAKLEY_KEY_LENGTH 14
#define OAKLEY_FIELD_SIZE 15
-#define OAKLEY_GROUP_ORDER 16 /* B/V */
+#define OAKLEY_GROUP_ORDER 16 /* B/V */
#define OAKLEY_BLOCK_SIZE 17
/* for each Oakley attribute, which enum_names describes its values? */
@@ -926,14 +824,14 @@ extern enum_names *oakley_attr_val_descs[];
extern enum_names ipsec_attr_names;
#define SA_LIFE_TYPE 1
-#define SA_LIFE_DURATION 2 /* B/V */
+#define SA_LIFE_DURATION 2 /* B/V */
#define GROUP_DESCRIPTION 3
#define ENCAPSULATION_MODE 4
#define AUTH_ALGORITHM 5
#define KEY_LENGTH 6
#define KEY_ROUNDS 7
#define COMPRESS_DICT_SIZE 8
-#define COMPRESS_PRIVATE_ALG 9 /* B/V */
+#define COMPRESS_PRIVATE_ALG 9 /* B/V */
/* for each IPsec attribute, which enum_names describes its values? */
extern enum_names *ipsec_attr_val_descs[];
@@ -961,9 +859,9 @@ extern enum_names sa_lifetime_names;
#define PLUTO_SA_LIFE_DURATION_DEFAULT 3600 /* one hour (pluto(8)) */
#define SA_LIFE_DURATION_MAXIMUM 86400 /* one day */
-#define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* (IPSEC & IKE) nine minutes */
-#define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* (IPSEC & IKE) 100% of MARGIN */
-#define SA_REPLACEMENT_RETRIES_DEFAULT 3 /* (IPSEC & IKE) */
+#define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* (IPSEC & IKE) nine minutes */
+#define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* (IPSEC & IKE) 100% of MARGIN */
+#define SA_REPLACEMENT_RETRIES_DEFAULT 3 /* (IPSEC & IKE) */
#define SA_LIFE_DURATION_K_DEFAULT 0xFFFFFFFFlu
@@ -971,7 +869,7 @@ extern enum_names sa_lifetime_names;
extern enum_names enc_mode_names;
-#define ENCAPSULATION_MODE_UNSPECIFIED 0 /* not legal -- used internally */
+#define ENCAPSULATION_MODE_UNSPECIFIED 0 /* not legal -- used internally */
#define ENCAPSULATION_MODE_TUNNEL 1
#define ENCAPSULATION_MODE_TRANSPORT 2
@@ -985,18 +883,18 @@ extern enum_names enc_mode_names;
extern enum_names auth_alg_names, extended_auth_alg_names;
-#define AUTH_ALGORITHM_NONE 0 /* our private designation */
-#define AUTH_ALGORITHM_HMAC_MD5 1
-#define AUTH_ALGORITHM_HMAC_SHA1 2
-#define AUTH_ALGORITHM_DES_MAC 3
-#define AUTH_ALGORITHM_KPDK 4
-#define AUTH_ALGORITHM_HMAC_SHA2_256 5
-#define AUTH_ALGORITHM_HMAC_SHA2_384 6
-#define AUTH_ALGORITHM_HMAC_SHA2_512 7
-#define AUTH_ALGORITHM_HMAC_RIPEMD 8
-#define AUTH_ALGORITHM_AES_XCBC_MAC 9
-#define AUTH_ALGORITHM_SIG_RSA 10
-#define AUTH_ALGORITHM_NULL 251
+#define AUTH_ALGORITHM_NONE 0 /* our private designation */
+#define AUTH_ALGORITHM_HMAC_MD5 1
+#define AUTH_ALGORITHM_HMAC_SHA1 2
+#define AUTH_ALGORITHM_DES_MAC 3
+#define AUTH_ALGORITHM_KPDK 4
+#define AUTH_ALGORITHM_HMAC_SHA2_256 5
+#define AUTH_ALGORITHM_HMAC_SHA2_384 6
+#define AUTH_ALGORITHM_HMAC_SHA2_512 7
+#define AUTH_ALGORITHM_HMAC_RIPEMD 8
+#define AUTH_ALGORITHM_AES_XCBC_MAC 9
+#define AUTH_ALGORITHM_SIG_RSA 10
+#define AUTH_ALGORITHM_NULL 251
/* Oakley Lifetime Type attribute
* draft-ietf-ipsec-ike-01.txt appendix A
@@ -1030,23 +928,24 @@ extern enum_names oakley_prf_names;
extern enum_names oakley_enc_names;
-#define OAKLEY_DES_CBC 1
-#define OAKLEY_IDEA_CBC 2
-#define OAKLEY_BLOWFISH_CBC 3
-#define OAKLEY_RC5_R16_B64_CBC 4
-#define OAKLEY_3DES_CBC 5
-#define OAKLEY_CAST_CBC 6
-#define OAKLEY_AES_CBC 7
+#define OAKLEY_DES_CBC 1
+#define OAKLEY_IDEA_CBC 2
+#define OAKLEY_BLOWFISH_CBC 3
+#define OAKLEY_RC5_R16_B64_CBC 4
+#define OAKLEY_3DES_CBC 5
+#define OAKLEY_CAST_CBC 6
+#define OAKLEY_AES_CBC 7
+#define OAKLEY_CAMELLIA_CBC 8
-#define OAKLEY_MARS_CBC 65001
-#define OAKLEY_RC6_CBC 65002
-#define OAKLEY_ID_65003 65003
-#define OAKLEY_SERPENT_CBC 65004
-#define OAKLEY_TWOFISH_CBC 65005
+#define OAKLEY_MARS_CBC 65001
+#define OAKLEY_RC6_CBC 65002
+#define OAKLEY_ID_65003 65003
+#define OAKLEY_SERPENT_CBC 65004
+#define OAKLEY_TWOFISH_CBC 65005
-#define OAKLEY_TWOFISH_CBC_SSH 65289
+#define OAKLEY_TWOFISH_CBC_SSH 65289
-#define OAKLEY_ENCRYPT_MAX 65535 /* pretty useless :) */
+#define OAKLEY_ENCRYPT_MAX 65535 /* pretty useless :) */
/* Oakley Hash Algorithm attribute
* draft-ietf-ipsec-ike-01.txt appendix A
@@ -1079,42 +978,35 @@ extern enum_names oakley_auth_names;
#define OAKLEY_RSA_ENC_REV 5
#define OAKLEY_ELGAMAL_ENC 6
#define OAKLEY_ELGAMAL_ENC_REV 7
+#define OAKLEY_ECDSA_SIG 8
+#define OAKLEY_ECDSA_256 9
+#define OAKLEY_ECDSA_384 10
+#define OAKLEY_ECDSA_521 11
-#define OAKLEY_AUTH_ROOF 8 /* roof on auth values THAT WE SUPPORT */
+#define OAKLEY_AUTH_ROOF 12 /* roof on auth values THAT WE SUPPORT */
-#define HybridInitRSA 64221
-#define HybridRespRSA 64222
-#define HybridInitDSS 64223
-#define HybridRespDSS 64224
+#define HybridInitRSA 64221
+#define HybridRespRSA 64222
+#define HybridInitDSS 64223
+#define HybridRespDSS 64224
-#define XAUTHInitPreShared 65001
-#define XAUTHRespPreShared 65002
-#define XAUTHInitDSS 65003
+#define XAUTHInitPreShared 65001
+#define XAUTHRespPreShared 65002
+#define XAUTHInitDSS 65003
#define XAUTHRespDSS 65004
-#define XAUTHInitRSA 65005
-#define XAUTHRespRSA 65006
-#define XAUTHInitRSAEncryption 65007
-#define XAUTHRespRSAEncryption 65008
-#define XAUTHInitRSARevisedEncryption 65009
-#define XAUTHRespRSARevisedEncryption 65010
+#define XAUTHInitRSA 65005
+#define XAUTHRespRSA 65006
+#define XAUTHInitRSAEncryption 65007
+#define XAUTHRespRSAEncryption 65008
+#define XAUTHInitRSARevisedEncryption 65009
+#define XAUTHRespRSARevisedEncryption 65010
/* Oakley Group Description attribute
* draft-ietf-ipsec-ike-01.txt appendix A
*/
extern enum_names oakley_group_names;
-#define OAKLEY_GROUP_MODP768 1
-#define OAKLEY_GROUP_MODP1024 2
-#define OAKLEY_GROUP_GP155 3
-#define OAKLEY_GROUP_GP185 4
-#define OAKLEY_GROUP_MODP1536 5
-
-#define OAKLEY_GROUP_MODP2048 14
-#define OAKLEY_GROUP_MODP3072 15
-#define OAKLEY_GROUP_MODP4096 16
-#define OAKLEY_GROUP_MODP6144 17
-#define OAKLEY_GROUP_MODP8192 18
-/* you must also touch: constants.c, crypto.c */
+/* you must also touch: constants.c, crypto.c */
/* Oakley Group Type attribute
* draft-ietf-ipsec-ike-01.txt appendix A
@@ -1134,54 +1026,54 @@ extern enum_names notification_names;
extern enum_names ipsec_notification_names;
typedef enum {
- NOTHING_WRONG = 0, /* unofficial! */
-
- INVALID_PAYLOAD_TYPE = 1,
- DOI_NOT_SUPPORTED = 2,
- SITUATION_NOT_SUPPORTED = 3,
- INVALID_COOKIE = 4,
- INVALID_MAJOR_VERSION = 5,
- INVALID_MINOR_VERSION = 6,
- INVALID_EXCHANGE_TYPE = 7,
- INVALID_FLAGS = 8,
- INVALID_MESSAGE_ID = 9,
- INVALID_PROTOCOL_ID = 10,
- INVALID_SPI = 11,
- INVALID_TRANSFORM_ID = 12,
- ATTRIBUTES_NOT_SUPPORTED = 13,
- NO_PROPOSAL_CHOSEN = 14,
- BAD_PROPOSAL_SYNTAX = 15,
- PAYLOAD_MALFORMED = 16,
- INVALID_KEY_INFORMATION = 17,
- INVALID_ID_INFORMATION = 18,
- INVALID_CERT_ENCODING = 19,
- INVALID_CERTIFICATE = 20,
- CERT_TYPE_UNSUPPORTED = 21,
- INVALID_CERT_AUTHORITY = 22,
- INVALID_HASH_INFORMATION = 23,
- AUTHENTICATION_FAILED = 24,
- INVALID_SIGNATURE = 25,
- ADDRESS_NOTIFICATION = 26,
- NOTIFY_SA_LIFETIME = 27,
- CERTIFICATE_UNAVAILABLE = 28,
- UNSUPPORTED_EXCHANGE_TYPE = 29,
- UNEQUAL_PAYLOAD_LENGTHS = 30,
-
- /* ISAKMP status type */
- CONNECTED = 16384,
-
- /* IPSEC DOI additions; status types (RFC2407 IPSEC DOI 4.6.3)
- * These must be sent under the protection of an ISAKMP SA.
- */
- IPSEC_RESPONDER_LIFETIME = 24576,
- IPSEC_REPLAY_STATUS = 24577,
- IPSEC_INITIAL_CONTACT = 24578,
-
- /* RFC 3706 DPD */
- R_U_THERE = 36136,
- R_U_THERE_ACK = 36137
-
- } notification_t;
+ NOTHING_WRONG = 0, /* unofficial! */
+
+ INVALID_PAYLOAD_TYPE = 1,
+ DOI_NOT_SUPPORTED = 2,
+ SITUATION_NOT_SUPPORTED = 3,
+ INVALID_COOKIE = 4,
+ INVALID_MAJOR_VERSION = 5,
+ INVALID_MINOR_VERSION = 6,
+ INVALID_EXCHANGE_TYPE = 7,
+ INVALID_FLAGS = 8,
+ INVALID_MESSAGE_ID = 9,
+ INVALID_PROTOCOL_ID = 10,
+ INVALID_SPI = 11,
+ INVALID_TRANSFORM_ID = 12,
+ ATTRIBUTES_NOT_SUPPORTED = 13,
+ NO_PROPOSAL_CHOSEN = 14,
+ BAD_PROPOSAL_SYNTAX = 15,
+ PAYLOAD_MALFORMED = 16,
+ INVALID_KEY_INFORMATION = 17,
+ INVALID_ID_INFORMATION = 18,
+ INVALID_CERT_ENCODING = 19,
+ INVALID_CERTIFICATE = 20,
+ CERT_TYPE_UNSUPPORTED = 21,
+ INVALID_CERT_AUTHORITY = 22,
+ INVALID_HASH_INFORMATION = 23,
+ AUTHENTICATION_FAILED = 24,
+ INVALID_SIGNATURE = 25,
+ ADDRESS_NOTIFICATION = 26,
+ NOTIFY_SA_LIFETIME = 27,
+ CERTIFICATE_UNAVAILABLE = 28,
+ UNSUPPORTED_EXCHANGE_TYPE = 29,
+ UNEQUAL_PAYLOAD_LENGTHS = 30,
+
+ /* ISAKMP status type */
+ CONNECTED = 16384,
+
+ /* IPSEC DOI additions; status types (RFC2407 IPSEC DOI 4.6.3)
+ * These must be sent under the protection of an ISAKMP SA.
+ */
+ IPSEC_RESPONDER_LIFETIME = 24576,
+ IPSEC_REPLAY_STATUS = 24577,
+ IPSEC_INITIAL_CONTACT = 24578,
+
+ /* RFC 3706 DPD */
+ R_U_THERE = 36136,
+ R_U_THERE_ACK = 36137
+
+ } notification_t;
/* Public key algorithm number
@@ -1192,8 +1084,8 @@ typedef enum {
enum pubkey_alg
{
- PUBKEY_ALG_RSA = 1,
- PUBKEY_ALG_DSA = 3,
+ PUBKEY_ALG_RSA = 1,
+ PUBKEY_ALG_DSA = 3,
};
/* Limits on size of RSA moduli.
@@ -1203,37 +1095,37 @@ enum pubkey_alg
* real security. For now, we require 512 bits.
*/
-#define RSA_MIN_OCTETS_RFC 12
+#define RSA_MIN_OCTETS_RFC 12
-#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE)
-#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 512 bits"
+#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE)
+#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 512 bits"
-#define RSA_MAX_OCTETS (8192 / BITS_PER_BYTE)
-#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits"
+#define RSA_MAX_OCTETS (8192 / BITS_PER_BYTE)
+#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits"
/* Note: RFC 2537 encoding adds a few bytes. If you use a small
* modulus like 3, the overhead is only 2 bytes
*/
-#define RSA_MAX_ENCODING_BYTES (RSA_MAX_OCTETS + 2)
+#define RSA_MAX_ENCODING_BYTES (RSA_MAX_OCTETS + 2)
/* socket address family info */
struct af_info
{
- int af;
- const char *name;
- size_t ia_sz;
- size_t sa_sz;
- int mask_cnt;
- u_int8_t id_addr, id_subnet, id_range;
- const ip_address *any;
- const ip_subnet *none; /* 0.0.0.0/32 or IPv6 equivalent */
- const ip_subnet *all; /* 0.0.0.0/0 or IPv6 equivalent */
+ int af;
+ const char *name;
+ size_t ia_sz;
+ size_t sa_sz;
+ int mask_cnt;
+ u_int8_t id_addr, id_subnet, id_range;
+ const ip_address *any;
+ const ip_subnet *none; /* 0.0.0.0/32 or IPv6 equivalent */
+ const ip_subnet *all; /* 0.0.0.0/0 or IPv6 equivalent */
};
extern const struct af_info
- af_inet4_info,
- af_inet6_info;
+ af_inet4_info,
+ af_inet6_info;
extern const struct af_info *aftoinfo(int af);
@@ -1245,18 +1137,18 @@ extern bool subnetisnone(const ip_subnet *sn);
/* BIND enumerated types */
extern enum_names
- rr_qtype_names,
- rr_type_names,
- rr_class_names;
+ rr_qtype_names,
+ rr_type_names,
+ rr_class_names;
/* How authenticated is info that might have come from DNS?
* In order of increasing confidence.
*/
enum dns_auth_level {
- DAL_UNSIGNED, /* AD in response, but no signature: no authentication */
- DAL_NOTSEC, /* no AD in response: authentication impossible */
- DAL_SIGNED, /* AD and signature in response: authentic */
- DAL_LOCAL /* locally provided (pretty good) */
+ DAL_UNSIGNED, /* AD in response, but no signature: no authentication */
+ DAL_NOTSEC, /* no AD in response: authentication impossible */
+ DAL_SIGNED, /* AD and signature in response: authentic */
+ DAL_LOCAL /* locally provided (pretty good) */
};
/*
@@ -1272,4 +1164,7 @@ enum dns_auth_level {
/* natt traversal types */
extern const char *const natt_type_bitnames[];
+/* secret value for responder cookies */
+extern u_char secret_of_the_day[HASH_SIZE_SHA1];
+
#endif /* _CONSTANTS_H */
diff --git a/src/pluto/cookie.c b/src/pluto/cookie.c
index 00197321c..00c863f18 100644
--- a/src/pluto/cookie.c
+++ b/src/pluto/cookie.c
@@ -1,6 +1,7 @@
/* cookie generation/verification routines.
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,8 +12,6 @@
* 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: cookie.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -23,45 +22,52 @@
#include <freeswan.h>
+#include <library.h>
+#include <crypto/rngs/rng.h>
+
#include "constants.h"
#include "defs.h"
-#include "sha1.h"
-#include "rnd.h"
#include "cookie.h"
-const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
+const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
/* Generate a cookie.
* First argument is true if we're to create an Initiator cookie.
* Length SHOULD be a multiple of sizeof(u_int32_t).
*/
-void
-get_cookie(bool initiator, u_int8_t *cookie, int length, const ip_address *addr)
+void get_cookie(bool initiator, u_int8_t *cookie, int length, ip_address *addr)
{
- u_char buffer[SHA1_DIGEST_SIZE];
- SHA1_CTX ctx;
+ hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ u_char buffer[HASH_SIZE_SHA1];
+
+ do {
+ if (initiator)
+ {
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ rng->get_bytes(rng, length, cookie);
+ rng->destroy(rng);
+ }
+ else /* Responder cookie */
+ {
+ chunk_t addr_chunk, secret_chunk, counter_chunk;
+ size_t addr_len;
+ static u_int32_t counter = 0;
+ unsigned char addr_buf[
+ sizeof(union {struct in_addr A; struct in6_addr B;})];
- do {
- if (initiator)
- {
- get_rnd_bytes(cookie, length);
- }
- else /* Responder cookie */
- {
- /* This looks as good as any way */
- size_t addr_length;
- static u_int32_t counter = 0;
- unsigned char addr_buff[
- sizeof(union {struct in_addr A; struct in6_addr B;})];
+ addr_len = addrbytesof(addr, addr_buf, sizeof(addr_buf));
+ addr_chunk = chunk_create(addr_buf, addr_len);
+ secret_chunk = chunk_create(secret_of_the_day, HASH_SIZE_SHA1);
+ counter++;
+ counter_chunk = chunk_create((void *) &counter, sizeof(counter));
+ hasher->get_hash(hasher, addr_chunk, NULL);
+ hasher->get_hash(hasher, secret_chunk, NULL);
+ hasher->get_hash(hasher, counter_chunk, buffer);
+ memcpy(cookie, buffer, length);
+ }
+ } while (is_zero_cookie(cookie)); /* probably never loops */
- addr_length = addrbytesof(addr, addr_buff, sizeof(addr_buff));
- SHA1Init(&ctx);
- SHA1Update(&ctx, addr_buff, addr_length);
- SHA1Update(&ctx, secret_of_the_day, sizeof(secret_of_the_day));
- counter++;
- SHA1Update(&ctx, (const void *) &counter, sizeof(counter));
- SHA1Final(buffer, &ctx);
- memcpy(cookie, buffer, length);
- }
- } while (is_zero_cookie(cookie)); /* probably never loops */
+ hasher->destroy(hasher);
}
diff --git a/src/pluto/cookie.h b/src/pluto/cookie.h
index b52bb2299..809d66491 100644
--- a/src/pluto/cookie.h
+++ b/src/pluto/cookie.h
@@ -10,15 +10,13 @@
* 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: cookie.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include <freeswan.h>
-extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
+extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
-extern void get_cookie(bool initiator, u_int8_t *cookie, int length
- , const ip_address *addr);
+extern void get_cookie(bool initiator, u_int8_t *cookie, int length,
+ ip_address *addr);
#define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE)
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index c891d19e6..c800f2acc 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -1,5 +1,7 @@
/* Support of X.509 certificate revocation lists (CRLs)
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2000-2009 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +12,6 @@
* 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: crl.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -23,13 +23,15 @@
#include <sys/types.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
+#include <crypto/hashers/hasher.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "asn1.h"
-#include <asn1/oid.h>
#include "x509.h"
#include "crl.h"
#include "ca.h"
@@ -37,482 +39,482 @@
#include "keys.h"
#include "whack.h"
#include "fetch.h"
-#include "sha1.h"
+
/* chained lists of X.509 crls */
static x509crl_t *x509crls = NULL;
-/* ASN.1 definition of an X.509 certificate list */
-
+/**
+ * ASN.1 definition of an X.509 certificate revocation list
+ */
static const asn1Object_t crlObjects[] = {
- { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
- { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
- { 2, "version", ASN1_INTEGER, ASN1_OPT |
- ASN1_BODY }, /* 2 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
- { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */
- { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
- { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */
- { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */
- { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT |
- ASN1_LOOP }, /* 8 */
- { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */
- { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */
- { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */
- { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT |
- ASN1_LOOP }, /* 12 */
- { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
- { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */
- { 6, "critical", ASN1_BOOLEAN, ASN1_DEF |
- ASN1_BODY }, /* 15 */
- { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
- { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */
- { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */
- { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */
- { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
- { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
- { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
- { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
- ASN1_BODY }, /* 23 */
- { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
- { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
- { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
- { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */
- };
-
-#define CRL_OBJ_CERTIFICATE_LIST 0
+ { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
+ { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
+ { 2, "version", ASN1_INTEGER, ASN1_OPT |
+ ASN1_BODY }, /* 2 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */
+ { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
+ { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */
+ { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */
+ { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT |
+ ASN1_LOOP }, /* 8 */
+ { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */
+ { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */
+ { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */
+ { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT |
+ ASN1_LOOP }, /* 12 */
+ { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
+ { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */
+ { 6, "critical", ASN1_BOOLEAN, ASN1_DEF |
+ ASN1_BODY }, /* 15 */
+ { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
+ { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */
+ { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */
+ { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */
+ { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
+ { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
+ { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
+ { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
+ ASN1_BODY }, /* 23 */
+ { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
+ { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
+ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
+ { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 28 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+
+#define CRL_OBJ_CERTIFICATE_LIST 0
#define CRL_OBJ_TBS_CERT_LIST 1
-#define CRL_OBJ_VERSION 2
-#define CRL_OBJ_SIG_ALG 4
-#define CRL_OBJ_ISSUER 5
-#define CRL_OBJ_THIS_UPDATE 6
-#define CRL_OBJ_NEXT_UPDATE 7
+#define CRL_OBJ_VERSION 2
+#define CRL_OBJ_SIG_ALG 4
+#define CRL_OBJ_ISSUER 5
+#define CRL_OBJ_THIS_UPDATE 6
+#define CRL_OBJ_NEXT_UPDATE 7
#define CRL_OBJ_USER_CERTIFICATE 10
#define CRL_OBJ_REVOCATION_DATE 11
#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14
#define CRL_OBJ_CRL_ENTRY_CRITICAL 15
-#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16
-#define CRL_OBJ_EXTN_ID 22
-#define CRL_OBJ_CRITICAL 23
-#define CRL_OBJ_EXTN_VALUE 24
-#define CRL_OBJ_ALGORITHM 27
-#define CRL_OBJ_SIGNATURE 28
-#define CRL_OBJ_ROOF 29
-
+#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16
+#define CRL_OBJ_EXTN_ID 22
+#define CRL_OBJ_CRITICAL 23
+#define CRL_OBJ_EXTN_VALUE 24
+#define CRL_OBJ_ALGORITHM 27
+#define CRL_OBJ_SIGNATURE 28
const x509crl_t empty_x509crl = {
- NULL , /* *next */
- UNDEFINED_TIME, /* installed */
- NULL , /* distributionPoints */
- { NULL, 0 } , /* certificateList */
- { NULL, 0 } , /* tbsCertList */
- 1 , /* version */
- OID_UNKNOWN , /* sigAlg */
- { NULL, 0 } , /* issuer */
- UNDEFINED_TIME, /* thisUpdate */
- UNDEFINED_TIME, /* nextUpdate */
- NULL , /* revokedCertificates */
- /* crlExtensions */
- /* extension */
- /* extnID */
- /* critical */
- /* extnValue */
- { NULL, 0 } , /* authKeyID */
- { NULL, 0 } , /* authKeySerialNumber */
- { NULL, 0 } , /* crlNumber */
- OID_UNKNOWN , /* algorithm */
- { NULL, 0 } /* signature */
+ NULL , /* *next */
+ UNDEFINED_TIME, /* installed */
+ NULL , /* distributionPoints */
+ { NULL, 0 } , /* certificateList */
+ { NULL, 0 } , /* tbsCertList */
+ 1 , /* version */
+ OID_UNKNOWN , /* sigAlg */
+ { NULL, 0 } , /* issuer */
+ UNDEFINED_TIME, /* thisUpdate */
+ UNDEFINED_TIME, /* nextUpdate */
+ NULL , /* revokedCertificates */
+ /* crlExtensions */
+ /* extension */
+ /* extnID */
+ /* critical */
+ /* extnValue */
+ { NULL, 0 } , /* authKeyID */
+ { NULL, 0 } , /* authKeySerialNumber */
+ { NULL, 0 } , /* crlNumber */
+ OID_UNKNOWN , /* algorithm */
+ { NULL, 0 } /* signature */
};
-/*
- * get the X.509 CRL with a given issuer
+/**
+ * Get the X.509 CRL with a given issuer
*/
-static x509crl_t*
-get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid)
+static x509crl_t* get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid)
{
- x509crl_t *crl = x509crls;
- x509crl_t *prev_crl = NULL;
-
- while (crl != NULL)
- {
- if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL)
- ? same_keyid(keyid, crl->authKeyID)
- : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber)))
+ x509crl_t *crl = x509crls;
+ x509crl_t *prev_crl = NULL;
+
+ while (crl != NULL)
{
- if (crl != x509crls)
- {
- /* bring the CRL up front */
- prev_crl->next = crl->next;
- crl->next = x509crls;
- x509crls = crl;
- }
- return crl;
+ if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL)
+ ? same_keyid(keyid, crl->authKeyID)
+ : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber)))
+ {
+ if (crl != x509crls)
+ {
+ /* bring the CRL up front */
+ prev_crl->next = crl->next;
+ crl->next = x509crls;
+ x509crls = crl;
+ }
+ return crl;
+ }
+ prev_crl = crl;
+ crl = crl->next;
}
- prev_crl = crl;
- crl = crl->next;
- }
- return NULL;
+ return NULL;
}
-/*
- * free the dynamic memory used to store revoked certificates
+/**
+ * Free the dynamic memory used to store revoked certificates
*/
-static void
-free_revoked_certs(revokedCert_t* revokedCerts)
+static void free_revoked_certs(revokedCert_t* revokedCerts)
{
- while (revokedCerts != NULL)
- {
- revokedCert_t * revokedCert = revokedCerts;
- revokedCerts = revokedCert->next;
- pfree(revokedCert);
- }
+ while (revokedCerts != NULL)
+ {
+ revokedCert_t * revokedCert = revokedCerts;
+ revokedCerts = revokedCert->next;
+ free(revokedCert);
+ }
}
-/*
- * free the dynamic memory used to store CRLs
+/**
+ * Free the dynamic memory used to store CRLs
*/
-void
-free_crl(x509crl_t *crl)
+void free_crl(x509crl_t *crl)
{
- free_revoked_certs(crl->revokedCertificates);
- free_generalNames(crl->distributionPoints, TRUE);
- pfree(crl->certificateList.ptr);
- pfree(crl);
+ free_revoked_certs(crl->revokedCertificates);
+ free_generalNames(crl->distributionPoints, TRUE);
+ free(crl->certificateList.ptr);
+ free(crl);
}
-static void
-free_first_crl(void)
+static void free_first_crl(void)
{
- x509crl_t *crl = x509crls;
+ x509crl_t *crl = x509crls;
- x509crls = crl->next;
- free_crl(crl);
+ x509crls = crl->next;
+ free_crl(crl);
}
-void
-free_crls(void)
+void free_crls(void)
{
- lock_crl_list("free_crls");
+ lock_crl_list("free_crls");
- while (x509crls != NULL)
- free_first_crl();
+ while (x509crls != NULL)
+ free_first_crl();
- unlock_crl_list("free_crls");
+ unlock_crl_list("free_crls");
}
-/*
+/**
* Insert X.509 CRL into chained list
*/
-bool
-insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl)
+bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl)
{
- x509crl_t *crl = alloc_thing(x509crl_t, "x509crl");
-
- *crl = empty_x509crl;
-
- if (parse_x509crl(blob, 0, crl))
- {
- x509cert_t *issuer_cert;
- x509crl_t *oldcrl;
- bool valid_sig;
- generalName_t *gn;
-
- /* add distribution point */
- gn = alloc_thing(generalName_t, "generalName");
- gn->kind = GN_URI;
- gn->name = crl_uri;
- gn->next = crl->distributionPoints;
- crl->distributionPoints = gn;
-
- lock_authcert_list("insert_crl");
- /* get the issuer cacert */
- issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
- crl->authKeyID, AUTH_CA);
- if (issuer_cert == NULL)
- {
- plog("crl issuer cacert not found");
- free_crl(crl);
- unlock_authcert_list("insert_crl");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("crl issuer cacert found")
- )
-
- /* check the issuer's signature of the crl */
- valid_sig = check_signature(crl->tbsCertList, crl->signature
- , crl->algorithm, crl->algorithm, issuer_cert);
- unlock_authcert_list("insert_crl");
+ x509crl_t *crl = malloc_thing(x509crl_t);
- if (!valid_sig)
- {
- free_crl(crl);
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("crl signature is valid")
- )
-
- lock_crl_list("insert_crl");
- oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
- , crl->authKeyID);
+ *crl = empty_x509crl;
- if (oldcrl != NULL)
+ if (parse_x509crl(blob, 0, crl))
{
- if (crl->thisUpdate > oldcrl->thisUpdate)
- {
- /* keep any known CRL distribution points */
- add_distribution_points(oldcrl->distributionPoints
- , &crl->distributionPoints);
-
- /* now delete the old CRL */
- free_first_crl();
+ x509cert_t *issuer_cert;
+ x509crl_t *oldcrl;
+ bool valid_sig;
+ generalName_t *gn;
+
+ /* add distribution point */
+ gn = malloc_thing(generalName_t);
+ gn->kind = GN_URI;
+ gn->name = crl_uri;
+ gn->next = crl->distributionPoints;
+ crl->distributionPoints = gn;
+
+ lock_authcert_list("insert_crl");
+ /* get the issuer cacert */
+ issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
+ crl->authKeyID, AUTH_CA);
+ if (issuer_cert == NULL)
+ {
+ plog("crl issuer cacert not found");
+ free_crl(crl);
+ unlock_authcert_list("insert_crl");
+ return FALSE;
+ }
DBG(DBG_CONTROL,
- DBG_log("thisUpdate is newer - existing crl deleted")
+ DBG_log("crl issuer cacert found")
)
- }
- else
- {
- unlock_crl_list("insert_crls");
+
+ /* check the issuer's signature of the crl */
+ valid_sig = x509_check_signature(crl->tbsCertList, crl->signature,
+ crl->algorithm, issuer_cert);
+ unlock_authcert_list("insert_crl");
+
+ if (!valid_sig)
+ {
+ free_crl(crl);
+ return FALSE;
+ }
DBG(DBG_CONTROL,
- DBG_log("thisUpdate is not newer - existing crl not replaced");
+ DBG_log("crl signature is valid")
)
- free_crl(crl);
- return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval;
- }
- }
- /* insert new CRL */
- crl->next = x509crls;
- x509crls = crl;
+ lock_crl_list("insert_crl");
+ oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
+ , crl->authKeyID);
- unlock_crl_list("insert_crl");
+ if (oldcrl != NULL)
+ {
+ if (crl->thisUpdate > oldcrl->thisUpdate)
+ {
+ /* keep any known CRL distribution points */
+ add_distribution_points(oldcrl->distributionPoints
+ , &crl->distributionPoints);
+
+ /* now delete the old CRL */
+ free_first_crl();
+ DBG(DBG_CONTROL,
+ DBG_log("thisUpdate is newer - existing crl deleted")
+ )
+ }
+ else
+ {
+ unlock_crl_list("insert_crls");
+ DBG(DBG_CONTROL,
+ DBG_log("thisUpdate is not newer - existing crl not replaced");
+ )
+ free_crl(crl);
+ return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval;
+ }
+ }
- /* If crl caching is enabled then the crl is saved locally.
- * Only http or ldap URIs are cached but not local file URIs.
- * The issuer's subjectKeyID is used as a unique filename
- */
- if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
+ /* insert new CRL */
+ crl->next = x509crls;
+ x509crls = crl;
+
+ unlock_crl_list("insert_crl");
+
+ /* If crl caching is enabled then the crl is saved locally.
+ * Only http or ldap URIs are cached but not local file URIs.
+ * The issuer's subjectKeyID is used as a unique filename
+ */
+ if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
+ {
+ char path[BUF_LEN], buf[BUF_LEN];
+ char digest_buf[HASH_SIZE_SHA1];
+ chunk_t subjectKeyID = chunk_from_buf(digest_buf);
+ bool has_keyID;
+
+ if (issuer_cert->subjectKeyID.ptr == NULL)
+ {
+ has_keyID = compute_subjectKeyID(issuer_cert, subjectKeyID);
+ }
+ else
+ {
+ subjectKeyID = issuer_cert->subjectKeyID;
+ has_keyID = TRUE;
+ }
+ if (has_keyID)
+ {
+ datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN);
+ snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf);
+ chunk_write(crl->certificateList, path, "crl", 0022, TRUE);
+ }
+ }
+
+ /* is the fetched crl valid? */
+ return crl->nextUpdate - time(NULL) > 2*crl_check_interval;
+ }
+ else
{
- char path[BUF_LEN];
- char buf[BUF_LEN];
- char digest_buf[SHA1_DIGEST_SIZE];
- chunk_t subjectKeyID = { digest_buf, SHA1_DIGEST_SIZE };
-
- if (issuer_cert->subjectKeyID.ptr == NULL)
- compute_subjectKeyID(issuer_cert, subjectKeyID);
- else
- subjectKeyID = issuer_cert->subjectKeyID;
-
- datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN);
- snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf);
- write_chunk(path, "crl", crl->certificateList, 0022, TRUE);
+ plog(" error in X.509 crl");
+ free_crl(crl);
+ return FALSE;
}
-
- /* is the fetched crl valid? */
- return crl->nextUpdate - time(NULL) > 2*crl_check_interval;
- }
- else
- {
- plog(" error in X.509 crl");
- free_crl(crl);
- return FALSE;
- }
}
-/*
+/**
* Loads CRLs
*/
-void
-load_crls(void)
+void load_crls(void)
{
- struct dirent **filelist;
- u_char buf[BUF_LEN];
- u_char *save_dir;
- int n;
-
- /* change directory to specified path */
- save_dir = getcwd(buf, BUF_LEN);
- if (chdir(CRL_PATH))
- {
- plog("Could not change to directory '%s'", CRL_PATH);
- }
- else
- {
- plog("Changing to directory '%s'", CRL_PATH);
- n = scandir(CRL_PATH, &filelist, file_select, alphasort);
-
- if (n < 0)
- plog(" scandir() error");
+ struct dirent **filelist;
+ u_char buf[BUF_LEN];
+ u_char *save_dir;
+ int n;
+
+ /* change directory to specified path */
+ save_dir = getcwd(buf, BUF_LEN);
+ if (chdir(CRL_PATH))
+ {
+ plog("Could not change to directory '%s'", CRL_PATH);
+ }
else
{
- while (n--)
- {
- bool pgp = FALSE;
- chunk_t blob = empty_chunk;
- char *filename = filelist[n]->d_name;
+ plog("Changing to directory '%s'", CRL_PATH);
+ n = scandir(CRL_PATH, &filelist, file_select, alphasort);
- if (load_coded_file(filename, NULL, "crl", &blob, &pgp))
+ if (n < 0)
+ plog(" scandir() error");
+ else
{
- chunk_t crl_uri;
-
- crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename);
- crl_uri.ptr = alloc_bytes(crl_uri.len + 1, "crl uri");
-
- /* build CRL file URI */
- snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s"
- , CRL_PATH, filename);
-
- insert_crl(blob, crl_uri, FALSE);
+ while (n--)
+ {
+ bool pgp = FALSE;
+ chunk_t blob = chunk_empty;
+ char *filename = filelist[n]->d_name;
+
+ if (load_coded_file(filename, NULL, "crl", &blob, &pgp))
+ {
+ chunk_t crl_uri;
+
+ crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename);
+ crl_uri.ptr = malloc(crl_uri.len + 1);
+
+ /* build CRL file URI */
+ snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s"
+ , CRL_PATH, filename);
+
+ insert_crl(blob, crl_uri, FALSE);
+ }
+ free(filelist[n]);
+ }
+ free(filelist);
}
- free(filelist[n]);
- }
- free(filelist);
}
- }
- /* restore directory path */
- ignore_result(chdir(save_dir));
+ /* restore directory path */
+ ignore_result(chdir(save_dir));
}
-/*
+/**
* Parses a CRL revocation reason code
*/
-static crl_reason_t
-parse_crl_reasonCode(chunk_t object)
+static crl_reason_t parse_crl_reasonCode(chunk_t object)
{
- crl_reason_t reason = REASON_UNSPECIFIED;
-
- if (*object.ptr == ASN1_ENUMERATED
- && asn1_length(&object) == 1)
- {
- reason = *object.ptr;
- }
-
- DBG(DBG_PARSING,
- DBG_log(" '%s'", enum_name(&crl_reason_names, reason))
- )
- return reason;
+ crl_reason_t reason = REASON_UNSPECIFIED;
+
+ if (*object.ptr == ASN1_ENUMERATED
+ && asn1_length(&object) == 1)
+ {
+ reason = *object.ptr;
+ }
+
+ DBG(DBG_PARSING,
+ DBG_log(" '%N'", crl_reason_names, reason)
+ )
+ return reason;
}
/*
* Parses an X.509 CRL
*/
-bool
-parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl)
+bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl)
{
- u_char buf[BUF_LEN];
- asn1_ctx_t ctx;
- bool critical;
- chunk_t extnID;
- chunk_t userCertificate = empty_chunk;
- chunk_t object;
- u_int level;
- int objectID = 0;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < CRL_OBJ_ROOF)
- {
- if (!extract_object(crlObjects, &objectID, &object, &level, &ctx))
- return FALSE;
-
- /* those objects which will parsed further need the next higher level */
- level++;
-
- switch (objectID) {
- case CRL_OBJ_CERTIFICATE_LIST:
- crl->certificateList = object;
- break;
- case CRL_OBJ_TBS_CERT_LIST:
- crl->tbsCertList = object;
- break;
- case CRL_OBJ_VERSION:
- crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
- DBG(DBG_PARSING,
- DBG_log(" v%d", crl->version);
- )
- break;
- case CRL_OBJ_SIG_ALG:
- crl->sigAlg = parse_algorithmIdentifier(object, level, NULL);
- break;
- case CRL_OBJ_ISSUER:
- crl->issuer = object;
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'",buf)
- )
- break;
- case CRL_OBJ_THIS_UPDATE:
- crl->thisUpdate = parse_time(object, level);
- break;
- case CRL_OBJ_NEXT_UPDATE:
- crl->nextUpdate = parse_time(object, level);
- break;
- case CRL_OBJ_USER_CERTIFICATE:
- userCertificate = object;
- break;
- case CRL_OBJ_REVOCATION_DATE:
- {
- /* put all the serial numbers and the revocation date in a chained list
- with revocedCertificates pointing to the first revoked certificate */
-
- revokedCert_t *revokedCert = alloc_thing(revokedCert_t, "revokedCert");
- revokedCert->userCertificate = userCertificate;
- revokedCert->revocationDate = parse_time(object, level);
- revokedCert->revocationReason = REASON_UNSPECIFIED;
- revokedCert->next = crl->revokedCertificates;
- crl->revokedCertificates = revokedCert;
- }
- break;
- case CRL_OBJ_CRL_ENTRY_EXTN_ID:
- case CRL_OBJ_EXTN_ID:
- extnID = object;
- break;
- case CRL_OBJ_CRL_ENTRY_CRITICAL:
- case CRL_OBJ_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- break;
- case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
- case CRL_OBJ_EXTN_VALUE:
- {
- u_int extn_oid = known_oid(extnID);
-
- if (extn_oid == OID_CRL_REASON_CODE)
- {
- crl->revokedCertificates->revocationReason =
- parse_crl_reasonCode(object);
- }
- else if (extn_oid == OID_AUTHORITY_KEY_ID)
- {
- parse_authorityKeyIdentifier(object, level
- , &crl->authKeyID, &crl->authKeySerialNumber);
- }
- else if (extn_oid == OID_CRL_NUMBER)
- {
- if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber"))
- return FALSE;
- crl->crlNumber = object;
+ u_char buf[BUF_LEN];
+ asn1_parser_t *parser;
+ chunk_t extnID;
+ chunk_t userCertificate = chunk_empty;
+ chunk_t object;
+ int objectID;
+ bool success = FALSE;
+ bool critical;
+
+ parser = asn1_parser_create(crlObjects, blob);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser)+1;
+
+ switch (objectID) {
+ case CRL_OBJ_CERTIFICATE_LIST:
+ crl->certificateList = object;
+ break;
+ case CRL_OBJ_TBS_CERT_LIST:
+ crl->tbsCertList = object;
+ break;
+ case CRL_OBJ_VERSION:
+ crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
+ DBG(DBG_PARSING,
+ DBG_log(" v%d", crl->version);
+ )
+ break;
+ case CRL_OBJ_SIG_ALG:
+ crl->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case CRL_OBJ_ISSUER:
+ crl->issuer = object;
+ DBG(DBG_PARSING,
+ dntoa(buf, BUF_LEN, object);
+ DBG_log(" '%s'",buf)
+ )
+ break;
+ case CRL_OBJ_THIS_UPDATE:
+ crl->thisUpdate = asn1_parse_time(object, level);
+ break;
+ case CRL_OBJ_NEXT_UPDATE:
+ crl->nextUpdate = asn1_parse_time(object, level);
+ break;
+ case CRL_OBJ_USER_CERTIFICATE:
+ userCertificate = object;
+ break;
+ case CRL_OBJ_REVOCATION_DATE:
+ {
+ /* put all the serial numbers and the revocation date in a chained list
+ with revocedCertificates pointing to the first revoked certificate */
+
+ revokedCert_t *revokedCert = malloc_thing(revokedCert_t);
+ revokedCert->userCertificate = userCertificate;
+ revokedCert->revocationDate = asn1_parse_time(object, level);
+ revokedCert->revocationReason = REASON_UNSPECIFIED;
+ revokedCert->next = crl->revokedCertificates;
+ crl->revokedCertificates = revokedCert;
+ }
+ break;
+ case CRL_OBJ_CRL_ENTRY_EXTN_ID:
+ case CRL_OBJ_EXTN_ID:
+ extnID = object;
+ break;
+ case CRL_OBJ_CRL_ENTRY_CRITICAL:
+ case CRL_OBJ_CRITICAL:
+ critical = object.len && *object.ptr;
+ DBG(DBG_PARSING,
+ DBG_log(" %s",(critical)?"TRUE":"FALSE");
+ )
+ break;
+ case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
+ case CRL_OBJ_EXTN_VALUE:
+ {
+ u_int extn_oid = asn1_known_oid(extnID);
+
+ if (extn_oid == OID_CRL_REASON_CODE)
+ {
+ crl->revokedCertificates->revocationReason =
+ parse_crl_reasonCode(object);
+ }
+ else if (extn_oid == OID_AUTHORITY_KEY_ID)
+ {
+ parse_authorityKeyIdentifier(object, level
+ , &crl->authKeyID, &crl->authKeySerialNumber);
+ }
+ else if (extn_oid == OID_CRL_NUMBER)
+ {
+ if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
+ level, "crlNumber"))
+ {
+ goto end;
+ }
+ crl->crlNumber = object;
+ }
+ }
+ break;
+ case CRL_OBJ_ALGORITHM:
+ crl->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case CRL_OBJ_SIGNATURE:
+ crl->signature = object;
+ break;
+ default:
+ break;
}
- }
- break;
- case CRL_OBJ_ALGORITHM:
- crl->algorithm = parse_algorithmIdentifier(object, level, NULL);
- break;
- case CRL_OBJ_SIGNATURE:
- crl->signature = object;
- break;
- default:
- break;
}
- objectID++;
- }
- time(&crl->installed);
- return TRUE;
+ success = parser->success(parser);
+ time(&crl->installed);
+
+end:
+ parser->destroy(parser);
+ return success;
}
/* Checks if the current certificate is revoked. It goes through the
@@ -523,28 +525,28 @@ static cert_status_t
check_revocation(const x509crl_t *crl, chunk_t serial
, time_t *revocationDate, crl_reason_t * revocationReason)
{
- revokedCert_t *revokedCert = crl->revokedCertificates;
-
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = REASON_UNSPECIFIED;
-
- DBG(DBG_CONTROL,
- DBG_dump_chunk("serial number:", serial)
- )
-
- while(revokedCert != NULL)
- {
- /* compare serial numbers */
- if (revokedCert->userCertificate.len == serial.len &&
- memcmp(revokedCert->userCertificate.ptr, serial.ptr, serial.len) == 0)
+ revokedCert_t *revokedCert = crl->revokedCertificates;
+
+ *revocationDate = UNDEFINED_TIME;
+ *revocationReason = REASON_UNSPECIFIED;
+
+ DBG(DBG_CONTROL,
+ DBG_dump_chunk("serial number:", serial)
+ )
+
+ while(revokedCert != NULL)
{
- *revocationDate = revokedCert->revocationDate;
- *revocationReason = revokedCert->revocationReason;
- return CERT_REVOKED;
+ /* compare serial numbers */
+ if (revokedCert->userCertificate.len == serial.len &&
+ memeq(revokedCert->userCertificate.ptr, serial.ptr, serial.len))
+ {
+ *revocationDate = revokedCert->revocationDate;
+ *revocationReason = revokedCert->revocationReason;
+ return CERT_REVOKED;
+ }
+ revokedCert = revokedCert->next;
}
- revokedCert = revokedCert->next;
- }
- return CERT_GOOD;
+ return CERT_GOOD;
}
/*
@@ -553,37 +555,37 @@ check_revocation(const x509crl_t *crl, chunk_t serial
void
check_crls(void)
{
- x509crl_t *crl;
+ x509crl_t *crl;
- lock_crl_list("check_crls");
- crl = x509crls;
-
- while (crl != NULL)
- {
- time_t time_left = crl->nextUpdate - time(NULL);
- u_char buf[BUF_LEN];
+ lock_crl_list("check_crls");
+ crl = x509crls;
- DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, crl->issuer);
- DBG_log("issuer: '%s'",buf);
- if (crl->authKeyID.ptr != NULL)
- {
- datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
- }
- DBG_log("%ld seconds left", time_left)
- )
- if (time_left < 2*crl_check_interval)
+ while (crl != NULL)
{
- fetch_req_t *req = build_crl_fetch_request(crl->issuer
- , crl->authKeySerialNumber
- , crl->authKeyID, crl->distributionPoints);
- add_crl_fetch_request(req);
+ time_t time_left = crl->nextUpdate - time(NULL);
+ u_char buf[BUF_LEN];
+
+ DBG(DBG_CONTROL,
+ dntoa(buf, BUF_LEN, crl->issuer);
+ DBG_log("issuer: '%s'",buf);
+ if (crl->authKeyID.ptr != NULL)
+ {
+ datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ DBG_log("authkey: %s", buf);
+ }
+ DBG_log("%ld seconds left", time_left)
+ )
+ if (time_left < 2*crl_check_interval)
+ {
+ fetch_req_t *req = build_crl_fetch_request(crl->issuer
+ , crl->authKeySerialNumber
+ , crl->authKeyID, crl->distributionPoints);
+ add_crl_fetch_request(req);
+ }
+ crl = crl->next;
}
- crl = crl->next;
- }
- unlock_crl_list("check_crls");
+ unlock_crl_list("check_crls");
}
/*
@@ -593,118 +595,117 @@ cert_status_t
verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
, crl_reason_t *revocationReason)
{
- x509crl_t *crl;
-
- ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID);
+ x509crl_t *crl;
- generalName_t *crluri = (ca == NULL)? NULL : ca->crluri;
+ ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
+ , cert->authKeyID);
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = REASON_UNSPECIFIED;
+ generalName_t *crluri = (ca == NULL)? NULL : ca->crluri;
- lock_crl_list("verify_by_crl");
- crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID);
+ *revocationDate = UNDEFINED_TIME;
+ *revocationReason = REASON_UNSPECIFIED;
- if (crl == NULL)
- {
- unlock_crl_list("verify_by_crl");
- plog("crl not found");
+ lock_crl_list("verify_by_crl");
+ crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID);
- if (cert->crlDistributionPoints != NULL)
+ if (crl == NULL)
{
- fetch_req_t *req = build_crl_fetch_request(cert->issuer
- , cert->authKeySerialNumber
- , cert->authKeyID, cert->crlDistributionPoints);
- add_crl_fetch_request(req);
- }
+ unlock_crl_list("verify_by_crl");
+ plog("crl not found");
- if (crluri != NULL)
- {
- fetch_req_t *req = build_crl_fetch_request(cert->issuer
- , cert->authKeySerialNumber
- , cert->authKeyID, crluri);
- add_crl_fetch_request(req);
- }
+ if (cert->crlDistributionPoints != NULL)
+ {
+ fetch_req_t *req = build_crl_fetch_request(cert->issuer
+ , cert->authKeySerialNumber
+ , cert->authKeyID, cert->crlDistributionPoints);
+ add_crl_fetch_request(req);
+ }
- if (cert->crlDistributionPoints != 0 || crluri != NULL)
- {
- wake_fetch_thread("verify_by_crl");
- return CERT_UNKNOWN;
+ if (crluri != NULL)
+ {
+ fetch_req_t *req = build_crl_fetch_request(cert->issuer
+ , cert->authKeySerialNumber
+ , cert->authKeyID, crluri);
+ add_crl_fetch_request(req);
+ }
+
+ if (cert->crlDistributionPoints != 0 || crluri != NULL)
+ {
+ wake_fetch_thread("verify_by_crl");
+ return CERT_UNKNOWN;
+ }
+ else
+ return CERT_UNDEFINED;
}
else
- return CERT_UNDEFINED;
- }
- else
- {
- x509cert_t *issuer_cert;
- bool valid;
-
- DBG(DBG_CONTROL,
- DBG_log("crl found")
- )
-
- add_distribution_points(cert->crlDistributionPoints
- , &crl->distributionPoints);
-
- add_distribution_points(crluri
- , &crl->distributionPoints);
-
- lock_authcert_list("verify_by_crl");
-
- issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber
- , crl->authKeyID, AUTH_CA);
- valid = check_signature(crl->tbsCertList, crl->signature
- , crl->algorithm, crl->algorithm, issuer_cert);
-
- unlock_authcert_list("verify_by_crl");
-
- if (valid)
{
- cert_status_t status;
+ x509cert_t *issuer_cert;
+ bool valid;
- DBG(DBG_CONTROL,
- DBG_log("crl signature is valid")
- )
- /* return the expiration date */
- *until = crl->nextUpdate;
+ DBG(DBG_CONTROL,
+ DBG_log("crl found")
+ )
- /* has the certificate been revoked? */
- status = check_revocation(crl, cert->serialNumber, revocationDate
- , revocationReason);
+ add_distribution_points(cert->crlDistributionPoints
+ , &crl->distributionPoints);
- if (*until < time(NULL))
- {
- fetch_req_t *req;
+ add_distribution_points(crluri
+ , &crl->distributionPoints);
- plog("crl update is overdue since %s"
- , timetoa(until, TRUE));
+ lock_authcert_list("verify_by_crl");
- /* try to fetch a crl update */
- req = build_crl_fetch_request(crl->issuer
- , crl->authKeySerialNumber
- , crl->authKeyID, crl->distributionPoints);
- unlock_crl_list("verify_by_crl");
+ issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber
+ , crl->authKeyID, AUTH_CA);
+ valid = x509_check_signature(crl->tbsCertList, crl->signature,
+ crl->algorithm, issuer_cert);
+
+ unlock_authcert_list("verify_by_crl");
- add_crl_fetch_request(req);
- wake_fetch_thread("verify_by_crl");
- }
- else
- {
- unlock_crl_list("verify_by_crl");
- DBG(DBG_CONTROL,
- DBG_log("crl is valid")
- )
- }
- return status;
- }
- else
- {
- unlock_crl_list("verify_by_crl");
- plog("crl signature is invalid");
- return CERT_UNKNOWN;
+ if (valid)
+ {
+ cert_status_t status;
+
+ DBG(DBG_CONTROL,
+ DBG_log("crl signature is valid")
+ )
+ /* return the expiration date */
+ *until = crl->nextUpdate;
+
+ /* has the certificate been revoked? */
+ status = check_revocation(crl, cert->serialNumber, revocationDate
+ , revocationReason);
+
+ if (*until < time(NULL))
+ {
+ fetch_req_t *req;
+
+ plog("crl update is overdue since %T", until, TRUE);
+
+ /* try to fetch a crl update */
+ req = build_crl_fetch_request(crl->issuer
+ , crl->authKeySerialNumber
+ , crl->authKeyID, crl->distributionPoints);
+ unlock_crl_list("verify_by_crl");
+
+ add_crl_fetch_request(req);
+ wake_fetch_thread("verify_by_crl");
+ }
+ else
+ {
+ unlock_crl_list("verify_by_crl");
+ DBG(DBG_CONTROL,
+ DBG_log("crl is valid")
+ )
+ }
+ return status;
+ }
+ else
+ {
+ unlock_crl_list("verify_by_crl");
+ plog("crl signature is invalid");
+ return CERT_UNKNOWN;
+ }
}
- }
}
/*
@@ -713,63 +714,63 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
void
list_crls(bool utc, bool strict)
{
- x509crl_t *crl;
+ x509crl_t *crl;
- lock_crl_list("list_crls");
- crl = x509crls;
+ lock_crl_list("list_crls");
+ crl = x509crls;
- if (crl != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 CRLs:");
- whack_log(RC_COMMENT, " ");
- }
-
- while (crl != NULL)
- {
- u_char buf[BUF_LEN];
- u_int revoked = 0;
- revokedCert_t *revokedCert = crl->revokedCertificates;
-
- /* count number of revoked certificates in CRL */
- while (revokedCert != NULL)
- {
- revoked++;
- revokedCert = revokedCert->next;
- }
-
- whack_log(RC_COMMENT, "%s, revoked certs: %d",
- timetoa(&crl->installed, utc), revoked);
- dntoa(buf, BUF_LEN, crl->issuer);
- whack_log(RC_COMMENT, " issuer: '%s'", buf);
- if (crl->crlNumber.ptr != NULL)
+ if (crl != NULL)
{
- datatot(crl->crlNumber.ptr, crl->crlNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " crlnumber: %s", buf);
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of X.509 CRLs:");
+ whack_log(RC_COMMENT, " ");
}
- list_distribution_points(crl->distributionPoints);
-
- whack_log(RC_COMMENT, " updates: this %s",
- timetoa(&crl->thisUpdate, utc));
- whack_log(RC_COMMENT, " next %s %s",
- timetoa(&crl->nextUpdate, utc),
- check_expiry(crl->nextUpdate, CRL_WARNING_INTERVAL, strict));
- if (crl->authKeyID.ptr != NULL)
- {
- datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
- }
- if (crl->authKeySerialNumber.ptr != NULL)
+
+ while (crl != NULL)
{
- datatot(crl->authKeySerialNumber.ptr, crl->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
- }
+ u_char buf[BUF_LEN];
+ u_int revoked = 0;
+ revokedCert_t *revokedCert = crl->revokedCertificates;
+
+ /* count number of revoked certificates in CRL */
+ while (revokedCert != NULL)
+ {
+ revoked++;
+ revokedCert = revokedCert->next;
+ }
+
+ whack_log(RC_COMMENT, "%T, revoked certs: %d",
+ &crl->installed, utc, revoked);
+ dntoa(buf, BUF_LEN, crl->issuer);
+ whack_log(RC_COMMENT, " issuer: '%s'", buf);
+ if (crl->crlNumber.ptr != NULL)
+ {
+ datatot(crl->crlNumber.ptr, crl->crlNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " crlnumber: %s", buf);
+ }
+ list_distribution_points(crl->distributionPoints);
+
+ whack_log(RC_COMMENT, " updates: this %T",
+ &crl->thisUpdate, utc);
+ whack_log(RC_COMMENT, " next %T %s",
+ &crl->nextUpdate, utc,
+ check_expiry(crl->nextUpdate, CRL_WARNING_INTERVAL, strict));
+ if (crl->authKeyID.ptr != NULL)
+ {
+ datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authkey: %s", buf);
+ }
+ if (crl->authKeySerialNumber.ptr != NULL)
+ {
+ datatot(crl->authKeySerialNumber.ptr, crl->authKeySerialNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " aserial: %s", buf);
+ }
- crl = crl->next;
- }
- unlock_crl_list("list_crls");
+ crl = crl->next;
+ }
+ unlock_crl_list("list_crls");
}
diff --git a/src/pluto/crl.h b/src/pluto/crl.h
index b5051dcac..7c110ad5a 100644
--- a/src/pluto/crl.h
+++ b/src/pluto/crl.h
@@ -10,8 +10,6 @@
* 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: crl.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include "constants.h"
@@ -22,9 +20,9 @@ typedef struct revokedCert revokedCert_t;
struct revokedCert{
revokedCert_t *next;
- chunk_t userCertificate;
- time_t revocationDate;
- crl_reason_t revocationReason;
+ chunk_t userCertificate;
+ time_t revocationDate;
+ crl_reason_t revocationReason;
};
/* storage structure for an X.509 CRL */
@@ -33,28 +31,28 @@ typedef struct x509crl x509crl_t;
struct x509crl {
x509crl_t *next;
- time_t installed;
+ time_t installed;
generalName_t *distributionPoints;
chunk_t certificateList;
chunk_t tbsCertList;
u_int version;
- /* signature */
+ /* signature */
int sigAlg;
chunk_t issuer;
time_t thisUpdate;
time_t nextUpdate;
revokedCert_t *revokedCertificates;
- /* v2 extensions */
- /* crlExtensions */
- /* extension */
- /* extnID */
- /* critical */
- /* extnValue */
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- chunk_t crlNumber;
+ /* v2 extensions */
+ /* crlExtensions */
+ /* extension */
+ /* extnID */
+ /* critical */
+ /* extnValue */
+ chunk_t authKeyID;
+ chunk_t authKeySerialNumber;
+ chunk_t crlNumber;
- /* signatureAlgorithm */
+ /* signatureAlgorithm */
int algorithm;
chunk_t signature;
};
@@ -82,7 +80,7 @@ extern void load_crls(void);
extern void check_crls(void);
extern bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl);
extern cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until
- , time_t *revocationDate, crl_reason_t *revocationReason);
+ , time_t *revocationDate, crl_reason_t *revocationReason);
extern void list_crls(bool utc, bool strict);
extern void free_crls(void);
extern void free_crl(x509crl_t *crl);
diff --git a/src/pluto/crypto.c b/src/pluto/crypto.c
index 207192e14..1adccc74e 100644
--- a/src/pluto/crypto.c
+++ b/src/pluto/crypto.c
@@ -1,6 +1,6 @@
/* crypto interfaces
- * Copyright (C) 1998-2001 D. Hugh Redelmeier
- * Copyright (C) 2007 Andreas Steffen
+ * Copyright (C) 1998-2001 D. Hugh Redelmeier
+ * Copyright (C) 2007-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,617 +11,582 @@
* 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: crypto.c 3252 2007-10-06 21:24:50Z andreas $
*/
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-
#include <freeswan.h>
-#define HEADER_DES_LOCL_H /* stupid trick to force prototype decl in <des.h> */
-#include <libdes/des.h>
-
-#include <errno.h>
#include "constants.h"
#include "defs.h"
-#include "state.h"
+#include "crypto.h"
#include "log.h"
-#include "md5.h"
-#include "sha1.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
-#include "alg_info.h"
-#include "ike_alg.h"
-
-
-/* moduli and generator. */
-
-static MP_INT
- modp1024_modulus,
- modp1536_modulus,
- modp2048_modulus,
- modp3072_modulus,
- modp4096_modulus,
- modp6144_modulus,
- modp8192_modulus;
-
-MP_INT groupgenerator; /* MODP group generator (2) */
-
-static void do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc);
-
-static struct encrypt_desc crypto_encryptor_3des =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_3DES_CBC,
- algo_next: NULL,
- enc_ctxsize: sizeof(des_key_schedule) * 3,
- enc_blocksize: DES_CBC_BLOCK_SIZE,
- keydeflen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE,
- keyminlen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE,
- keymaxlen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE,
- do_crypt: do_3des,
-};
-
-/* MD5 hash test vectors
- * from RFC 1321 "MD5 Message-Digest Algorithm"
- * April 1992, R. Rivest, RSA Data Security
- */
-
-static const u_char md5_test0_msg[] = {
-
-};
-
-static const u_char md5_test0_msg_digest[] = {
- 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
- 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
-};
-
-static const u_char md5_test1_msg[] = {
- 0x61
-};
-
-static const u_char md5_test1_msg_digest[] = {
- 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
- 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61
-};
-
-static const u_char md5_test2_msg[] = {
- 0x61, 0x62, 0x63
-};
-
-static const u_char md5_test2_msg_digest[] = {
- 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
- 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72
-};
-
-static const u_char md5_test3_msg[] = {
- 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20,
- 0x64, 0x69, 0x67, 0x65, 0x73, 0x74
-};
-
-static const u_char md5_test3_msg_digest[] = {
- 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
- 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0
-};
-
-static const u_char md5_test4_msg[] = {
- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
- 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- 0x79, 0x7a
-};
-static const u_char md5_test4_msg_digest[] = {
- 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
- 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b
-};
-
-static const u_char md5_test5_msg[] = {
- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
- 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
- 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
- 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
- 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39
-};
+static struct encrypt_desc encrypt_desc_3des =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_3DES_CBC,
+ algo_next: NULL,
-static const u_char md5_test5_msg_digest[] = {
- 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
- 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f
+ enc_blocksize: DES_BLOCK_SIZE,
+ keydeflen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
+ keyminlen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
+ keymaxlen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
};
-static const u_char md5_test6_msg[] = {
- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
- 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34,
- 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32,
- 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
- 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34,
- 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32,
- 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30
-};
+#define AES_KEY_MIN_LEN 128
+#define AES_KEY_DEF_LEN 128
+#define AES_KEY_MAX_LEN 256
-static const u_char md5_test6_msg_digest[] = {
- 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
- 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a
-};
-
-static const hash_testvector_t md5_hash_testvectors[] = {
- { sizeof(md5_test0_msg), md5_test0_msg, md5_test0_msg_digest },
- { sizeof(md5_test1_msg), md5_test1_msg, md5_test1_msg_digest },
- { sizeof(md5_test2_msg), md5_test2_msg, md5_test2_msg_digest },
- { sizeof(md5_test3_msg), md5_test3_msg, md5_test3_msg_digest },
- { sizeof(md5_test4_msg), md5_test4_msg, md5_test4_msg_digest },
- { sizeof(md5_test5_msg), md5_test5_msg, md5_test5_msg_digest },
- { sizeof(md5_test6_msg), md5_test6_msg, md5_test6_msg_digest },
- { 0, NULL, NULL }
-};
-
-/* MD5 hmac test vectors
- * from RFC 2202 "Test Cases for HMAC-MD5 and HMAC-SHA-1"
- * September 1997, P. Cheng, IBM & R. Glenn, NIST
- */
-
-static const u_char md5_hmac1_key[] = {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
-};
-
-static const u_char md5_hmac1_msg[] = {
- 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
-};
-
-static const u_char md5_hmac1[] = {
- 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
- 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d
-};
-
-static const u_char md5_hmac2_key[] = {
- 0x4a, 0x65, 0x66, 0x65
-};
-
-static const u_char md5_hmac2_msg[] = {
- 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
- 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
- 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
- 0x69, 0x6e, 0x67, 0x3f
-};
+static struct encrypt_desc encrypt_desc_aes =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_AES_CBC,
+ algo_next: NULL,
-static const u_char md5_hmac2[] = {
- 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
- 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38
+ enc_blocksize: AES_BLOCK_SIZE,
+ keyminlen: AES_KEY_MIN_LEN,
+ keydeflen: AES_KEY_DEF_LEN,
+ keymaxlen: AES_KEY_MAX_LEN,
};
-static const u_char md5_hmac3_key[] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
-};
+#define BLOWFISH_KEY_MIN_LEN 128
+#define BLOWFISH_KEY_MAX_LEN 448
-static const u_char md5_hmac3_msg[] = {
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd
-};
+static struct encrypt_desc encrypt_desc_blowfish =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_BLOWFISH_CBC,
+ algo_next: NULL,
-static const u_char md5_hmac3[] = {
- 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
- 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6
+ enc_blocksize: BLOWFISH_BLOCK_SIZE,
+ keyminlen: BLOWFISH_KEY_MIN_LEN,
+ keydeflen: BLOWFISH_KEY_MIN_LEN,
+ keymaxlen: BLOWFISH_KEY_MAX_LEN,
};
-static const u_char md5_hmac4_key[] = {
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19
-};
+#define SERPENT_KEY_MIN_LEN 128
+#define SERPENT_KEY_DEF_LEN 128
+#define SERPENT_KEY_MAX_LEN 256
-static const u_char md5_hmac4_msg[] = {
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
- 0xcd, 0xcd
-};
-
-static const u_char md5_hmac4[] = {
- 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
- 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79
-};
+static struct encrypt_desc encrypt_desc_serpent =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_SERPENT_CBC,
+ algo_next: NULL,
-static const u_char md5_hmac6_key[] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ enc_blocksize: SERPENT_BLOCK_SIZE,
+ keyminlen: SERPENT_KEY_MIN_LEN,
+ keydeflen: SERPENT_KEY_DEF_LEN,
+ keymaxlen: SERPENT_KEY_MAX_LEN,
};
-static const u_char md5_hmac6_msg[] = {
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
- 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
- 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
- 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
- 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
- 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
- 0x20, 0x46, 0x69, 0x72, 0x73, 0x74
-};
+#define TWOFISH_KEY_MIN_LEN 128
+#define TWOFISH_KEY_DEF_LEN 128
+#define TWOFISH_KEY_MAX_LEN 256
-static const u_char md5_hmac6[] = {
- 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
- 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd
-};
+static struct encrypt_desc encrypt_desc_twofish =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_TWOFISH_CBC,
+ algo_next: NULL,
-static const u_char md5_hmac7_msg[] = {
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
- 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
- 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
- 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
- 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x61, 0x6e,
- 0x64, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x72,
- 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x4f, 0x6e,
- 0x65, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d,
- 0x53, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x61, 0x74,
- 0x61
+ enc_blocksize: TWOFISH_BLOCK_SIZE,
+ keydeflen: TWOFISH_KEY_MIN_LEN,
+ keyminlen: TWOFISH_KEY_DEF_LEN,
+ keymaxlen: TWOFISH_KEY_MAX_LEN,
};
-static const u_char md5_hmac7[] = {
- 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
- 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e
-};
+static struct encrypt_desc encrypt_desc_twofish_ssh =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_TWOFISH_CBC_SSH,
+ algo_next: NULL,
-static const hmac_testvector_t md5_hmac_testvectors[] = {
- { sizeof(md5_hmac1_key), md5_hmac1_key, sizeof(md5_hmac1_msg), md5_hmac1_msg, md5_hmac1 },
- { sizeof(md5_hmac2_key), md5_hmac2_key, sizeof(md5_hmac2_msg), md5_hmac2_msg, md5_hmac2 },
- { sizeof(md5_hmac3_key), md5_hmac3_key, sizeof(md5_hmac3_msg), md5_hmac3_msg, md5_hmac3 },
- { sizeof(md5_hmac4_key), md5_hmac4_key, sizeof(md5_hmac4_msg), md5_hmac4_msg, md5_hmac4 },
- { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac6_msg), md5_hmac6_msg, md5_hmac6 },
- { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac7_msg), md5_hmac7_msg, md5_hmac7 },
- { 0, NULL, 0, NULL, NULL }
+ enc_blocksize: TWOFISH_BLOCK_SIZE,
+ keydeflen: TWOFISH_KEY_MIN_LEN,
+ keyminlen: TWOFISH_KEY_DEF_LEN,
+ keymaxlen: TWOFISH_KEY_MAX_LEN,
};
-static struct hash_desc crypto_hasher_md5 =
-{
+static struct hash_desc hash_desc_md5 =
+{
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_MD5,
algo_next: NULL,
- hash_ctx_size: sizeof(MD5_CTX),
- hash_block_size: MD5_BLOCK_SIZE,
- hash_digest_size: MD5_DIGEST_SIZE,
- hash_testvectors: md5_hash_testvectors,
- hmac_testvectors: md5_hmac_testvectors,
- hash_init: (void (*)(void *)) MD5Init,
- hash_update: (void (*)(void *, const u_int8_t *, size_t)) MD5Update,
- hash_final: (void (*)(u_char *, void *)) MD5Final
+ hash_digest_size: HASH_SIZE_MD5,
};
-/* SHA-1 test vectors
- * from "The Secure Hash Algorithm Validation System (SHAVS)"
- * July 22, 2004, Lawrence E. Bassham III, NIST
- */
-
-static const u_char sha1_short2_msg[] = {
- 0x5e
+static struct hash_desc hash_desc_sha1 =
+{
+ algo_type: IKE_ALG_HASH,
+ algo_id: OAKLEY_SHA,
+ algo_next: NULL,
+ hash_digest_size: HASH_SIZE_SHA1,
};
-static const u_char sha1_short2_msg_digest[] = {
- 0x5e, 0x6f, 0x80, 0xa3, 0x4a, 0x97, 0x98, 0xca,
- 0xfc, 0x6a, 0x5d, 0xb9, 0x6c, 0xc5, 0x7b, 0xa4,
- 0xc4, 0xdb, 0x59, 0xc2
+static struct hash_desc hash_desc_sha2_256 = {
+ algo_type: IKE_ALG_HASH,
+ algo_id: OAKLEY_SHA2_256,
+ algo_next: NULL,
+ hash_digest_size: HASH_SIZE_SHA256,
};
-static const u_char sha1_short4_msg[] = {
- 0x9a, 0x7d, 0xfd, 0xf1, 0xec, 0xea, 0xd0, 0x6e,
- 0xd6, 0x46, 0xaa, 0x55, 0xfe, 0x75, 0x71, 0x46
+static struct hash_desc hash_desc_sha2_384 = {
+ algo_type: IKE_ALG_HASH,
+ algo_id: OAKLEY_SHA2_384,
+ algo_next: NULL,
+ hash_digest_size: HASH_SIZE_SHA384,
};
-static const u_char sha1_short4_msg_digest[] = {
- 0x82, 0xab, 0xff, 0x66, 0x05, 0xdb, 0xe1, 0xc1,
- 0x7d, 0xef, 0x12, 0xa3, 0x94, 0xfa, 0x22, 0xa8,
- 0x2b, 0x54, 0x4a, 0x35
+static struct hash_desc hash_desc_sha2_512 = {
+ algo_type: IKE_ALG_HASH,
+ algo_id: OAKLEY_SHA2_512,
+ algo_next: NULL,
+ hash_digest_size: HASH_SIZE_SHA512,
};
-static const u_char sha1_long2_msg[] = {
- 0xf7, 0x8f, 0x92, 0x14, 0x1b, 0xcd, 0x17, 0x0a,
- 0xe8, 0x9b, 0x4f, 0xba, 0x15, 0xa1, 0xd5, 0x9f,
- 0x3f, 0xd8, 0x4d, 0x22, 0x3c, 0x92, 0x51, 0xbd,
- 0xac, 0xbb, 0xae, 0x61, 0xd0, 0x5e, 0xd1, 0x15,
- 0xa0, 0x6a, 0x7c, 0xe1, 0x17, 0xb7, 0xbe, 0xea,
- 0xd2, 0x44, 0x21, 0xde, 0xd9, 0xc3, 0x25, 0x92,
- 0xbd, 0x57, 0xed, 0xea, 0xe3, 0x9c, 0x39, 0xfa,
- 0x1f, 0xe8, 0x94, 0x6a, 0x84, 0xd0, 0xcf, 0x1f,
- 0x7b, 0xee, 0xad, 0x17, 0x13, 0xe2, 0xe0, 0x95,
- 0x98, 0x97, 0x34, 0x7f, 0x67, 0xc8, 0x0b, 0x04,
- 0x00, 0xc2, 0x09, 0x81, 0x5d, 0x6b, 0x10, 0xa6,
- 0x83, 0x83, 0x6f, 0xd5, 0x56, 0x2a, 0x56, 0xca,
- 0xb1, 0xa2, 0x8e, 0x81, 0xb6, 0x57, 0x66, 0x54,
- 0x63, 0x1c, 0xf1, 0x65, 0x66, 0xb8, 0x6e, 0x3b,
- 0x33, 0xa1, 0x08, 0xb0, 0x53, 0x07, 0xc0, 0x0a,
- 0xff, 0x14, 0xa7, 0x68, 0xed, 0x73, 0x50, 0x60,
- 0x6a, 0x0f, 0x85, 0xe6, 0xa9, 0x1d, 0x39, 0x6f,
- 0x5b, 0x5c, 0xbe, 0x57, 0x7f, 0x9b, 0x38, 0x80,
- 0x7c, 0x7d, 0x52, 0x3d, 0x6d, 0x79, 0x2f, 0x6e,
- 0xbc, 0x24, 0xa4, 0xec, 0xf2, 0xb3, 0xa4, 0x27,
- 0xcd, 0xbb, 0xfb
+const struct dh_desc unset_group = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_NONE,
+ algo_next: NULL,
+ ke_size: 0
};
-static const u_char sha1_long2_msg_digest[] = {
- 0xcb, 0x00, 0x82, 0xc8, 0xf1, 0x97, 0xd2, 0x60,
- 0x99, 0x1b, 0xa6, 0xa4, 0x60, 0xe7, 0x6e, 0x20,
- 0x2b, 0xad, 0x27, 0xb3
+static struct dh_desc dh_desc_modp_1024 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_1024_BIT,
+ algo_next: NULL,
+ ke_size: 1024 / BITS_PER_BYTE
};
-static const hash_testvector_t sha1_hash_testvectors[] = {
- { sizeof(sha1_short2_msg), sha1_short2_msg, sha1_short2_msg_digest },
- { sizeof(sha1_short4_msg), sha1_short4_msg, sha1_short4_msg_digest },
- { sizeof(sha1_long2_msg), sha1_long2_msg, sha1_long2_msg_digest },
- { 0, NULL, NULL }
+static struct dh_desc dh_desc_modp_1536 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_1536_BIT,
+ algo_next: NULL,
+ ke_size: 1536 / BITS_PER_BYTE
};
-/* SHA-1 hmac test vectors
- * from RFC 2202 "Test Cases for HMAC-MD5 and HMAC-SHA-1"
- * September 1997, P. Cheng, IBM & R. Glenn, NIST
- */
-
-static const u_char sha1_hmac1_key[] = {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b
+static struct dh_desc dh_desc_modp_2048 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_2048_BIT,
+ algo_next: NULL,
+ ke_size: 2048 / BITS_PER_BYTE
};
-static const u_char sha1_hmac1[] = {
- 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
- 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
- 0xf1, 0x46, 0xbe, 0x00
+static struct dh_desc dh_desc_modp_3072 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_3072_BIT,
+ algo_next: NULL,
+ ke_size: 3072 / BITS_PER_BYTE
};
-static const u_char sha1_hmac2[] = {
- 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2,
- 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c,
- 0x25, 0x9a, 0x7c, 0x79
+static struct dh_desc dh_desc_modp_4096 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_4096_BIT,
+ algo_next: NULL,
+ ke_size: 4096 / BITS_PER_BYTE
};
-static const u_char sha1_hmac3_key[] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa
+static struct dh_desc dh_desc_modp_6144 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_6144_BIT,
+ algo_next: NULL,
+ ke_size: 6144 / BITS_PER_BYTE
};
-static const u_char sha1_hmac3[] = {
- 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd,
- 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f,
- 0x63, 0xf1, 0x75, 0xd3
+static struct dh_desc dh_desc_modp_8192 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: MODP_8192_BIT,
+ algo_next: NULL,
+ ke_size: 8192 / BITS_PER_BYTE
};
-static const u_char sha1_hmac4[] = {
- 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6,
- 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c,
- 0x2d, 0x72, 0x35, 0xda
+static struct dh_desc dh_desc_ecp_256 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: ECP_256_BIT,
+ algo_next: NULL,
+ ke_size: 2*256 / BITS_PER_BYTE
};
-static const u_char sha1_hmac6[] = {
- 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
- 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55,
- 0xed, 0x40, 0x21, 0x12
+static struct dh_desc dh_desc_ecp_384 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: ECP_384_BIT,
+ algo_next: NULL,
+ ke_size: 2*384 / BITS_PER_BYTE
};
-static const u_char sha1_hmac7[] = {
- 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78,
- 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08,
- 0xbb, 0xff, 0x1a, 0x91
+static struct dh_desc dh_desc_ecp_521 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: ECP_521_BIT,
+ algo_next: NULL,
+ ke_size: 2*528 / BITS_PER_BYTE
};
-static const hmac_testvector_t sha1_hmac_testvectors[] = {
- { sizeof(sha1_hmac1_key), sha1_hmac1_key, sizeof(md5_hmac1_msg), md5_hmac1_msg, sha1_hmac1 },
- { sizeof(md5_hmac2_key), md5_hmac2_key, sizeof(md5_hmac2_msg), md5_hmac2_msg, sha1_hmac2 },
- { sizeof(sha1_hmac3_key), sha1_hmac3_key, sizeof(md5_hmac3_msg), md5_hmac3_msg, sha1_hmac3 },
- { sizeof(md5_hmac4_key), md5_hmac4_key, sizeof(md5_hmac4_msg), md5_hmac4_msg, sha1_hmac4 },
- { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac6_msg), md5_hmac6_msg, sha1_hmac6 },
- { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac7_msg), md5_hmac7_msg, sha1_hmac7 },
- { 0, NULL, 0, NULL, NULL }
+static struct dh_desc dh_desc_ecp_192 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: ECP_192_BIT,
+ algo_next: NULL,
+ ke_size: 2*192 / BITS_PER_BYTE
};
-static struct hash_desc crypto_hasher_sha1 =
-{
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA,
- algo_next: NULL,
- hash_ctx_size: sizeof(SHA1_CTX),
- hash_block_size: SHA1_BLOCK_SIZE,
- hash_digest_size: SHA1_DIGEST_SIZE,
- hash_testvectors: sha1_hash_testvectors,
- hmac_testvectors: sha1_hmac_testvectors,
- hash_init: (void (*)(void *)) SHA1Init,
- hash_update: (void (*)(void *, const u_int8_t *, size_t)) SHA1Update,
- hash_final: (void (*)(u_char *, void *)) SHA1Final
+static struct dh_desc dh_desc_ecp_224 = {
+ algo_type: IKE_ALG_DH_GROUP,
+ algo_id: ECP_224_BIT,
+ algo_next: NULL,
+ ke_size: 2*224 / BITS_PER_BYTE
};
-void
-init_crypto(void)
+void init_crypto(void)
{
- if (mpz_init_set_str(&groupgenerator, MODP_GENERATOR, 10) != 0
- || mpz_init_set_str(&modp1024_modulus, MODP1024_MODULUS, 16) != 0
- || mpz_init_set_str(&modp1536_modulus, MODP1536_MODULUS, 16) != 0
- || mpz_init_set_str(&modp2048_modulus, MODP2048_MODULUS, 16) != 0
- || mpz_init_set_str(&modp3072_modulus, MODP3072_MODULUS, 16) != 0
- || mpz_init_set_str(&modp4096_modulus, MODP4096_MODULUS, 16) != 0
- || mpz_init_set_str(&modp6144_modulus, MODP6144_MODULUS, 16) != 0
- || mpz_init_set_str(&modp8192_modulus, MODP8192_MODULUS, 16) != 0)
- exit_log("mpz_init_set_str() failed in init_crypto()");
-
- ike_alg_add((struct ike_alg *) &crypto_encryptor_3des);
- ike_alg_add((struct ike_alg *) &crypto_hasher_sha1);
- ike_alg_add((struct ike_alg *) &crypto_hasher_md5);
- ike_alg_init();
- ike_alg_test();
+ enumerator_t *enumerator;
+ encryption_algorithm_t encryption_alg;
+ hash_algorithm_t hash_alg;
+ diffie_hellman_group_t dh_group;
+ bool no_md5 = TRUE;
+ bool no_sha1 = TRUE;
+
+ enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &hash_alg))
+ {
+ const struct hash_desc *desc;
+
+ switch (hash_alg)
+ {
+ case HASH_SHA1:
+ desc = &hash_desc_sha1;
+ no_sha1 = FALSE;
+ break;
+ case HASH_SHA256:
+ desc = &hash_desc_sha2_256;
+ break;
+ case HASH_SHA384:
+ desc = &hash_desc_sha2_384;
+ break;
+ case HASH_SHA512:
+ desc = &hash_desc_sha2_512;
+ break;
+ case HASH_MD5:
+ desc = &hash_desc_md5;
+ no_md5 = FALSE;
+ break;
+ default:
+ continue;
+ }
+ ike_alg_add((struct ike_alg *)desc);
+ }
+ enumerator->destroy(enumerator);
+
+ if (no_sha1)
+ {
+ exit_log("pluto cannot run without a SHA-1 hasher");
+ }
+ if (no_md5)
+ {
+ exit_log("pluto cannot run without an MD5 hasher");
+ }
+
+ enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &encryption_alg))
+ {
+ const struct encrypt_desc *desc;
+
+ switch (encryption_alg)
+ {
+ case ENCR_3DES:
+ desc = &encrypt_desc_3des;
+ break;
+ case ENCR_BLOWFISH:
+ desc = &encrypt_desc_blowfish;
+ break;
+ case ENCR_AES_CBC:
+ desc = &encrypt_desc_aes;
+ break;
+ case ENCR_TWOFISH_CBC:
+ desc = &encrypt_desc_twofish;
+ ike_alg_add((struct ike_alg *)&encrypt_desc_twofish_ssh);
+ break;
+ case ENCR_SERPENT_CBC:
+ desc = &encrypt_desc_serpent;
+ break;
+ default:
+ continue;
+ }
+ ike_alg_add((struct ike_alg *)desc);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &dh_group))
+ {
+ const struct dh_desc *desc;
+
+ switch (dh_group)
+ {
+ case MODP_1024_BIT:
+ desc = &dh_desc_modp_1024;
+ break;
+ case MODP_1536_BIT:
+ desc = &dh_desc_modp_1536;
+ break;
+ case MODP_2048_BIT:
+ desc = &dh_desc_modp_2048;
+ break;
+ case MODP_3072_BIT:
+ desc = &dh_desc_modp_3072;
+ break;
+ case MODP_4096_BIT:
+ desc = &dh_desc_modp_4096;
+ break;
+ case MODP_6144_BIT:
+ desc = &dh_desc_modp_6144;
+ break;
+ case MODP_8192_BIT:
+ desc = &dh_desc_modp_8192;
+ break;
+ case ECP_256_BIT:
+ desc = &dh_desc_ecp_256;
+ break;
+ case ECP_384_BIT:
+ desc = &dh_desc_ecp_384;
+ break;
+ case ECP_521_BIT:
+ desc = &dh_desc_ecp_521;
+ break;
+ case ECP_192_BIT:
+ desc = &dh_desc_ecp_192;
+ break;
+ case ECP_224_BIT:
+ desc = &dh_desc_ecp_224;
+ break;
+ default:
+ continue;
+ }
+ ike_alg_add((struct ike_alg *)desc);
+ }
+ enumerator->destroy(enumerator);
}
-/* Oakley group description
- *
- * See RFC2409 "The Internet key exchange (IKE)" 6.
- */
-
-const struct oakley_group_desc unset_group = {0, NULL, 0}; /* magic signifier */
-
-const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE] = {
-# define BYTES(bits) (((bits) + BITS_PER_BYTE - 1) / BITS_PER_BYTE)
- { OAKLEY_GROUP_MODP1024, &modp1024_modulus, BYTES(1024) },
- { OAKLEY_GROUP_MODP1536, &modp1536_modulus, BYTES(1536) },
- { OAKLEY_GROUP_MODP2048, &modp2048_modulus, BYTES(2048) },
- { OAKLEY_GROUP_MODP3072, &modp3072_modulus, BYTES(3072) },
- { OAKLEY_GROUP_MODP4096, &modp4096_modulus, BYTES(4096) },
- { OAKLEY_GROUP_MODP6144, &modp6144_modulus, BYTES(6144) },
- { OAKLEY_GROUP_MODP8192, &modp8192_modulus, BYTES(8192) },
-# undef BYTES
-};
-
-const struct oakley_group_desc *
-lookup_group(u_int16_t group)
+void free_crypto(void)
{
- int i;
-
- for (i = 0; i != elemsof(oakley_group); i++)
- if (group == oakley_group[i].group)
- return &oakley_group[i];
- return NULL;
+ /* currently nothing to do */
}
-/* Encryption Routines
- *
- * Each uses and updates the state object's st_new_iv.
- * This must already be initialized.
+/**
+ * Converts IKEv1 encryption algorithm name to crypter name
*/
+encryption_algorithm_t oakley_to_encryption_algorithm(int alg)
+{
+ switch (alg)
+ {
+ case OAKLEY_DES_CBC:
+ return ENCR_DES;
+ case OAKLEY_IDEA_CBC:
+ return ENCR_IDEA;
+ case OAKLEY_BLOWFISH_CBC:
+ return ENCR_BLOWFISH;
+ case OAKLEY_RC5_R16_B64_CBC:
+ return ENCR_RC5;
+ case OAKLEY_3DES_CBC:
+ return ENCR_3DES;
+ case OAKLEY_CAST_CBC:
+ return ENCR_CAST;
+ case OAKLEY_AES_CBC:
+ return ENCR_AES_CBC;
+ case OAKLEY_SERPENT_CBC:
+ return ENCR_SERPENT_CBC;
+ case OAKLEY_TWOFISH_CBC:
+ case OAKLEY_TWOFISH_CBC_SSH:
+ return ENCR_TWOFISH_CBC;
+ default:
+ return ENCR_UNDEFINED;
+ }
+}
-/* encrypt or decrypt part of an IKE message using DES
- * See RFC 2409 "IKE" Appendix B
+/**
+ * Converts IKEv1 hash algorithm name to hasher name
*/
-static void __attribute__ ((unused))
-do_des(bool enc, void *buf, size_t buf_len, struct state *st)
+hash_algorithm_t oakley_to_hash_algorithm(int alg)
{
- des_key_schedule ks;
-
- (void) des_set_key((des_cblock *)st->st_enc_key.ptr, ks);
-
- passert(st->st_new_iv_len >= DES_CBC_BLOCK_SIZE);
- st->st_new_iv_len = DES_CBC_BLOCK_SIZE; /* truncate */
-
- des_ncbc_encrypt((des_cblock *)buf, (des_cblock *)buf, buf_len,
- ks,
- (des_cblock *)st->st_new_iv, enc);
+ switch (alg)
+ {
+ case OAKLEY_MD5:
+ return HASH_MD5;
+ case OAKLEY_SHA:
+ return HASH_SHA1;
+ case OAKLEY_SHA2_256:
+ return HASH_SHA256;
+ case OAKLEY_SHA2_384:
+ return HASH_SHA384;
+ case OAKLEY_SHA2_512:
+ return HASH_SHA512;
+ default:
+ return HASH_UNKNOWN;
+ }
}
-/* encrypt or decrypt part of an IKE message using 3DES
- * See RFC 2409 "IKE" Appendix B
+/**
+ * Converts IKEv1 hash algorithm name to IKEv2 prf name
*/
-static void
-do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc)
+pseudo_random_function_t oakley_to_prf(int alg)
{
- des_key_schedule ks[3];
-
- passert (!key_size || (key_size==(DES_CBC_BLOCK_SIZE * 3)))
- (void) des_set_key((des_cblock *)key + 0, ks[0]);
- (void) des_set_key((des_cblock *)key + 1, ks[1]);
- (void) des_set_key((des_cblock *)key + 2, ks[2]);
-
- des_ede3_cbc_encrypt((des_cblock *)buf, (des_cblock *)buf, buf_len,
- ks[0], ks[1], ks[2],
- (des_cblock *)iv, enc);
+ switch (alg)
+ {
+ case OAKLEY_MD5:
+ return PRF_HMAC_MD5;
+ case OAKLEY_SHA:
+ return PRF_HMAC_SHA1;
+ case OAKLEY_SHA2_256:
+ return PRF_HMAC_SHA2_256;
+ case OAKLEY_SHA2_384:
+ return PRF_HMAC_SHA2_384;
+ case OAKLEY_SHA2_512:
+ return PRF_HMAC_SHA2_512;
+ default:
+ return PRF_UNDEFINED;
+ }
}
-/* hash and prf routines */
-void
-crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t size, struct state *st)
+/**
+ * Maps IKEv1 authentication method to IKEv2 signature scheme
+ */
+signature_scheme_t oakley_to_signature_scheme(int method)
{
- passert(st->st_new_iv_len >= e->enc_blocksize);
- st->st_new_iv_len = e->enc_blocksize; /* truncate */
-
- e->do_crypt(buf, size, st->st_enc_key.ptr, st->st_enc_key.len, st->st_new_iv, enc);
- /*
- e->set_key(&ctx, st->st_enc_key.ptr, st->st_enc_key.len);
- e->cbc_crypt(&ctx, buf, size, st->st_new_iv, enc);
- */
+ switch (method)
+ {
+ case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ return SIGN_RSA_EMSA_PKCS1_NULL;
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ return SIGN_ECDSA_WITH_NULL;
+ default:
+ return SIGN_UNKNOWN;
+ }
}
-/* HMAC package
- * rfc2104.txt specifies how HMAC works.
+/**
+ * Converts IKEv2 encryption to IKEv1 encryption algorithm
*/
-
-void
-hmac_init(struct hmac_ctx *ctx,
- const struct hash_desc *h,
- const u_char *key, size_t key_len)
+int oakley_from_encryption_algorithm(encryption_algorithm_t alg)
{
- int k;
-
- ctx->h = h;
- ctx->hmac_digest_size = h->hash_digest_size;
-
- /* Prepare the two pads for the HMAC */
-
- memset(ctx->buf1, '\0', h->hash_block_size);
-
- if (key_len <= h->hash_block_size)
- {
- memcpy(ctx->buf1, key, key_len);
- }
- else
- {
- h->hash_init(&ctx->hash_ctx);
- h->hash_update(&ctx->hash_ctx, key, key_len);
- h->hash_final(ctx->buf1, &ctx->hash_ctx);
- }
-
- memcpy(ctx->buf2, ctx->buf1, h->hash_block_size);
-
- for (k = 0; k < h->hash_block_size; k++)
- {
- ctx->buf1[k] ^= HMAC_IPAD;
- ctx->buf2[k] ^= HMAC_OPAD;
- }
-
- hmac_reinit(ctx);
+ switch (alg)
+ {
+ case ENCR_DES:
+ return OAKLEY_DES_CBC;
+ case ENCR_3DES:
+ return OAKLEY_3DES_CBC;
+ case ENCR_RC5:
+ return OAKLEY_RC5_R16_B64_CBC;
+ case ENCR_IDEA:
+ return OAKLEY_IDEA_CBC;
+ case ENCR_CAST:
+ return OAKLEY_CAST_CBC;
+ case ENCR_BLOWFISH:
+ return OAKLEY_BLOWFISH_CBC;
+ case ENCR_AES_CBC:
+ return OAKLEY_AES_CBC;
+ case ENCR_CAMELLIA_CBC:
+ return OAKLEY_CAMELLIA_CBC;
+ case ENCR_SERPENT_CBC:
+ return OAKLEY_SERPENT_CBC;
+ case ENCR_TWOFISH_CBC:
+ return OAKLEY_TWOFISH_CBC;
+ default:
+ return 0;
+ }
}
-void
-hmac_reinit(struct hmac_ctx *ctx)
+/**
+ * Converts IKEv2 integrity to IKEv1 hash algorithm
+ */
+int oakley_from_integrity_algorithm(integrity_algorithm_t alg)
{
- ctx->h->hash_init(&ctx->hash_ctx);
- ctx->h->hash_update(&ctx->hash_ctx, ctx->buf1, ctx->h->hash_block_size);
+ switch (alg)
+ {
+ case AUTH_HMAC_MD5_96:
+ return OAKLEY_MD5;
+ case AUTH_HMAC_SHA1_96:
+ return OAKLEY_SHA;
+ case AUTH_HMAC_SHA2_256_128:
+ return OAKLEY_SHA2_256;
+ case AUTH_HMAC_SHA2_384_192:
+ return OAKLEY_SHA2_384;
+ case AUTH_HMAC_SHA2_512_256:
+ return OAKLEY_SHA2_512;
+ default:
+ return 0;
+ }
}
-void
-hmac_update(struct hmac_ctx *ctx,
- const u_char *data, size_t data_len)
+/**
+ * Converts IKEv2 encryption to IKEv1 ESP encryption algorithm
+ */
+int esp_from_encryption_algorithm(encryption_algorithm_t alg)
{
- ctx->h->hash_update(&ctx->hash_ctx, data, data_len);
+ switch (alg)
+ {
+ case ENCR_DES:
+ return ESP_DES;
+ case ENCR_3DES:
+ return ESP_3DES;
+ case ENCR_RC5:
+ return ESP_RC5;
+ case ENCR_IDEA:
+ return ESP_IDEA;
+ case ENCR_CAST:
+ return ESP_CAST;
+ case ENCR_BLOWFISH:
+ return ESP_BLOWFISH;
+ case ENCR_NULL:
+ return ESP_NULL;
+ case ENCR_AES_CBC:
+ return ESP_AES;
+ case ENCR_AES_CTR:
+ return ESP_AES_CTR;
+ case ENCR_AES_CCM_ICV8:
+ return ESP_AES_CCM_8;
+ case ENCR_AES_CCM_ICV12:
+ return ESP_AES_CCM_12;
+ case ENCR_AES_CCM_ICV16:
+ return ESP_AES_CCM_16;
+ case ENCR_AES_GCM_ICV8:
+ return ESP_AES_GCM_8;
+ case ENCR_AES_GCM_ICV12:
+ return ESP_AES_GCM_12;
+ case ENCR_AES_GCM_ICV16:
+ return ESP_AES_GCM_16;
+ case ENCR_CAMELLIA_CBC:
+ return ESP_CAMELLIA;
+ case ENCR_SERPENT_CBC:
+ return ESP_SERPENT;
+ case ENCR_TWOFISH_CBC:
+ return ESP_TWOFISH;
+ default:
+ return 0;
+ }
}
-void
-hmac_final(u_char *output, struct hmac_ctx *ctx)
+/**
+ * Converts IKEv2 integrity to IKEv1 ESP authentication algorithm
+ */
+int esp_from_integrity_algorithm(integrity_algorithm_t alg)
{
- const struct hash_desc *h = ctx->h;
-
- h->hash_final(output, &ctx->hash_ctx);
-
- h->hash_init(&ctx->hash_ctx);
- h->hash_update(&ctx->hash_ctx, ctx->buf2, h->hash_block_size);
- h->hash_update(&ctx->hash_ctx, output, h->hash_digest_size);
- h->hash_final(output, &ctx->hash_ctx);
+ switch (alg)
+ {
+ case AUTH_HMAC_MD5_96:
+ return AUTH_ALGORITHM_HMAC_MD5;
+ case AUTH_HMAC_SHA1_96:
+ return AUTH_ALGORITHM_HMAC_SHA1;
+ case AUTH_AES_XCBC_96:
+ return AUTH_ALGORITHM_AES_XCBC_MAC;
+ case AUTH_HMAC_SHA2_256_128:
+ return AUTH_ALGORITHM_HMAC_SHA2_256;
+ case AUTH_HMAC_SHA2_384_192:
+ return AUTH_ALGORITHM_HMAC_SHA2_384;
+ case AUTH_HMAC_SHA2_512_256:
+ return AUTH_ALGORITHM_HMAC_SHA2_512;
+ default:
+ return 0;
+ }
}
diff --git a/src/pluto/crypto.h b/src/pluto/crypto.h
index e773d86df..06c4e1d1a 100644
--- a/src/pluto/crypto.h
+++ b/src/pluto/crypto.h
@@ -10,31 +10,20 @@
* 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: crypto.h 3252 2007-10-06 21:24:50Z andreas $
*/
-#include <gmp.h> /* GNU MP library */
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/prfs/prf.h>
+#include <credentials/keys/public_key.h>
-#include "libsha2/sha2.h"
#include "ike_alg.h"
extern void init_crypto(void);
+extern void free_crypto(void);
-/* Oakley group descriptions */
-
-extern MP_INT groupgenerator; /* MODP group generator (2) */
-
-struct oakley_group_desc {
- u_int16_t group;
- MP_INT *modulus;
- size_t bytes;
-};
-
-extern const struct oakley_group_desc unset_group; /* magic signifier */
-extern const struct oakley_group_desc *lookup_group(u_int16_t group);
-#define OAKLEY_GROUP_SIZE 7
-extern const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE];
+extern const struct dh_desc unset_group; /* magic signifier */
/* unification of cryptographic encoding/decoding algorithms
* The IV is taken from and returned to st->st_new_iv.
@@ -46,63 +35,23 @@ extern const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE];
#define MAX_OAKLEY_KEY_LEN0 (3 * DES_CBC_BLOCK_SIZE)
#define MAX_OAKLEY_KEY_LEN (256/BITS_PER_BYTE)
-struct state; /* forward declaration, dammit */
+struct state; /* forward declaration, dammit */
-void crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t size, struct state *st);
-
-#define update_iv(st) memcpy((st)->st_iv, (st)->st_new_iv \
- , (st)->st_iv_len = (st)->st_new_iv_len)
+#define update_iv(st) memcpy((st)->st_iv, (st)->st_new_iv \
+ , (st)->st_iv_len = (st)->st_new_iv_len)
#define set_ph1_iv(st, iv) \
- passert((st)->st_ph1_iv_len <= sizeof((st)->st_ph1_iv)); \
- memcpy((st)->st_ph1_iv, (iv), (st)->st_ph1_iv_len);
+ passert((st)->st_ph1_iv_len <= sizeof((st)->st_ph1_iv)); \
+ memcpy((st)->st_ph1_iv, (iv), (st)->st_ph1_iv_len);
/* unification of cryptographic hashing mechanisms */
-#ifndef NO_HASH_CTX
-union hash_ctx {
- MD5_CTX ctx_md5;
- SHA1_CTX ctx_sha1;
- sha256_context ctx_sha256;
- sha512_context ctx_sha512;
- };
-
-/* HMAC package
- * Note that hmac_ctx can be (and is) copied since there are
- * no persistent pointers into it.
- */
-
-struct hmac_ctx {
- const struct hash_desc *h; /* underlying hash function */
- size_t hmac_digest_size; /* copy of h->hash_digest_size */
- union hash_ctx hash_ctx; /* ctx for hash function */
- u_char buf1[MAX_HASH_BLOCK_SIZE];
- u_char buf2[MAX_HASH_BLOCK_SIZE];
- };
-
-extern void hmac_init(
- struct hmac_ctx *ctx,
- const struct hash_desc *h,
- const u_char *key,
- size_t key_len);
-
-#define hmac_init_chunk(ctx, h, ch) hmac_init((ctx), (h), (ch).ptr, (ch).len)
-
-extern void hmac_reinit(struct hmac_ctx *ctx); /* saves recreating pads */
-
-extern void hmac_update(
- struct hmac_ctx *ctx,
- const u_char *data,
- size_t data_len);
-
-#define hmac_update_chunk(ctx, ch) hmac_update((ctx), (ch).ptr, (ch).len)
-
-extern void hmac_final(u_char *output, struct hmac_ctx *ctx);
+extern encryption_algorithm_t oakley_to_encryption_algorithm(int alg);
+extern hash_algorithm_t oakley_to_hash_algorithm(int alg);
+extern pseudo_random_function_t oakley_to_prf(int alg);
+extern signature_scheme_t oakley_to_signature_scheme(int method);
+extern int oakley_from_encryption_algorithm(encryption_algorithm_t alg);
+extern int oakley_from_integrity_algorithm(integrity_algorithm_t alg);
+extern int esp_from_encryption_algorithm(encryption_algorithm_t alg);
+extern int esp_from_integrity_algorithm(integrity_algorithm_t alg);
-#define hmac_final_chunk(ch, name, ctx) { \
- pfreeany((ch).ptr); \
- (ch).len = (ctx)->hmac_digest_size; \
- (ch).ptr = alloc_bytes((ch).len, name); \
- hmac_final((ch).ptr, (ctx)); \
- }
-#endif
diff --git a/src/pluto/db_ops.c b/src/pluto/db_ops.c
index 993baf53e..4ba4fa324 100644
--- a/src/pluto/db_ops.c
+++ b/src/pluto/db_ops.c
@@ -10,8 +10,6 @@
* 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: db_ops.c 3252 2007-10-06 21:24:50Z andreas $
*/
/*
@@ -31,22 +29,22 @@
* also update attrs_cur (by offset)
*
* db_context structure:
- * +---------------------+
- * | prop |
- * | .protoid |
- * | .trans | --+
- * | .trans_cnt | |
- * +---------------------+ <-+
- * | trans0 | ----> { trans#1 | ... | trans#i | ... }
- * +---------------------+ ^
- * | trans_cur | ----------------------' current transf.
- * +---------------------+
- * | attrs0 | ----> { attr#1 | ... | attr#j | ... }
- * +---------------------+ ^
- * | attrs_cur | ---------------------' current attr.
- * +---------------------+
- * | max_trans,max_attrs | max_trans/attrs: number of elem. of each vector
- * +---------------------+
+ * +---------------------+
+ * | prop |
+ * | .protoid |
+ * | .trans | --+
+ * | .trans_cnt | |
+ * +---------------------+ <-+
+ * | trans0 | ----> { trans#1 | ... | trans#i | ... }
+ * +---------------------+ ^
+ * | trans_cur | ----------------------' current transf.
+ * +---------------------+
+ * | attrs0 | ----> { attr#1 | ... | attr#j | ... }
+ * +---------------------+ ^
+ * | attrs_cur | ---------------------' current attr.
+ * +---------------------+
+ * | max_trans,max_attrs | max_trans/attrs: number of elem. of each vector
+ * +---------------------+
*
* See testing examples at end for interface usage.
*/
@@ -69,50 +67,31 @@
#include <assert.h>
-#ifndef NO_PLUTO
-#else
-#define passert(x) assert(x)
-extern int debug; /* eg: spi.c */
-#define DBG(cond, action) { if (debug) { action ; } }
-#define DBG_log(x, args...) fprintf(stderr, x "\n" , ##args);
-#define alloc_thing(thing, name) alloc_bytes(sizeof (thing), name)
-void * alloc_bytes(size_t size, const char *name) {
- void *p=malloc(size);
- if (p == NULL)
- fprintf(stderr, "unable to malloc %lu bytes for %s",
- (unsigned long) size, name);
- memset(p, '\0', size);
- return p;
-}
-#define pfreeany(ptr) free(ptr)
-
-#endif
-
#ifdef NOT_YET
/*
- * Allocator cache:
- * Because of the single-threaded nature of pluto/spdb.c,
- * alloc()/free() is exercised many times with very small
- * lifetime objects.
- * Just caching last object (currently it will select the
- * largest) will avoid this allocation mas^Wperturbations
+ * Allocator cache:
+ * Because of the single-threaded nature of pluto/spdb.c,
+ * alloc()/free() is exercised many times with very small
+ * lifetime objects.
+ * Just caching last object (currently it will select the
+ * largest) will avoid this allocation mas^Wperturbations
*
*/
struct db_ops_alloc_cache {
- void *ptr;
- int size;
+ void *ptr;
+ int size;
};
#endif
#ifndef NO_DB_OPS_STATS
-/*
- * stats: do account for allocations
- * displayed in db_ops_show_status()
+/*
+ * stats: do account for allocations
+ * displayed in db_ops_show_status()
*/
struct db_ops_stats {
- int st_curr_cnt; /* current number of allocations */
- int st_total_cnt; /* total allocations so far */
- size_t st_maxsz; /* max. size requested */
+ int st_curr_cnt; /* current number of allocations */
+ int st_total_cnt; /* total allocations so far */
+ size_t st_maxsz; /* max. size requested */
};
#define DB_OPS_ZERO { 0, 0, 0};
#define DB_OPS_STATS_DESC "{curr_cnt, total_cnt, maxsz}"
@@ -121,239 +100,233 @@ struct db_ops_stats {
static struct db_ops_stats db_context_st = DB_OPS_ZERO;
static struct db_ops_stats db_trans_st = DB_OPS_ZERO;
static struct db_ops_stats db_attrs_st = DB_OPS_ZERO;
-static __inline__ void * alloc_bytes_st (size_t size, const char *str, struct db_ops_stats *st)
+static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st)
{
- void *ptr = alloc_bytes(size, str);
- if (ptr) {
- st->st_curr_cnt++;
- st->st_total_cnt++;
- if (size > st->st_maxsz) st->st_maxsz=size;
- }
- return ptr;
+ void *ptr = malloc(size);
+ if (ptr)
+ {
+ st->st_curr_cnt++;
+ st->st_total_cnt++;
+ if (size > st->st_maxsz) st->st_maxsz=size;
+ }
+ return ptr;
}
-#define ALLOC_BYTES_ST(z,s,st) alloc_bytes_st(z, s, &st);
-#define PFREE_ST(p,st) do { st.st_curr_cnt--; pfree(p); } while (0);
+#define ALLOC_BYTES_ST(z,st) malloc_bytes_st(z, &st);
+#define PFREE_ST(p,st) do { st.st_curr_cnt--; free(p); } while (0);
#else
-#define ALLOC_BYTES_ST(z,s,n) alloc_bytes(z, s);
-#define PFREE_ST(p,n) pfree(p);
+#define ALLOC_BYTES_ST(z,n) malloc(z);
+#define PFREE_ST(p,n) free(p);
#endif /* NO_DB_OPS_STATS */
-/* Initialize db object
- * max_trans and max_attrs can be 0, will be dynamically expanded
- * as a result of "add" operations
+/* Initialize db object
+ * max_trans and max_attrs can be 0, will be dynamically expanded
+ * as a result of "add" operations
*/
int
db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs)
{
- int ret=-1;
+ ctx->trans0 = NULL;
+ ctx->attrs0 = NULL;
- ctx->trans0 = NULL;
- ctx->attrs0 = NULL;
+ if (max_trans > 0) { /* quite silly if not */
+ ctx->trans0 = ALLOC_BYTES_ST ( sizeof(struct db_trans) * max_trans,
+ db_trans_st);
+ memset(ctx->trans0, '\0', sizeof(struct db_trans) * max_trans);
+ }
- if (max_trans > 0) { /* quite silly if not */
- ctx->trans0 = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans,
- "db_context->trans", db_trans_st);
- if (!ctx->trans0) goto out;
- }
+ if (max_attrs > 0) { /* quite silly if not */
+ ctx->attrs0 = ALLOC_BYTES_ST (sizeof(struct db_attr) * max_attrs,
+ db_attrs_st);
+ memset(ctx->attrs0, '\0', sizeof(struct db_attr) * max_attrs);
+ }
- if (max_attrs > 0) { /* quite silly if not */
- ctx->attrs0 = ALLOC_BYTES_ST (sizeof (struct db_attr) * max_attrs,
- "db_context->attrs", db_attrs_st);
- if (!ctx->attrs0) goto out;
- }
- ret = 0;
-out:
- if (ret < 0 && ctx->trans0) {
- PFREE_ST(ctx->trans0, db_trans_st);
- ctx->trans0 = NULL;
- }
- ctx->max_trans = max_trans;
- ctx->max_attrs = max_attrs;
- ctx->trans_cur = ctx->trans0;
- ctx->attrs_cur = ctx->attrs0;
- ctx->prop.protoid = protoid;
- ctx->prop.trans = ctx->trans0;
- ctx->prop.trans_cnt = 0;
- return ret;
+ ctx->max_trans = max_trans;
+ ctx->max_attrs = max_attrs;
+ ctx->trans_cur = ctx->trans0;
+ ctx->attrs_cur = ctx->attrs0;
+ ctx->prop.protoid = protoid;
+ ctx->prop.trans = ctx->trans0;
+ ctx->prop.trans_cnt = 0;
+ return 0;
}
-/* Expand storage for transforms by number delta_trans */
+/* Expand storage for transforms by number delta_trans */
static int
db_trans_expand(struct db_context *ctx, int delta_trans)
{
- int ret = -1;
- struct db_trans *new_trans, *old_trans;
- int max_trans = ctx->max_trans + delta_trans;
- int offset;
+ int ret = -1;
+ struct db_trans *new_trans, *old_trans;
+ int max_trans = ctx->max_trans + delta_trans;
+ int offset;
- old_trans = ctx->trans0;
- new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans,
- "db_context->trans (expand)", db_trans_st);
- if (!new_trans)
- goto out;
- memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans));
-
- /* update trans0 (obviously) */
- ctx->trans0 = ctx->prop.trans = new_trans;
- /* update trans_cur (by offset) */
- offset = (char *)(new_trans) - (char *)(old_trans);
+ old_trans = ctx->trans0;
+ new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans,
+ db_trans_st);
+ if (!new_trans)
+ goto out;
+ memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans));
+
+ /* update trans0 (obviously) */
+ ctx->trans0 = ctx->prop.trans = new_trans;
+ /* update trans_cur (by offset) */
+ offset = (char *)(new_trans) - (char *)(old_trans);
- {
- char *cctx = (char *)(ctx->trans_cur);
-
- cctx += offset;
- ctx->trans_cur = (struct db_trans *)cctx;
- }
- /* update elem count */
- ctx->max_trans = max_trans;
- PFREE_ST(old_trans, db_trans_st);
- ret = 0;
+ {
+ char *cctx = (char *)(ctx->trans_cur);
+
+ cctx += offset;
+ ctx->trans_cur = (struct db_trans *)cctx;
+ }
+ /* update elem count */
+ ctx->max_trans = max_trans;
+ PFREE_ST(old_trans, db_trans_st);
+ ret = 0;
out:
- return ret;
+ return ret;
}
-/*
- * Expand storage for attributes by delta_attrs number AND
- * rewrite trans->attr pointers
+/*
+ * Expand storage for attributes by delta_attrs number AND
+ * rewrite trans->attr pointers
*/
static int
db_attrs_expand(struct db_context *ctx, int delta_attrs)
{
- int ret = -1;
- struct db_attr *new_attrs, *old_attrs;
- struct db_trans *t;
- int ti;
- int max_attrs = ctx->max_attrs + delta_attrs;
- int offset;
+ int ret = -1;
+ struct db_attr *new_attrs, *old_attrs;
+ struct db_trans *t;
+ int ti;
+ int max_attrs = ctx->max_attrs + delta_attrs;
+ int offset;
+
+ old_attrs = ctx->attrs0;
+ new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs,
+ db_attrs_st);
+ if (!new_attrs)
+ goto out;
- old_attrs = ctx->attrs0;
- new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs,
- "db_context->attrs (expand)", db_attrs_st);
- if (!new_attrs)
- goto out;
+ memcpy(new_attrs, old_attrs, ctx->max_attrs * sizeof(struct db_attr));
+
+ /* update attrs0 and attrs_cur (obviously) */
+ offset = (char *)(new_attrs) - (char *)(old_attrs);
+
+ {
+ char *actx = (char *)(ctx->attrs0);
+
+ actx += offset;
+ ctx->attrs0 = (struct db_attr *)actx;
+
+ actx = (char *)ctx->attrs_cur;
+ actx += offset;
+ ctx->attrs_cur = (struct db_attr *)actx;
+ }
- memcpy(new_attrs, old_attrs, ctx->max_attrs * sizeof(struct db_attr));
-
- /* update attrs0 and attrs_cur (obviously) */
- offset = (char *)(new_attrs) - (char *)(old_attrs);
-
- {
- char *actx = (char *)(ctx->attrs0);
-
- actx += offset;
- ctx->attrs0 = (struct db_attr *)actx;
-
- actx = (char *)ctx->attrs_cur;
- actx += offset;
- ctx->attrs_cur = (struct db_attr *)actx;
- }
+ /* for each transform, rewrite attrs pointer by offsetting it */
+ for (t=ctx->prop.trans, ti=0; ti < ctx->prop.trans_cnt; t++, ti++) {
+ char *actx = (char *)(t->attrs);
- /* for each transform, rewrite attrs pointer by offsetting it */
- for (t=ctx->prop.trans, ti=0; ti < ctx->prop.trans_cnt; t++, ti++) {
- char *actx = (char *)(t->attrs);
-
- actx += offset;
- t->attrs = (struct db_attr *)actx;
- }
- /* update elem count */
- ctx->max_attrs = max_attrs;
- PFREE_ST(old_attrs, db_attrs_st);
- ret = 0;
+ actx += offset;
+ t->attrs = (struct db_attr *)actx;
+ }
+ /* update elem count */
+ ctx->max_attrs = max_attrs;
+ PFREE_ST(old_attrs, db_attrs_st);
+ ret = 0;
out:
- return ret;
+ return ret;
}
-/* Allocate a new db object */
+/* Allocate a new db object */
struct db_context *
db_prop_new(u_int8_t protoid, int max_trans, int max_attrs)
{
- struct db_context *ctx;
- ctx = ALLOC_BYTES_ST ( sizeof (struct db_context), "db_context", db_context_st);
- if (!ctx) goto out;
-
- if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) {
- PFREE_ST(ctx, db_context_st);
- ctx=NULL;
- }
+ struct db_context *ctx;
+ ctx = ALLOC_BYTES_ST ( sizeof (struct db_context), db_context_st);
+ if (!ctx) goto out;
+
+ if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) {
+ PFREE_ST(ctx, db_context_st);
+ ctx=NULL;
+ }
out:
- return ctx;
+ return ctx;
}
-/* Free a db object */
+/* Free a db object */
void
db_destroy(struct db_context *ctx)
{
- if (ctx->trans0) PFREE_ST(ctx->trans0, db_trans_st);
- if (ctx->attrs0) PFREE_ST(ctx->attrs0, db_attrs_st);
- PFREE_ST(ctx, db_context_st);
+ if (ctx->trans0) PFREE_ST(ctx->trans0, db_trans_st);
+ if (ctx->attrs0) PFREE_ST(ctx->attrs0, db_attrs_st);
+ PFREE_ST(ctx, db_context_st);
}
-/* Start a new transform, expand trans0 is needed */
+/* Start a new transform, expand trans0 is needed */
int
db_trans_add(struct db_context *ctx, u_int8_t transid)
{
- /* skip incrementing current trans pointer the 1st time*/
- if (ctx->trans_cur && ctx->trans_cur->attr_cnt)
- ctx->trans_cur++;
- /*
- * Strategy: if more space is needed, expand by
- * <current_size>/2 + 1
- *
- * This happens to produce a "reasonable" sequence
- * after few allocations, eg.:
- * 0,1,2,4,8,13,20,31,47
- */
- if ((ctx->trans_cur - ctx->trans0) >= ctx->max_trans) {
- /* XXX:jjo if fails should shout and flag it */
- if (db_trans_expand(ctx, ctx->max_trans/2 + 1)<0)
- return -1;
- }
- ctx->trans_cur->transid = transid;
- ctx->trans_cur->attrs=ctx->attrs_cur;
- ctx->trans_cur->attr_cnt = 0;
- ctx->prop.trans_cnt++;
- return 0;
+ /* skip incrementing current trans pointer the 1st time*/
+ if (ctx->trans_cur && ctx->trans_cur->attr_cnt)
+ ctx->trans_cur++;
+ /*
+ * Strategy: if more space is needed, expand by
+ * <current_size>/2 + 1
+ *
+ * This happens to produce a "reasonable" sequence
+ * after few allocations, eg.:
+ * 0,1,2,4,8,13,20,31,47
+ */
+ if ((ctx->trans_cur - ctx->trans0) >= ctx->max_trans) {
+ /* XXX:jjo if fails should shout and flag it */
+ if (db_trans_expand(ctx, ctx->max_trans/2 + 1)<0)
+ return -1;
+ }
+ ctx->trans_cur->transid = transid;
+ ctx->trans_cur->attrs=ctx->attrs_cur;
+ ctx->trans_cur->attr_cnt = 0;
+ ctx->prop.trans_cnt++;
+ return 0;
}
-/* Add attr copy to current transform, expanding attrs0 if needed */
+/* Add attr copy to current transform, expanding attrs0 if needed */
int
db_attr_add(struct db_context *ctx, const struct db_attr *a)
{
- /*
- * Strategy: if more space is needed, expand by
- * <current_size>/2 + 1
- */
- if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) {
- /* XXX:jjo if fails should shout and flag it */
- if (db_attrs_expand(ctx, ctx->max_attrs/2 + 1) < 0)
- return -1;
- }
- *ctx->attrs_cur++=*a;
- ctx->trans_cur->attr_cnt++;
- return 0;
+ /*
+ * Strategy: if more space is needed, expand by
+ * <current_size>/2 + 1
+ */
+ if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) {
+ /* XXX:jjo if fails should shout and flag it */
+ if (db_attrs_expand(ctx, ctx->max_attrs/2 + 1) < 0)
+ return -1;
+ }
+ *ctx->attrs_cur++=*a;
+ ctx->trans_cur->attr_cnt++;
+ return 0;
}
-/* Add attr copy (by value) to current transform,
- * expanding attrs0 if needed, just calls db_attr_add().
+/* Add attr copy (by value) to current transform,
+ * expanding attrs0 if needed, just calls db_attr_add().
*/
int
db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val)
{
- struct db_attr attr;
- attr.type = type;
- attr.val = val;
- return db_attr_add (ctx, &attr);
+ struct db_attr attr;
+ attr.type = type;
+ attr.val = val;
+ return db_attr_add (ctx, &attr);
}
#ifndef NO_DB_OPS_STATS
int
db_ops_show_status(void)
{
- whack_log(RC_COMMENT, "stats " __FILE__ ": "
- DB_OPS_STATS_DESC " :"
- DB_OPS_STATS_STR("context")
- DB_OPS_STATS_STR("trans")
- DB_OPS_STATS_STR("attrs"),
- DB_OPS_STATS_F(db_context_st),
- DB_OPS_STATS_F(db_trans_st),
- DB_OPS_STATS_F(db_attrs_st)
- );
- return 0;
+ whack_log(RC_COMMENT, "stats " __FILE__ ": "
+ DB_OPS_STATS_DESC " :"
+ DB_OPS_STATS_STR("context")
+ DB_OPS_STATS_STR("trans")
+ DB_OPS_STATS_STR("attrs"),
+ DB_OPS_STATS_F(db_context_st),
+ DB_OPS_STATS_F(db_trans_st),
+ DB_OPS_STATS_F(db_attrs_st)
+ );
+ return 0;
}
#endif /* NO_DB_OPS_STATS */
/*
@@ -362,51 +335,51 @@ db_ops_show_status(void)
#ifdef TEST
static void db_prop_print(struct db_prop *p)
{
- struct db_trans *t;
- struct db_attr *a;
- int ti, ai;
- enum_names *n, *n_at, *n_av;
- printf("protoid=\"%s\"\n", enum_name(&protocol_names, p->protoid));
- for (ti=0, t=p->trans; ti< p->trans_cnt; ti++, t++) {
- switch( t->transid) {
- case PROTO_ISAKMP:
- n=&isakmp_transformid_names;break;
- case PROTO_IPSEC_ESP:
- n=&esp_transformid_names;break;
- default:
- continue;
- }
- printf(" transid=\"%s\"\n",
- enum_name(n, t->transid));
- for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) {
- int i;
- switch( t->transid) {
- case PROTO_ISAKMP:
- n_at=&oakley_attr_names;
- i=a->type|ISAKMP_ATTR_AF_TV;
- n_av=oakley_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
- break;
- case PROTO_IPSEC_ESP:
- n_at=&ipsec_attr_names;
- i=a->type|ISAKMP_ATTR_AF_TV;
- n_av=ipsec_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
- break;
- default:
- continue;
- }
- printf(" type=\"%s\" value=\"%s\"\n",
- enum_name(n_at, i),
- enum_name(n_av, a->val));
+ struct db_trans *t;
+ struct db_attr *a;
+ int ti, ai;
+ enum_names *n, *n_at, *n_av;
+ printf("protoid=\"%s\"\n", enum_name(&protocol_names, p->protoid));
+ for (ti=0, t=p->trans; ti< p->trans_cnt; ti++, t++) {
+ switch( t->transid) {
+ case PROTO_ISAKMP:
+ n=&isakmp_transformid_names;break;
+ case PROTO_IPSEC_ESP:
+ n=&esp_transformid_names;break;
+ default:
+ continue;
+ }
+ printf(" transid=\"%s\"\n",
+ enum_name(n, t->transid));
+ for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) {
+ int i;
+ switch( t->transid) {
+ case PROTO_ISAKMP:
+ n_at=&oakley_attr_names;
+ i=a->type|ISAKMP_ATTR_AF_TV;
+ n_av=oakley_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
+ break;
+ case PROTO_IPSEC_ESP:
+ n_at=&ipsec_attr_names;
+ i=a->type|ISAKMP_ATTR_AF_TV;
+ n_av=ipsec_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
+ break;
+ default:
+ continue;
+ }
+ printf(" type=\"%s\" value=\"%s\"\n",
+ enum_name(n_at, i),
+ enum_name(n_av, a->val));
+ }
}
- }
}
static void db_print(struct db_context *ctx)
{
- printf("trans_cur diff=%d, attrs_cur diff=%d\n",
- ctx->trans_cur - ctx->trans0,
- ctx->attrs_cur - ctx->attrs0);
- db_prop_print(&ctx->prop);
+ printf("trans_cur diff=%d, attrs_cur diff=%d\n",
+ ctx->trans_cur - ctx->trans0,
+ ctx->attrs_cur - ctx->attrs0);
+ db_prop_print(&ctx->prop);
}
void
@@ -415,25 +388,25 @@ void abort(void);
void
passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
{
- fprintf(stderr, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
- abort(); /* exiting correctly doesn't always work */
+ fprintf(stderr, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
+ abort(); /* exiting correctly doesn't always work */
}
int main(void) {
- struct db_context *ctx=db_prop_new(PROTO_ISAKMP, 0, 0);
- db_trans_add(ctx, KEY_IKE);
- db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC);
- db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
- db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
- db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024);
- db_trans_add(ctx, KEY_IKE);
- db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_AES_CBC);
- db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
- db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
- db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536);
- db_trans_add(ctx, ESP_3DES);
- db_attr_add_values(ctx, AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1);
- db_print(ctx);
- db_destroy(ctx);
- return 0;
+ struct db_context *ctx=db_prop_new(PROTO_ISAKMP, 0, 0);
+ db_trans_add(ctx, KEY_IKE);
+ db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC);
+ db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
+ db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
+ db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024);
+ db_trans_add(ctx, KEY_IKE);
+ db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_AES_CBC);
+ db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
+ db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
+ db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536);
+ db_trans_add(ctx, ESP_3DES);
+ db_attr_add_values(ctx, AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1);
+ db_print(ctx);
+ db_destroy(ctx);
+ return 0;
}
#endif
diff --git a/src/pluto/db_ops.h b/src/pluto/db_ops.h
index 4004e710a..464c245dd 100644
--- a/src/pluto/db_ops.h
+++ b/src/pluto/db_ops.h
@@ -10,47 +10,45 @@
* 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: db_ops.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _DB_OPS_H
#define _DB_OPS_H
/*
- * Main db object, (quite proposal "oriented")
+ * Main db object, (quite proposal "oriented")
*/
#ifndef NO_DB_CONTEXT
struct db_context {
- struct db_prop prop; /* proposal buffer (not pointer) */
- struct db_trans *trans0; /* transf. list, dynamically sized */
- struct db_trans *trans_cur; /* current transform ptr */
- struct db_attr *attrs0; /* attr. list, dynamically sized */
- struct db_attr *attrs_cur; /* current attribute ptr */
- int max_trans; /* size of trans list */
- int max_attrs; /* size of attrs list */
+ struct db_prop prop; /* proposal buffer (not pointer) */
+ struct db_trans *trans0; /* transf. list, dynamically sized */
+ struct db_trans *trans_cur; /* current transform ptr */
+ struct db_attr *attrs0; /* attr. list, dynamically sized */
+ struct db_attr *attrs_cur; /* current attribute ptr */
+ int max_trans; /* size of trans list */
+ int max_attrs; /* size of attrs list */
};
/*
- * Allocate a new db object
+ * Allocate a new db object
*/
struct db_context * db_prop_new(u_int8_t protoid, int max_trans, int max_attrs);
-/* Initialize object for proposal building */
+/* Initialize object for proposal building */
int db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs);
-/* Free all resourses for this db */
+/* Free all resourses for this db */
void db_destroy(struct db_context *ctx);
-/* Start a new transform */
+/* Start a new transform */
int db_trans_add(struct db_context *ctx, u_int8_t transid);
-/* Add a new attribute by copying db_attr content */
+/* Add a new attribute by copying db_attr content */
int db_attr_add(struct db_context *db_ctx, const struct db_attr *attr);
-/* Add a new attribute by value */
+/* Add a new attribute by value */
int db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val);
-/* Get proposal from db object */
+/* Get proposal from db object */
static __inline__ struct db_prop *db_prop_get(struct db_context *ctx) {
- return &ctx->prop;
+ return &ctx->prop;
}
-/* Show stats (allocation, etc) */
+/* Show stats (allocation, etc) */
#endif /* NO_DB_CONTEXT */
int db_ops_show_status(void);
#endif /* _DB_OPS_H */
diff --git a/src/pluto/defs.c b/src/pluto/defs.c
index f2c1eab48..f83318e12 100644
--- a/src/pluto/defs.c
+++ b/src/pluto/defs.c
@@ -10,8 +10,6 @@
* 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: defs.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -27,296 +25,62 @@
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-
-const chunk_t empty_chunk = { NULL, 0 };
+#include "whack.h" /* for RC_LOG_SERIOUS */
bool
all_zero(const unsigned char *m, size_t len)
{
- size_t i;
-
- for (i = 0; i != len; i++)
- if (m[i] != '\0')
- return FALSE;
- return TRUE;
-}
-
-/* memory allocation
- *
- * LEAK_DETECTIVE puts a wrapper around each allocation and maintains
- * a list of live ones. If a dead one is freed, an assertion MIGHT fail.
- * If the live list is currupted, that will often be detected.
- * In the end, report_leaks() is called, and the names of remaining
- * live allocations are printed. At the moment, it is hoped, not that
- * the list is empty, but that there will be no surprises.
- *
- * Accepted Leaks:
- * - "struct iface" and "device name" (for "discovered" net interfaces)
- * - "struct event in event_schedule()" (events not associated with states)
- * - "Pluto lock name" (one only, needed until end -- why bother?)
- */
-
-#ifdef LEAK_DETECTIVE
-
-/* this magic number is 3671129837 decimal (623837458 complemented) */
-#define LEAK_MAGIC 0xDAD0FEEDul
-
-union mhdr {
- struct {
- const char *name;
- union mhdr *older, *newer;
- unsigned long magic;
- } i; /* info */
- unsigned long junk; /* force maximal alignment */
-};
-
-static union mhdr *allocs = NULL;
-
-void *alloc_bytes(size_t size, const char *name)
-{
- union mhdr *p = malloc(sizeof(union mhdr) + size);
-
- if (p == NULL)
- exit_log("unable to malloc %lu bytes for %s"
- , (unsigned long) size, name);
- p->i.name = name;
- p->i.older = allocs;
- if (allocs != NULL)
- allocs->i.newer = p;
- allocs = p;
- p->i.newer = NULL;
- p->i.magic = LEAK_MAGIC;
-
- memset(p+1, '\0', size);
- return p+1;
-}
-
-void *
-clone_bytes(const void *orig, size_t size, const char *name)
-{
- void *p = alloc_bytes(size, name);
-
- memcpy(p, orig, size);
- return p;
-}
-
-void
-pfree(void *ptr)
-{
- union mhdr *p;
-
- passert(ptr != NULL);
- p = ((union mhdr *)ptr) - 1;
- passert(p->i.magic == LEAK_MAGIC);
- if (p->i.older != NULL)
- {
- passert(p->i.older->i.newer == p);
- p->i.older->i.newer = p->i.newer;
- }
- if (p->i.newer == NULL)
- {
- passert(p == allocs);
- allocs = p->i.older;
- }
- else
- {
- passert(p->i.newer->i.older == p);
- p->i.newer->i.older = p->i.older;
- }
- p->i.magic = ~LEAK_MAGIC;
- free(p);
-}
-
-void
-report_leaks(void)
-{
- union mhdr
- *p = allocs,
- *pprev = NULL;
- unsigned long n = 0;
-
- while (p != NULL)
- {
- passert(p->i.magic == LEAK_MAGIC);
- passert(pprev == p->i.newer);
- pprev = p;
- p = p->i.older;
- n++;
- if (p == NULL || pprev->i.name != p->i.name)
- {
- if (n != 1)
- plog("leak: %lu * %s", n, pprev->i.name);
- else
- plog("leak: %s", pprev->i.name);
- n = 0;
- }
- }
-}
-
-#else /* !LEAK_DETECTIVE */
-
-void *alloc_bytes(size_t size, const char *name)
-{
- void *p = malloc(size);
-
- if (p == NULL)
- exit_log("unable to malloc %lu bytes for %s"
- , (unsigned long) size, name);
- memset(p, '\0', size);
- return p;
-}
-
-void *clone_bytes(const void *orig, size_t size, const char *name)
-{
- void *p = malloc(size);
+ size_t i;
- if (p == NULL)
- exit_log("unable to malloc %lu bytes for %s"
- , (unsigned long) size, name);
- memcpy(p, orig, size);
- return p;
+ for (i = 0; i != len; i++)
+ if (m[i] != '\0')
+ return FALSE;
+ return TRUE;
}
-#endif /* !LEAK_DETECTIVE */
/* Note that there may be as many as six IDs that are temporary at
* one time before unsharing the two ends of a connection. So we need
* at least six temporary buffers for DER_ASN1_DN IDs.
* We rotate them. Be careful!
*/
-#define MAX_BUF 10
+#define MAX_BUF 10
char*
temporary_cyclic_buffer(void)
{
- static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */
- static int counter = 0; /* cyclic counter */
+ static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */
+ static int counter = 0; /* cyclic counter */
- if (++counter == MAX_BUF) counter = 0; /* next internal buffer */
- return buf[counter]; /* assign temporary buffer */
+ if (++counter == MAX_BUF) counter = 0; /* next internal buffer */
+ return buf[counter]; /* assign temporary buffer */
}
/* concatenates two sub paths into a string with a maximum size of BUF_LEN
* use for temporary storage only
*/
-const char*
-concatenate_paths(const char *a, const char *b)
+char* concatenate_paths(char *a, char *b)
{
- char *c;
+ char *c;
- if (*b == '/' || *b == '.')
- return b;
+ if (*b == '/' || *b == '.')
+ return b;
- c = temporary_cyclic_buffer();
- snprintf(c, BUF_LEN, "%s/%s", a, b);
- return c;
+ c = temporary_cyclic_buffer();
+ snprintf(c, BUF_LEN, "%s/%s", a, b);
+ return c;
}
-/* compare two chunks, returns zero if a equals b
- * negative/positive if a is earlier/later in the alphabet than b
- */
-int
-cmp_chunk(chunk_t a, chunk_t b)
-{
- int cmp_len, len, cmp_value;
-
- cmp_len = a.len - b.len;
- len = (cmp_len < 0)? a.len : b.len;
- cmp_value = memcmp(a.ptr, b.ptr, len);
-
- return (cmp_value == 0)? cmp_len : cmp_value;
-};
-
/* moves a chunk to a memory position, chunk is freed afterwards
* position pointer is advanced after the insertion point
*/
void
mv_chunk(u_char **pos, chunk_t content)
{
- if (content.len > 0)
- {
- chunkcpy(*pos, content);
- freeanychunk(content);
- }
-}
-
-/*
- * write the binary contents of a chunk_t to a file
- */
-bool
-write_chunk(const char *filename, const char *label, chunk_t ch
-, mode_t mask, bool force)
-{
- mode_t oldmask;
- FILE *fd;
- size_t written;
-
- if (!force)
- {
- fd = fopen(filename, "r");
- if (fd)
- {
- fclose(fd);
- plog(" %s file '%s' already exists", label, filename);
- return FALSE;
- }
- }
-
- /* set umask */
- oldmask = umask(mask);
-
- fd = fopen(filename, "w");
-
- if (fd)
- {
- written = fwrite(ch.ptr, sizeof(u_char), ch.len, fd);
- fclose(fd);
- if (written != ch.len)
+ if (content.len > 0)
{
- plog(" writing to %s file '%s' failed", label, filename);
- umask(oldmask);
- return FALSE;
+ chunkcpy(*pos, content);
+ free(content.ptr);
}
- plog(" written %s file '%s' (%d bytes)", label, filename, (int)ch.len);
- umask(oldmask);
- return TRUE;
- }
- else
- {
- plog(" could not open %s file '%s' for writing", label, filename);
- umask(oldmask);
- return FALSE;
- }
-}
-
-/* Names of the months */
-
-static const char* months[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-
-/*
- * Display a date either in local or UTC time
- */
-char*
-timetoa(const time_t *time, bool utc)
-{
- static char buf[TIMETOA_BUF];
-
- if (*time == UNDEFINED_TIME)
- sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" ");
- else
- {
- struct tm *t = (utc)? gmtime(time) : localtime(time);
-
- sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d",
- months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
- (utc)?" UTC ":" ", t->tm_year + 1900
- );
- }
- return buf;
}
/* checks if the expiration date has been reached and
@@ -327,44 +91,44 @@ timetoa(const time_t *time, bool utc)
const char*
check_expiry(time_t expiration_date, int warning_interval, bool strict)
{
- time_t now;
- int time_left;
-
- if (expiration_date == UNDEFINED_TIME)
- return "ok (expires never)";
+ time_t now;
+ int time_left;
- /* determine the current time */
- time(&now);
+ if (expiration_date == UNDEFINED_TIME)
+ return "ok (expires never)";
- time_left = (expiration_date - now);
- if (time_left < 0)
- return strict? "fatal (expired)" : "warning (expired)";
+ /* determine the current time */
+ time(&now);
- if (time_left > 86400*warning_interval)
- return "ok";
- {
- static char buf[35]; /* temporary storage */
- const char* unit = "second";
+ time_left = (expiration_date - now);
+ if (time_left < 0)
+ return strict? "fatal (expired)" : "warning (expired)";
- if (time_left > 172800)
- {
- time_left /= 86400;
- unit = "day";
- }
- else if (time_left > 7200)
- {
- time_left /= 3600;
- unit = "hour";
- }
- else if (time_left > 120)
+ if (time_left > 86400*warning_interval)
+ return "ok";
{
- time_left /= 60;
- unit = "minute";
+ static char buf[35]; /* temporary storage */
+ const char* unit = "second";
+
+ if (time_left > 172800)
+ {
+ time_left /= 86400;
+ unit = "day";
+ }
+ else if (time_left > 7200)
+ {
+ time_left /= 3600;
+ unit = "hour";
+ }
+ else if (time_left > 120)
+ {
+ time_left /= 60;
+ unit = "minute";
+ }
+ snprintf(buf, 35, "warning (expires in %d %s%s)", time_left,
+ unit, (time_left == 1)?"":"s");
+ return buf;
}
- snprintf(buf, 35, "warning (expires in %d %s%s)", time_left,
- unit, (time_left == 1)?"":"s");
- return buf;
- }
}
@@ -374,8 +138,8 @@ check_expiry(time_t expiration_date, int warning_interval, bool strict)
int
file_select(const struct dirent *entry)
{
- return strcmp(entry->d_name, "." ) &&
- strcmp(entry->d_name, "..");
+ return strcmp(entry->d_name, "." ) &&
+ strcmp(entry->d_name, "..");
}
diff --git a/src/pluto/defs.h b/src/pluto/defs.h
index 574ce4a1a..8491f4ae8 100644
--- a/src/pluto/defs.h
+++ b/src/pluto/defs.h
@@ -11,128 +11,77 @@
* 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: defs.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _DEFS_H
#define _DEFS_H
+#include <string.h>
#include <sys/types.h>
+#include <chunk.h>
+
#ifdef KLIPS
-# define USED_BY_KLIPS /* ignore */
+# define USED_BY_KLIPS /* ignore */
#else
-# define USED_BY_KLIPS UNUSED
+# define USED_BY_KLIPS UNUSED
#endif
#ifdef DEBUG
-# define USED_BY_DEBUG /* ignore */
+# define USED_BY_DEBUG /* ignore */
#else
-# define USED_BY_DEBUG UNUSED
+# define USED_BY_DEBUG UNUSED
#endif
-/* Length of temporary buffers */
-
-#define BUF_LEN 512
-
/* type of serial number of a state object
* Needed in connections.h and state.h; here to simplify dependencies.
*/
typedef unsigned long so_serial_t;
-#define SOS_NOBODY 0 /* null serial number */
-#define SOS_FIRST 1 /* first normal serial number */
+#define SOS_NOBODY 0 /* null serial number */
+#define SOS_FIRST 1 /* first normal serial number */
/* memory allocation */
-extern void *alloc_bytes(size_t size, const char *name);
-#define alloc_thing(thing, name) (alloc_bytes(sizeof(thing), (name)))
+#define clone_thing(orig) clalloc((void *)&(orig), sizeof(orig))
-extern void *clone_bytes(const void *orig, size_t size, const char *name);
-#define clone_thing(orig, name) clone_bytes((const void *)&(orig), sizeof(orig), (name))
-#define clone_str(str, name) \
- ((str) == NULL? NULL : clone_bytes((str), strlen((str))+1, (name)))
+#define clone_str(str) \
+ ((str) == NULL? NULL : strdup(str))
+
+#define replace(p, q) \
+ { free(p); (p) = (q); }
-#ifdef LEAK_DETECTIVE
- extern void pfree(void *ptr);
- extern void report_leaks(void);
-#else
-# define pfree(ptr) free(ptr) /* ordinary stdc free */
-#endif
-#define pfreeany(p) { if ((p) != NULL) pfree(p); }
-#define replace(p, q) { pfreeany(p); (p) = (q); }
-
-
-/* chunk is a simple pointer-and-size abstraction */
-
-struct chunk {
- u_char *ptr;
- size_t len;
- };
-typedef struct chunk chunk_t;
-
-#define setchunk(ch, addr, size) { (ch).ptr = (addr); (ch).len = (size); }
-#define strchunk(str) { str, sizeof(str) }
-/* NOTE: freeanychunk, unlike pfreeany, NULLs .ptr */
-#define freeanychunk(ch) { pfreeany((ch).ptr); (ch).ptr = NULL; }
-#define clonetochunk(ch, addr, size, name) \
- { (ch).ptr = clone_bytes((addr), (ch).len = (size), name); }
-#define clonereplacechunk(ch, addr, size, name) \
- { pfreeany((ch).ptr); clonetochunk(ch, addr, size, name); }
#define chunkcpy(dst, chunk) \
- { memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;}
-#define same_chunk(a, b) \
- ( (a).len == (b).len && memcmp((a).ptr, (b).ptr, (b).len) == 0 )
+ { memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;}
extern char* temporary_cyclic_buffer(void);
-extern const char* concatenate_paths(const char *a, const char *b);
-
-extern const chunk_t empty_chunk;
-
-/* compare two chunks */
-extern int cmp_chunk(chunk_t a, chunk_t b);
+extern char* concatenate_paths(char *a, char *b);
/* move a chunk to a memory position and free it after insertion */
extern void mv_chunk(u_char **pos, chunk_t content);
-/* write the binary contents of a chunk_t to a file */
-extern bool write_chunk(const char *filename, const char *label, chunk_t ch
- ,mode_t mask, bool force);
-
-/* display a date either in local or UTC time */
-extern char* timetoa(const time_t *time, bool utc);
-
/* warns a predefined interval before expiry */
extern const char* check_expiry(time_t expiration_date,
- int warning_interval, bool strict);
+ int warning_interval, bool strict);
-#define MAX_PROMPT_PASS_TRIALS 5
-#define PROMPT_PASS_LEN 64
+#define MAX_PROMPT_PASS_TRIALS 5
+#define PROMPT_PASS_LEN 64
/* struct used to prompt for a secret passphrase
* from a console with file descriptor fd
*/
typedef struct {
- char secret[PROMPT_PASS_LEN+1];
- bool prompt;
- int fd;
+ char secret[PROMPT_PASS_LEN+1];
+ bool prompt;
+ int fd;
} prompt_pass_t;
-/* no time defined in time_t */
-#define UNDEFINED_TIME 0
-
-/* size of timetoa string buffer */
-#define TIMETOA_BUF 30
-
/* filter eliminating the directory entries '.' and '..' */
typedef struct dirent dirent_t;
extern int file_select(const dirent_t *entry);
/* cleanly exit Pluto */
-
extern void exit_pluto(int /*status*/) NEVER_RETURNS;
-
/* zero all bytes */
#define zero(x) memset((x), '\0', sizeof(*(x)))
diff --git a/src/pluto/demux.c b/src/pluto/demux.c
index 04728a4a8..3cfc909af 100644
--- a/src/pluto/demux.c
+++ b/src/pluto/demux.c
@@ -11,8 +11,6 @@
* 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: demux.c 3686 2008-03-28 11:48:14Z martin $
*/
/* Ordering Constraints on Payloads
@@ -110,8 +108,8 @@
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/time.h> /* only used for belt-and-suspenders select call */
-#include <sys/poll.h> /* only used for forensic poll call */
+#include <sys/time.h> /* only used for belt-and-suspenders select call */
+#include <sys/poll.h> /* only used for forensic poll call */
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
@@ -119,9 +117,9 @@
#include <sys/queue.h>
#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
-# include <asm/types.h> /* for __u8, __u32 */
+# include <asm/types.h> /* for __u8, __u32 */
# include <linux/errqueue.h>
-# include <sys/uio.h> /* struct iovec */
+# include <sys/uio.h> /* struct iovec */
#endif
#include <freeswan.h>
@@ -132,15 +130,13 @@
#include "connections.h"
#include "state.h"
#include "packet.h"
-#include "md5.h"
-#include "sha1.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
+#include "crypto.h"
#include "ike_alg.h"
#include "log.h"
-#include "demux.h" /* needs packet.h */
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "demux.h" /* needs packet.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "timer.h"
-#include "whack.h" /* requires connections.h */
+#include "whack.h" /* requires connections.h */
#include "server.h"
#include "nat_traversal.h"
#include "vendor.h"
@@ -173,14 +169,14 @@ u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE];
*/
struct state_microcode {
- enum state_kind state, next_state;
- lset_t flags;
- lset_t req_payloads; /* required payloads (allows just one) */
- lset_t opt_payloads; /* optional payloads (any mumber) */
- /* if not ISAKMP_NEXT_NONE, process_packet will emit HDR with this as np */
- u_int8_t first_out_payload;
- enum event_type timeout_event;
- state_transition_fn *processor;
+ enum state_kind state, next_state;
+ lset_t flags;
+ lset_t req_payloads; /* required payloads (allows just one) */
+ lset_t opt_payloads; /* optional payloads (any mumber) */
+ /* if not ISAKMP_NEXT_NONE, process_packet will emit HDR with this as np */
+ u_int8_t first_out_payload;
+ enum event_type timeout_event;
+ state_transition_fn *processor;
};
/* State Microcode Flags, in several groups */
@@ -190,19 +186,21 @@ struct state_microcode {
* Note: SMF_ALL_AUTH matches 0 for those circumstances when no auth
* has been set.
*/
-#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1)
-#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY)
-#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG))
-#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC))
-#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV))
+#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1)
+#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY)
+#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG) | \
+ LELEM(OAKLEY_ECDSA_SIG) | LELEM(OAKLEY_ECDSA_256) | \
+ LELEM(OAKLEY_ECDSA_384) | LELEM(OAKLEY_ECDSA_521))
+#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC))
+#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV))
/* misc flags */
-#define SMF_INITIATOR LELEM(OAKLEY_AUTH_ROOF + 0)
-#define SMF_FIRST_ENCRYPTED_INPUT LELEM(OAKLEY_AUTH_ROOF + 1)
-#define SMF_INPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 2)
-#define SMF_OUTPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 3)
-#define SMF_RETRANSMIT_ON_DUPLICATE LELEM(OAKLEY_AUTH_ROOF + 4)
+#define SMF_INITIATOR LELEM(OAKLEY_AUTH_ROOF + 0)
+#define SMF_FIRST_ENCRYPTED_INPUT LELEM(OAKLEY_AUTH_ROOF + 1)
+#define SMF_INPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 2)
+#define SMF_OUTPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 3)
+#define SMF_RETRANSMIT_ON_DUPLICATE LELEM(OAKLEY_AUTH_ROOF + 4)
#define SMF_ENCRYPTED (SMF_INPUT_ENCRYPTED | SMF_OUTPUT_ENCRYPTED)
@@ -210,14 +208,14 @@ struct state_microcode {
#define SMF_REPLY LELEM(OAKLEY_AUTH_ROOF + 5)
/* this state completes P1, so any pending P2 negotiations should start */
-#define SMF_RELEASE_PENDING_P2 LELEM(OAKLEY_AUTH_ROOF + 6)
+#define SMF_RELEASE_PENDING_P2 LELEM(OAKLEY_AUTH_ROOF + 6)
/* end of flags */
-static state_transition_fn /* forward declaration */
- unexpected,
- informational;
+static state_transition_fn /* forward declaration */
+ unexpected,
+ informational;
/* state_microcode_table is a table of all state_microcode tuples.
* It must be in order of state (the first element).
@@ -228,288 +226,288 @@ static state_transition_fn /* forward declaration */
*/
static const struct state_microcode
- *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR];
+ *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR];
static const struct state_microcode state_microcode_table[] = {
#define PT(n) ISAKMP_NEXT_##n
#define P(n) LELEM(PT(n))
- /***** Phase 1 Main Mode *****/
-
- /* No state for main_outI1: --> HDR, SA */
-
- /* STATE_MAIN_R0: I1 --> R1
- * HDR, SA --> HDR, SA
- */
- { STATE_MAIN_R0, STATE_MAIN_R1
- , SMF_ALL_AUTH | SMF_REPLY
- , P(SA), P(VID) | P(CR), PT(NONE)
- , EVENT_RETRANSMIT, main_inI1_outR1},
-
- /* STATE_MAIN_I1: R1 --> I2
- * HDR, SA --> auth dependent
- * SMF_PSK_AUTH, SMF_DS_AUTH: --> HDR, KE, Ni
- * SMF_PKE_AUTH:
- * --> HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- * SMF_RPKE_AUTH:
- * --> HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
- * Note: since we don't know auth at start, we cannot differentiate
- * microcode entries based on it.
- */
- { STATE_MAIN_I1, STATE_MAIN_I2
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY
- , P(SA), P(VID) | P(CR), PT(NONE) /* don't know yet */
- , EVENT_RETRANSMIT, main_inR1_outI2 },
-
- /* STATE_MAIN_R1: I2 --> R2
- * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr
- * SMF_PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- * --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * SMF_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
- */
- { STATE_MAIN_R1, STATE_MAIN_R2
- , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY
- , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(KE)
- , EVENT_RETRANSMIT, main_inI2_outR2 },
-
- { STATE_MAIN_R1, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_REPLY
- , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), PT(KE)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- { STATE_MAIN_R1, STATE_UNDEFINED
- , SMF_RPKE_AUTH | SMF_REPLY
- , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), PT(NONCE)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- /* for states from here on, output message must be encrypted */
-
- /* STATE_MAIN_I2: R2 --> I3
- * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
- * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
- * 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
- */
- { STATE_MAIN_I2, STATE_MAIN_I3
- , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
- , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(ID)
- , EVENT_RETRANSMIT, main_inR2_outI3 },
-
- { STATE_MAIN_I2, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
- , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- { STATE_MAIN_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
- , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), PT(HASH)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- /* for states from here on, input message must be encrypted */
-
- /* STATE_MAIN_R2: I3 --> R3
- * SMF_PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
- * SMF_DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R
- * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R
- */
- { STATE_MAIN_R2, STATE_MAIN_R3
- , SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
- | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, main_inI3_outR3 },
-
- { STATE_MAIN_R2, STATE_MAIN_R3
- , SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
- | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE)
- , EVENT_SA_REPLACE, main_inI3_outR3 },
-
- { STATE_MAIN_R2, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
- | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
-
- /* STATE_MAIN_I3: R3 --> done
- * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done
- * SMF_DS_AUTH: HDR*, IDr1, [ CERT, ] SIG_R --> done
- * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_R --> done
- * May initiate quick mode by calling quick_outI1
- */
- { STATE_MAIN_I3, STATE_MAIN_I4
- , SMF_PSK_AUTH | SMF_INITIATOR
- | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, main_inR3 },
-
- { STATE_MAIN_I3, STATE_MAIN_I4
- , SMF_DS_AUTH | SMF_INITIATOR
- | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE)
- , EVENT_SA_REPLACE, main_inR3 },
-
- { STATE_MAIN_I3, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR
- | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
-
- /* STATE_MAIN_R3: can only get here due to packet loss */
- { STATE_MAIN_R3, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE
- , LEMPTY, LEMPTY
- , PT(NONE), EVENT_NULL, unexpected },
-
- /* STATE_MAIN_I4: can only get here due to packet loss */
- { STATE_MAIN_I4, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED
- , LEMPTY, LEMPTY
- , PT(NONE), EVENT_NULL, unexpected },
-
-
- /***** Phase 2 Quick Mode *****/
-
- /* No state for quick_outI1:
- * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ]
- */
-
- /* STATE_QUICK_R0:
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] -->
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ]
- * Installs inbound IPsec SAs.
- * Because it may suspend for asynchronous DNS, first_out_payload
- * is set to NONE to suppress early emission of HDR*.
- * ??? it is legal to have multiple SAs, but we don't support it yet.
- */
- { STATE_QUICK_R0, STATE_QUICK_R1
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
- , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(NONE)
- , EVENT_RETRANSMIT, quick_inI1_outR1 },
-
- /* STATE_QUICK_I1:
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] -->
- * HDR*, HASH(3)
- * Installs inbound and outbound IPsec SAs, routing, etc.
- * ??? it is legal to have multiple SAs, but we don't support it yet.
- */
- { STATE_QUICK_I1, STATE_QUICK_I2
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY
- , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(HASH)
- , EVENT_SA_REPLACE, quick_inR1_outI2 },
-
- /* STATE_QUICK_R1: HDR*, HASH(3) --> done
- * Installs outbound IPsec SAs, routing, etc.
- */
- { STATE_QUICK_R1, STATE_QUICK_R2
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , P(HASH), LEMPTY, PT(NONE)
- , EVENT_SA_REPLACE, quick_inI2 },
-
- /* STATE_QUICK_I2: can only happen due to lost packet */
- { STATE_QUICK_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- /* STATE_QUICK_R2: can only happen due to lost packet */
- { STATE_QUICK_R2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
-
- /***** informational messages *****/
-
- /* STATE_INFO: */
- { STATE_INFO, STATE_UNDEFINED
- , SMF_ALL_AUTH
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, informational },
-
- /* STATE_INFO_PROTECTED: */
- { STATE_INFO_PROTECTED, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , P(HASH), LEMPTY, PT(NONE)
- , EVENT_NULL, informational },
-
- /* XAUTH state transitions */
- { STATE_XAUTH_I0, STATE_XAUTH_I1
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_RETRANSMIT, xauth_inI0 },
-
- { STATE_XAUTH_R1, STATE_XAUTH_R2
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_RETRANSMIT, xauth_inR1 },
-
- { STATE_XAUTH_I1, STATE_XAUTH_I2
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, xauth_inI1 },
-
- { STATE_XAUTH_R2, STATE_XAUTH_R3
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(NONE)
- , EVENT_SA_REPLACE, xauth_inR2 },
-
- { STATE_XAUTH_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- { STATE_XAUTH_R3, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- /* ModeCfg pull mode state transitions */
-
- { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inR0 },
-
- { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inI1 },
-
- { STATE_MODE_CFG_R1, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- { STATE_MODE_CFG_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
+ /***** Phase 1 Main Mode *****/
+
+ /* No state for main_outI1: --> HDR, SA */
+
+ /* STATE_MAIN_R0: I1 --> R1
+ * HDR, SA --> HDR, SA
+ */
+ { STATE_MAIN_R0, STATE_MAIN_R1
+ , SMF_ALL_AUTH | SMF_REPLY
+ , P(SA), P(VID) | P(CR), PT(NONE)
+ , EVENT_RETRANSMIT, main_inI1_outR1},
+
+ /* STATE_MAIN_I1: R1 --> I2
+ * HDR, SA --> auth dependent
+ * SMF_PSK_AUTH, SMF_DS_AUTH: --> HDR, KE, Ni
+ * SMF_PKE_AUTH:
+ * --> HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
+ * SMF_RPKE_AUTH:
+ * --> HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
+ * Note: since we don't know auth at start, we cannot differentiate
+ * microcode entries based on it.
+ */
+ { STATE_MAIN_I1, STATE_MAIN_I2
+ , SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY
+ , P(SA), P(VID) | P(CR), PT(NONE) /* don't know yet */
+ , EVENT_RETRANSMIT, main_inR1_outI2 },
+
+ /* STATE_MAIN_R1: I2 --> R2
+ * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr
+ * SMF_PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
+ * --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ * SMF_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
+ */
+ { STATE_MAIN_R1, STATE_MAIN_R2
+ , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY
+ , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(KE)
+ , EVENT_RETRANSMIT, main_inI2_outR2 },
+
+ { STATE_MAIN_R1, STATE_UNDEFINED
+ , SMF_PKE_AUTH | SMF_REPLY
+ , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), PT(KE)
+ , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+
+ { STATE_MAIN_R1, STATE_UNDEFINED
+ , SMF_RPKE_AUTH | SMF_REPLY
+ , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), PT(NONCE)
+ , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+
+ /* for states from here on, output message must be encrypted */
+
+ /* STATE_MAIN_I2: R2 --> I3
+ * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
+ * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
+ * 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
+ */
+ { STATE_MAIN_I2, STATE_MAIN_I3
+ , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
+ , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(ID)
+ , EVENT_RETRANSMIT, main_inR2_outI3 },
+
+ { STATE_MAIN_I2, STATE_UNDEFINED
+ , SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
+ , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH)
+ , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+
+ { STATE_MAIN_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
+ , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), PT(HASH)
+ , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+
+ /* for states from here on, input message must be encrypted */
+
+ /* STATE_MAIN_R2: I3 --> R3
+ * SMF_PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
+ * SMF_DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R
+ * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R
+ */
+ { STATE_MAIN_R2, STATE_MAIN_R3
+ , SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
+ | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE)
+ , EVENT_SA_REPLACE, main_inI3_outR3 },
+
+ { STATE_MAIN_R2, STATE_MAIN_R3
+ , SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
+ | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE)
+ , EVENT_SA_REPLACE, main_inI3_outR3 },
+
+ { STATE_MAIN_R2, STATE_UNDEFINED
+ , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
+ | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(HASH), P(VID) | P(CR), PT(NONE)
+ , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
+
+ /* STATE_MAIN_I3: R3 --> done
+ * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done
+ * SMF_DS_AUTH: HDR*, IDr1, [ CERT, ] SIG_R --> done
+ * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_R --> done
+ * May initiate quick mode by calling quick_outI1
+ */
+ { STATE_MAIN_I3, STATE_MAIN_I4
+ , SMF_PSK_AUTH | SMF_INITIATOR
+ | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE)
+ , EVENT_SA_REPLACE, main_inR3 },
+
+ { STATE_MAIN_I3, STATE_MAIN_I4
+ , SMF_DS_AUTH | SMF_INITIATOR
+ | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE)
+ , EVENT_SA_REPLACE, main_inR3 },
+
+ { STATE_MAIN_I3, STATE_UNDEFINED
+ , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR
+ | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(HASH), P(VID) | P(CR), PT(NONE)
+ , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
+
+ /* STATE_MAIN_R3: can only get here due to packet loss */
+ { STATE_MAIN_R3, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE
+ , LEMPTY, LEMPTY
+ , PT(NONE), EVENT_NULL, unexpected },
+
+ /* STATE_MAIN_I4: can only get here due to packet loss */
+ { STATE_MAIN_I4, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY
+ , PT(NONE), EVENT_NULL, unexpected },
+
+
+ /***** Phase 2 Quick Mode *****/
+
+ /* No state for quick_outI1:
+ * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ]
+ */
+
+ /* STATE_QUICK_R0:
+ * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] -->
+ * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ]
+ * Installs inbound IPsec SAs.
+ * Because it may suspend for asynchronous DNS, first_out_payload
+ * is set to NONE to suppress early emission of HDR*.
+ * ??? it is legal to have multiple SAs, but we don't support it yet.
+ */
+ { STATE_QUICK_R0, STATE_QUICK_R1
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
+ , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(NONE)
+ , EVENT_RETRANSMIT, quick_inI1_outR1 },
+
+ /* STATE_QUICK_I1:
+ * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] -->
+ * HDR*, HASH(3)
+ * Installs inbound and outbound IPsec SAs, routing, etc.
+ * ??? it is legal to have multiple SAs, but we don't support it yet.
+ */
+ { STATE_QUICK_I1, STATE_QUICK_I2
+ , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY
+ , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(HASH)
+ , EVENT_SA_REPLACE, quick_inR1_outI2 },
+
+ /* STATE_QUICK_R1: HDR*, HASH(3) --> done
+ * Installs outbound IPsec SAs, routing, etc.
+ */
+ { STATE_QUICK_R1, STATE_QUICK_R2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , P(HASH), LEMPTY, PT(NONE)
+ , EVENT_SA_REPLACE, quick_inI2 },
+
+ /* STATE_QUICK_I2: can only happen due to lost packet */
+ { STATE_QUICK_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ /* STATE_QUICK_R2: can only happen due to lost packet */
+ { STATE_QUICK_R2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+
+ /***** informational messages *****/
+
+ /* STATE_INFO: */
+ { STATE_INFO, STATE_UNDEFINED
+ , SMF_ALL_AUTH
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, informational },
+
+ /* STATE_INFO_PROTECTED: */
+ { STATE_INFO_PROTECTED, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , P(HASH), LEMPTY, PT(NONE)
+ , EVENT_NULL, informational },
+
+ /* XAUTH state transitions */
+ { STATE_XAUTH_I0, STATE_XAUTH_I1
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_RETRANSMIT, xauth_inI0 },
+
+ { STATE_XAUTH_R1, STATE_XAUTH_R2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_RETRANSMIT, xauth_inR1 },
+
+ { STATE_XAUTH_I1, STATE_XAUTH_I2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, xauth_inI1 },
+
+ { STATE_XAUTH_R2, STATE_XAUTH_R3
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(NONE)
+ , EVENT_SA_REPLACE, xauth_inR2 },
+
+ { STATE_XAUTH_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ { STATE_XAUTH_R3, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ /* ModeCfg pull mode state transitions */
+
+ { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, modecfg_inR0 },
+
+ { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, modecfg_inI1 },
+
+ { STATE_MODE_CFG_R1, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ { STATE_MODE_CFG_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
/* ModeCfg push mode state transitions */
- { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inI0 },
+ { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, modecfg_inI0 },
- { STATE_MODE_CFG_R3, STATE_MODE_CFG_R4
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inR3 },
+ { STATE_MODE_CFG_R3, STATE_MODE_CFG_R4
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, modecfg_inR3 },
- { STATE_MODE_CFG_I3, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
+ { STATE_MODE_CFG_I3, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
- { STATE_MODE_CFG_R4, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
+ { STATE_MODE_CFG_R4, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
#undef P
#undef PT
@@ -518,23 +516,23 @@ static const struct state_microcode state_microcode_table[] = {
void
init_demux(void)
{
- /* fill ike_microcode_index:
- * make ike_microcode_index[s] point to first entry in
- * state_microcode_table for state s (backward scan makes this easier).
- * Check that table is in order -- catch coding errors.
- * For what it's worth, this routine is idempotent.
- */
- const struct state_microcode *t;
-
- for (t = &state_microcode_table[elemsof(state_microcode_table) - 1];;)
- {
- passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF);
- ike_microcode_index[t->state - STATE_IKE_FLOOR] = t;
- if (t == state_microcode_table)
- break;
- t--;
- passert(t[0].state <= t[1].state);
- }
+ /* fill ike_microcode_index:
+ * make ike_microcode_index[s] point to first entry in
+ * state_microcode_table for state s (backward scan makes this easier).
+ * Check that table is in order -- catch coding errors.
+ * For what it's worth, this routine is idempotent.
+ */
+ const struct state_microcode *t;
+
+ for (t = &state_microcode_table[countof(state_microcode_table) - 1];;)
+ {
+ passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF);
+ ike_microcode_index[t->state - STATE_IKE_FLOOR] = t;
+ if (t == state_microcode_table)
+ break;
+ t--;
+ passert(t[0].state <= t[1].state);
+ }
}
/* Process any message on the MSG_ERRQUEUE
@@ -586,357 +584,357 @@ init_demux(void)
static bool
check_msg_errqueue(const struct iface *ifp, short interest)
{
- struct pollfd pfd;
+ struct pollfd pfd;
- pfd.fd = ifp->fd;
- pfd.events = interest | POLLPRI | POLLOUT;
+ pfd.fd = ifp->fd;
+ pfd.events = interest | POLLPRI | POLLOUT;
- while (pfd.revents = 0
- , poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLERR))
- {
- u_int8_t buffer[3000]; /* hope that this is big enough */
- union
+ while (pfd.revents = 0
+ , poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLERR))
{
- struct sockaddr sa;
- struct sockaddr_in sa_in4;
- struct sockaddr_in6 sa_in6;
- } from;
+ u_int8_t buffer[3000]; /* hope that this is big enough */
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_in sa_in4;
+ struct sockaddr_in6 sa_in6;
+ } from;
- int from_len = sizeof(from);
+ int from_len = sizeof(from);
- int packet_len;
+ int packet_len;
- struct msghdr emh;
- struct iovec eiov;
- union {
- /* force alignment (not documented as necessary) */
- struct cmsghdr ecms;
+ struct msghdr emh;
+ struct iovec eiov;
+ union {
+ /* force alignment (not documented as necessary) */
+ struct cmsghdr ecms;
- /* how much space is enough? */
- unsigned char space[256];
- } ecms_buf;
+ /* how much space is enough? */
+ unsigned char space[256];
+ } ecms_buf;
- struct cmsghdr *cm;
- char fromstr[sizeof(" for message to port 65536") + INET6_ADDRSTRLEN];
- struct state *sender = NULL;
+ struct cmsghdr *cm;
+ char fromstr[sizeof(" for message to port 65536") + INET6_ADDRSTRLEN];
+ struct state *sender = NULL;
- zero(&from.sa);
- from_len = sizeof(from);
+ zero(&from.sa);
+ from_len = sizeof(from);
- emh.msg_name = &from.sa; /* ??? filled in? */
- emh.msg_namelen = sizeof(from);
- emh.msg_iov = &eiov;
- emh.msg_iovlen = 1;
- emh.msg_control = &ecms_buf;
- emh.msg_controllen = sizeof(ecms_buf);
- emh.msg_flags = 0;
+ emh.msg_name = &from.sa; /* ??? filled in? */
+ emh.msg_namelen = sizeof(from);
+ emh.msg_iov = &eiov;
+ emh.msg_iovlen = 1;
+ emh.msg_control = &ecms_buf;
+ emh.msg_controllen = sizeof(ecms_buf);
+ emh.msg_flags = 0;
- eiov.iov_base = buffer; /* see readv(2) */
- eiov.iov_len = sizeof(buffer);
+ eiov.iov_base = buffer; /* see readv(2) */
+ eiov.iov_len = sizeof(buffer);
- packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUE);
+ packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUE);
- if (packet_len == -1)
- {
- log_errno((e, "recvmsg(,, MSG_ERRQUEUE) on %s failed in comm_handle"
- , ifp->rname));
- break;
- }
- else if (packet_len == sizeof(buffer))
- {
- plog("MSG_ERRQUEUE message longer than %lu bytes; truncated"
- , (unsigned long) sizeof(buffer));
- }
- else
- {
- sender = find_sender((size_t) packet_len, buffer);
- }
-
- DBG_cond_dump(DBG_ALL, "rejected packet:\n", buffer, packet_len);
- DBG_cond_dump(DBG_ALL, "control:\n", emh.msg_control, emh.msg_controllen);
- /* ??? Andi Kleen <ak@suse.de> and misc documentation
- * suggests that name will have the original destination
- * of the packet. We seem to see msg_namelen == 0.
- * Andi says that this is a kernel bug and has fixed it.
- * Perhaps in 2.2.18/2.4.0.
- */
- passert(emh.msg_name == &from.sa);
- DBG_cond_dump(DBG_ALL, "name:\n", emh.msg_name
- , emh.msg_namelen);
-
- fromstr[0] = '\0'; /* usual case :-( */
- switch (from.sa.sa_family)
- {
- char as[INET6_ADDRSTRLEN];
-
- case AF_INET:
- if (emh.msg_namelen == sizeof(struct sockaddr_in))
- snprintf(fromstr, sizeof(fromstr)
- , " for message to %s port %u"
- , inet_ntop(from.sa.sa_family
- , &from.sa_in4.sin_addr, as, sizeof(as))
- , ntohs(from.sa_in4.sin_port));
- break;
- case AF_INET6:
- if (emh.msg_namelen == sizeof(struct sockaddr_in6))
- snprintf(fromstr, sizeof(fromstr)
- , " for message to %s port %u"
- , inet_ntop(from.sa.sa_family
- , &from.sa_in6.sin6_addr, as, sizeof(as))
- , ntohs(from.sa_in6.sin6_port));
- break;
- }
-
- for (cm = CMSG_FIRSTHDR(&emh)
- ; cm != NULL
- ; cm = CMSG_NXTHDR(&emh,cm))
- {
- if (cm->cmsg_level == SOL_IP
- && cm->cmsg_type == IP_RECVERR)
- {
- /* ip(7) and recvmsg(2) specify:
- * ee_origin is SO_EE_ORIGIN_ICMP for ICMP
- * or SO_EE_ORIGIN_LOCAL for locally generated errors.
- * ee_type and ee_code are from the ICMP header.
- * ee_info is the discovered MTU for EMSGSIZE errors
- * ee_data is not used.
- *
- * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but
- * means "SO_EE_OFFENDER". The OFFENDER is really
- * the router that complained. As such, the port
- * is meaningless.
- */
+ if (packet_len == -1)
+ {
+ log_errno((e, "recvmsg(,, MSG_ERRQUEUE) on %s failed in comm_handle"
+ , ifp->rname));
+ break;
+ }
+ else if (packet_len == sizeof(buffer))
+ {
+ plog("MSG_ERRQUEUE message longer than %lu bytes; truncated"
+ , (unsigned long) sizeof(buffer));
+ }
+ else
+ {
+ sender = find_sender((size_t) packet_len, buffer);
+ }
- /* ??? cmsg(3) claims that CMSG_DATA returns
- * void *, but RFC 2292 and /usr/include/bits/socket.h
- * say unsigned char *. The manual is being fixed.
+ DBG_cond_dump(DBG_ALL, "rejected packet:\n", buffer, packet_len);
+ DBG_cond_dump(DBG_ALL, "control:\n", emh.msg_control, emh.msg_controllen);
+ /* ??? Andi Kleen <ak@suse.de> and misc documentation
+ * suggests that name will have the original destination
+ * of the packet. We seem to see msg_namelen == 0.
+ * Andi says that this is a kernel bug and has fixed it.
+ * Perhaps in 2.2.18/2.4.0.
*/
- struct sock_extended_err *ee = (void *)CMSG_DATA(cm);
- const char *offstr = "unspecified";
- char offstrspace[INET6_ADDRSTRLEN];
- char orname[50];
+ passert(emh.msg_name == &from.sa);
+ DBG_cond_dump(DBG_ALL, "name:\n", emh.msg_name
+ , emh.msg_namelen);
- if (cm->cmsg_len > CMSG_LEN(sizeof(struct sock_extended_err)))
+ fromstr[0] = '\0'; /* usual case :-( */
+ switch (from.sa.sa_family)
{
- const struct sockaddr *offender = SO_EE_OFFENDER(ee);
-
- switch (offender->sa_family)
- {
- case AF_INET:
- offstr = inet_ntop(offender->sa_family
- , &((const struct sockaddr_in *)offender)->sin_addr
- , offstrspace, sizeof(offstrspace));
- break;
- case AF_INET6:
- offstr = inet_ntop(offender->sa_family
- , &((const struct sockaddr_in6 *)offender)->sin6_addr
- , offstrspace, sizeof(offstrspace));
+ char as[INET6_ADDRSTRLEN];
+
+ case AF_INET:
+ if (emh.msg_namelen == sizeof(struct sockaddr_in))
+ snprintf(fromstr, sizeof(fromstr)
+ , " for message to %s port %u"
+ , inet_ntop(from.sa.sa_family
+ , &from.sa_in4.sin_addr, as, sizeof(as))
+ , ntohs(from.sa_in4.sin_port));
break;
- default:
- offstr = "unknown";
+ case AF_INET6:
+ if (emh.msg_namelen == sizeof(struct sockaddr_in6))
+ snprintf(fromstr, sizeof(fromstr)
+ , " for message to %s port %u"
+ , inet_ntop(from.sa.sa_family
+ , &from.sa_in6.sin6_addr, as, sizeof(as))
+ , ntohs(from.sa_in6.sin6_port));
break;
- }
}
- switch (ee->ee_origin)
+ for (cm = CMSG_FIRSTHDR(&emh)
+ ; cm != NULL
+ ; cm = CMSG_NXTHDR(&emh,cm))
{
- case SO_EE_ORIGIN_NONE:
- snprintf(orname, sizeof(orname), "none");
- break;
- case SO_EE_ORIGIN_LOCAL:
- snprintf(orname, sizeof(orname), "local");
- break;
- case SO_EE_ORIGIN_ICMP:
- snprintf(orname, sizeof(orname)
- , "ICMP type %d code %d (not authenticated)"
- , ee->ee_type, ee->ee_code
- );
- break;
- case SO_EE_ORIGIN_ICMP6:
- snprintf(orname, sizeof(orname)
- , "ICMP6 type %d code %d (not authenticated)"
- , ee->ee_type, ee->ee_code
- );
- break;
- default:
- snprintf(orname, sizeof(orname), "invalid origin %lu"
- , (unsigned long) ee->ee_origin);
- break;
- }
-
- {
- struct state *old_state = cur_state;
-
- cur_state = sender;
-
- /* note dirty trick to suppress ~ at start of format
- * if we know what state to blame.
- */
- if ((packet_len == 1) && (buffer[0] = 0xff)
+ if (cm->cmsg_level == SOL_IP
+ && cm->cmsg_type == IP_RECVERR)
+ {
+ /* ip(7) and recvmsg(2) specify:
+ * ee_origin is SO_EE_ORIGIN_ICMP for ICMP
+ * or SO_EE_ORIGIN_LOCAL for locally generated errors.
+ * ee_type and ee_code are from the ICMP header.
+ * ee_info is the discovered MTU for EMSGSIZE errors
+ * ee_data is not used.
+ *
+ * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but
+ * means "SO_EE_OFFENDER". The OFFENDER is really
+ * the router that complained. As such, the port
+ * is meaningless.
+ */
+
+ /* ??? cmsg(3) claims that CMSG_DATA returns
+ * void *, but RFC 2292 and /usr/include/bits/socket.h
+ * say unsigned char *. The manual is being fixed.
+ */
+ struct sock_extended_err *ee = (void *)CMSG_DATA(cm);
+ const char *offstr = "unspecified";
+ char offstrspace[INET6_ADDRSTRLEN];
+ char orname[50];
+
+ if (cm->cmsg_len > CMSG_LEN(sizeof(struct sock_extended_err)))
+ {
+ const struct sockaddr *offender = SO_EE_OFFENDER(ee);
+
+ switch (offender->sa_family)
+ {
+ case AF_INET:
+ offstr = inet_ntop(offender->sa_family
+ , &((const struct sockaddr_in *)offender)->sin_addr
+ , offstrspace, sizeof(offstrspace));
+ break;
+ case AF_INET6:
+ offstr = inet_ntop(offender->sa_family
+ , &((const struct sockaddr_in6 *)offender)->sin6_addr
+ , offstrspace, sizeof(offstrspace));
+ break;
+ default:
+ offstr = "unknown";
+ break;
+ }
+ }
+
+ switch (ee->ee_origin)
+ {
+ case SO_EE_ORIGIN_NONE:
+ snprintf(orname, sizeof(orname), "none");
+ break;
+ case SO_EE_ORIGIN_LOCAL:
+ snprintf(orname, sizeof(orname), "local");
+ break;
+ case SO_EE_ORIGIN_ICMP:
+ snprintf(orname, sizeof(orname)
+ , "ICMP type %d code %d (not authenticated)"
+ , ee->ee_type, ee->ee_code
+ );
+ break;
+ case SO_EE_ORIGIN_ICMP6:
+ snprintf(orname, sizeof(orname)
+ , "ICMP6 type %d code %d (not authenticated)"
+ , ee->ee_type, ee->ee_code
+ );
+ break;
+ default:
+ snprintf(orname, sizeof(orname), "invalid origin %lu"
+ , (unsigned long) ee->ee_origin);
+ break;
+ }
+
+ {
+ struct state *old_state = cur_state;
+
+ cur_state = sender;
+
+ /* note dirty trick to suppress ~ at start of format
+ * if we know what state to blame.
+ */
+ if ((packet_len == 1) && (buffer[0] = 0xff)
#ifdef DEBUG
- && ((cur_debugging & DBG_NATT) == 0)
+ && ((cur_debugging & DBG_NATT) == 0)
#endif
- ) {
- /* don't log NAT-T keepalive related errors unless NATT debug is
- * enabled
- */
- }
- else
- plog((sender != NULL) + "~"
- "ERROR: asynchronous network error report on %s"
- "%s"
- ", complainant %s"
- ": %s"
- " [errno %lu, origin %s"
- /* ", pad %d, info %ld" */
- /* ", data %ld" */
- "]"
- , ifp->rname
- , fromstr
- , offstr
- , strerror(ee->ee_errno)
- , (unsigned long) ee->ee_errno
- , orname
- /* , ee->ee_pad, (unsigned long)ee->ee_info */
- /* , (unsigned long)ee->ee_data */
- );
- cur_state = old_state;
+ ) {
+ /* don't log NAT-T keepalive related errors unless NATT debug is
+ * enabled
+ */
+ }
+ else
+ plog((sender != NULL) + "~"
+ "ERROR: asynchronous network error report on %s"
+ "%s"
+ ", complainant %s"
+ ": %s"
+ " [errno %lu, origin %s"
+ /* ", pad %d, info %ld" */
+ /* ", data %ld" */
+ "]"
+ , ifp->rname
+ , fromstr
+ , offstr
+ , strerror(ee->ee_errno)
+ , (unsigned long) ee->ee_errno
+ , orname
+ /* , ee->ee_pad, (unsigned long)ee->ee_info */
+ /* , (unsigned long)ee->ee_data */
+ );
+ cur_state = old_state;
+ }
+ }
+ else
+ {
+ /* .cmsg_len is a kernel_size_t(!), but the value
+ * certainly ought to fit in an unsigned long.
+ */
+ plog("unknown cmsg: level %d, type %d, len %lu"
+ , cm->cmsg_level, cm->cmsg_type
+ , (unsigned long) cm->cmsg_len);
+ }
}
- }
- else
- {
- /* .cmsg_len is a kernel_size_t(!), but the value
- * certainly ought to fit in an unsigned long.
- */
- plog("unknown cmsg: level %d, type %d, len %lu"
- , cm->cmsg_level, cm->cmsg_type
- , (unsigned long) cm->cmsg_len);
- }
}
- }
- return (pfd.revents & interest) != 0;
+ return (pfd.revents & interest) != 0;
}
#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
bool
send_packet(struct state *st, const char *where)
{
- struct connection *c = st->st_connection;
- int port_buf;
- bool err;
- u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE];
- u_int8_t *ptr;
- unsigned long len;
-
- if (c->interface->ike_float && st->st_tpacket.len != 1)
- {
- if ((unsigned long) st->st_tpacket.len > (MAX_OUTPUT_UDP_SIZE-sizeof(u_int32_t)))
+ struct connection *c = st->st_connection;
+ int port_buf;
+ bool err;
+ u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE];
+ u_int8_t *ptr;
+ unsigned long len;
+
+ if (c->interface->ike_float && st->st_tpacket.len != 1)
{
- DBG_log("send_packet(): really too big");
- return FALSE;
+ if ((unsigned long) st->st_tpacket.len > (MAX_OUTPUT_UDP_SIZE-sizeof(u_int32_t)))
+ {
+ DBG_log("send_packet(): really too big");
+ return FALSE;
+ }
+ ptr = ike_pkt;
+ /** Add Non-ESP marker **/
+ memset(ike_pkt, 0, sizeof(u_int32_t));
+ memcpy(ike_pkt + sizeof(u_int32_t), st->st_tpacket.ptr,
+ (unsigned long)st->st_tpacket.len);
+ len = (unsigned long) st->st_tpacket.len + sizeof(u_int32_t);
}
- ptr = ike_pkt;
- /** Add Non-ESP marker **/
- memset(ike_pkt, 0, sizeof(u_int32_t));
- memcpy(ike_pkt + sizeof(u_int32_t), st->st_tpacket.ptr,
- (unsigned long)st->st_tpacket.len);
- len = (unsigned long) st->st_tpacket.len + sizeof(u_int32_t);
- }
- else
- {
- ptr = st->st_tpacket.ptr;
- len = (unsigned long) st->st_tpacket.len;
- }
-
- DBG(DBG_RAW,
+ else
{
- DBG_log("sending %lu bytes for %s through %s to %s:%u:"
- , (unsigned long) st->st_tpacket.len
- , where
- , c->interface->rname
- , ip_str(&c->spd.that.host_addr)
- , (unsigned)c->spd.that.host_port);
- DBG_dump_chunk(NULL, st->st_tpacket);
- });
-
- /* XXX: Not very clean. We manipulate the port of the ip_address to
- * have a port in the sockaddr*, but we retain the original port
- * and restore it afterwards.
- */
-
- port_buf = portof(&c->spd.that.host_addr);
- setportof(htons(c->spd.that.host_port), &c->spd.that.host_addr);
+ ptr = st->st_tpacket.ptr;
+ len = (unsigned long) st->st_tpacket.len;
+ }
+
+ DBG(DBG_RAW,
+ {
+ DBG_log("sending %lu bytes for %s through %s to %s:%u:"
+ , (unsigned long) st->st_tpacket.len
+ , where
+ , c->interface->rname
+ , ip_str(&c->spd.that.host_addr)
+ , (unsigned)c->spd.that.host_port);
+ DBG_dump_chunk(NULL, st->st_tpacket);
+ });
+
+ /* XXX: Not very clean. We manipulate the port of the ip_address to
+ * have a port in the sockaddr*, but we retain the original port
+ * and restore it afterwards.
+ */
+
+ port_buf = portof(&c->spd.that.host_addr);
+ setportof(htons(c->spd.that.host_port), &c->spd.that.host_addr);
#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
- (void) check_msg_errqueue(c->interface, POLLOUT);
+ (void) check_msg_errqueue(c->interface, POLLOUT);
#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
- err = sendto(c->interface->fd
- , ptr, len, 0
- , sockaddrof(&c->spd.that.host_addr)
- , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)len;
-
- /* restore port */
- setportof(port_buf, &c->spd.that.host_addr);
-
- if (err)
- {
- /* do not log NAT-T Keep Alive packets */
- if (streq(where, "NAT-T Keep Alive"))
- return FALSE;
- log_errno((e, "sendto on %s to %s:%u failed in %s"
- , c->interface->rname
- , ip_str(&c->spd.that.host_addr)
- , (unsigned)c->spd.that.host_port
- , where));
- return FALSE;
- }
- else
- {
- return TRUE;
- }
+ err = sendto(c->interface->fd
+ , ptr, len, 0
+ , sockaddrof(&c->spd.that.host_addr)
+ , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)len;
+
+ /* restore port */
+ setportof(port_buf, &c->spd.that.host_addr);
+
+ if (err)
+ {
+ /* do not log NAT-T Keep Alive packets */
+ if (streq(where, "NAT-T Keep Alive"))
+ return FALSE;
+ log_errno((e, "sendto on %s to %s:%u failed in %s"
+ , c->interface->rname
+ , ip_str(&c->spd.that.host_addr)
+ , (unsigned)c->spd.that.host_port
+ , where));
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
}
static stf_status
unexpected(struct msg_digest *md)
{
- loglog(RC_LOG_SERIOUS, "unexpected message received in state %s"
- , enum_name(&state_names, md->st->st_state));
- return STF_IGNORE;
+ loglog(RC_LOG_SERIOUS, "unexpected message received in state %s"
+ , enum_name(&state_names, md->st->st_state));
+ return STF_IGNORE;
}
static stf_status
informational(struct msg_digest *md UNUSED)
{
- struct payload_digest *const n_pld = md->chain[ISAKMP_NEXT_N];
-
- /* If the Notification Payload is not null... */
- if (n_pld != NULL)
- {
- pb_stream *const n_pbs = &n_pld->pbs;
- struct isakmp_notification *const n = &n_pld->payload.notification;
- int disp_len;
- char disp_buf[200];
-
- /* Switch on Notification Type (enum) */
- switch (n->isan_type)
- {
- case R_U_THERE:
- return dpd_inI_outR(md->st, n, n_pbs);
-
- case R_U_THERE_ACK:
- return dpd_inR(md->st, n, n_pbs);
- default:
- if (pbs_left(n_pbs) >= sizeof(disp_buf)-1)
- disp_len = sizeof(disp_buf)-1;
- else
- disp_len = pbs_left(n_pbs);
- memcpy(disp_buf, n_pbs->cur, disp_len);
- disp_buf[disp_len] = '\0';
- break;
- }
- }
- return STF_IGNORE;
+ struct payload_digest *const n_pld = md->chain[ISAKMP_NEXT_N];
+
+ /* If the Notification Payload is not null... */
+ if (n_pld != NULL)
+ {
+ pb_stream *const n_pbs = &n_pld->pbs;
+ struct isakmp_notification *const n = &n_pld->payload.notification;
+ int disp_len;
+ char disp_buf[200];
+
+ /* Switch on Notification Type (enum) */
+ switch (n->isan_type)
+ {
+ case R_U_THERE:
+ return dpd_inI_outR(md->st, n, n_pbs);
+
+ case R_U_THERE_ACK:
+ return dpd_inR(md->st, n, n_pbs);
+ default:
+ if (pbs_left(n_pbs) >= sizeof(disp_buf)-1)
+ disp_len = sizeof(disp_buf)-1;
+ else
+ disp_len = pbs_left(n_pbs);
+ memcpy(disp_buf, n_pbs->cur, disp_len);
+ disp_buf[disp_len] = '\0';
+ break;
+ }
+ }
+ return STF_IGNORE;
}
/* message digest allocation and deallocation */
@@ -947,54 +945,57 @@ static struct msg_digest *md_pool = NULL;
void
free_md_pool(void)
{
- for (;;)
- {
- struct msg_digest *md = md_pool;
+ for (;;)
+ {
+ struct msg_digest *md = md_pool;
- if (md == NULL)
- break;
- md_pool = md->next;
- pfree(md);
- }
+ if (md == NULL)
+ break;
+ md_pool = md->next;
+ free(md);
+ }
}
static struct msg_digest *
-alloc_md(void)
+malloc_md(void)
{
- struct msg_digest *md = md_pool;
-
- /* convenient initializer:
- * - all pointers NULL
- * - .note = NOTHING_WRONG
- * - .encrypted = FALSE
- */
- static const struct msg_digest blank_md;
-
- if (md == NULL)
- md = alloc_thing(struct msg_digest, "msg_digest");
- else
- md_pool = md->next;
-
- *md = blank_md;
- md->digest_roof = md->digest;
-
- /* note: although there may be multiple msg_digests at once
- * (due to suspended state transitions), there is a single
- * global reply_buffer. It will need to be saved and restored.
- */
- init_pbs(&md->reply, reply_buffer, sizeof(reply_buffer), "reply packet");
-
- return md;
+ struct msg_digest *md = md_pool;
+
+ /* convenient initializer:
+ * - all pointers NULL
+ * - .note = NOTHING_WRONG
+ * - .encrypted = FALSE
+ */
+ static const struct msg_digest blank_md;
+
+ if (md == NULL)
+ {
+ md = malloc_thing(struct msg_digest);
+ zero(md);
+ }
+ else
+ md_pool = md->next;
+
+ *md = blank_md;
+ md->digest_roof = md->digest;
+
+ /* note: although there may be multiple msg_digests at once
+ * (due to suspended state transitions), there is a single
+ * global reply_buffer. It will need to be saved and restored.
+ */
+ init_pbs(&md->reply, reply_buffer, sizeof(reply_buffer), "reply packet");
+
+ return md;
}
void
release_md(struct msg_digest *md)
{
- freeanychunk(md->raw_packet);
- pfreeany(md->packet_pbs.start);
- md->packet_pbs.start = NULL;
- md->next = md_pool;
- md_pool = md;
+ chunk_free(&md->raw_packet);
+ free(md->packet_pbs.start);
+ md->packet_pbs.start = NULL;
+ md->next = md_pool;
+ md_pool = md;
}
/* wrapper for read_packet and process_packet
@@ -1013,35 +1014,35 @@ release_md(struct msg_digest *md)
void
comm_handle(const struct iface *ifp)
{
- static struct msg_digest *md;
+ static struct msg_digest *md;
#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
- /* Even though select(2) says that there is a message,
- * it might only be a MSG_ERRQUEUE message. At least
- * sometimes that leads to a hanging recvfrom. To avoid
- * what appears to be a kernel bug, check_msg_errqueue
- * uses poll(2) and tells us if there is anything for us
- * to read.
- *
- * This is early enough that teardown isn't required:
- * just return on failure.
- */
- if (!check_msg_errqueue(ifp, POLLIN))
- return; /* no normal message to read */
+ /* Even though select(2) says that there is a message,
+ * it might only be a MSG_ERRQUEUE message. At least
+ * sometimes that leads to a hanging recvfrom. To avoid
+ * what appears to be a kernel bug, check_msg_errqueue
+ * uses poll(2) and tells us if there is anything for us
+ * to read.
+ *
+ * This is early enough that teardown isn't required:
+ * just return on failure.
+ */
+ if (!check_msg_errqueue(ifp, POLLIN))
+ return; /* no normal message to read */
#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
- md = alloc_md();
- md->iface = ifp;
+ md = malloc_md();
+ md->iface = ifp;
- if (read_packet(md))
- process_packet(&md);
+ if (read_packet(md))
+ process_packet(&md);
- if (md != NULL)
- release_md(md);
+ if (md != NULL)
+ release_md(md);
- cur_state = NULL;
- reset_cur_connection();
- cur_from = NULL;
+ cur_state = NULL;
+ reset_cur_connection();
+ cur_from = NULL;
}
/* read the message.
@@ -1052,177 +1053,177 @@ comm_handle(const struct iface *ifp)
static bool
read_packet(struct msg_digest *md)
{
- const struct iface *ifp = md->iface;
- int packet_len;
- u_int8_t *buffer;
- u_int8_t *buffer_nat;
- union
- {
- struct sockaddr sa;
- struct sockaddr_in sa_in4;
- struct sockaddr_in6 sa_in6;
- } from;
- int from_len = sizeof(from);
- err_t from_ugh = NULL;
- static const char undisclosed[] = "unknown source";
-
- happy(anyaddr(addrtypeof(&ifp->addr), &md->sender));
- zero(&from.sa);
- ioctl(ifp->fd, FIONREAD, &packet_len);
- buffer = alloc_bytes(packet_len, "buffer read packet");
- packet_len = recvfrom(ifp->fd, buffer, packet_len, 0
- , &from.sa, &from_len);
-
- /* First: digest the from address.
- * We presume that nothing here disturbs errno.
- */
- if (packet_len == -1
- && from_len == sizeof(from)
- && all_zero((const void *)&from.sa, sizeof(from)))
- {
- /* "from" is untouched -- not set by recvfrom */
- from_ugh = undisclosed;
- }
- else if (from_len
- < (int) (offsetof(struct sockaddr, sa_family) + sizeof(from.sa.sa_family)))
- {
- from_ugh = "truncated";
- }
- else
- {
- const struct af_info *afi = aftoinfo(from.sa.sa_family);
-
- if (afi == NULL)
+ const struct iface *ifp = md->iface;
+ int packet_len;
+ u_int8_t *buffer;
+ u_int8_t *buffer_nat;
+ union
{
- from_ugh = "unexpected Address Family";
+ struct sockaddr sa;
+ struct sockaddr_in sa_in4;
+ struct sockaddr_in6 sa_in6;
+ } from;
+ int from_len = sizeof(from);
+ err_t from_ugh = NULL;
+ static const char undisclosed[] = "unknown source";
+
+ happy(anyaddr(addrtypeof(&ifp->addr), &md->sender));
+ zero(&from.sa);
+ ioctl(ifp->fd, FIONREAD, &packet_len);
+ buffer = malloc(packet_len);
+ packet_len = recvfrom(ifp->fd, buffer, packet_len, 0
+ , &from.sa, &from_len);
+
+ /* First: digest the from address.
+ * We presume that nothing here disturbs errno.
+ */
+ if (packet_len == -1
+ && from_len == sizeof(from)
+ && all_zero((const void *)&from.sa, sizeof(from)))
+ {
+ /* "from" is untouched -- not set by recvfrom */
+ from_ugh = undisclosed;
}
- else if (from_len != (int)afi->sa_sz)
+ else if (from_len
+ < (int) (offsetof(struct sockaddr, sa_family) + sizeof(from.sa.sa_family)))
{
- from_ugh = "wrong length";
+ from_ugh = "truncated";
}
else
{
- switch (from.sa.sa_family)
- {
- case AF_INET:
- from_ugh = initaddr((void *) &from.sa_in4.sin_addr
- , sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender);
- md->sender_port = ntohs(from.sa_in4.sin_port);
- break;
- case AF_INET6:
- from_ugh = initaddr((void *) &from.sa_in6.sin6_addr
- , sizeof(from.sa_in6.sin6_addr), AF_INET6, &md->sender);
- md->sender_port = ntohs(from.sa_in6.sin6_port);
- break;
- }
+ const struct af_info *afi = aftoinfo(from.sa.sa_family);
+
+ if (afi == NULL)
+ {
+ from_ugh = "unexpected Address Family";
+ }
+ else if (from_len != (int)afi->sa_sz)
+ {
+ from_ugh = "wrong length";
+ }
+ else
+ {
+ switch (from.sa.sa_family)
+ {
+ case AF_INET:
+ from_ugh = initaddr((void *) &from.sa_in4.sin_addr
+ , sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender);
+ md->sender_port = ntohs(from.sa_in4.sin_port);
+ break;
+ case AF_INET6:
+ from_ugh = initaddr((void *) &from.sa_in6.sin6_addr
+ , sizeof(from.sa_in6.sin6_addr), AF_INET6, &md->sender);
+ md->sender_port = ntohs(from.sa_in6.sin6_port);
+ break;
+ }
+ }
}
- }
- /* now we report any actual I/O error */
- if (packet_len == -1)
- {
- if (from_ugh == undisclosed
- && errno == ECONNREFUSED)
+ /* now we report any actual I/O error */
+ if (packet_len == -1)
{
- /* Tone down scary message for vague event:
- * We get "connection refused" in response to some
- * datagram we sent, but we cannot tell which one.
- */
- plog("some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)");
+ if (from_ugh == undisclosed
+ && errno == ECONNREFUSED)
+ {
+ /* Tone down scary message for vague event:
+ * We get "connection refused" in response to some
+ * datagram we sent, but we cannot tell which one.
+ */
+ plog("some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)");
+ }
+ else if (from_ugh != NULL)
+ {
+ log_errno((e, "recvfrom on %s failed; Pluto cannot decode source sockaddr in rejection: %s"
+ , ifp->rname, from_ugh));
+ }
+ else
+ {
+ log_errno((e, "recvfrom on %s from %s:%u failed"
+ , ifp->rname
+ , ip_str(&md->sender), (unsigned)md->sender_port));
+ }
+
+ return FALSE;
}
else if (from_ugh != NULL)
{
- log_errno((e, "recvfrom on %s failed; Pluto cannot decode source sockaddr in rejection: %s"
- , ifp->rname, from_ugh));
- }
- else
- {
- log_errno((e, "recvfrom on %s from %s:%u failed"
- , ifp->rname
- , ip_str(&md->sender), (unsigned)md->sender_port));
+ plog("recvfrom on %s returned misformed source sockaddr: %s"
+ , ifp->rname, from_ugh);
+ return FALSE;
}
+ cur_from = &md->sender;
+ cur_from_port = md->sender_port;
- return FALSE;
- }
- else if (from_ugh != NULL)
- {
- plog("recvfrom on %s returned misformed source sockaddr: %s"
- , ifp->rname, from_ugh);
- return FALSE;
- }
- cur_from = &md->sender;
- cur_from_port = md->sender_port;
-
- if (ifp->ike_float == TRUE)
- {
- u_int32_t non_esp;
-
- if (packet_len < (int)sizeof(u_int32_t))
- {
- plog("recvfrom %s:%u too small packet (%d)"
- , ip_str(cur_from), (unsigned) cur_from_port, packet_len);
- return FALSE;
- }
- memcpy(&non_esp, buffer, sizeof(u_int32_t));
- if (non_esp != 0)
+ if (ifp->ike_float == TRUE)
{
- plog("recvfrom %s:%u has no Non-ESP marker"
- , ip_str(cur_from), (unsigned) cur_from_port);
- return FALSE;
+ u_int32_t non_esp;
+
+ if (packet_len < (int)sizeof(u_int32_t))
+ {
+ plog("recvfrom %s:%u too small packet (%d)"
+ , ip_str(cur_from), (unsigned) cur_from_port, packet_len);
+ return FALSE;
+ }
+ memcpy(&non_esp, buffer, sizeof(u_int32_t));
+ if (non_esp != 0)
+ {
+ plog("recvfrom %s:%u has no Non-ESP marker"
+ , ip_str(cur_from), (unsigned) cur_from_port);
+ return FALSE;
+ }
+ packet_len -= sizeof(u_int32_t);
+ buffer_nat = malloc(packet_len);
+ memcpy(buffer_nat, buffer + sizeof(u_int32_t), packet_len);
+ free(buffer);
+ buffer = buffer_nat;
}
- packet_len -= sizeof(u_int32_t);
- buffer_nat = alloc_bytes(packet_len, "buffer read packet");
- memcpy(buffer_nat, buffer + sizeof(u_int32_t), packet_len);
- pfree(buffer);
- buffer = buffer_nat;
- }
-
- /* Clone actual message contents
- * and set up md->packet_pbs to describe it.
- */
- init_pbs(&md->packet_pbs, buffer, packet_len, "packet");
-
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL,
- {
- DBG_log(BLANK_FORMAT);
- DBG_log("*received %d bytes from %s:%u on %s"
- , (int) pbs_room(&md->packet_pbs)
- , ip_str(cur_from), (unsigned) cur_from_port
- , ifp->rname);
- });
- DBG(DBG_RAW,
- DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs)));
+ /* Clone actual message contents
+ * and set up md->packet_pbs to describe it.
+ */
+ init_pbs(&md->packet_pbs, buffer, packet_len, "packet");
- if ((pbs_room(&md->packet_pbs)==1) && (md->packet_pbs.start[0]==0xff))
- {
- /**
- * NAT-T Keep-alive packets should be discarded by kernel ESPinUDP
- * layer. But bogus keep-alive packets (sent with a non-esp marker)
- * can reach this point. Complain and discard them.
- */
- DBG(DBG_NATT,
- DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. "
- "Ignored. Sender: %s:%u", ip_str(cur_from),
- (unsigned) cur_from_port);
- )
- return FALSE;
- }
+ DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL,
+ {
+ DBG_log(BLANK_FORMAT);
+ DBG_log("*received %d bytes from %s:%u on %s"
+ , (int) pbs_room(&md->packet_pbs)
+ , ip_str(cur_from), (unsigned) cur_from_port
+ , ifp->rname);
+ });
+
+ DBG(DBG_RAW,
+ DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs)));
-#define IKEV2_VERSION_OFFSET 17
-#define IKEV2_VERSION 0x20
+ if ((pbs_room(&md->packet_pbs)==1) && (md->packet_pbs.start[0]==0xff))
+ {
+ /**
+ * NAT-T Keep-alive packets should be discarded by kernel ESPinUDP
+ * layer. But bogus keep-alive packets (sent with a non-esp marker)
+ * can reach this point. Complain and discard them.
+ */
+ DBG(DBG_NATT,
+ DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. "
+ "Ignored. Sender: %s:%u", ip_str(cur_from),
+ (unsigned) cur_from_port);
+ )
+ return FALSE;
+ }
- /* ignore IKEv2 packets - they will be handled by charon */
- if (pbs_room(&md->packet_pbs) > IKEV2_VERSION_OFFSET
- && md->packet_pbs.start[IKEV2_VERSION_OFFSET] == IKEV2_VERSION)
- {
- DBG(DBG_CONTROLMORE,
- DBG_log(" ignoring IKEv2 packet")
- )
- return FALSE;
- }
+#define IKEV2_VERSION_OFFSET 17
+#define IKEV2_VERSION 0x20
+
+ /* ignore IKEv2 packets - they will be handled by charon */
+ if (pbs_room(&md->packet_pbs) > IKEV2_VERSION_OFFSET
+ && md->packet_pbs.start[IKEV2_VERSION_OFFSET] == IKEV2_VERSION)
+ {
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" ignoring IKEv2 packet")
+ )
+ return FALSE;
+ }
- return TRUE;
+ return TRUE;
}
/* process an input packet, possibly generating a reply.
@@ -1233,860 +1234,881 @@ read_packet(struct msg_digest *md)
static void
process_packet(struct msg_digest **mdp)
{
- struct msg_digest *md = *mdp;
- const struct state_microcode *smc;
- bool new_iv_set = FALSE;
- bool restore_iv = FALSE;
- u_char new_iv[MAX_DIGEST_LEN];
- u_int new_iv_len = 0;
+ struct msg_digest *md = *mdp;
+ const struct state_microcode *smc;
+ bool new_iv_set = FALSE;
+ bool restore_iv = FALSE;
+ u_char new_iv[MAX_DIGEST_LEN];
+ u_int new_iv_len = 0;
- struct state *st = NULL;
- enum state_kind from_state = STATE_UNDEFINED; /* state we started in */
+ struct state *st = NULL;
+ enum state_kind from_state = STATE_UNDEFINED; /* state we started in */
#define SEND_NOTIFICATION(t) { \
- if (st) send_notification_from_state(st, from_state, t); \
- else send_notification_from_md(md, t); }
+ if (st) send_notification_from_state(st, from_state, t); \
+ else send_notification_from_md(md, t); }
- if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs))
- {
- /* Identify specific failures:
- * - bad ISAKMP major/minor version numbers
- */
- if (md->packet_pbs.roof - md->packet_pbs.cur >= (ptrdiff_t)isakmp_hdr_desc.size)
+ if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs))
{
- struct isakmp_hdr *hdr = (struct isakmp_hdr *)md->packet_pbs.cur;
- if ((hdr->isa_version >> ISA_MAJ_SHIFT) != ISAKMP_MAJOR_VERSION)
- {
- SEND_NOTIFICATION(INVALID_MAJOR_VERSION);
- return;
- }
- else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION)
- {
- SEND_NOTIFICATION(INVALID_MINOR_VERSION);
+ /* Identify specific failures:
+ * - bad ISAKMP major/minor version numbers
+ */
+ if (md->packet_pbs.roof - md->packet_pbs.cur >= (ptrdiff_t)isakmp_hdr_desc.size)
+ {
+ struct isakmp_hdr *hdr = (struct isakmp_hdr *)md->packet_pbs.cur;
+ if ((hdr->isa_version >> ISA_MAJ_SHIFT) != ISAKMP_MAJOR_VERSION)
+ {
+ SEND_NOTIFICATION(INVALID_MAJOR_VERSION);
+ return;
+ }
+ else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION)
+ {
+ SEND_NOTIFICATION(INVALID_MINOR_VERSION);
+ return;
+ }
+ }
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
return;
- }
}
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
- }
-
- if (md->packet_pbs.roof != md->message_pbs.roof)
- {
- plog("size (%u) differs from size specified in ISAKMP HDR (%u)"
- , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length);
+
+ if (md->packet_pbs.roof != md->message_pbs.roof)
+ {
+ plog("size (%u) differs from size specified in ISAKMP HDR (%u)"
+ , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length);
#ifdef CISCO_QUIRKS
- if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16)
- plog("Cisco VPN client appends 16 surplus NULL bytes");
- else
+ if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16)
+ plog("Cisco VPN client appends 16 surplus NULL bytes");
+ else
#endif
- return;
- }
+ return;
+ }
- switch (md->hdr.isa_xchg)
- {
+ switch (md->hdr.isa_xchg)
+ {
#ifdef NOTYET
- case ISAKMP_XCHG_NONE:
- case ISAKMP_XCHG_BASE:
+ case ISAKMP_XCHG_NONE:
+ case ISAKMP_XCHG_BASE:
#endif
- case ISAKMP_XCHG_IDPROT: /* part of a Main Mode exchange */
- if (md->hdr.isa_msgid != MAINMODE_MSGID)
- {
- plog("Message ID was 0x%08lx but should be zero in Main Mode",
- (unsigned long) md->hdr.isa_msgid);
- SEND_NOTIFICATION(INVALID_MESSAGE_ID);
- return;
- }
-
- if (is_zero_cookie(md->hdr.isa_icookie))
- {
- plog("Initiator Cookie must not be zero in Main Mode message");
- SEND_NOTIFICATION(INVALID_COOKIE);
- return;
- }
+ case ISAKMP_XCHG_IDPROT: /* part of a Main Mode exchange */
+ if (md->hdr.isa_msgid != MAINMODE_MSGID)
+ {
+ plog("Message ID was 0x%08lx but should be zero in Main Mode",
+ (unsigned long) md->hdr.isa_msgid);
+ SEND_NOTIFICATION(INVALID_MESSAGE_ID);
+ return;
+ }
- if (is_zero_cookie(md->hdr.isa_rcookie))
- {
- /* initial message from initiator
- * ??? what if this is a duplicate of another message?
- */
- if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
- {
- plog("initial Main Mode message is invalid:"
- " its Encrypted Flag is on");
- SEND_NOTIFICATION(INVALID_FLAGS);
- return;
- }
+ if (is_zero_cookie(md->hdr.isa_icookie))
+ {
+ plog("Initiator Cookie must not be zero in Main Mode message");
+ SEND_NOTIFICATION(INVALID_COOKIE);
+ return;
+ }
- /* don't build a state until the message looks tasty */
- from_state = STATE_MAIN_R0;
- }
- else
- {
- /* not an initial message */
+ if (is_zero_cookie(md->hdr.isa_rcookie))
+ {
+ /* initial message from initiator
+ * ??? what if this is a duplicate of another message?
+ */
+ if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
+ {
+ plog("initial Main Mode message is invalid:"
+ " its Encrypted Flag is on");
+ SEND_NOTIFICATION(INVALID_FLAGS);
+ return;
+ }
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, md->hdr.isa_msgid);
+ /* don't build a state until the message looks tasty */
+ from_state = STATE_MAIN_R0;
+ }
+ else
+ {
+ /* not an initial message */
- if (st == NULL)
- {
- /* perhaps this is a first message from the responder
- * and contains a responder cookie that we've not yet seen.
- */
- st = find_state(md->hdr.isa_icookie, zero_cookie
- , &md->sender, md->hdr.isa_msgid);
+ st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
+ , &md->sender, md->hdr.isa_msgid);
- if (st == NULL)
- {
- plog("Main Mode message is part of an unknown exchange");
- /* XXX Could send notification back */
- return;
+ if (st == NULL)
+ {
+ /* perhaps this is a first message from the responder
+ * and contains a responder cookie that we've not yet seen.
+ */
+ st = find_state(md->hdr.isa_icookie, zero_cookie
+ , &md->sender, md->hdr.isa_msgid);
+
+ if (st == NULL)
+ {
+ plog("Main Mode message is part of an unknown exchange");
+ /* XXX Could send notification back */
+ return;
+ }
+ }
+ set_cur_state(st);
+ from_state = st->st_state;
}
- }
- set_cur_state(st);
- from_state = st->st_state;
- }
- break;
+ break;
#ifdef NOTYET
- case ISAKMP_XCHG_AO:
- case ISAKMP_XCHG_AGGR:
+ case ISAKMP_XCHG_AO:
+ case ISAKMP_XCHG_AGGR:
#endif
- case ISAKMP_XCHG_INFO: /* an informational exchange */
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, MAINMODE_MSGID);
+ case ISAKMP_XCHG_INFO: /* an informational exchange */
+ st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
+ , &md->sender, MAINMODE_MSGID);
- if (st != NULL)
- set_cur_state(st);
+ if (st != NULL)
+ set_cur_state(st);
- if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
- {
- if (st == NULL)
- {
- plog("Informational Exchange is for an unknown (expired?) SA");
- /* XXX Could send notification back */
- return;
- }
+ if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
+ {
+ if (st == NULL)
+ {
+ plog("Informational Exchange is for an unknown (expired?) SA");
+ /* XXX Could send notification back */
+ return;
+ }
- if (!IS_ISAKMP_ENCRYPTED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "encrypted Informational Exchange message is invalid"
- " because no key is known");
- /* XXX Could send notification back */
- return;
- }
+ if (!IS_ISAKMP_ENCRYPTED(st->st_state))
+ {
+ loglog(RC_LOG_SERIOUS, "encrypted Informational Exchange message is invalid"
+ " because no key is known");
+ /* XXX Could send notification back */
+ return;
+ }
- if (md->hdr.isa_msgid == MAINMODE_MSGID)
- {
- loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
- " it has a Message ID of 0");
- /* XXX Could send notification back */
- return;
- }
-
- if (!reserve_msgid(st, md->hdr.isa_msgid))
- {
- loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
- " it has a previously used Message ID (0x%08lx)"
- , (unsigned long)md->hdr.isa_msgid);
- /* XXX Could send notification back */
- return;
- }
+ if (md->hdr.isa_msgid == MAINMODE_MSGID)
+ {
+ loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
+ " it has a Message ID of 0");
+ /* XXX Could send notification back */
+ return;
+ }
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- memcpy(st->st_ph1_iv, st->st_new_iv, st->st_new_iv_len);
- st->st_ph1_iv_len = st->st_new_iv_len;
-
- /* backup new_iv */
- new_iv_len = st->st_new_iv_len;
- passert(new_iv_len <= MAX_DIGEST_LEN)
- memcpy(new_iv, st->st_new_iv, new_iv_len);
- restore_iv = TRUE;
- }
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
-
- from_state = STATE_INFO_PROTECTED;
- }
- else
- {
- if (st != NULL && IS_ISAKMP_ENCRYPTED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "Informational Exchange message"
- " must be encrypted");
- /* XXX Could send notification back */
- return;
- }
- from_state = STATE_INFO;
- }
- break;
+ if (!reserve_msgid(st, md->hdr.isa_msgid))
+ {
+ loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
+ " it has a previously used Message ID (0x%08lx)"
+ , (unsigned long)md->hdr.isa_msgid);
+ /* XXX Could send notification back */
+ return;
+ }
- case ISAKMP_XCHG_QUICK: /* part of a Quick Mode exchange */
- if (is_zero_cookie(md->hdr.isa_icookie))
- {
- plog("Quick Mode message is invalid because"
- " it has an Initiator Cookie of 0");
- SEND_NOTIFICATION(INVALID_COOKIE);
- return;
- }
+ if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ memcpy(st->st_ph1_iv, st->st_new_iv, st->st_new_iv_len);
+ st->st_ph1_iv_len = st->st_new_iv_len;
+
+ /* backup new_iv */
+ new_iv_len = st->st_new_iv_len;
+ passert(new_iv_len <= MAX_DIGEST_LEN)
+ memcpy(new_iv, st->st_new_iv, new_iv_len);
+ restore_iv = TRUE;
+ }
+ init_phase2_iv(st, &md->hdr.isa_msgid);
+ new_iv_set = TRUE;
- if (is_zero_cookie(md->hdr.isa_rcookie))
- {
- plog("Quick Mode message is invalid because"
- " it has a Responder Cookie of 0");
- SEND_NOTIFICATION(INVALID_COOKIE);
- return;
- }
+ from_state = STATE_INFO_PROTECTED;
+ }
+ else
+ {
+ if (st != NULL && IS_ISAKMP_ENCRYPTED(st->st_state))
+ {
+ loglog(RC_LOG_SERIOUS, "Informational Exchange message"
+ " must be encrypted");
+ /* XXX Could send notification back */
+ return;
+ }
+ from_state = STATE_INFO;
+ }
+ break;
- if (md->hdr.isa_msgid == MAINMODE_MSGID)
- {
- plog("Quick Mode message is invalid because"
- " it has a Message ID of 0");
- SEND_NOTIFICATION(INVALID_MESSAGE_ID);
- return;
- }
+ case ISAKMP_XCHG_QUICK: /* part of a Quick Mode exchange */
+ if (is_zero_cookie(md->hdr.isa_icookie))
+ {
+ plog("Quick Mode message is invalid because"
+ " it has an Initiator Cookie of 0");
+ SEND_NOTIFICATION(INVALID_COOKIE);
+ return;
+ }
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, md->hdr.isa_msgid);
+ if (is_zero_cookie(md->hdr.isa_rcookie))
+ {
+ plog("Quick Mode message is invalid because"
+ " it has a Responder Cookie of 0");
+ SEND_NOTIFICATION(INVALID_COOKIE);
+ return;
+ }
- if (st == NULL)
- {
- /* No appropriate Quick Mode state.
- * See if we have a Main Mode state.
- * ??? what if this is a duplicate of another message?
- */
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, MAINMODE_MSGID);
-
- if (st == NULL)
- {
- plog("Quick Mode message is for a non-existent (expired?)"
- " ISAKMP SA");
- /* XXX Could send notification back */
- return;
- }
+ if (md->hdr.isa_msgid == MAINMODE_MSGID)
+ {
+ plog("Quick Mode message is invalid because"
+ " it has a Message ID of 0");
+ SEND_NOTIFICATION(INVALID_MESSAGE_ID);
+ return;
+ }
- set_cur_state(st);
+ st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
+ , &md->sender, md->hdr.isa_msgid);
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because"
- " it is for an incomplete ISAKMP SA");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
- return;
- }
-
- /* only accept this new Quick Mode exchange if it has a unique message ID */
- if (!reserve_msgid(st, md->hdr.isa_msgid))
- {
- loglog(RC_LOG_SERIOUS, "Quick Mode I1 message is unacceptable because"
- " it uses a previously used Message ID 0x%08lx"
- " (perhaps this is a duplicated packet)"
- , (unsigned long) md->hdr.isa_msgid);
- SEND_NOTIFICATION(INVALID_MESSAGE_ID);
- return;
- }
+ if (st == NULL)
+ {
+ /* No appropriate Quick Mode state.
+ * See if we have a Main Mode state.
+ * ??? what if this is a duplicate of another message?
+ */
+ st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
+ , &md->sender, MAINMODE_MSGID);
- /* Quick Mode Initial IV */
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
+ if (st == NULL)
+ {
+ plog("Quick Mode message is for a non-existent (expired?)"
+ " ISAKMP SA");
+ /* XXX Could send notification back */
+ return;
+ }
- from_state = STATE_QUICK_R0;
- }
- else
- {
- set_cur_state(st);
- from_state = st->st_state;
- }
+ set_cur_state(st);
- break;
+ if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because"
+ " it is for an incomplete ISAKMP SA");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
+ return;
+ }
- case ISAKMP_XCHG_MODE_CFG:
- if (is_zero_cookie(md->hdr.isa_icookie))
- {
- plog("ModeCfg message is invalid because"
- " it has an Initiator Cookie of 0");
- /* XXX Could send notification back */
- return;
- }
+ /* only accept this new Quick Mode exchange if it has a unique message ID */
+ if (!reserve_msgid(st, md->hdr.isa_msgid))
+ {
+ loglog(RC_LOG_SERIOUS, "Quick Mode I1 message is unacceptable because"
+ " it uses a previously used Message ID 0x%08lx"
+ " (perhaps this is a duplicated packet)"
+ , (unsigned long) md->hdr.isa_msgid);
+ SEND_NOTIFICATION(INVALID_MESSAGE_ID);
+ return;
+ }
- if (is_zero_cookie(md->hdr.isa_rcookie))
- {
- plog("ModeCfg message is invalid because"
- " it has a Responder Cookie of 0");
- /* XXX Could send notification back */
- return;
- }
+ /* Quick Mode Initial IV */
+ init_phase2_iv(st, &md->hdr.isa_msgid);
+ new_iv_set = TRUE;
- if (md->hdr.isa_msgid == 0)
- {
- plog("ModeCfg message is invalid because"
- " it has a Message ID of 0");
- /* XXX Could send notification back */
- return;
- }
+ from_state = STATE_QUICK_R0;
+ }
+ else
+ {
+ set_cur_state(st);
+ from_state = st->st_state;
+ }
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, md->hdr.isa_msgid);
+ break;
- if (st == NULL)
- {
- bool has_xauth_policy;
-
- /* No appropriate ModeCfg state.
- * See if we have a Main Mode state.
- * ??? what if this is a duplicate of another message?
- */
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, 0);
-
- if (st == NULL)
- {
- plog("ModeCfg message is for a non-existent (expired?)"
- " ISAKMP SA");
- /* XXX Could send notification back */
- return;
- }
+ case ISAKMP_XCHG_MODE_CFG:
+ if (is_zero_cookie(md->hdr.isa_icookie))
+ {
+ plog("ModeCfg message is invalid because"
+ " it has an Initiator Cookie of 0");
+ /* XXX Could send notification back */
+ return;
+ }
+
+ if (is_zero_cookie(md->hdr.isa_rcookie))
+ {
+ plog("ModeCfg message is invalid because"
+ " it has a Responder Cookie of 0");
+ /* XXX Could send notification back */
+ return;
+ }
+
+ if (md->hdr.isa_msgid == 0)
+ {
+ plog("ModeCfg message is invalid because"
+ " it has a Message ID of 0");
+ /* XXX Could send notification back */
+ return;
+ }
- set_cur_state(st);
+ st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
+ , &md->sender, md->hdr.isa_msgid);
- /* the XAUTH_STATUS message might have a new msgid */
- if (st->st_state == STATE_XAUTH_I1)
- {
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
- from_state = st->st_state;
+ if (st == NULL)
+ {
+ bool has_xauth_policy;
+
+ /* No appropriate ModeCfg state.
+ * See if we have a Main Mode state.
+ * ??? what if this is a duplicate of another message?
+ */
+ st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
+ , &md->sender, 0);
+
+ if (st == NULL)
+ {
+ plog("ModeCfg message is for a non-existent (expired?)"
+ " ISAKMP SA");
+ /* XXX Could send notification back */
+ return;
+ }
+
+ set_cur_state(st);
+
+ /* the XAUTH_STATUS message might have a new msgid */
+ if (st->st_state == STATE_XAUTH_I1)
+ {
+ init_phase2_iv(st, &md->hdr.isa_msgid);
+ new_iv_set = TRUE;
+ from_state = st->st_state;
+ break;
+ }
+
+ if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because"
+ " it is for an incomplete ISAKMP SA (state=%s)"
+ , enum_name(&state_names, st->st_state));
+ /* XXX Could send notification back */
+ return;
+ }
+ init_phase2_iv(st, &md->hdr.isa_msgid);
+ new_iv_set = TRUE;
+
+ /*
+ * okay, now we have to figure out if we are receiving a bogus
+ * new message in an oustanding XAUTH server conversation
+ * (i.e. a reply to our challenge)
+ * (this occurs with some broken other implementations).
+ *
+ * or if receiving for the first time, an XAUTH challenge.
+ *
+ * or if we are getting a MODECFG request.
+ *
+ * we distinguish these states because we can not both be an
+ * XAUTH server and client, and our policy tells us which
+ * one we are.
+ *
+ * to complicate further, it is normal to start a new msgid
+ * when going from one state to another, or when restarting
+ * the challenge.
+ *
+ */
+
+ has_xauth_policy = (st->st_connection->policy
+ & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
+ != LEMPTY;
+
+ if (has_xauth_policy && !st->st_xauth.started
+ && IS_PHASE1(st->st_state))
+ {
+ from_state = STATE_XAUTH_I0;
+ }
+ else if (st->st_connection->spd.that.modecfg
+ && IS_PHASE1(st->st_state))
+ {
+ from_state = STATE_MODE_CFG_R0;
+ }
+ else if (st->st_connection->spd.this.modecfg
+ && IS_PHASE1(st->st_state))
+ {
+ from_state = STATE_MODE_CFG_I0;
+ }
+ else
+ {
+ /* XXX check if we are being a mode config server here */
+ plog("received ModeCfg message when in state %s, and we aren't mode config client"
+ , enum_name(&state_names, st->st_state));
+ return;
+ }
+ }
+ else
+ {
+ set_cur_state(st);
+ from_state = st->st_state;
+ }
break;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because"
- " it is for an incomplete ISAKMP SA (state=%s)"
- , enum_name(&state_names, st->st_state));
- /* XXX Could send notification back */
- return;
- }
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
-
- /*
- * okay, now we have to figure out if we are receiving a bogus
- * new message in an oustanding XAUTH server conversation
- * (i.e. a reply to our challenge)
- * (this occurs with some broken other implementations).
- *
- * or if receiving for the first time, an XAUTH challenge.
- *
- * or if we are getting a MODECFG request.
- *
- * we distinguish these states because we can not both be an
- * XAUTH server and client, and our policy tells us which
- * one we are.
- *
- * to complicate further, it is normal to start a new msgid
- * when going from one state to another, or when restarting
- * the challenge.
- *
- */
-
- has_xauth_policy = (st->st_connection->policy
- & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
- != LEMPTY;
-
- if (has_xauth_policy && !st->st_xauth.started
- && IS_PHASE1(st->st_state))
- {
- from_state = STATE_XAUTH_I0;
- }
- else if (st->st_connection->spd.that.modecfg
- && IS_PHASE1(st->st_state))
- {
- from_state = STATE_MODE_CFG_R0;
- }
- else if (st->st_connection->spd.this.modecfg
- && IS_PHASE1(st->st_state))
- {
- from_state = STATE_MODE_CFG_I0;
- }
- else
- {
- /* XXX check if we are being a mode config server here */
- plog("received ModeCfg message when in state %s, and we aren't mode config client"
- , enum_name(&state_names, st->st_state));
- return;
- }
- }
- else
- {
- set_cur_state(st);
- from_state = st->st_state;
- }
- break;
#ifdef NOTYET
- case ISAKMP_XCHG_NGRP:
- case ISAKMP_XCHG_ACK_INFO:
+ case ISAKMP_XCHG_NGRP:
+ case ISAKMP_XCHG_ACK_INFO:
#endif
- default:
- plog("unsupported exchange type %s in message"
- , enum_show(&exchange_names, md->hdr.isa_xchg));
- SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE);
- return;
- }
-
- /* We have found a from_state, and perhaps a state object.
- * If we need to build a new state object,
- * we wait until the packet has been sanity checked.
- */
-
- /* We don't support the Commit Flag. It is such a bad feature.
- * It isn't protected -- neither encrypted nor authenticated.
- * A man in the middle turns it on, leading to DoS.
- * We just ignore it, with a warning.
- * By placing the check here, we could easily add a policy bit
- * to a connection to suppress the warning. This might be useful
- * because the Commit Flag is expected from some peers.
- */
- if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT)
- {
- plog("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag");
- }
-
- /* Set smc to describe this state's properties.
- * Look up the appropriate microcode based on state and
- * possibly Oakley Auth type.
- */
- passert(STATE_IKE_FLOOR <= from_state && from_state <= STATE_IKE_ROOF);
- smc = ike_microcode_index[from_state - STATE_IKE_FLOOR];
-
- if (st != NULL)
- {
- u_int16_t auth;
-
- switch (st->st_oakley.auth)
- {
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- auth = OAKLEY_PRESHARED_KEY;
- break;
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- auth = OAKLEY_RSA_SIG;
- break;
default:
- auth = st->st_oakley.auth;
+ plog("unsupported exchange type %s in message"
+ , enum_show(&exchange_names, md->hdr.isa_xchg));
+ SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE);
+ return;
}
-
- while (!LHAS(smc->flags, auth))
+
+ /* We have found a from_state, and perhaps a state object.
+ * If we need to build a new state object,
+ * we wait until the packet has been sanity checked.
+ */
+
+ /* We don't support the Commit Flag. It is such a bad feature.
+ * It isn't protected -- neither encrypted nor authenticated.
+ * A man in the middle turns it on, leading to DoS.
+ * We just ignore it, with a warning.
+ * By placing the check here, we could easily add a policy bit
+ * to a connection to suppress the warning. This might be useful
+ * because the Commit Flag is expected from some peers.
+ */
+ if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT)
{
- smc++;
- passert(smc->state == from_state);
+ plog("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag");
}
- }
-
- /* Ignore a packet if the state has a suspended state transition
- * Probably a duplicated packet but the original packet is not yet
- * recorded in st->st_rpacket, so duplicate checking won't catch.
- * ??? Should the packet be recorded earlier to improve diagnosis?
- */
- if (st != NULL && st->st_suspended_md != NULL)
- {
- loglog(RC_LOG, "discarding packet received during DNS lookup in %s"
- , enum_name(&state_names, st->st_state));
- return;
- }
-
- /* Detect and handle duplicated packets.
- * This won't work for the initial packet of an exchange
- * because we won't have a state object to remember it.
- * If we are in a non-receiving state (terminal), and the preceding
- * state did transmit, then the duplicate may indicate that that
- * transmission wasn't received -- retransmit it.
- * Otherwise, just discard it.
- * ??? Notification packets are like exchanges -- I hope that
- * they are idempotent!
- */
- if (st != NULL
- && st->st_rpacket.ptr != NULL
- && st->st_rpacket.len == pbs_room(&md->packet_pbs)
- && memcmp(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len) == 0)
- {
- if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE)
+
+ /* Set smc to describe this state's properties.
+ * Look up the appropriate microcode based on state and
+ * possibly Oakley Auth type.
+ */
+ passert(STATE_IKE_FLOOR <= from_state && from_state <= STATE_IKE_ROOF);
+ smc = ike_microcode_index[from_state - STATE_IKE_FLOOR];
+
+ if (st != NULL)
{
- if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
- {
- st->st_retransmit++;
- loglog(RC_RETRANSMISSION
- , "retransmitting in response to duplicate packet; already %s"
- , enum_name(&state_names, st->st_state));
- send_packet(st, "retransmit in response to duplicate");
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s"
- , enum_name(&state_names, st->st_state));
- }
+ u_int16_t auth;
+
+ switch (st->st_oakley.auth)
+ {
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth = OAKLEY_PRESHARED_KEY;
+ break;
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth = OAKLEY_RSA_SIG;
+ break;
+ default:
+ auth = st->st_oakley.auth;
+ }
+
+ while (!LHAS(smc->flags, auth))
+ {
+ smc++;
+ passert(smc->state == from_state);
+ }
}
- else
+
+ /* Ignore a packet if the state has a suspended state transition
+ * Probably a duplicated packet but the original packet is not yet
+ * recorded in st->st_rpacket, so duplicate checking won't catch.
+ * ??? Should the packet be recorded earlier to improve diagnosis?
+ */
+ if (st != NULL && st->st_suspended_md != NULL)
{
- loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s"
- , enum_name(&state_names, st->st_state));
+ loglog(RC_LOG, "discarding packet received during DNS lookup in %s"
+ , enum_name(&state_names, st->st_state));
+ return;
}
- return;
- }
-
- if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
- {
- DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u"
- , ip_str(&md->sender), (unsigned)md->sender_port));
- if (st == NULL)
+ /* Detect and handle duplicated packets.
+ * This won't work for the initial packet of an exchange
+ * because we won't have a state object to remember it.
+ * If we are in a non-receiving state (terminal), and the preceding
+ * state did transmit, then the duplicate may indicate that that
+ * transmission wasn't received -- retransmit it.
+ * Otherwise, just discard it.
+ * ??? Notification packets are like exchanges -- I hope that
+ * they are idempotent!
+ */
+ if (st != NULL
+ && st->st_rpacket.ptr != NULL
+ && st->st_rpacket.len == pbs_room(&md->packet_pbs)
+ && memeq(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len))
{
- plog("discarding encrypted message for an unknown ISAKMP SA");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
- return;
+ if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE)
+ {
+ if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
+ {
+ st->st_retransmit++;
+ loglog(RC_RETRANSMISSION
+ , "retransmitting in response to duplicate packet; already %s"
+ , enum_name(&state_names, st->st_state));
+ send_packet(st, "retransmit in response to duplicate");
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s"
+ , enum_name(&state_names, st->st_state));
+ }
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s"
+ , enum_name(&state_names, st->st_state));
+ }
+ return;
}
- if (st->st_skeyid_e.ptr == (u_char *) NULL)
+
+ if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
{
- loglog(RC_LOG_SERIOUS, "discarding encrypted message"
- " because we haven't yet negotiated keying materiel");
- SEND_NOTIFICATION(INVALID_FLAGS);
- return;
- }
+ DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u"
+ , ip_str(&md->sender), (unsigned)md->sender_port));
- /* Mark as encrypted */
- md->encrypted = TRUE;
+ if (st == NULL)
+ {
+ plog("discarding encrypted message for an unknown ISAKMP SA");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
+ return;
+ }
+ if (st->st_skeyid_e.ptr == (u_char *) NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "discarding encrypted message"
+ " because we haven't yet negotiated keying materiel");
+ SEND_NOTIFICATION(INVALID_FLAGS);
+ return;
+ }
- DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s"
- , (unsigned) pbs_left(&md->message_pbs)
- , enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
+ /* Mark as encrypted */
+ md->encrypted = TRUE;
- /* do the specified decryption
- *
- * IV is from st->st_iv or (if new_iv_set) st->st_new_iv.
- * The new IV is placed in st->st_new_iv
- *
- * See RFC 2409 "IKE" Appendix B
- *
- * XXX The IV should only be updated really if the packet
- * is successfully processed.
- * We should keep this value, check for a success return
- * value from the parsing routines and then replace.
- *
- * Each post phase 1 exchange generates IVs from
- * the last phase 1 block, not the last block sent.
- */
- {
- const struct encrypt_desc *e = st->st_oakley.encrypter;
+ DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s"
+ , (unsigned) pbs_left(&md->message_pbs)
+ , enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
- if (pbs_left(&md->message_pbs) % e->enc_blocksize != 0)
- {
- loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
- }
-
- /* XXX Detect weak keys */
-
- /* grab a copy of raw packet (for duplicate packet detection) */
- clonetochunk(md->raw_packet, md->packet_pbs.start
- , pbs_room(&md->packet_pbs), "raw packet");
-
- /* Decrypt everything after header */
- if (!new_iv_set)
- {
- /* use old IV */
- passert(st->st_iv_len <= sizeof(st->st_new_iv));
- st->st_new_iv_len = st->st_iv_len;
- memcpy(st->st_new_iv, st->st_iv, st->st_new_iv_len);
- }
- crypto_cbc_encrypt(e, FALSE, md->message_pbs.cur,
- pbs_left(&md->message_pbs) , st);
- if (restore_iv)
- {
- memcpy(st->st_new_iv, new_iv, new_iv_len);
- st->st_new_iv_len = new_iv_len;
- }
- }
+ /* do the specified decryption
+ *
+ * IV is from st->st_iv or (if new_iv_set) st->st_new_iv.
+ * The new IV is placed in st->st_new_iv
+ *
+ * See RFC 2409 "IKE" Appendix B
+ *
+ * XXX The IV should only be updated really if the packet
+ * is successfully processed.
+ * We should keep this value, check for a success return
+ * value from the parsing routines and then replace.
+ *
+ * Each post phase 1 exchange generates IVs from
+ * the last phase 1 block, not the last block sent.
+ */
+ {
+ size_t crypter_block_size;
+ encryption_algorithm_t enc_alg;
+ crypter_t *crypter;
+ chunk_t data, iv;
+ char *new_iv;
+
+ enc_alg = oakley_to_encryption_algorithm(st->st_oakley.encrypt);
+ crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, st->st_enc_key.len);
+ crypter_block_size = crypter->get_block_size(crypter);
+
+ if (pbs_left(&md->message_pbs) % crypter_block_size != 0)
+ {
+ loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
- DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur
- , md->message_pbs.roof - md->message_pbs.cur);
+ /* XXX Detect weak keys */
- DBG_cond_dump(DBG_CRYPT, "next IV:"
- , st->st_new_iv, st->st_new_iv_len);
- }
- else
- {
- /* packet was not encryped -- should it have been? */
+ /* grab a copy of raw packet (for duplicate packet detection) */
+ md->raw_packet = chunk_create(md->packet_pbs.start, pbs_room(&md->packet_pbs));
+ md->raw_packet = chunk_clone(md->raw_packet);
- if (smc->flags & SMF_INPUT_ENCRYPTED)
- {
- loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted");
- SEND_NOTIFICATION(INVALID_FLAGS);
- return;
+ data = chunk_create(md->message_pbs.cur, pbs_left(&md->message_pbs));
+
+ /* Decrypt everything after header */
+ if (!new_iv_set)
+ {
+ /* use old IV */
+ passert(st->st_iv_len <= sizeof(st->st_new_iv));
+ st->st_new_iv_len = st->st_iv_len;
+ memcpy(st->st_new_iv, st->st_iv, st->st_new_iv_len);
+ }
+
+ /* form iv by truncation */
+ st->st_new_iv_len = crypter_block_size;
+ iv = chunk_create(st->st_new_iv, st->st_new_iv_len);
+ new_iv = alloca(crypter_block_size);
+ memcpy(new_iv, data.ptr + data.len - crypter_block_size,
+ crypter_block_size);
+
+ crypter->set_key(crypter, st->st_enc_key);
+ crypter->decrypt(crypter, data, iv, NULL);
+ crypter->destroy(crypter);
+
+ memcpy(st->st_new_iv, new_iv, crypter_block_size);
+ if (restore_iv)
+ {
+ memcpy(st->st_new_iv, new_iv, new_iv_len);
+ st->st_new_iv_len = new_iv_len;
+ }
+ }
+
+ DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur
+ , md->message_pbs.roof - md->message_pbs.cur);
+
+ DBG_cond_dump(DBG_CRYPT, "next IV:"
+ , st->st_new_iv, st->st_new_iv_len);
}
- }
-
- /* Digest the message.
- * Padding must be removed to make hashing work.
- * Padding comes from encryption (so this code must be after decryption).
- * Padding rules are described before the definition of
- * struct isakmp_hdr in packet.h.
- */
- {
- struct payload_digest *pd = md->digest;
- int np = md->hdr.isa_np;
- lset_t needed = smc->req_payloads;
- const char *excuse
- = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags)
- ? "probable authentication failure (mismatch of preshared secrets?): "
- : "";
-
- while (np != ISAKMP_NEXT_NONE)
+ else
{
- struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;
+ /* packet was not encryped -- should it have been? */
- if (pd == &md->digest[PAYLIMIT])
- {
- loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
- }
-
- switch (np)
- {
- case ISAKMP_NEXT_NATD_RFC:
- case ISAKMP_NEXT_NATOA_RFC:
- if (!st || !(st->nat_traversal & NAT_T_WITH_RFC_VALUES))
- {
- /*
- * don't accept NAT-D/NAT-OA reloc directly in message, unless
- * we're using NAT-T RFC
- */
- sd = NULL;
- }
- break;
- }
-
- if (sd == NULL)
- {
- /* payload type is out of range or requires special handling */
- switch (np)
+ if (smc->flags & SMF_INPUT_ENCRYPTED)
{
- case ISAKMP_NEXT_ID:
- sd = IS_PHASE1(from_state)
- ? &isakmp_identification_desc : &isakmp_ipsec_identification_desc;
- break;
- case ISAKMP_NEXT_NATD_DRAFTS:
- np = ISAKMP_NEXT_NATD_RFC; /* NAT-D relocated */
- sd = payload_descs[np];
- break;
- case ISAKMP_NEXT_NATOA_DRAFTS:
- np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA relocated */
- sd = payload_descs[np];
- break;
- default:
- loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or"
- " unexpected payload type (%s) at the outermost level"
- , excuse, enum_show(&payload_names, np));
- SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
- return;
+ loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted");
+ SEND_NOTIFICATION(INVALID_FLAGS);
+ return;
}
- }
-
- {
- lset_t s = LELEM(np);
+ }
- if (LDISJOINT(s
- , needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D)))
+ /* Digest the message.
+ * Padding must be removed to make hashing work.
+ * Padding comes from encryption (so this code must be after decryption).
+ * Padding rules are described before the definition of
+ * struct isakmp_hdr in packet.h.
+ */
+ {
+ struct payload_digest *pd = md->digest;
+ int np = md->hdr.isa_np;
+ lset_t needed = smc->req_payloads;
+ const char *excuse
+ = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags)
+ ? "probable authentication failure (mismatch of preshared secrets?): "
+ : "";
+
+ while (np != ISAKMP_NEXT_NONE)
{
- loglog(RC_LOG_SERIOUS, "%smessage ignored because it "
- "contains an unexpected payload type (%s)"
- , excuse, enum_show(&payload_names, np));
- SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
- return;
+ struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;
+
+ if (pd == &md->digest[PAYLIMIT])
+ {
+ loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
+
+ switch (np)
+ {
+ case ISAKMP_NEXT_NATD_RFC:
+ case ISAKMP_NEXT_NATOA_RFC:
+ if (!st || !(st->nat_traversal & NAT_T_WITH_RFC_VALUES))
+ {
+ /*
+ * don't accept NAT-D/NAT-OA reloc directly in message, unless
+ * we're using NAT-T RFC
+ */
+ sd = NULL;
+ }
+ break;
+ }
+
+ if (sd == NULL)
+ {
+ /* payload type is out of range or requires special handling */
+ switch (np)
+ {
+ case ISAKMP_NEXT_ID:
+ sd = IS_PHASE1(from_state)
+ ? &isakmp_identification_desc : &isakmp_ipsec_identification_desc;
+ break;
+ case ISAKMP_NEXT_NATD_DRAFTS:
+ np = ISAKMP_NEXT_NATD_RFC; /* NAT-D relocated */
+ sd = payload_descs[np];
+ break;
+ case ISAKMP_NEXT_NATOA_DRAFTS:
+ np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA relocated */
+ sd = payload_descs[np];
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or"
+ " unexpected payload type (%s) at the outermost level"
+ , excuse, enum_show(&payload_names, np));
+ SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
+ return;
+ }
+ }
+
+ {
+ lset_t s = LELEM(np);
+
+ if (LDISJOINT(s
+ , needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D)))
+ {
+ loglog(RC_LOG_SERIOUS, "%smessage ignored because it "
+ "contains an unexpected payload type (%s)"
+ , excuse, enum_show(&payload_names, np));
+ SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
+ return;
+ }
+ needed &= ~s;
+ }
+
+ if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs))
+ {
+ loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
+ if (md->hdr.isa_xchg != ISAKMP_XCHG_INFO)
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
+
+ /* place this payload at the end of the chain for this type */
+ {
+ struct payload_digest **p;
+
+ for (p = &md->chain[np]; *p != NULL; p = &(*p)->next)
+ ;
+ *p = pd;
+ pd->next = NULL;
+ }
+
+ np = pd->payload.generic.isag_np;
+ pd++;
+
+ /* since we've digested one payload happily, it is probably
+ * the case that any decryption worked. So we will not suggest
+ * encryption failure as an excuse for subsequent payload
+ * problems.
+ */
+ excuse = "";
}
- needed &= ~s;
- }
-
- if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs))
- {
- loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
- if (md->hdr.isa_xchg != ISAKMP_XCHG_INFO)
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
- }
-
- /* place this payload at the end of the chain for this type */
- {
- struct payload_digest **p;
-
- for (p = &md->chain[np]; *p != NULL; p = &(*p)->next)
- ;
- *p = pd;
- pd->next = NULL;
- }
-
- np = pd->payload.generic.isag_np;
- pd++;
-
- /* since we've digested one payload happily, it is probably
- * the case that any decryption worked. So we will not suggest
- * encryption failure as an excuse for subsequent payload
- * problems.
- */
- excuse = "";
- }
- md->digest_roof = pd;
+ md->digest_roof = pd;
- DBG(DBG_PARSING,
- if (pbs_left(&md->message_pbs) != 0)
- DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs)));
+ DBG(DBG_PARSING,
+ if (pbs_left(&md->message_pbs) != 0)
+ DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs)));
- md->message_pbs.roof = md->message_pbs.cur;
+ md->message_pbs.roof = md->message_pbs.cur;
- /* check that all mandatory payloads appeared */
+ /* check that all mandatory payloads appeared */
- if (needed != 0)
- {
- loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s"
- , enum_show(&state_names, from_state)
- , bitnamesof(payload_name, needed));
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
+ if (needed != 0)
+ {
+ loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s"
+ , enum_show(&state_names, from_state)
+ , bitnamesof(payload_name, needed));
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
}
- }
- /* more sanity checking: enforce most ordering constraints */
+ /* more sanity checking: enforce most ordering constraints */
- if (IS_PHASE1(from_state))
- {
- /* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges:
- * "The SA payload MUST precede all other payloads in a phase 1 exchange."
- */
- if (md->chain[ISAKMP_NEXT_SA] != NULL
- && md->hdr.isa_np != ISAKMP_NEXT_SA)
+ if (IS_PHASE1(from_state))
{
- loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
+ /* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges:
+ * "The SA payload MUST precede all other payloads in a phase 1 exchange."
+ */
+ if (md->chain[ISAKMP_NEXT_SA] != NULL
+ && md->hdr.isa_np != ISAKMP_NEXT_SA)
+ {
+ loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
}
- }
- else if (IS_QUICK(from_state))
- {
- /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode
- *
- * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP
- * header and a SA payload MUST immediately follow the HASH."
- * [NOTE: there may be more than one SA payload, so this is not
- * totally reasonable. Probably all SAs should be so constrained.]
- *
- * "If ISAKMP is acting as a client negotiator on behalf of another
- * party, the identities of the parties MUST be passed as IDci and
- * then IDcr."
- *
- * "With the exception of the HASH, SA, and the optional ID payloads,
- * there are no payload ordering restrictions on Quick Mode."
- */
-
- if (md->hdr.isa_np != ISAKMP_NEXT_HASH)
+ else if (IS_QUICK(from_state))
{
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
- }
+ /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode
+ *
+ * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP
+ * header and a SA payload MUST immediately follow the HASH."
+ * [NOTE: there may be more than one SA payload, so this is not
+ * totally reasonable. Probably all SAs should be so constrained.]
+ *
+ * "If ISAKMP is acting as a client negotiator on behalf of another
+ * party, the identities of the parties MUST be passed as IDci and
+ * then IDcr."
+ *
+ * "With the exception of the HASH, SA, and the optional ID payloads,
+ * there are no payload ordering restrictions on Quick Mode."
+ */
- {
- struct payload_digest *p;
- int i;
+ if (md->hdr.isa_np != ISAKMP_NEXT_HASH)
+ {
+ loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
- for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL
- ; p = p->next, i++)
- {
- if (p != &md->digest[i])
{
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
+ struct payload_digest *p;
+ int i;
+
+ for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL
+ ; p = p->next, i++)
+ {
+ if (p != &md->digest[i])
+ {
+ loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
+ }
+ }
+
+ /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode:
+ * "If ISAKMP is acting as a client negotiator on behalf of another
+ * party, the identities of the parties MUST be passed as IDci and
+ * then IDcr."
+ */
+ {
+ struct payload_digest *id = md->chain[ISAKMP_NEXT_ID];
+
+ if (id != NULL)
+ {
+ if (id->next == NULL || id->next->next != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
+ " if any ID payload is present,"
+ " there must be exactly two");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
+ if (id+1 != id->next)
+ {
+ loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
+ " the ID payloads are not adjacent");
+ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ return;
+ }
+ }
}
- }
}
- /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode:
- * "If ISAKMP is acting as a client negotiator on behalf of another
- * party, the identities of the parties MUST be passed as IDci and
- * then IDcr."
+ /* Ignore payloads that we don't handle:
+ * Delete, Notification, VendorID
*/
+ /* XXX Handle deletions */
+ /* XXX Handle Notifications */
+ /* XXX Handle VID payloads */
{
- struct payload_digest *id = md->chain[ISAKMP_NEXT_ID];
+ struct payload_digest *p;
- if (id != NULL)
- {
- if (id->next == NULL || id->next->next != NULL)
+ for (p = md->chain[ISAKMP_NEXT_N]; p != NULL; p = p->next)
{
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
- " if any ID payload is present,"
- " there must be exactly two");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
+ if (p->payload.notification.isan_type != R_U_THERE
+ && p->payload.notification.isan_type != R_U_THERE_ACK)
+ {
+ loglog(RC_LOG_SERIOUS, "ignoring informational payload, type %s"
+ , enum_show(&notification_names, p->payload.notification.isan_type));
+ }
+ DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs));
}
- if (id+1 != id->next)
+
+ for (p = md->chain[ISAKMP_NEXT_D]; p != NULL; p = p->next)
{
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
- " the ID payloads are not adjacent");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
- return;
+ accept_delete(st, md, p);
+ DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs));
}
- }
- }
- }
-
- /* Ignore payloads that we don't handle:
- * Delete, Notification, VendorID
- */
- /* XXX Handle deletions */
- /* XXX Handle Notifications */
- /* XXX Handle VID payloads */
- {
- struct payload_digest *p;
-
- for (p = md->chain[ISAKMP_NEXT_N]; p != NULL; p = p->next)
- {
- if (p->payload.notification.isan_type != R_U_THERE
- && p->payload.notification.isan_type != R_U_THERE_ACK)
- {
- loglog(RC_LOG_SERIOUS, "ignoring informational payload, type %s"
- , enum_show(&notification_names, p->payload.notification.isan_type));
- }
- DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs));
- }
-
- for (p = md->chain[ISAKMP_NEXT_D]; p != NULL; p = p->next)
- {
- accept_delete(st, md, p);
- DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs));
- }
- for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next)
- {
- handle_vendorid(md, p->pbs.cur, pbs_left(&p->pbs));
+ for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next)
+ {
+ handle_vendorid(md, p->pbs.cur, pbs_left(&p->pbs));
+ }
}
- }
- md->from_state = from_state;
- md->smc = smc;
- md->st = st;
+ md->from_state = from_state;
+ md->smc = smc;
+ md->st = st;
- /* possibly fill in hdr */
- if (smc->first_out_payload != ISAKMP_NEXT_NONE)
- echo_hdr(md, (smc->flags & SMF_OUTPUT_ENCRYPTED) != 0
- , smc->first_out_payload);
+ /* possibly fill in hdr */
+ if (smc->first_out_payload != ISAKMP_NEXT_NONE)
+ echo_hdr(md, (smc->flags & SMF_OUTPUT_ENCRYPTED) != 0
+ , smc->first_out_payload);
- complete_state_transition(mdp, smc->processor(md));
+ complete_state_transition(mdp, smc->processor(md));
}
/* complete job started by the state-specific state transition function */
@@ -2094,406 +2116,406 @@ process_packet(struct msg_digest **mdp)
void
complete_state_transition(struct msg_digest **mdp, stf_status result)
{
- bool has_xauth_policy;
- bool is_xauth_server;
- struct msg_digest *md = *mdp;
- const struct state_microcode *smc = md->smc;
- enum state_kind from_state = md->from_state;
- struct state *st;
-
- cur_state = st = md->st; /* might have changed */
-
- /* If state has DPD support, import it */
- if (st && md->dpd)
- st->st_dpd = TRUE;
-
- switch (result)
- {
- case STF_IGNORE:
- break;
-
- case STF_SUSPEND:
- /* the stf didn't complete its job: don't relase md */
- *mdp = NULL;
- break;
-
- case STF_OK:
- /* advance the state */
- st->st_state = smc->next_state;
-
- /* Delete previous retransmission event.
- * New event will be scheduled below.
- */
- delete_event(st);
-
- /* replace previous receive packet with latest */
-
- pfreeany(st->st_rpacket.ptr);
-
- if (md->encrypted)
- {
- /* if encrypted, duplication already done */
- st->st_rpacket = md->raw_packet;
- md->raw_packet.ptr = NULL;
- }
- else
- {
- clonetochunk(st->st_rpacket
- , md->packet_pbs.start
- , pbs_room(&md->packet_pbs), "raw packet");
- }
-
- /* free previous transmit packet */
- freeanychunk(st->st_tpacket);
-
- /* if requested, send the new reply packet */
- if (smc->flags & SMF_REPLY)
- {
- close_output_pbs(&md->reply); /* good form, but actually a no-op */
-
- clonetochunk(st->st_tpacket, md->reply.start
- , pbs_offset(&md->reply), "reply packet");
-
- if (nat_traversal_enabled)
- nat_traversal_change_port_lookup(md, md->st);
-
- /* actually send the packet
- * Note: this is a great place to implement "impairments"
- * for testing purposes. Suppress or duplicate the
- * send_packet call depending on st->st_state.
- */
- send_packet(st, enum_name(&state_names, from_state));
- }
+ bool has_xauth_policy;
+ bool is_xauth_server;
+ struct msg_digest *md = *mdp;
+ const struct state_microcode *smc = md->smc;
+ enum state_kind from_state = md->from_state;
+ struct state *st;
- /* Schedule for whatever timeout is specified */
- {
- time_t delay = UNDEFINED_TIME;
- enum event_type kind = smc->timeout_event;
- bool agreed_time = FALSE;
- struct connection *c = st->st_connection;
+ cur_state = st = md->st; /* might have changed */
- switch (kind)
- {
- case EVENT_RETRANSMIT: /* Retransmit packet */
- delay = EVENT_RETRANSMIT_DELAY_0;
- break;
-
- case EVENT_SA_REPLACE: /* SA replacement event */
- if (IS_PHASE1(st->st_state))
- {
- /* Note: we will defer to the "negotiated" (dictated)
- * lifetime if we are POLICY_DONT_REKEY.
- * This allows the other side to dictate
- * a time we would not otherwise accept
- * but it prevents us from having to initiate
- * rekeying. The negative consequences seem
- * minor.
+ /* If state has DPD support, import it */
+ if (st && md->dpd)
+ st->st_dpd = TRUE;
+
+ switch (result)
+ {
+ case STF_IGNORE:
+ break;
+
+ case STF_SUSPEND:
+ /* the stf didn't complete its job: don't relase md */
+ *mdp = NULL;
+ break;
+
+ case STF_OK:
+ /* advance the state */
+ st->st_state = smc->next_state;
+
+ /* Delete previous retransmission event.
+ * New event will be scheduled below.
*/
- delay = c->sa_ike_life_seconds;
- if ((c->policy & POLICY_DONT_REKEY)
- || delay >= st->st_oakley.life_seconds)
+ delete_event(st);
+
+ /* replace previous receive packet with latest */
+
+ free(st->st_rpacket.ptr);
+
+ if (md->encrypted)
{
- agreed_time = TRUE;
- delay = st->st_oakley.life_seconds;
+ /* if encrypted, duplication already done */
+ st->st_rpacket = md->raw_packet;
+ md->raw_packet.ptr = NULL;
}
- }
- else
- {
- /* Delay is min of up to four things:
- * each can limit the lifetime.
- */
- delay = c->sa_ipsec_life_seconds;
- if (st->st_ah.present
- && delay >= st->st_ah.attrs.life_seconds)
+ else
{
- agreed_time = TRUE;
- delay = st->st_ah.attrs.life_seconds;
+ st->st_rpacket = chunk_create(md->packet_pbs.start,
+ pbs_room(&md->packet_pbs));
+ st->st_rpacket = chunk_clone(st->st_rpacket);
}
- if (st->st_esp.present
- && delay >= st->st_esp.attrs.life_seconds)
+
+ /* free previous transmit packet */
+ chunk_free(&st->st_tpacket);
+
+ /* if requested, send the new reply packet */
+ if (smc->flags & SMF_REPLY)
{
- agreed_time = TRUE;
- delay = st->st_esp.attrs.life_seconds;
+ close_output_pbs(&md->reply); /* good form, but actually a no-op */
+
+ st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
+ st->st_tpacket = chunk_clone(st->st_tpacket);
+
+ if (nat_traversal_enabled)
+ nat_traversal_change_port_lookup(md, md->st);
+
+ /* actually send the packet
+ * Note: this is a great place to implement "impairments"
+ * for testing purposes. Suppress or duplicate the
+ * send_packet call depending on st->st_state.
+ */
+ send_packet(st, enum_name(&state_names, from_state));
}
- if (st->st_ipcomp.present
- && delay >= st->st_ipcomp.attrs.life_seconds)
+
+ /* Schedule for whatever timeout is specified */
{
- agreed_time = TRUE;
- delay = st->st_ipcomp.attrs.life_seconds;
+ time_t delay = UNDEFINED_TIME;
+ enum event_type kind = smc->timeout_event;
+ bool agreed_time = FALSE;
+ struct connection *c = st->st_connection;
+
+ switch (kind)
+ {
+ case EVENT_RETRANSMIT: /* Retransmit packet */
+ delay = EVENT_RETRANSMIT_DELAY_0;
+ break;
+
+ case EVENT_SA_REPLACE: /* SA replacement event */
+ if (IS_PHASE1(st->st_state))
+ {
+ /* Note: we will defer to the "negotiated" (dictated)
+ * lifetime if we are POLICY_DONT_REKEY.
+ * This allows the other side to dictate
+ * a time we would not otherwise accept
+ * but it prevents us from having to initiate
+ * rekeying. The negative consequences seem
+ * minor.
+ */
+ delay = c->sa_ike_life_seconds;
+ if ((c->policy & POLICY_DONT_REKEY)
+ || delay >= st->st_oakley.life_seconds)
+ {
+ agreed_time = TRUE;
+ delay = st->st_oakley.life_seconds;
+ }
+ }
+ else
+ {
+ /* Delay is min of up to four things:
+ * each can limit the lifetime.
+ */
+ delay = c->sa_ipsec_life_seconds;
+ if (st->st_ah.present
+ && delay >= st->st_ah.attrs.life_seconds)
+ {
+ agreed_time = TRUE;
+ delay = st->st_ah.attrs.life_seconds;
+ }
+ if (st->st_esp.present
+ && delay >= st->st_esp.attrs.life_seconds)
+ {
+ agreed_time = TRUE;
+ delay = st->st_esp.attrs.life_seconds;
+ }
+ if (st->st_ipcomp.present
+ && delay >= st->st_ipcomp.attrs.life_seconds)
+ {
+ agreed_time = TRUE;
+ delay = st->st_ipcomp.attrs.life_seconds;
+ }
+ }
+
+ /* By default, we plan to rekey.
+ *
+ * If there isn't enough time to rekey, plan to
+ * expire.
+ *
+ * If we are --dontrekey, a lot more rules apply.
+ * If we are the Initiator, use REPLACE_IF_USED.
+ * If we are the Responder, and the dictated time
+ * was unacceptable (too large), plan to REPLACE
+ * (the only way to ratchet down the time).
+ * If we are the Responder, and the dictated time
+ * is acceptable, plan to EXPIRE.
+ *
+ * Important policy lies buried here.
+ * For example, we favour the initiator over the
+ * responder by making the initiator start rekeying
+ * sooner. Also, fuzz is only added to the
+ * initiator's margin.
+ *
+ * Note: for ISAKMP SA, we let the negotiated
+ * time stand (implemented by earlier logic).
+ */
+ if (agreed_time
+ && (c->policy & POLICY_DONT_REKEY))
+ {
+ kind = (smc->flags & SMF_INITIATOR)
+ ? EVENT_SA_REPLACE_IF_USED
+ : EVENT_SA_EXPIRE;
+ }
+ if (kind != EVENT_SA_EXPIRE)
+ {
+ unsigned long marg = c->sa_rekey_margin;
+
+ if (smc->flags & SMF_INITIATOR)
+ marg += marg
+ * c->sa_rekey_fuzz / 100.E0
+ * (rand() / (RAND_MAX + 1.E0));
+ else
+ marg /= 2;
+
+ if ((unsigned long)delay > marg)
+ {
+ delay -= marg;
+ st->st_margin = marg;
+ }
+ else
+ {
+ kind = EVENT_SA_EXPIRE;
+ }
+ }
+ break;
+
+ case EVENT_NULL: /* non-event */
+ case EVENT_REINIT_SECRET: /* Refresh cookie secret */
+ default:
+ bad_case(kind);
+ }
+ event_schedule(kind, delay, st);
}
- }
-
- /* By default, we plan to rekey.
- *
- * If there isn't enough time to rekey, plan to
- * expire.
- *
- * If we are --dontrekey, a lot more rules apply.
- * If we are the Initiator, use REPLACE_IF_USED.
- * If we are the Responder, and the dictated time
- * was unacceptable (too large), plan to REPLACE
- * (the only way to ratchet down the time).
- * If we are the Responder, and the dictated time
- * is acceptable, plan to EXPIRE.
- *
- * Important policy lies buried here.
- * For example, we favour the initiator over the
- * responder by making the initiator start rekeying
- * sooner. Also, fuzz is only added to the
- * initiator's margin.
- *
- * Note: for ISAKMP SA, we let the negotiated
- * time stand (implemented by earlier logic).
- */
- if (agreed_time
- && (c->policy & POLICY_DONT_REKEY))
- {
- kind = (smc->flags & SMF_INITIATOR)
- ? EVENT_SA_REPLACE_IF_USED
- : EVENT_SA_EXPIRE;
- }
- if (kind != EVENT_SA_EXPIRE)
- {
- unsigned long marg = c->sa_rekey_margin;
-
- if (smc->flags & SMF_INITIATOR)
- marg += marg
- * c->sa_rekey_fuzz / 100.E0
- * (rand() / (RAND_MAX + 1.E0));
- else
- marg /= 2;
- if ((unsigned long)delay > marg)
+ /* tell whack and log of progress */
{
- delay -= marg;
- st->st_margin = marg;
+ const char *story = state_story[st->st_state - STATE_MAIN_R0];
+ enum rc_type w = RC_NEW_STATE + st->st_state;
+ char sadetails[128];
+
+ sadetails[0]='\0';
+
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ {
+ char *b = sadetails;
+ const char *ini = " {";
+ const char *fin = "";
+
+ /* -1 is to leave space for "fin" */
+
+ if (st->st_esp.present)
+ {
+ snprintf(b, sizeof(sadetails)-(b-sadetails)-1
+ , "%sESP=>0x%08x <0x%08x"
+ , ini
+ , ntohl(st->st_esp.attrs.spi)
+ , ntohl(st->st_esp.our_spi));
+ ini = " ";
+ fin = "}";
+ }
+ /* advance b to end of string */
+ b = b + strlen(b);
+
+ if (st->st_ah.present)
+ {
+ snprintf(b, sizeof(sadetails)-(b-sadetails)-1
+ , "%sAH=>0x%08x <0x%08x"
+ , ini
+ , ntohl(st->st_ah.attrs.spi)
+ , ntohl(st->st_ah.our_spi));
+ ini = " ";
+ fin = "}";
+ }
+ /* advance b to end of string */
+ b = b + strlen(b);
+
+ if (st->st_ipcomp.present)
+ {
+ snprintf(b, sizeof(sadetails)-(b-sadetails)-1
+ , "%sIPCOMP=>0x%08x <0x%08x"
+ , ini
+ , ntohl(st->st_ipcomp.attrs.spi)
+ , ntohl(st->st_ipcomp.our_spi));
+ ini = " ";
+ fin = "}";
+ }
+ /* advance b to end of string */
+ b = b + strlen(b);
+
+ if (st->nat_traversal)
+ {
+ char oa[ADDRTOT_BUF];
+ addrtot(&st->nat_oa, 0, oa, sizeof(oa));
+ snprintf(b, sizeof(sadetails)-(b-sadetails)-1
+ , "%sNATOA=%s"
+ , ini, oa);
+ ini = " ";
+ fin = "}";
+ }
+
+ /* advance b to end of string */
+ b = b + strlen(b);
+
+ if (st->st_dpd)
+ {
+ snprintf(b, sizeof(sadetails)-(b-sadetails)-1
+ , "%sDPD"
+ , ini);
+ ini = " ";
+ fin = "}";
+ }
+
+ strcat(b, fin);
+ }
+
+ if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ || IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ {
+ /* log our success */
+ plog("%s%s", story, sadetails);
+ w = RC_SUCCESS;
+ }
+
+ /* tell whack our progress */
+ whack_log(w
+ , "%s: %s%s"
+ , enum_name(&state_names, st->st_state)
+ , story, sadetails);
}
- else
+
+ has_xauth_policy = (st->st_connection->policy
+ & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
+ != LEMPTY;
+ is_xauth_server = (st->st_connection->policy
+ & POLICY_XAUTH_SERVER)
+ != LEMPTY;
+
+ /* Should we start XAUTH as a server */
+ if (has_xauth_policy && is_xauth_server
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_xauth.started)
{
- kind = EVENT_SA_EXPIRE;
+ DBG(DBG_CONTROL,
+ DBG_log("starting XAUTH server")
+ )
+ xauth_send_request(st);
+ break;
}
- }
- break;
- case EVENT_NULL: /* non-event */
- case EVENT_REINIT_SECRET: /* Refresh cookie secret */
- default:
- bad_case(kind);
- }
- event_schedule(kind, delay, st);
- }
-
- /* tell whack and log of progress */
- {
- const char *story = state_story[st->st_state - STATE_MAIN_R0];
- enum rc_type w = RC_NEW_STATE + st->st_state;
- char sadetails[128];
-
- sadetails[0]='\0';
+ /* Wait for XAUTH request from server */
+ if (has_xauth_policy && !is_xauth_server
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_xauth.started)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("waiting for XAUTH request from server")
+ )
+ break;
+ }
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- char *b = sadetails;
- const char *ini = " {";
- const char *fin = "";
-
- /* -1 is to leave space for "fin" */
-
- if (st->st_esp.present)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sESP=>0x%08x <0x%08x"
- , ini
- , ntohl(st->st_esp.attrs.spi)
- , ntohl(st->st_esp.our_spi));
- ini = " ";
- fin = "}";
- }
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->st_ah.present)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sAH=>0x%08x <0x%08x"
- , ini
- , ntohl(st->st_ah.attrs.spi)
- , ntohl(st->st_ah.our_spi));
- ini = " ";
- fin = "}";
- }
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->st_ipcomp.present)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sIPCOMP=>0x%08x <0x%08x"
- , ini
- , ntohl(st->st_ipcomp.attrs.spi)
- , ntohl(st->st_ipcomp.our_spi));
- ini = " ";
- fin = "}";
- }
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->nat_traversal)
- {
- char oa[ADDRTOT_BUF];
- addrtot(&st->nat_oa, 0, oa, sizeof(oa));
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sNATOA=%s"
- , ini, oa);
- ini = " ";
- fin = "}";
- }
-
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->st_dpd)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sDPD"
- , ini);
- ini = " ";
- fin = "}";
- }
-
- strcat(b, fin);
- }
+ /* Should we start ModeConfig as a client? */
+ if (st->st_connection->spd.this.modecfg
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !(st->st_connection->policy & POLICY_MODECFG_PUSH)
+ && !st->st_modecfg.started)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("starting ModeCfg client in pull mode")
+ )
+ modecfg_send_request(st);
+ break;
+ }
- if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- || IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- /* log our success */
- plog("%s%s", story, sadetails);
- w = RC_SUCCESS;
- }
+ /* Should we start ModeConfig as a server? */
+ if (st->st_connection->spd.that.modecfg
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_modecfg.started
+ && (st->st_connection->policy & POLICY_MODECFG_PUSH))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("starting ModeCfg server in push mode")
+ )
+ modecfg_send_set(st);
+ break;
+ }
- /* tell whack our progress */
- whack_log(w
- , "%s: %s%s"
- , enum_name(&state_names, st->st_state)
- , story, sadetails);
- }
-
- has_xauth_policy = (st->st_connection->policy
- & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
- != LEMPTY;
- is_xauth_server = (st->st_connection->policy
- & POLICY_XAUTH_SERVER)
- != LEMPTY;
-
- /* Should we start XAUTH as a server */
- if (has_xauth_policy && is_xauth_server
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_xauth.started)
- {
- DBG(DBG_CONTROL,
- DBG_log("starting XAUTH server")
- )
- xauth_send_request(st);
- break;
- }
-
- /* Wait for XAUTH request from server */
- if (has_xauth_policy && !is_xauth_server
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_xauth.started)
- {
- DBG(DBG_CONTROL,
- DBG_log("waiting for XAUTH request from server")
- )
- break;
- }
-
- /* Should we start ModeConfig as a client? */
- if (st->st_connection->spd.this.modecfg
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !(st->st_connection->policy & POLICY_MODECFG_PUSH)
- && !st->st_modecfg.started)
- {
- DBG(DBG_CONTROL,
- DBG_log("starting ModeCfg client in pull mode")
- )
- modecfg_send_request(st);
- break;
- }
-
- /* Should we start ModeConfig as a server? */
- if (st->st_connection->spd.that.modecfg
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_modecfg.started
- && (st->st_connection->policy & POLICY_MODECFG_PUSH))
- {
- DBG(DBG_CONTROL,
- DBG_log("starting ModeCfg server in push mode")
- )
- modecfg_send_set(st);
- break;
- }
-
- /* Wait for ModeConfig set from server */
- if (st->st_connection->spd.this.modecfg
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_modecfg.vars_set)
- {
- DBG(DBG_CONTROL,
- DBG_log("waiting for ModeCfg set from server")
- )
- break;
- }
+ /* Wait for ModeConfig set from server */
+ if (st->st_connection->spd.this.modecfg
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_modecfg.vars_set)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("waiting for ModeCfg set from server")
+ )
+ break;
+ }
- if (smc->flags & SMF_RELEASE_PENDING_P2)
- {
- /* Initiate any Quick Mode negotiations that
- * were waiting to piggyback on this Keying Channel.
- *
- * ??? there is a potential race condition
- * if we are the responder: the initial Phase 2
- * message might outrun the final Phase 1 message.
- * I think that retransmission will recover.
- */
- unpend(st);
- }
-
- if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- || IS_IPSEC_SA_ESTABLISHED(st->st_state))
- release_whack(st);
- break;
-
- case STF_INTERNAL_ERROR:
- whack_log(RC_INTERNALERR + md->note
- , "%s: internal error"
- , enum_name(&state_names, st->st_state));
-
- DBG(DBG_CONTROL,
- DBG_log("state transition function for %s had internal error"
- , enum_name(&state_names, from_state)));
- break;
-
- default: /* a shortcut to STF_FAIL, setting md->note */
- passert(result > STF_FAIL);
- md->note = result - STF_FAIL;
- result = STF_FAIL;
- /* FALL THROUGH ... */
- case STF_FAIL:
- /* As it is, we act as if this message never happened:
- * whatever retrying was in place, remains in place.
- */
- whack_log(RC_NOTIFICATION + md->note
- , "%s: %s"
- , enum_name(&state_names, (st == NULL)? STATE_MAIN_R0:st->st_state)
- , enum_name(&notification_names, md->note));
-
- SEND_NOTIFICATION(md->note);
-
- DBG(DBG_CONTROL,
- DBG_log("state transition function for %s failed: %s"
- , enum_name(&state_names, from_state)
- , enum_name(&notification_names, md->note)));
- break;
- }
+ if (smc->flags & SMF_RELEASE_PENDING_P2)
+ {
+ /* Initiate any Quick Mode negotiations that
+ * were waiting to piggyback on this Keying Channel.
+ *
+ * ??? there is a potential race condition
+ * if we are the responder: the initial Phase 2
+ * message might outrun the final Phase 1 message.
+ * I think that retransmission will recover.
+ */
+ unpend(st);
+ }
+
+ if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ || IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ release_whack(st);
+ break;
+
+ case STF_INTERNAL_ERROR:
+ whack_log(RC_INTERNALERR + md->note
+ , "%s: internal error"
+ , enum_name(&state_names, st->st_state));
+
+ DBG(DBG_CONTROL,
+ DBG_log("state transition function for %s had internal error"
+ , enum_name(&state_names, from_state)));
+ break;
+
+ default: /* a shortcut to STF_FAIL, setting md->note */
+ passert(result > STF_FAIL);
+ md->note = result - STF_FAIL;
+ result = STF_FAIL;
+ /* FALL THROUGH ... */
+ case STF_FAIL:
+ /* As it is, we act as if this message never happened:
+ * whatever retrying was in place, remains in place.
+ */
+ whack_log(RC_NOTIFICATION + md->note
+ , "%s: %s"
+ , enum_name(&state_names, (st == NULL)? STATE_MAIN_R0:st->st_state)
+ , enum_name(&notification_names, md->note));
+
+ SEND_NOTIFICATION(md->note);
+
+ DBG(DBG_CONTROL,
+ DBG_log("state transition function for %s failed: %s"
+ , enum_name(&state_names, from_state)
+ , enum_name(&notification_names, md->note)));
+ break;
+ }
}
diff --git a/src/pluto/demux.h b/src/pluto/demux.h
index 0348b3579..4faf6e532 100644
--- a/src/pluto/demux.h
+++ b/src/pluto/demux.h
@@ -10,13 +10,11 @@
* 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: demux.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include "packet.h"
-struct state; /* forward declaration of tag */
+struct state; /* forward declaration of tag */
extern void init_demux(void);
extern bool send_packet(struct state *st, const char *where);
extern void comm_handle(const struct iface *ifp);
@@ -36,9 +34,9 @@ extern u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE];
*/
struct payload_digest {
- pb_stream pbs;
- union payload payload;
- struct payload_digest *next; /* of same kind */
+ pb_stream pbs;
+ union payload payload;
+ struct payload_digest *next; /* of same kind */
};
/* message digest
@@ -46,30 +44,30 @@ struct payload_digest {
*/
struct msg_digest {
- struct msg_digest *next; /* for free list */
- chunk_t raw_packet; /* if encrypted, received packet before decryption */
- const struct iface *iface; /* interface on which message arrived */
- ip_address sender; /* where message came from */
- u_int16_t sender_port; /* host order */
- pb_stream packet_pbs; /* whole packet */
- pb_stream message_pbs; /* message to be processed */
- struct isakmp_hdr hdr; /* message's header */
- bool encrypted; /* was it encrypted? */
- enum state_kind from_state; /* state we started in */
- const struct state_microcode *smc; /* microcode for initial state */
- struct state *st; /* current state object */
- pb_stream reply; /* room for reply */
- pb_stream rbody; /* room for reply body (after header) */
- notification_t note; /* reason for failure */
- bool dpd; /* peer supports RFC 3706 DPD */
- bool openpgp; /* peer supports OpenPGP certificates */
+ struct msg_digest *next; /* for free list */
+ chunk_t raw_packet; /* if encrypted, received packet before decryption */
+ const struct iface *iface; /* interface on which message arrived */
+ ip_address sender; /* where message came from */
+ u_int16_t sender_port; /* host order */
+ pb_stream packet_pbs; /* whole packet */
+ pb_stream message_pbs; /* message to be processed */
+ struct isakmp_hdr hdr; /* message's header */
+ bool encrypted; /* was it encrypted? */
+ enum state_kind from_state; /* state we started in */
+ const struct state_microcode *smc; /* microcode for initial state */
+ struct state *st; /* current state object */
+ pb_stream reply; /* room for reply */
+ pb_stream rbody; /* room for reply body (after header) */
+ notification_t note; /* reason for failure */
+ bool dpd; /* peer supports RFC 3706 DPD */
+ bool openpgp; /* peer supports OpenPGP certificates */
# define PAYLIMIT 40
- struct payload_digest
- digest[PAYLIMIT],
- *digest_roof,
- *chain[ISAKMP_NEXT_ROOF];
- unsigned short nat_traversal_vid;
+ struct payload_digest
+ digest[PAYLIMIT],
+ *digest_roof,
+ *chain[ISAKMP_NEXT_ROOF];
+ unsigned short nat_traversal_vid;
};
extern void release_md(struct msg_digest *md);
@@ -79,11 +77,11 @@ extern void release_md(struct msg_digest *md);
*/
typedef enum {
- STF_IGNORE, /* don't respond */
- STF_SUSPEND, /* unfinished -- don't release resources */
- STF_OK, /* success */
- STF_INTERNAL_ERROR, /* discard everything, we failed */
- STF_FAIL /* discard everything, something failed. notification_t added. */
+ STF_IGNORE, /* don't respond */
+ STF_SUSPEND, /* unfinished -- don't release resources */
+ STF_OK, /* success */
+ STF_INTERNAL_ERROR, /* discard everything, we failed */
+ STF_FAIL /* discard everything, something failed. notification_t added. */
} stf_status;
typedef stf_status state_transition_fn(struct msg_digest *md);
diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c
index 8ba0f7b73..ed901ade5 100644
--- a/src/pluto/dnskey.c
+++ b/src/pluto/dnskey.c
@@ -10,8 +10,6 @@
* 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: dnskey.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdlib.h>
@@ -26,32 +24,34 @@
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#include <netdb.h> /* ??? for h_errno */
+#include <netdb.h> /* ??? for h_errno */
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <utils/identification.h>
+#include <credentials/keys/public_key.h>
#include "constants.h"
-#include "adns.h" /* needs <resolv.h> */
+#include "adns.h" /* needs <resolv.h> */
#include "defs.h"
#include "log.h"
#include "id.h"
#include "connections.h"
-#include "keys.h" /* needs connections.h */
+#include "keys.h" /* needs connections.h */
#include "dnskey.h"
#include "packet.h"
#include "timer.h"
/* somebody has to decide */
-#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */
+#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */
/* ADNS stuff */
-int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */
- adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
+int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */
+ adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
static pid_t adns_pid = 0;
-const char *pluto_adns_option = NULL; /* path from --pluto_adns */
+const char *pluto_adns_option = NULL; /* path from --pluto_adns */
int adns_restart_count;
#define ADNS_RESTART_MAX 20
@@ -59,152 +59,168 @@ int adns_restart_count;
void
init_adns(void)
{
- const char *adns_path = pluto_adns_option;
+ const char *adns_path = pluto_adns_option;
#ifndef USE_LWRES
- static const char adns_name[] = "_pluto_adns";
- const char *helper_bin_dir = getenv("IPSEC_LIBDIR");
+ static const char adns_name[] = "_pluto_adns";
+ const char *helper_bin_dir = getenv("IPSEC_LIBDIR");
#else /* USE_LWRES */
- static const char adns_name[] = "lwdnsq";
- const char *helper_bin_dir = getenv("IPSEC_EXECDIR");
+ static const char adns_name[] = "lwdnsq";
+ const char *helper_bin_dir = getenv("IPSEC_EXECDIR");
#endif /* USE_LWRES */
- char adns_path_space[4096]; /* plenty long? */
- int qfds[2];
- int afds[2];
-
- /* find a pathname to the ADNS program */
- if (adns_path == NULL)
- {
- /* pathname was not specified as an option: build it.
- * First, figure out the directory to be used.
- */
- ssize_t n;
+ char adns_path_space[4096]; /* plenty long? */
+ int qfds[2];
+ int afds[2];
- if (helper_bin_dir != NULL)
+ /* find a pathname to the ADNS program */
+ if (adns_path == NULL)
{
- n = strlen(helper_bin_dir);
- if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
- {
- strcpy(adns_path_space, helper_bin_dir);
- if (n > 0 && adns_path_space[n -1] != '/')
- adns_path_space[n++] = '/';
- }
- }
- else
- {
- /* The program will be in the same directory as Pluto,
- * so we use the sympolic link /proc/self/exe to
- * tell us of the path prefix.
- */
- n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
-
- if (n < 0)
- exit_log_errno((e
- , "readlink(\"/proc/self/exe\") failed in init_adns()"));
-
- }
-
- if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
- exit_log("path to %s is too long", adns_name);
+ /* pathname was not specified as an option: build it.
+ * First, figure out the directory to be used.
+ */
+ ssize_t n;
- while (n > 0 && adns_path_space[n - 1] != '/')
- n--;
+ if (helper_bin_dir != NULL)
+ {
+ n = strlen(helper_bin_dir);
+ if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
+ {
+ strcpy(adns_path_space, helper_bin_dir);
+ if (n > 0 && adns_path_space[n -1] != '/')
+ {
+ adns_path_space[n++] = '/';
+ }
+ }
+ }
+ else
+ {
+ /* The program will be in the same directory as Pluto,
+ * so we use the sympolic link /proc/self/exe to
+ * tell us of the path prefix.
+ */
+ n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
+
+ if (n < 0)
+ {
+ exit_log_errno((e
+ , "readlink(\"/proc/self/exe\") failed in init_adns()"));
+ }
+ }
- strcpy(adns_path_space + n, adns_name);
- adns_path = adns_path_space;
- }
- if (access(adns_path, X_OK) < 0)
- exit_log_errno((e, "%s missing or not executable", adns_path));
+ if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
+ {
+ exit_log("path to %s is too long", adns_name);
+ }
- if (pipe(qfds) != 0 || pipe(afds) != 0)
- exit_log_errno((e, "pipe(2) failed in init_adns()"));
+ while (n > 0 && adns_path_space[n - 1] != '/')
+ {
+ n--;
+ }
+ strcpy(adns_path_space + n, adns_name);
+ adns_path = adns_path_space;
+ }
+ if (access(adns_path, X_OK) < 0)
+ {
+ exit_log_errno((e, "%s missing or not executable", adns_path));
+ }
- adns_pid = fork();
- switch (adns_pid)
- {
- case -1:
- exit_log_errno((e, "fork() failed in init_adns()"));
+ if (pipe(qfds) != 0 || pipe(afds) != 0)
+ {
+ exit_log_errno((e, "pipe(2) failed in init_adns()"));
+ }
- case 0:
- /* child */
+ adns_pid = fork();
+ switch (adns_pid)
{
- /* Make stdin and stdout our pipes.
- * Take care to handle case where pipes already use these fds.
- */
- if (afds[1] == 0)
- afds[1] = dup(afds[1]); /* avoid being overwritten */
- if (qfds[0] != 0)
- {
- dup2(qfds[0], 0);
+ case -1:
+ exit_log_errno((e, "fork() failed in init_adns()"));
+
+ case 0:
+ /* child */
+ {
+ /* Make stdin and stdout our pipes.
+ * Take care to handle case where pipes already use these fds.
+ */
+ if (afds[1] == 0)
+ {
+ afds[1] = dup(afds[1]); /* avoid being overwritten */
+ }
+ if (qfds[0] != 0)
+ {
+ dup2(qfds[0], 0);
+ close(qfds[0]);
+ }
+ if (afds[1] != 1)
+ {
+ dup2(afds[1], 1);
+ close(qfds[1]);
+ }
+ if (afds[0] > 1)
+ {
+ close(afds[0]);
+ }
+ if (afds[1] > 1)
+ {
+ close(afds[1]);
+ }
+ DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL));
+
+ execlp(adns_path, adns_name, NULL);
+ exit_log_errno((e, "execlp of %s failed", adns_path));
+ }
+ default:
+ /* parent */
close(qfds[0]);
- }
- if (afds[1] != 1)
- {
- dup2(afds[1], 1);
- close(qfds[1]);
- }
- if (afds[0] > 1)
- close(afds[0]);
- if (afds[1] > 1)
+ adns_qfd = qfds[1];
+ adns_afd = afds[0];
close(afds[1]);
-
- DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL));
-
- execlp(adns_path, adns_name, NULL);
- exit_log_errno((e, "execlp of %s failed", adns_path));
+ fcntl(adns_qfd, F_SETFD, FD_CLOEXEC);
+ fcntl(adns_afd, F_SETFD, FD_CLOEXEC);
+ fcntl(adns_qfd, F_SETFL, O_NONBLOCK);
+ break;
}
-
- default:
- /* parent */
- close(qfds[0]);
- adns_qfd = qfds[1];
- adns_afd = afds[0];
- close(afds[1]);
- fcntl(adns_qfd, F_SETFD, FD_CLOEXEC);
- fcntl(adns_afd, F_SETFD, FD_CLOEXEC);
- fcntl(adns_qfd, F_SETFL, O_NONBLOCK);
- break;
- }
}
void
stop_adns(void)
{
- close_any(adns_qfd);
- adns_qfd = NULL_FD;
- close_any(adns_afd);
- adns_afd = NULL_FD;
-
- if (adns_pid != 0)
- {
- int status;
- pid_t p = waitpid(adns_pid, &status, 0);
+ close_any(adns_qfd);
+ adns_qfd = NULL_FD;
+ close_any(adns_afd);
+ adns_afd = NULL_FD;
- if (p == -1)
- {
- log_errno((e, "waitpid for ADNS process failed"));
- }
- else if (WIFEXITED(status))
+ if (adns_pid != 0)
{
- if (WEXITSTATUS(status) != 0)
- plog("ADNS process exited with status %d"
- , (int) WEXITSTATUS(status));
- }
- else if (WIFSIGNALED(status))
- {
- plog("ADNS process terminated by signal %d", (int)WTERMSIG(status));
- }
- else
- {
- plog("wait for end of ADNS process returned odd status 0x%x\n"
- , status);
+ int status;
+ pid_t p = waitpid(adns_pid, &status, 0);
+
+ if (p == -1)
+ {
+ log_errno((e, "waitpid for ADNS process failed"));
+ }
+ else if (WIFEXITED(status))
+ {
+ if (WEXITSTATUS(status) != 0)
+ {
+ plog("ADNS process exited with status %d"
+ , (int) WEXITSTATUS(status));
+ }
+ }
+ else if (WIFSIGNALED(status))
+ {
+ plog("ADNS process terminated by signal %d", (int)WTERMSIG(status));
+ }
+ else
+ {
+ plog("wait for end of ADNS process returned odd status 0x%x\n"
+ , status);
+ }
}
- }
}
/* tricky macro to pass any hot potato */
-#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; }
+#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; }
/* Process TXT X-IPsec-Server record, accumulating relevant ones
@@ -225,246 +241,270 @@ static const char our_TXT_attr[] = our_TXT_attr_string;
static err_t
decode_iii(u_char **pp, struct id *gw_id)
{
- u_char *p = *pp + strspn(*pp, " \t");
- u_char *e = p + strcspn(p, " \t");
- u_char under = *e;
-
- if (p == e)
- return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
-
- *e = '\0';
- if (*p == '@')
- {
- /* gateway specification in this record is @FQDN */
- err_t ugh = atoid(p, gw_id, FALSE);
-
- if (ugh != NULL)
- return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
- , ugh);
- }
- else
- {
- /* gateway specification is numeric */
- ip_address ip;
- err_t ugh = tnatoaddr(p, e-p
- , strchr(p, ':') == NULL? AF_INET : AF_INET6
- , &ip);
-
- if (ugh != NULL)
- return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
- , ugh);
-
- if (isanyaddr(&ip))
- return "gateway address must not be 0.0.0.0 or 0::0";
-
- iptoid(&ip, gw_id);
- }
-
- *e = under;
- *pp = e + strspn(e, " \t");
-
- return NULL;
+ u_char *p = *pp + strspn(*pp, " \t");
+ u_char *e = p + strcspn(p, " \t");
+ u_char under = *e;
+
+ if (p == e)
+ {
+ return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
+ }
+ *e = '\0';
+ if (*p == '@')
+ {
+ /* gateway specification in this record is @FQDN */
+ err_t ugh = atoid(p, gw_id, FALSE);
+
+ if (ugh != NULL)
+ {
+ return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
+ , ugh);
+ }
+ }
+ else
+ {
+ /* gateway specification is numeric */
+ ip_address ip;
+ err_t ugh = tnatoaddr(p, e-p
+ , strchr(p, ':') == NULL? AF_INET : AF_INET6
+ , &ip);
+
+ if (ugh != NULL)
+ {
+ return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
+ , ugh);
+ }
+ if (isanyaddr(&ip))
+ {
+ return "gateway address must not be 0.0.0.0 or 0::0";
+ }
+ iptoid(&ip, gw_id);
+ }
+
+ *e = under;
+ *pp = e + strspn(e, " \t");
+
+ return NULL;
}
static err_t
process_txt_rr_body(u_char *str
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- const struct id *client_id = &cr->id; /* subject of query */
- u_char *p = str;
- unsigned long pref = 0;
- struct gw_info gi;
+ const struct id *client_id = &cr->id; /* subject of query */
+ u_char *p = str;
+ unsigned long pref = 0;
+ struct gw_info gi;
+
+ p += strspn(p, " \t"); /* ignore leading whitespace */
- p += strspn(p, " \t"); /* ignore leading whitespace */
+ /* is this for us? */
+ if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
+ {
+ return NULL; /* neither interesting nor bad */
+ }
- /* is this for us? */
- if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
- return NULL; /* neither interesting nor bad */
+ p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
+ p += strspn(p, " \t"); /* ignore leading whitespace */
- p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
- p += strspn(p, " \t"); /* ignore leading whitespace */
+ /* decode '(' nnn ')' */
+ if (*p != '(')
+ {
+ return "X-IPsec-Server missing '('";
+ }
- /* decode '(' nnn ')' */
- if (*p != '(')
- return "X-IPsec-Server missing '('";
+ {
+ char *e;
- {
- char *e;
+ p++;
+ pref = strtoul(p, &e, 0);
+ if ((u_char *)e == p)
+ {
+ return "malformed X-IPsec-Server priority";
+ }
+ p = e + strspn(e, " \t");
- p++;
- pref = strtoul(p, &e, 0);
- if ((u_char *)e == p)
- return "malformed X-IPsec-Server priority";
+ if (*p != ')')
+ {
+ return "X-IPsec-Server priority missing ')'";
+ }
+ p++;
+ p += strspn(p, " \t");
- p = e + strspn(e, " \t");
+ if (pref > 0xFFFF)
+ {
+ return "X-IPsec-Server priority larger than 0xFFFF";
+ }
+ }
- if (*p != ')')
- return "X-IPsec-Server priority missing ')'";
+ /* time for '=' */
+ if (*p != '=')
+ {
+ return "X-IPsec-Server priority missing '='";
+ }
p++;
p += strspn(p, " \t");
- if (pref > 0xFFFF)
- return "X-IPsec-Server priority larger than 0xFFFF";
- }
-
- /* time for '=' */
+ /* Decode iii (Security Gateway ID). */
- if (*p != '=')
- return "X-IPsec-Server priority missing '='";
+ zero(&gi); /* before first use */
- p++;
- p += strspn(p, " \t");
+ TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
- /* Decode iii (Security Gateway ID). */
-
- zero(&gi); /* before first use */
-
- TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
-
- if (!cr->sgw_specified)
- {
- /* we don't know the peer's ID (because we are initiating
- * and we don't know who to initiate with.
- * So we're looking for gateway specs with an IP address
- */
- if (!id_is_ipaddr(&gi.gw_id))
+ if (!cr->sgw_specified)
{
- DBG(DBG_DNS,
+ /* we don't know the peer's ID (because we are initiating
+ * and we don't know who to initiate with.
+ * So we're looking for gateway specs with an IP address
+ */
+ if (!id_is_ipaddr(&gi.gw_id))
{
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- DBG_log("TXT %s record for %s: security gateway %s;"
- " ignored because gateway's IP is unspecified"
- , our_TXT_attr, cidb, gwidb);
- });
- return NULL; /* we cannot use this record, but it isn't wrong */
+ DBG(DBG_DNS,
+ {
+ char cidb[BUF_LEN];
+ char gwidb[BUF_LEN];
+
+ idtoa(client_id, cidb, sizeof(cidb));
+ idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ DBG_log("TXT %s record for %s: security gateway %s;"
+ " ignored because gateway's IP is unspecified"
+ , our_TXT_attr, cidb, gwidb);
+ });
+ return NULL; /* we cannot use this record, but it isn't wrong */
+ }
}
- }
- else
- {
- /* We do know the peer's ID (because we are responding)
- * So we're looking for gateway specs specifying this known ID.
- */
- const struct id *peer_id = &cr->sgw_id;
-
- if (!same_id(peer_id, &gi.gw_id))
+ else
{
- DBG(DBG_DNS,
+ /* We do know the peer's ID (because we are responding)
+ * So we're looking for gateway specs specifying this known ID.
+ */
+ const struct id *peer_id = &cr->sgw_id;
+
+ if (!same_id(peer_id, &gi.gw_id))
{
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
- char pidb[BUF_LEN];
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- idtoa(peer_id, pidb, sizeof(pidb));
- DBG_log("TXT %s record for %s: security gateway %s;"
- " ignored -- looking to confirm %s as gateway"
- , our_TXT_attr, cidb, gwidb, pidb);
- });
- return NULL; /* we cannot use this record, but it isn't wrong */
+ DBG(DBG_DNS,
+ {
+ char cidb[BUF_LEN];
+ char gwidb[BUF_LEN];
+ char pidb[BUF_LEN];
+
+ idtoa(client_id, cidb, sizeof(cidb));
+ idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ idtoa(peer_id, pidb, sizeof(pidb));
+ DBG_log("TXT %s record for %s: security gateway %s;"
+ " ignored -- looking to confirm %s as gateway"
+ , our_TXT_attr, cidb, gwidb, pidb);
+ });
+ return NULL; /* we cannot use this record, but it isn't wrong */
+ }
}
- }
-
- if (doit)
- {
- /* really accept gateway */
- struct gw_info **gwip; /* gateway insertion point */
- gi.client_id = *client_id; /* will need to unshare_id_content */
-
- /* decode optional kkk: base 64 encoding of key */
-
- gi.gw_key_present = *p != '\0';
- if (gi.gw_key_present)
+ if (doit)
{
- /* Decode base 64 encoding of key.
- * Similar code is in process_lwdnsq_key.
- */
- u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
- chunk_t kbc;
- struct RSA_public_key r;
-
- err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len
- , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
-
- if (ugh != NULL)
- return builddiag("malformed key data: %s", ugh);
-
- if (kbc.len > sizeof(kb))
- return builddiag("key data larger than %lu bytes"
- , (unsigned long) sizeof(kb));
-
- kbc.ptr = kb;
- ugh = unpack_RSA_public_key(&r, &kbc);
- if (ugh != NULL)
- return builddiag("invalid key data: %s", ugh);
-
- /* now find a key entry to put it in */
- gi.key = public_key_from_rsa(&r);
-
- free_RSA_public_content(&r);
+ /* really accept gateway */
+ struct gw_info **gwip; /* gateway insertion point */
- unreference_key(&cr->last_info);
- cr->last_info = reference_key(gi.key);
- }
-
- /* we're home free! Allocate everything and add to gateways list. */
- gi.refcnt = 1;
- gi.pref = pref;
- gi.key->dns_auth_level = dns_auth_level;
- gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME;
-
- /* find insertion point */
- for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
- ;
+ gi.client_id = *client_id; /* will need to unshare_id_content */
- DBG(DBG_DNS,
- {
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
+ /* decode optional kkk: base 64 encoding of key */
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ gi.gw_key_present = *p != '\0';
if (gi.gw_key_present)
{
- DBG_log("gateway for %s is %s with key %s"
- , cidb, gwidb, gi.key->u.rsa.keyid);
+ /* Decode base 64 encoding of key.
+ * Similar code is in process_lwdnsq_key.
+ */
+ u_char buf[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
+ size_t sz;
+ err_t ugh;
+ chunk_t rfc3110_chunk;
+ public_key_t *key;
+
+ ugh = ttodatav(p, 0, 64, buf, sizeof(buf), &sz,
+ diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh)
+ {
+ return builddiag("malformed key data: %s", ugh);
+ }
+ if (sz > sizeof(buf))
+ {
+ return builddiag("key data larger than %lu bytes",
+ (unsigned long) sizeof(buf));
+ }
+ rfc3110_chunk = chunk_create(buf, sz);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_RFC_3110, rfc3110_chunk,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return builddiag("invalid key data");
+ }
+
+ /* now find a key entry to put it in */
+ gi.key = public_key_from_rsa(key);
+
+ unreference_key(&cr->last_info);
+ cr->last_info = reference_key(gi.key);
}
- else
- {
- DBG_log("gateway for %s is %s; no key specified"
- , cidb, gwidb);
- }
- });
- gi.next = *gwip;
- *gwip = clone_thing(gi, "gateway info");
- unshare_id_content(&(*gwip)->gw_id);
- unshare_id_content(&(*gwip)->client_id);
- }
+ /* we're home free! Allocate everything and add to gateways list. */
+ gi.refcnt = 1;
+ gi.pref = pref;
+ gi.key->dns_auth_level = dns_auth_level;
+ gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME;
+
+ /* find insertion point */
+ for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
+ ;
+
+ DBG(DBG_DNS,
+ {
+ char cidb[BUF_LEN];
+ char gwidb[BUF_LEN];
+ identification_t *keyid;
+ public_key_t *pub_key;
+
+ idtoa(client_id, cidb, sizeof(cidb));
+ idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ pub_key = gi.key->public_key;
+ keyid = pub_key->get_id(pub_key, ID_PUBKEY_SHA1);
+
+ if (gi.gw_key_present)
+ {
+ DBG_log("gateway for %s is %s with key %Y"
+ , cidb, gwidb, keyid);
+ }
+ else
+ {
+ DBG_log("gateway for %s is %s; no key specified"
+ , cidb, gwidb);
+ }
+ });
+
+ gi.next = *gwip;
+ *gwip = clone_thing(gi);
+ unshare_id_content(&(*gwip)->gw_id);
+ unshare_id_content(&(*gwip)->client_id);
+ }
- return NULL;
+ return NULL;
}
static const char *
rr_typename(int type)
{
- switch (type)
- {
- case T_TXT:
- return "TXT";
- case T_KEY:
- return "KEY";
- default:
- return "???";
- }
+ switch (type)
+ {
+ case T_TXT:
+ return "TXT";
+ case T_KEY:
+ return "KEY";
+ default:
+ return "???";
+ }
}
@@ -476,72 +516,72 @@ process_lwdnsq_key(u_char *str
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */
- unsigned long flags /* 16 bits */
- , protocol /* 8 bits */
- , algorithm; /* 8 bits */
-
- char *rest = str
- , *p
- , *endofnumber;
-
- /* flags */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq KEY: missing flags";
-
- flags = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq KEY: malformed flags";
-
- /* protocol */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq KEY: missing protocol";
-
- protocol = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq KEY: malformed protocol";
-
- /* algorithm */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq KEY: missing algorithm";
-
- algorithm = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq KEY: malformed algorithm";
-
- /* is this key interesting? */
- if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
- && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
- && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */
- && (flags & 0x2CF0ul) == 0) /* must be zero */
- {
- /* Decode base 64 encoding of key.
- * Similar code is in process_txt_rr_body.
- */
- u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
- chunk_t kbc;
- err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len
- , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE);
-
- if (ugh != NULL)
- return builddiag("malformed key data: %s", ugh);
-
- if (kbc.len > sizeof(kb))
- return builddiag("key data larger than %lu bytes"
- , (unsigned long) sizeof(kb));
-
- kbc.ptr = kb;
- TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc
- , &cr->keys_from_dns));
-
- /* keep a reference to last one */
- unreference_key(&cr->last_info);
- cr->last_info = reference_key(cr->keys_from_dns->key);
- }
- return NULL;
+ /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */
+ unsigned long flags /* 16 bits */
+ , protocol /* 8 bits */
+ , algorithm; /* 8 bits */
+
+ char *rest = str
+ , *p
+ , *endofnumber;
+
+ /* flags */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq KEY: missing flags";
+
+ flags = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq KEY: malformed flags";
+
+ /* protocol */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq KEY: missing protocol";
+
+ protocol = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq KEY: malformed protocol";
+
+ /* algorithm */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq KEY: missing algorithm";
+
+ algorithm = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq KEY: malformed algorithm";
+
+ /* is this key interesting? */
+ if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
+ && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
+ && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */
+ && (flags & 0x2CF0ul) == 0) /* must be zero */
+ {
+ /* Decode base 64 encoding of key.
+ * Similar code is in process_txt_rr_body.
+ */
+ u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
+ chunk_t kbc;
+ err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len
+ , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE);
+
+ if (ugh != NULL)
+ return builddiag("malformed key data: %s", ugh);
+
+ if (kbc.len > sizeof(kb))
+ return builddiag("key data larger than %lu bytes"
+ , (unsigned long) sizeof(kb));
+
+ kbc.ptr = kb;
+ TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc
+ , &cr->keys_from_dns));
+
+ /* keep a reference to last one */
+ unreference_key(&cr->last_info);
+ cr->last_info = reference_key(cr->keys_from_dns->key);
+ }
+ return NULL;
}
# endif /* USE_KEYRR */
@@ -580,158 +620,158 @@ process_lwdnsq_key(u_char *str
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/
struct qr_header {
- u_int16_t id; /* 16-bit identifier to match query */
+ u_int16_t id; /* 16-bit identifier to match query */
- u_int16_t stuff; /* packed crud: */
+ u_int16_t stuff; /* packed crud: */
-#define QRS_QR 0x8000 /* QR: on if this is a response */
+#define QRS_QR 0x8000 /* QR: on if this is a response */
-#define QRS_OPCODE_SHIFT 11 /* OPCODE field */
-#define QRS_OPCODE_MASK 0xF
-#define QRSO_QUERY 0 /* standard query */
-#define QRSO_IQUERY 1 /* inverse query */
-#define QRSO_STATUS 2 /* server status request query */
+#define QRS_OPCODE_SHIFT 11 /* OPCODE field */
+#define QRS_OPCODE_MASK 0xF
+#define QRSO_QUERY 0 /* standard query */
+#define QRSO_IQUERY 1 /* inverse query */
+#define QRSO_STATUS 2 /* server status request query */
-#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */
-#define QRS_TC 0x0200 /* TC: on if truncation happened */
-#define QRS_RD 0x0100 /* RD: on if recursion desired */
-#define QRS_RA 0x0080 /* RA: on if recursion available */
-#define QRS_Z 0x0040 /* Z: reserved; must be zero */
-#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */
-#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */
+#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */
+#define QRS_TC 0x0200 /* TC: on if truncation happened */
+#define QRS_RD 0x0100 /* RD: on if recursion desired */
+#define QRS_RA 0x0080 /* RA: on if recursion available */
+#define QRS_Z 0x0040 /* Z: reserved; must be zero */
+#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */
+#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */
-#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
-#define QRS_RCODE_MASK 0xF
-#define QRSR_OK 0
+#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
+#define QRS_RCODE_MASK 0xF
+#define QRSR_OK 0
- u_int16_t qdcount; /* number of entries in question section */
- u_int16_t ancount; /* number of resource records in answer section */
- u_int16_t nscount; /* number of name server resource records in authority section */
- u_int16_t arcount; /* number of resource records in additional records section */
+ u_int16_t qdcount; /* number of entries in question section */
+ u_int16_t ancount; /* number of resource records in answer section */
+ u_int16_t nscount; /* number of name server resource records in authority section */
+ u_int16_t arcount; /* number of resource records in additional records section */
};
static field_desc qr_header_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc qr_header_desc = {
- "Query Response Header",
- qr_header_fields,
- sizeof(struct qr_header)
+ "Query Response Header",
+ qr_header_fields,
+ sizeof(struct qr_header)
};
/* Messages for codes in RCODE (see RFC 1035 4.1.1) */
static const err_t rcode_text[QRS_RCODE_MASK + 1] = {
- NULL, /* not an error */
- "Format error - The name server was unable to interpret the query",
- "Server failure - The name server was unable to process this query"
- " due to a problem with the name server",
- "Name Error - Meaningful only for responses from an authoritative name"
- " server, this code signifies that the domain name referenced in"
- " the query does not exist",
- "Not Implemented - The name server does not support the requested"
- " kind of query",
- "Refused - The name server refuses to perform the specified operation"
- " for policy reasons",
- /* the rest are reserved for future use */
- };
+ NULL, /* not an error */
+ "Format error - The name server was unable to interpret the query",
+ "Server failure - The name server was unable to process this query"
+ " due to a problem with the name server",
+ "Name Error - Meaningful only for responses from an authoritative name"
+ " server, this code signifies that the domain name referenced in"
+ " the query does not exist",
+ "Not Implemented - The name server does not support the requested"
+ " kind of query",
+ "Refused - The name server refuses to perform the specified operation"
+ " for policy reasons",
+ /* the rest are reserved for future use */
+ };
/* throw away a possibly compressed domain name */
static err_t
eat_name(pb_stream *pbs)
{
- u_char name_buf[NS_MAXDNAME + 2];
- u_char *ip = pbs->cur;
- unsigned oi = 0;
- unsigned jump_count = 0;
-
- for (;;)
- {
- u_int8_t b;
+ u_char name_buf[NS_MAXDNAME + 2];
+ u_char *ip = pbs->cur;
+ unsigned oi = 0;
+ unsigned jump_count = 0;
- if (ip >= pbs->roof)
- return "ran out of message while skipping domain name";
-
- b = *ip++;
- if (jump_count == 0)
- pbs->cur = ip;
-
- if (b == 0)
- break;
-
- switch (b & 0xC0)
+ for (;;)
{
- case 0x00:
- /* we grab the next b characters */
- if (oi + b > NS_MAXDNAME)
- return "domain name too long";
+ u_int8_t b;
- if (pbs->roof - ip <= b)
- return "domain name falls off end of message";
+ if (ip >= pbs->roof)
+ return "ran out of message while skipping domain name";
- if (oi != 0)
- name_buf[oi++] = '.';
-
- memcpy(name_buf + oi, ip, b);
- oi += b;
- ip += b;
+ b = *ip++;
if (jump_count == 0)
- pbs->cur = ip;
- break;
-
- case 0xC0:
- {
- unsigned ix;
-
- if (ip >= pbs->roof)
- return "ran out of message in middle of compressed domain name";
-
- ix = ((b & ~0xC0u) << 8) | *ip++;
- if (jump_count == 0)
pbs->cur = ip;
- if (ix >= pbs_room(pbs))
- return "impossible compressed domain name";
+ if (b == 0)
+ break;
- /* Avoid infinite loop.
- * There can be no more jumps than there are bytes
- * in the packet. Not a tight limit, but good enough.
- */
- jump_count++;
- if (jump_count > pbs_room(pbs))
- return "loop in compressed domain name";
-
- ip = pbs->start + ix;
+ switch (b & 0xC0)
+ {
+ case 0x00:
+ /* we grab the next b characters */
+ if (oi + b > NS_MAXDNAME)
+ return "domain name too long";
+
+ if (pbs->roof - ip <= b)
+ return "domain name falls off end of message";
+
+ if (oi != 0)
+ name_buf[oi++] = '.';
+
+ memcpy(name_buf + oi, ip, b);
+ oi += b;
+ ip += b;
+ if (jump_count == 0)
+ pbs->cur = ip;
+ break;
+
+ case 0xC0:
+ {
+ unsigned ix;
+
+ if (ip >= pbs->roof)
+ return "ran out of message in middle of compressed domain name";
+
+ ix = ((b & ~0xC0u) << 8) | *ip++;
+ if (jump_count == 0)
+ pbs->cur = ip;
+
+ if (ix >= pbs_room(pbs))
+ return "impossible compressed domain name";
+
+ /* Avoid infinite loop.
+ * There can be no more jumps than there are bytes
+ * in the packet. Not a tight limit, but good enough.
+ */
+ jump_count++;
+ if (jump_count > pbs_room(pbs))
+ return "loop in compressed domain name";
+
+ ip = pbs->start + ix;
+ }
+ break;
+
+ default:
+ return "invalid code in label";
}
- break;
-
- default:
- return "invalid code in label";
}
- }
- name_buf[oi++] = '\0';
+ name_buf[oi++] = '\0';
- DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
+ DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
- return NULL;
+ return NULL;
}
static err_t
eat_name_helpfully(pb_stream *pbs, const char *context)
{
- err_t ugh = eat_name(pbs);
+ err_t ugh = eat_name(pbs);
- return ugh == NULL? ugh
- : builddiag("malformed name within DNS record of %s: %s", context, ugh);
+ return ugh == NULL? ugh
+ : builddiag("malformed name within DNS record of %s: %s", context, ugh);
}
/* non-variable part of 4.1.2 Question Section entry:
@@ -749,20 +789,20 @@ eat_name_helpfully(pb_stream *pbs, const char *context)
*/
struct qs_fixed {
- u_int16_t qtype;
- u_int16_t qclass;
+ u_int16_t qtype;
+ u_int16_t qclass;
};
static field_desc qs_fixed_fields[] = {
- { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
- { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
- { ft_end, 0, NULL, NULL }
+ { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
+ { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc qs_fixed_desc = {
- "Question Section entry fixed part",
- qs_fixed_fields,
- sizeof(struct qs_fixed)
+ "Question Section entry fixed part",
+ qs_fixed_fields,
+ sizeof(struct qs_fixed)
};
/* 4.1.3. Resource record format:
@@ -789,26 +829,26 @@ static struct_desc qs_fixed_desc = {
*/
struct rr_fixed {
- u_int16_t type;
- u_int16_t class;
- u_int32_t ttl; /* actually signed */
- u_int16_t rdlength;
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl; /* actually signed */
+ u_int16_t rdlength;
};
static field_desc rr_fixed_fields[] = {
- { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
- { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
- { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
+ { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
+ { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc rr_fixed_desc = {
- "Resource Record fixed part",
- rr_fixed_fields,
- /* note: following is tricky: avoids padding problems */
- offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
+ "Resource Record fixed part",
+ rr_fixed_fields,
+ /* note: following is tricky: avoids padding problems */
+ offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
};
/* RFC 1035 3.3.14: TXT RRs have text in the RDATA field.
@@ -830,22 +870,22 @@ static struct_desc rr_fixed_desc = {
*/
struct key_rdata {
- u_int16_t flags;
- u_int8_t protocol;
- u_int8_t algorithm;
+ u_int16_t flags;
+ u_int8_t protocol;
+ u_int8_t algorithm;
};
static field_desc key_rdata_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc key_rdata_desc = {
- "KEY RR RData fixed part",
- key_rdata_fields,
- sizeof(struct key_rdata)
+ "KEY RR RData fixed part",
+ key_rdata_fields,
+ sizeof(struct key_rdata)
};
/* RFC 2535 4.1 SIG RDATA format:
@@ -872,30 +912,30 @@ static struct_desc key_rdata_desc = {
*/
struct sig_rdata {
- u_int16_t type_covered;
- u_int8_t algorithm;
- u_int8_t labels;
- u_int32_t original_ttl;
- u_int32_t sig_expiration;
- u_int32_t sig_inception;
- u_int16_t key_tag;
+ u_int16_t type_covered;
+ u_int8_t algorithm;
+ u_int8_t labels;
+ u_int32_t original_ttl;
+ u_int32_t sig_expiration;
+ u_int32_t sig_inception;
+ u_int16_t key_tag;
};
static field_desc sig_rdata_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
- { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
- { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
- { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
- { ft_end, 0, NULL, NULL }
+ { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
+ { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
+ { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
+ { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
+ { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
+ { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
+ { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
+ { ft_end, 0, NULL, NULL }
};
static struct_desc sig_rdata_desc = {
- "SIG RR RData fixed part",
- sig_rdata_fields,
- sizeof(struct sig_rdata)
+ "SIG RR RData fixed part",
+ sig_rdata_fields,
+ sizeof(struct sig_rdata)
};
/* handle a KEY Resource Record. */
@@ -903,38 +943,37 @@ static struct_desc sig_rdata_desc = {
#ifdef USE_KEYRR
static err_t
process_key_rr(u_char *ptr, size_t len
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- pb_stream pbs;
- struct key_rdata kr;
-
- if (len < sizeof(struct key_rdata))
- return "KEY Resource Record's RD Length is too small";
+ pb_stream pbs;
+ struct key_rdata kr;
- init_pbs(&pbs, ptr, len, "KEY RR");
+ if (len < sizeof(struct key_rdata))
+ return "KEY Resource Record's RD Length is too small";
- if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
- return "failed to get fixed part of KEY Resource Record RDATA";
+ init_pbs(&pbs, ptr, len, "KEY RR");
- if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
- && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
- && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
- && (kr.flags & 0x2CF0) == 0) /* must be zero */
- {
- /* we have what seems to be a tasty key */
+ if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
+ return "failed to get fixed part of KEY Resource Record RDATA";
- if (doit)
+ if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
+ && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
+ && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
+ && (kr.flags & 0x2CF0) == 0) /* must be zero */
{
- chunk_t k;
+ /* we have what seems to be a tasty key */
+
+ if (doit)
+ {
+ chunk_t k = { pbs.cur, pbs_left(&pbs) };
- setchunk(k, pbs.cur, pbs_left(&pbs));
- TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k
- , &cr->keys_from_dns));
+ TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k
+ , &cr->keys_from_dns));
+ }
}
- }
- return NULL;
+ return NULL;
}
#endif /* USE_KEYRR */
@@ -946,130 +985,130 @@ process_key_rr(u_char *ptr, size_t len
static err_t
unpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen)
{
- size_t i = 0
- , o = 0;
+ size_t i = 0
+ , o = 0;
- while (i < slen)
- {
- size_t cl = s[i++];
+ while (i < slen)
+ {
+ size_t cl = s[i++];
- if (i + cl > slen)
- return "TXT rr RDATA representation malformed";
+ if (i + cl > slen)
+ return "TXT rr RDATA representation malformed";
- if (o + cl >= dlen)
- return "TXT rr RDATA too large";
+ if (o + cl >= dlen)
+ return "TXT rr RDATA too large";
- memcpy(d + o, s + i, cl);
- i += cl;
- o += cl;
- }
- d[o] = '\0';
- if (strlen(d) != o)
- return "TXT rr RDATA contains a NUL";
+ memcpy(d + o, s + i, cl);
+ i += cl;
+ o += cl;
+ }
+ d[o] = '\0';
+ if (strlen(d) != o)
+ return "TXT rr RDATA contains a NUL";
- return NULL;
+ return NULL;
}
static err_t
process_txt_rr(u_char *rdata, size_t rdlen
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */
+ u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */
- TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
- return process_txt_rr_body(str, doit, dns_auth_level, cr);
+ TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
+ return process_txt_rr_body(str, doit, dns_auth_level, cr);
}
static err_t
process_answer_section(pb_stream *pbs
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level *dns_auth_level
-, u_int16_t ancount /* number of RRs in the answer section */
+, u_int16_t ancount /* number of RRs in the answer section */
, struct adns_continuation *const cr)
{
- const int type = cr->query.type; /* type of RR of interest */
- unsigned c;
+ const int type = cr->query.type; /* type of RR of interest */
+ unsigned c;
- DBG(DBG_DNS, DBG_log("*Answer Section:"));
+ DBG(DBG_DNS, DBG_log("*Answer Section:"));
- for (c = 0; c != ancount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
+ for (c = 0; c != ancount; c++)
+ {
+ struct rr_fixed rrf;
+ size_t tail;
- /* ??? do we need to match the name? */
+ /* ??? do we need to match the name? */
- TRY(eat_name_helpfully(pbs, "Answer Section"));
+ TRY(eat_name_helpfully(pbs, "Answer Section"));
- if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
- return "failed to get fixed part of Answer Section Resource Record";
+ if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
+ return "failed to get fixed part of Answer Section Resource Record";
- if (rrf.rdlength > pbs_left(pbs))
- return "RD Length extends beyond end of message";
+ if (rrf.rdlength > pbs_left(pbs))
+ return "RD Length extends beyond end of message";
- /* ??? should we care about ttl? */
+ /* ??? should we care about ttl? */
- tail = rrf.rdlength;
+ tail = rrf.rdlength;
- if (rrf.type == type && rrf.class == C_IN)
- {
- err_t ugh = NULL;
+ if (rrf.type == type && rrf.class == C_IN)
+ {
+ err_t ugh = NULL;
- switch (type)
- {
+ switch (type)
+ {
#ifdef USE_KEYRR
- case T_KEY:
- ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
- break;
+ case T_KEY:
+ ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
+ break;
#endif /* USE_KEYRR */
- case T_TXT:
- ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
- break;
- case T_SIG:
- /* Check if SIG RR authenticates what we are learning.
- * The RRset covered by a SIG must have the same owner,
- * class, and type.
- * For us, the class is always C_IN, so that matches.
- * We decode the SIG RR's fixed part to check
- * that the type_covered field matches our query type
- * (this may be redundant).
- * We don't check the owner (apparently this is the
- * name on the record) -- we assume that it matches
- * or we would not have been given this SIG in the
- * Answer Section.
- *
- * We only look on first pass, and only if we've something
- * to learn. This cuts down on useless decoding.
- */
- if (!doit && *dns_auth_level == DAL_UNSIGNED)
- {
- struct sig_rdata sr;
-
- if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
- ugh = "failed to get fixed part of SIG Resource Record RDATA";
- else if (sr.type_covered == type)
- *dns_auth_level = DAL_SIGNED;
+ case T_TXT:
+ ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
+ break;
+ case T_SIG:
+ /* Check if SIG RR authenticates what we are learning.
+ * The RRset covered by a SIG must have the same owner,
+ * class, and type.
+ * For us, the class is always C_IN, so that matches.
+ * We decode the SIG RR's fixed part to check
+ * that the type_covered field matches our query type
+ * (this may be redundant).
+ * We don't check the owner (apparently this is the
+ * name on the record) -- we assume that it matches
+ * or we would not have been given this SIG in the
+ * Answer Section.
+ *
+ * We only look on first pass, and only if we've something
+ * to learn. This cuts down on useless decoding.
+ */
+ if (!doit && *dns_auth_level == DAL_UNSIGNED)
+ {
+ struct sig_rdata sr;
+
+ if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
+ ugh = "failed to get fixed part of SIG Resource Record RDATA";
+ else if (sr.type_covered == type)
+ *dns_auth_level = DAL_SIGNED;
+ }
+ break;
+ default:
+ ugh = builddiag("unexpected RR type %d", type);
+ break;
+ }
+ if (ugh != NULL)
+ return ugh;
}
- break;
- default:
- ugh = builddiag("unexpected RR type %d", type);
- break;
- }
- if (ugh != NULL)
- return ugh;
+ in_raw(NULL, tail, pbs, "RR RDATA");
}
- in_raw(NULL, tail, pbs, "RR RDATA");
- }
- return doit
- && cr->gateways_from_dns == NULL
+ return doit
+ && cr->gateways_from_dns == NULL
#ifdef USE_KEYRR
- && cr->keys_from_dns == NULL
+ && cr->keys_from_dns == NULL
#endif /* USE_KEYRR */
- ? builddiag("no suitable %s record found in DNS", rr_typename(type))
- : NULL;
+ ? builddiag("no suitable %s record found in DNS", rr_typename(type))
+ : NULL;
}
/* process DNS answer -- TXT or KEY query */
@@ -1078,153 +1117,153 @@ static err_t
process_dns_answer(struct adns_continuation *const cr
, u_char ans[], int anslen)
{
- const int type = cr->query.type; /* type of record being sought */
- int r; /* all-purpose return value holder */
- u_int16_t c; /* number of current RR in current answer section */
- pb_stream pbs;
- u_int8_t *ans_start; /* saved position of answer section */
- struct qr_header qr_header;
- enum dns_auth_level dns_auth_level;
+ const int type = cr->query.type; /* type of record being sought */
+ int r; /* all-purpose return value holder */
+ u_int16_t c; /* number of current RR in current answer section */
+ pb_stream pbs;
+ u_int8_t *ans_start; /* saved position of answer section */
+ struct qr_header qr_header;
+ enum dns_auth_level dns_auth_level;
- init_pbs(&pbs, ans, anslen, "Query Response Message");
+ init_pbs(&pbs, ans, anslen, "Query Response Message");
- /* decode and check header */
+ /* decode and check header */
- if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
- return "malformed header";
+ if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
+ return "malformed header";
- /* ID: nothing to do with us */
+ /* ID: nothing to do with us */
- /* stuff -- lots of things */
- if ((qr_header.stuff & QRS_QR) == 0)
- return "not a response?!?";
+ /* stuff -- lots of things */
+ if ((qr_header.stuff & QRS_QR) == 0)
+ return "not a response?!?";
- if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
- return "unexpected opcode";
+ if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
+ return "unexpected opcode";
- /* I don't think we care about AA */
+ /* I don't think we care about AA */
- if (qr_header.stuff & QRS_TC)
- return "response truncated";
+ if (qr_header.stuff & QRS_TC)
+ return "response truncated";
- /* I don't think we care about RD, RA, or CD */
+ /* I don't think we care about RD, RA, or CD */
- /* AD means "authentic data" */
- dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
+ /* AD means "authentic data" */
+ dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
- if (qr_header.stuff & QRS_Z)
- return "Z bit is not zero";
+ if (qr_header.stuff & QRS_Z)
+ return "Z bit is not zero";
- r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
- if (r != 0)
- return r < (int)elemsof(rcode_text)? rcode_text[r] : "unknown rcode";
+ r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
+ if (r != 0)
+ return r < (int)countof(rcode_text)? rcode_text[r] : "unknown rcode";
- if (qr_header.ancount == 0)
- return builddiag("no %s RR found by DNS", rr_typename(type));
+ if (qr_header.ancount == 0)
+ return builddiag("no %s RR found by DNS", rr_typename(type));
- /* end of header checking */
+ /* end of header checking */
- /* Question Section processing */
+ /* Question Section processing */
- /* 4.1.2. Question section format:
- * 1 1 1 1 1 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | |
- * / QNAME /
- * / /
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QTYPE |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QCLASS |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
+ /* 4.1.2. Question section format:
+ * 1 1 1 1 1 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | |
+ * / QNAME /
+ * / /
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | QTYPE |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | QCLASS |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
- DBG(DBG_DNS, DBG_log("*Question Section:"));
+ DBG(DBG_DNS, DBG_log("*Question Section:"));
- for (c = 0; c != qr_header.qdcount; c++)
- {
- struct qs_fixed qsf;
+ for (c = 0; c != qr_header.qdcount; c++)
+ {
+ struct qs_fixed qsf;
- TRY(eat_name_helpfully(&pbs, "Question Section"));
+ TRY(eat_name_helpfully(&pbs, "Question Section"));
- if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Question Section";
+ if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
+ return "failed to get fixed part of Question Section";
- if (qsf.qtype != type)
- return "unexpected QTYPE in Question Section";
+ if (qsf.qtype != type)
+ return "unexpected QTYPE in Question Section";
- if (qsf.qclass != C_IN)
- return "unexpected QCLASS in Question Section";
- }
+ if (qsf.qclass != C_IN)
+ return "unexpected QCLASS in Question Section";
+ }
- /* rest of sections are made up of Resource Records */
+ /* rest of sections are made up of Resource Records */
- /* Answer Section processing -- error checking, noting T_SIG */
+ /* Answer Section processing -- error checking, noting T_SIG */
- ans_start = pbs.cur; /* remember start of answer section */
+ ans_start = pbs.cur; /* remember start of answer section */
- TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
- , qr_header.ancount, cr));
+ TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
+ , qr_header.ancount, cr));
- /* Authority Section processing (just sanity checking) */
+ /* Authority Section processing (just sanity checking) */
- DBG(DBG_DNS, DBG_log("*Authority Section:"));
+ DBG(DBG_DNS, DBG_log("*Authority Section:"));
- for (c = 0; c != qr_header.nscount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
+ for (c = 0; c != qr_header.nscount; c++)
+ {
+ struct rr_fixed rrf;
+ size_t tail;
- TRY(eat_name_helpfully(&pbs, "Authority Section"));
+ TRY(eat_name_helpfully(&pbs, "Authority Section"));
- if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Authority Section Resource Record";
+ if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
+ return "failed to get fixed part of Authority Section Resource Record";
- if (rrf.rdlength > pbs_left(&pbs))
- return "RD Length extends beyond end of message";
+ if (rrf.rdlength > pbs_left(&pbs))
+ return "RD Length extends beyond end of message";
- /* ??? should we care about ttl? */
+ /* ??? should we care about ttl? */
- tail = rrf.rdlength;
+ tail = rrf.rdlength;
- in_raw(NULL, tail, &pbs, "RR RDATA");
- }
+ in_raw(NULL, tail, &pbs, "RR RDATA");
+ }
- /* Additional Section processing (just sanity checking) */
+ /* Additional Section processing (just sanity checking) */
- DBG(DBG_DNS, DBG_log("*Additional Section:"));
+ DBG(DBG_DNS, DBG_log("*Additional Section:"));
- for (c = 0; c != qr_header.arcount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
+ for (c = 0; c != qr_header.arcount; c++)
+ {
+ struct rr_fixed rrf;
+ size_t tail;
- TRY(eat_name_helpfully(&pbs, "Additional Section"));
+ TRY(eat_name_helpfully(&pbs, "Additional Section"));
- if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Additional Section Resource Record";
+ if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
+ return "failed to get fixed part of Additional Section Resource Record";
- if (rrf.rdlength > pbs_left(&pbs))
- return "RD Length extends beyond end of message";
+ if (rrf.rdlength > pbs_left(&pbs))
+ return "RD Length extends beyond end of message";
- /* ??? should we care about ttl? */
+ /* ??? should we care about ttl? */
- tail = rrf.rdlength;
+ tail = rrf.rdlength;
- in_raw(NULL, tail, &pbs, "RR RDATA");
- }
+ in_raw(NULL, tail, &pbs, "RR RDATA");
+ }
- /* done all sections */
+ /* done all sections */
- /* ??? is padding legal, or can we complain if more left in record? */
+ /* ??? is padding legal, or can we complain if more left in record? */
- /* process Answer Section again -- accept contents */
+ /* process Answer Section again -- accept contents */
- pbs.cur = ans_start; /* go back to start of answer section */
+ pbs.cur = ans_start; /* go back to start of answer section */
- return process_answer_section(&pbs, TRUE, &dns_auth_level
- , qr_header.ancount, cr);
+ return process_answer_section(&pbs, TRUE, &dns_auth_level
+ , qr_header.ancount, cr);
}
#endif /* ! USE_LWRES */
@@ -1239,101 +1278,101 @@ build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
, const char *typename USED_BY_DEBUG
, const char *gwname USED_BY_DEBUG)
{
- /* note: all end in "." to suppress relative searches */
- id = resolve_myid(id);
- switch (id->kind)
- {
- case ID_IPV4_ADDR:
- {
- /* XXX: this is really ugly and only temporary until addrtot can
- * generate the correct format
- */
- const unsigned char *b;
- size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
-
- passert(bl == 4);
- snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
- , b[3], b[2], b[1], b[0]);
- break;
- }
-
- case ID_IPV6_ADDR:
- {
- /* ??? is this correct? */
- const unsigned char *b;
- size_t bl;
- u_char *op = name_buf;
- static const char suffix[] = "IP6.INT.";
-
- for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
+ /* note: all end in "." to suppress relative searches */
+ id = resolve_myid(id);
+ switch (id->kind)
+ {
+ case ID_IPV4_ADDR:
{
- if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
- return "IPv6 reverse name too long";
- op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
+ /* XXX: this is really ugly and only temporary until addrtot can
+ * generate the correct format
+ */
+ const unsigned char *b;
+ size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
+
+ passert(bl == 4);
+ snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
+ , b[3], b[2], b[1], b[0]);
+ break;
}
- strcpy(op, suffix);
- break;
- }
- case ID_FQDN:
- /* strip trailing "." characters, then add one */
+ case ID_IPV6_ADDR:
{
- size_t il = id->name.len;
-
- while (il > 0 && id->name.ptr[il - 1] == '.')
- il--;
- if (il > NS_MAXDNAME)
- return "FQDN too long for domain name";
+ /* ??? is this correct? */
+ const unsigned char *b;
+ size_t bl;
+ u_char *op = name_buf;
+ static const char suffix[] = "IP6.INT.";
- memcpy(name_buf, id->name.ptr, il);
- strcpy(name_buf + il, ".");
+ for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
+ {
+ if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
+ return "IPv6 reverse name too long";
+ op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
+ }
+ strcpy(op, suffix);
+ break;
}
- break;
- default:
- return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
- }
+ case ID_FQDN:
+ /* strip trailing "." characters, then add one */
+ {
+ size_t il = id->name.len;
+
+ while (il > 0 && id->name.ptr[il - 1] == '.')
+ il--;
+ if (il > NS_MAXDNAME)
+ return "FQDN too long for domain name";
- DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)"
- , serial, typename, name_buf, gwname));
- return NULL;
+ memcpy(name_buf, id->name.ptr, il);
+ strcpy(name_buf + il, ".");
+ }
+ break;
+
+ default:
+ return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
+ }
+
+ DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)"
+ , serial, typename, name_buf, gwname));
+ return NULL;
}
void
gw_addref(struct gw_info *gw)
{
- if (gw != NULL)
- {
- DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt))
- gw->refcnt++;
- }
+ if (gw != NULL)
+ {
+ DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt))
+ gw->refcnt++;
+ }
}
void
gw_delref(struct gw_info **gwp)
{
- struct gw_info *gw = *gwp;
-
- if (gw != NULL)
- {
- DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt));
+ struct gw_info *gw = *gwp;
- passert(gw->refcnt != 0);
- gw->refcnt--;
- if (gw->refcnt == 0)
+ if (gw != NULL)
{
- free_id_content(&gw->client_id);
- free_id_content(&gw->gw_id);
- if (gw->gw_key_present)
- unreference_key(&gw->key);
- gw_delref(&gw->next);
- pfree(gw); /* trickery could make this a tail-call */
+ DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt));
+
+ passert(gw->refcnt != 0);
+ gw->refcnt--;
+ if (gw->refcnt == 0)
+ {
+ free_id_content(&gw->client_id);
+ free_id_content(&gw->gw_id);
+ if (gw->gw_key_present)
+ unreference_key(&gw->key);
+ gw_delref(&gw->next);
+ free(gw); /* trickery could make this a tail-call */
+ }
+ *gwp = NULL;
}
- *gwp = NULL;
- }
}
-static int adns_in_flight = 0; /* queries outstanding */
+static int adns_in_flight = 0; /* queries outstanding */
/* Start an asynchronous DNS query.
*
@@ -1372,123 +1411,123 @@ static int adns_in_flight = 0; /* queries outstanding */
* disestablishing any logging context (whack_log_fd, cur_*).
*/
-static struct adns_continuation *continuations = NULL; /* newest of queue */
-static struct adns_continuation *next_query = NULL; /* oldest not sent */
+static struct adns_continuation *continuations = NULL; /* newest of queue */
+static struct adns_continuation *next_query = NULL; /* oldest not sent */
static struct adns_continuation *
continuation_for_qtid(unsigned long qtid)
{
- struct adns_continuation *cr = NULL;
+ struct adns_continuation *cr = NULL;
- if (qtid != 0)
- for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous)
- ;
- return cr;
+ if (qtid != 0)
+ for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous)
+ ;
+ return cr;
}
static void
release_adns_continuation(struct adns_continuation *cr)
{
- passert(cr != next_query);
- gw_delref(&cr->gateways_from_dns);
+ passert(cr != next_query);
+ gw_delref(&cr->gateways_from_dns);
#ifdef USE_KEYRR
- free_public_keys(&cr->keys_from_dns);
+ free_public_keys(&cr->keys_from_dns);
#endif /* USE_KEYRR */
- unshare_id_content(&cr->id);
- unshare_id_content(&cr->sgw_id);
-
- /* unlink from doubly-linked list */
- if (cr->next == NULL)
- {
- passert(continuations == cr);
- continuations = cr->previous;
- }
- else
- {
- passert(cr->next->previous == cr);
- cr->next->previous = cr->previous;
- }
-
- if (cr->previous != NULL)
- {
- passert(cr->previous->next == cr);
- cr->previous->next = cr->next;
- }
-
- pfree(cr);
+ unshare_id_content(&cr->id);
+ unshare_id_content(&cr->sgw_id);
+
+ /* unlink from doubly-linked list */
+ if (cr->next == NULL)
+ {
+ passert(continuations == cr);
+ continuations = cr->previous;
+ }
+ else
+ {
+ passert(cr->next->previous == cr);
+ cr->next->previous = cr->previous;
+ }
+
+ if (cr->previous != NULL)
+ {
+ passert(cr->previous->next == cr);
+ cr->previous->next = cr->next;
+ }
+
+ free(cr);
}
err_t
-start_adns_query(const struct id *id /* domain to query */
-, const struct id *sgw_id /* if non-null, any accepted gw_info must match */
-, int type /* T_TXT or T_KEY, selecting rr type of interest */
+start_adns_query(const struct id *id /* domain to query */
+, const struct id *sgw_id /* if non-null, any accepted gw_info must match */
+, int type /* T_TXT or T_KEY, selecting rr type of interest */
, cont_fn_t cont_fn
, struct adns_continuation *cr)
{
- static unsigned long qtid = 1; /* query transaction id; NOTE: static */
- const char *typename = rr_typename(type);
- char gwidb[BUF_LEN];
-
- if(adns_pid == 0
- && adns_restart_count < ADNS_RESTART_MAX)
- {
- plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count);
- init_adns();
- }
-
-
- /* Splice this in at head of doubly-linked list of continuations.
- * Note: this must be done before any release_adns_continuation().
- */
- cr->next = NULL;
- cr->previous = continuations;
- if (continuations != NULL)
- {
- passert(continuations->next == NULL);
- continuations->next = cr;
- }
- continuations = cr;
-
- cr->qtid = qtid++;
- cr->type = type;
- cr->cont_fn = cont_fn;
- cr->id = *id;
- unshare_id_content(&cr->id);
- cr->sgw_specified = sgw_id != NULL;
- cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
- unshare_id_content(&cr->sgw_id);
- cr->gateways_from_dns = NULL;
+ static unsigned long qtid = 1; /* query transaction id; NOTE: static */
+ const char *typename = rr_typename(type);
+ char gwidb[BUF_LEN];
+
+ if(adns_pid == 0
+ && adns_restart_count < ADNS_RESTART_MAX)
+ {
+ plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count);
+ init_adns();
+ }
+
+
+ /* Splice this in at head of doubly-linked list of continuations.
+ * Note: this must be done before any release_adns_continuation().
+ */
+ cr->next = NULL;
+ cr->previous = continuations;
+ if (continuations != NULL)
+ {
+ passert(continuations->next == NULL);
+ continuations->next = cr;
+ }
+ continuations = cr;
+
+ cr->qtid = qtid++;
+ cr->type = type;
+ cr->cont_fn = cont_fn;
+ cr->id = *id;
+ unshare_id_content(&cr->id);
+ cr->sgw_specified = sgw_id != NULL;
+ cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
+ unshare_id_content(&cr->sgw_id);
+ cr->gateways_from_dns = NULL;
#ifdef USE_KEYRR
- cr->keys_from_dns = NULL;
+ cr->keys_from_dns = NULL;
#endif /* USE_KEYRR */
#ifdef DEBUG
- cr->debugging = cur_debugging;
+ cr->debugging = cur_debugging;
#else
- cr->debugging = LEMPTY;
+ cr->debugging = LEMPTY;
#endif
- idtoa(&cr->sgw_id, gwidb, sizeof(gwidb));
+ idtoa(&cr->sgw_id, gwidb, sizeof(gwidb));
- zero(&cr->query);
+ zero(&cr->query);
- {
- err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid
- , id, typename, gwidb);
-
- if (ugh != NULL)
{
- release_adns_continuation(cr);
- return ugh;
+ err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid
+ , id, typename, gwidb);
+
+ if (ugh != NULL)
+ {
+ release_adns_continuation(cr);
+ return ugh;
+ }
}
- }
- if (next_query == NULL)
- next_query = cr;
+ if (next_query == NULL)
+ next_query = cr;
- unsent_ADNS_queries = TRUE;
+ unsent_ADNS_queries = TRUE;
- return NULL;
+ return NULL;
}
/* send remaining ADNS queries (until pipe full or none left)
@@ -1501,79 +1540,79 @@ bool unsent_ADNS_queries = FALSE;
void
send_unsent_ADNS_queries(void)
{
- static const unsigned char *buf_end = NULL; /* NOTE STATIC */
- static const unsigned char *buf_cur = NULL; /* NOTE STATIC */
+ static const unsigned char *buf_end = NULL; /* NOTE STATIC */
+ static const unsigned char *buf_cur = NULL; /* NOTE STATIC */
- if (adns_qfd == NULL_FD)
- return; /* nothing useful to do */
+ if (adns_qfd == NULL_FD)
+ return; /* nothing useful to do */
- for (;;)
- {
- if (buf_cur != buf_end)
+ for (;;)
{
- static int try = 0; /* NOTE STATIC */
- size_t n = buf_end - buf_cur;
- ssize_t r = write(adns_qfd, buf_cur, n);
-
- if (r == -1)
- {
- switch (errno)
+ if (buf_cur != buf_end)
{
- case EINTR:
- continue; /* try again now */
- case EAGAIN:
- DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS"));
- break; /* try again later */
- default:
- try++;
- log_errno((e, "error %d writing DNS query", try));
- break; /* try again later */
+ static int try = 0; /* NOTE STATIC */
+ size_t n = buf_end - buf_cur;
+ ssize_t r = write(adns_qfd, buf_cur, n);
+
+ if (r == -1)
+ {
+ switch (errno)
+ {
+ case EINTR:
+ continue; /* try again now */
+ case EAGAIN:
+ DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS"));
+ break; /* try again later */
+ default:
+ try++;
+ log_errno((e, "error %d writing DNS query", try));
+ break; /* try again later */
+ }
+ unsent_ADNS_queries = TRUE;
+ break; /* done! */
+ }
+ else
+ {
+ passert(r >= 0);
+ try = 0;
+ buf_cur += r;
+ }
}
- unsent_ADNS_queries = TRUE;
- break; /* done! */
- }
- else
- {
- passert(r >= 0);
- try = 0;
- buf_cur += r;
- }
- }
- else
- {
- if (next_query == NULL)
- {
- unsent_ADNS_queries = FALSE;
- break; /* done! */
- }
+ else
+ {
+ if (next_query == NULL)
+ {
+ unsent_ADNS_queries = FALSE;
+ break; /* done! */
+ }
#ifdef USE_LWRES
- next_query->used = FALSE;
- {
- /* NOTE STATIC: */
- static unsigned char qbuf[LWDNSQ_CMDBUF_LEN + 1]; /* room for NUL */
-
- snprintf(qbuf, sizeof(qbuf), "%s %lu %s\n"
- , rr_typename(next_query->type)
- , next_query->qtid
- , next_query->query.name_buf);
- DBG(DBG_DNS, DBG_log("lwdnsq query: %.*s", (int)(strlen(qbuf) - 1), qbuf));
- buf_cur = qbuf;
- buf_end = qbuf + strlen(qbuf);
- }
+ next_query->used = FALSE;
+ {
+ /* NOTE STATIC: */
+ static unsigned char qbuf[LWDNSQ_CMDBUF_LEN + 1]; /* room for NUL */
+
+ snprintf(qbuf, sizeof(qbuf), "%s %lu %s\n"
+ , rr_typename(next_query->type)
+ , next_query->qtid
+ , next_query->query.name_buf);
+ DBG(DBG_DNS, DBG_log("lwdnsq query: %.*s", (int)(strlen(qbuf) - 1), qbuf));
+ buf_cur = qbuf;
+ buf_end = qbuf + strlen(qbuf);
+ }
#else /* !USE_LWRES */
- next_query->query.debugging = next_query->debugging;
- next_query->query.serial = next_query->qtid;
- next_query->query.len = sizeof(next_query->query);
- next_query->query.qmagic = ADNS_Q_MAGIC;
- next_query->query.type = next_query->type;
- buf_cur = (const void *)&next_query->query;
- buf_end = buf_cur + sizeof(next_query->query);
+ next_query->query.debugging = next_query->debugging;
+ next_query->query.serial = next_query->qtid;
+ next_query->query.len = sizeof(next_query->query);
+ next_query->query.qmagic = ADNS_Q_MAGIC;
+ next_query->query.type = next_query->type;
+ buf_cur = (const void *)&next_query->query;
+ buf_end = buf_cur + sizeof(next_query->query);
#endif /* !USE_LWRES */
- next_query = next_query->next;
- adns_in_flight++;
+ next_query = next_query->next;
+ adns_in_flight++;
+ }
}
- }
}
#ifdef USE_LWRES
@@ -1584,379 +1623,379 @@ send_unsent_ADNS_queries(void)
static err_t
process_lwdnsq_answer(char *ts)
{
- err_t ugh = NULL;
- char *rest;
- char *p;
- char *endofnumber;
- struct adns_continuation *cr = NULL;
- unsigned long qtid;
- time_t anstime; /* time of answer */
- char *atype; /* type of answer */
- long ttl; /* ttl of answer; int, but long for conversion */
- bool AuthenticatedData = FALSE;
- static char scratch_null_str[] = ""; /* cannot be const, but isn't written */
-
- /* query transaction id */
- rest = ts;
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq: answer missing query transaction ID";
-
- qtid = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq: malformed query transaction ID";
-
- cr = continuation_for_qtid(qtid);
- if (qtid != 0 && cr == NULL)
- return "lwdnsq: unrecognized qtid"; /* can't happen! */
-
- /* time */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq: missing time";
-
- anstime = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq: malformed time";
-
- /* TTL */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq: missing TTL";
-
- ttl = strtol(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq: malformed TTL";
-
- /* type */
- atype = strsep(&rest, " \t");
- if (atype == NULL)
- return "lwdnsq: missing type";
-
- /* if rest is NULL, make it "", otherwise eat whitespace after type */
- rest = rest == NULL? scratch_null_str : rest + strspn(rest, " \t");
-
- if (strncasecmp(atype, "AD-", 3) == 0)
- {
- AuthenticatedData = TRUE;
- atype += 3;
- }
-
- /* deal with each type */
-
- if (cr == NULL)
- {
- /* we don't actually know which this applies to */
- return builddiag("lwdnsq: 0 qtid invalid with %s", atype);
- }
- else if (strcaseeq(atype, "START"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "DONE"))
- {
- if (!cr->used)
+ err_t ugh = NULL;
+ char *rest;
+ char *p;
+ char *endofnumber;
+ struct adns_continuation *cr = NULL;
+ unsigned long qtid;
+ time_t anstime; /* time of answer */
+ char *atype; /* type of answer */
+ long ttl; /* ttl of answer; int, but long for conversion */
+ bool AuthenticatedData = FALSE;
+ static char scratch_null_str[] = ""; /* cannot be const, but isn't written */
+
+ /* query transaction id */
+ rest = ts;
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq: answer missing query transaction ID";
+
+ qtid = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq: malformed query transaction ID";
+
+ cr = continuation_for_qtid(qtid);
+ if (qtid != 0 && cr == NULL)
+ return "lwdnsq: unrecognized qtid"; /* can't happen! */
+
+ /* time */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq: missing time";
+
+ anstime = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq: malformed time";
+
+ /* TTL */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq: missing TTL";
+
+ ttl = strtol(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq: malformed TTL";
+
+ /* type */
+ atype = strsep(&rest, " \t");
+ if (atype == NULL)
+ return "lwdnsq: missing type";
+
+ /* if rest is NULL, make it "", otherwise eat whitespace after type */
+ rest = rest == NULL? scratch_null_str : rest + strspn(rest, " \t");
+
+ if (strncasecmp(atype, "AD-", 3) == 0)
{
- /* "no results returned by lwdnsq" should not happen */
- cr->cont_fn(cr
- , cr->gateways_from_dns == NULL
+ AuthenticatedData = TRUE;
+ atype += 3;
+ }
+
+ /* deal with each type */
+
+ if (cr == NULL)
+ {
+ /* we don't actually know which this applies to */
+ return builddiag("lwdnsq: 0 qtid invalid with %s", atype);
+ }
+ else if (strcaseeq(atype, "START"))
+ {
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "DONE"))
+ {
+ if (!cr->used)
+ {
+ /* "no results returned by lwdnsq" should not happen */
+ cr->cont_fn(cr
+ , cr->gateways_from_dns == NULL
#ifdef USE_KEYRR
- && cr->keys_from_dns == NULL
+ && cr->keys_from_dns == NULL
#endif /* USE_KEYRR */
- ? "no results returned by lwdnsq" : NULL);
- cr->used = TRUE;
+ ? "no results returned by lwdnsq" : NULL);
+ cr->used = TRUE;
+ }
+ reset_globals();
+ release_adns_continuation(cr);
+ adns_in_flight--;
+ }
+ else if (strcaseeq(atype, "RETRY"))
+ {
+ if (!cr->used)
+ {
+ cr->cont_fn(cr, rest);
+ cr->used = TRUE;
+ }
}
- reset_globals();
- release_adns_continuation(cr);
- adns_in_flight--;
- }
- else if (strcaseeq(atype, "RETRY"))
- {
- if (!cr->used)
+ else if (strcaseeq(atype, "FATAL"))
{
- cr->cont_fn(cr, rest);
- cr->used = TRUE;
+ if (!cr->used)
+ {
+ cr->cont_fn(cr, rest);
+ cr->used = TRUE;
+ }
}
- }
- else if (strcaseeq(atype, "FATAL"))
- {
- if (!cr->used)
+ else if (strcaseeq(atype, "DNSSEC"))
{
- cr->cont_fn(cr, rest);
- cr->used = TRUE;
+ /* ignore */
}
- }
- else if (strcaseeq(atype, "DNSSEC"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "NAME"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "TXT"))
- {
- char *end = rest + strlen(rest);
- err_t txt_ugh;
-
- if (*rest == '"' && end[-1] == '"')
+ else if (strcaseeq(atype, "NAME"))
{
- /* strip those pesky quotes */
- rest++;
- *--end = '\0';
+ /* ignore */
}
+ else if (strcaseeq(atype, "TXT"))
+ {
+ char *end = rest + strlen(rest);
+ err_t txt_ugh;
+
+ if (*rest == '"' && end[-1] == '"')
+ {
+ /* strip those pesky quotes */
+ rest++;
+ *--end = '\0';
+ }
- txt_ugh = process_txt_rr_body(rest
- , TRUE
- , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
- , cr);
+ txt_ugh = process_txt_rr_body(rest
+ , TRUE
+ , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
+ , cr);
- if (txt_ugh != NULL)
+ if (txt_ugh != NULL)
+ {
+ DBG(DBG_DNS,
+ DBG_log("error processing TXT resource record (%s) while processing: %s"
+ , txt_ugh, rest));
+ cr->cont_fn(cr, txt_ugh);
+ cr->used = TRUE;
+ }
+ }
+ else if (strcaseeq(atype, "SIG"))
+ {
+ /* record the SIG records for posterity */
+ if (cr->last_info != NULL)
+ {
+ free(cr->last_info->dns_sig);
+ cr->last_info->dns_sig = clone_str(rest);
+ }
+ }
+ else if (strcaseeq(atype, "A"))
+ {
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "AAAA"))
{
- DBG(DBG_DNS,
- DBG_log("error processing TXT resource record (%s) while processing: %s"
- , txt_ugh, rest));
- cr->cont_fn(cr, txt_ugh);
- cr->used = TRUE;
+ /* ignore */
}
- }
- else if (strcaseeq(atype, "SIG"))
- {
- /* record the SIG records for posterity */
- if (cr->last_info != NULL)
+ else if (strcaseeq(atype, "CNAME"))
{
- pfreeany(cr->last_info->dns_sig);
- cr->last_info->dns_sig = clone_str(rest, "sigrecord");
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "CNAMEFROM"))
+ {
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "PTR"))
+ {
+ /* ignore */
}
- }
- else if (strcaseeq(atype, "A"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "AAAA"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "CNAME"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "CNAMEFROM"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "PTR"))
- {
- /* ignore */
- }
#ifdef USE_KEYRR
- else if (strcaseeq(atype, "KEY"))
- {
- err_t key_ugh = process_lwdnsq_key(rest
- , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
- , cr);
-
- if (key_ugh != NULL)
+ else if (strcaseeq(atype, "KEY"))
{
- DBG(DBG_DNS,
- DBG_log("error processing KEY resource record (%s) while processing: %s"
- , key_ugh, rest));
- cr->cont_fn(cr, key_ugh);
- cr->used = TRUE;
+ err_t key_ugh = process_lwdnsq_key(rest
+ , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
+ , cr);
+
+ if (key_ugh != NULL)
+ {
+ DBG(DBG_DNS,
+ DBG_log("error processing KEY resource record (%s) while processing: %s"
+ , key_ugh, rest));
+ cr->cont_fn(cr, key_ugh);
+ cr->used = TRUE;
+ }
}
- }
#endif /* USE_KEYRR */
- else
- {
- ugh = "lwdnsq: unrecognized type";
- }
- return ugh;
+ else
+ {
+ ugh = "lwdnsq: unrecognized type";
+ }
+ return ugh;
}
#endif /* USE_LWRES */
static void
recover_adns_die(void)
{
- struct adns_continuation *cr = NULL;
-
- adns_pid = 0;
- if(adns_restart_count < ADNS_RESTART_MAX) {
- adns_restart_count++;
+ struct adns_continuation *cr = NULL;
+
+ adns_pid = 0;
+ if(adns_restart_count < ADNS_RESTART_MAX) {
+ adns_restart_count++;
- /* next DNS query will restart it */
+ /* next DNS query will restart it */
- /* we have to walk the list of the outstanding requests,
- * and redo them!
- */
+ /* we have to walk the list of the outstanding requests,
+ * and redo them!
+ */
- cr = continuations;
+ cr = continuations;
- /* find the head of the list */
- if(continuations != NULL) {
- for (; cr->previous != NULL; cr = cr->previous);
- }
-
- next_query = cr;
+ /* find the head of the list */
+ if(continuations != NULL) {
+ for (; cr->previous != NULL; cr = cr->previous);
+ }
+
+ next_query = cr;
- if(next_query != NULL) {
- unsent_ADNS_queries = TRUE;
+ if(next_query != NULL) {
+ unsent_ADNS_queries = TRUE;
+ }
}
- }
}
void reset_adns_restart_count(void)
{
- adns_restart_count=0;
+ adns_restart_count=0;
}
void
handle_adns_answer(void)
{
/* These are retained across calls to handle_adns_answer. */
- static size_t buflen = 0; /* bytes in answer buffer */
+ static size_t buflen = 0; /* bytes in answer buffer */
#ifndef USE_LWRES
- static struct adns_answer buf;
+ static struct adns_answer buf;
#else /* USE_LWRES */
- static char buf[LWDNSQ_RESULT_LEN_MAX];
- static char buf_copy[LWDNSQ_RESULT_LEN_MAX];
+ static char buf[LWDNSQ_RESULT_LEN_MAX];
+ static char buf_copy[LWDNSQ_RESULT_LEN_MAX];
#endif /* USE_LWRES */
- ssize_t n;
+ ssize_t n;
- passert(buflen < sizeof(buf));
- n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen);
+ passert(buflen < sizeof(buf));
+ n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen);
- if (n < 0)
- {
- if (errno != EINTR)
+ if (n < 0)
{
- log_errno((e, "error reading answer from adns"));
- /* ??? how can we recover? */
+ if (errno != EINTR)
+ {
+ log_errno((e, "error reading answer from adns"));
+ /* ??? how can we recover? */
+ }
+ n = 0; /* now n reflects amount read */
}
- n = 0; /* now n reflects amount read */
- }
- else if (n == 0)
- {
- /* EOF */
- if (adns_in_flight != 0)
+ else if (n == 0)
{
- plog("EOF from ADNS with %d queries outstanding (restarts %d)"
- , adns_in_flight, adns_restart_count);
- recover_adns_die();
+ /* EOF */
+ if (adns_in_flight != 0)
+ {
+ plog("EOF from ADNS with %d queries outstanding (restarts %d)"
+ , adns_in_flight, adns_restart_count);
+ recover_adns_die();
+ }
+ if (buflen != 0)
+ {
+ plog("EOF from ADNS with %lu bytes of a partial answer outstanding"
+ "(restarts %d)"
+ , (unsigned long)buflen
+ , adns_restart_count);
+ recover_adns_die();
+ }
+ stop_adns();
+ return;
}
- if (buflen != 0)
+ else
{
- plog("EOF from ADNS with %lu bytes of a partial answer outstanding"
- "(restarts %d)"
- , (unsigned long)buflen
- , adns_restart_count);
- recover_adns_die();
+ passert(adns_in_flight > 0);
}
- stop_adns();
- return;
- }
- else
- {
- passert(adns_in_flight > 0);
- }
-
- buflen += n;
+
+ buflen += n;
#ifndef USE_LWRES
- while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len)
- {
- /* we've got a tasty answer -- process it */
- err_t ugh;
- struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */
- const char *typename = rr_typename(cr->query.type);
- const char *name_buf = cr->query.name_buf;
+ while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len)
+ {
+ /* we've got a tasty answer -- process it */
+ err_t ugh;
+ struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */
+ const char *typename = rr_typename(cr->query.type);
+ const char *name_buf = cr->query.name_buf;
#ifdef USE_KEYRR
- passert(cr->keys_from_dns == NULL);
+ passert(cr->keys_from_dns == NULL);
#endif /* USE_KEYRR */
- passert(cr->gateways_from_dns == NULL);
- adns_in_flight--;
- if (buf.result == -1)
- {
- /* newer resolvers support statp->res_h_errno as well as h_errno.
- * That might be better, but older resolvers don't.
- * See resolver(3), if you have it.
- * The undocumented(!) h_errno values are defined in
- * /usr/include/netdb.h.
- */
- switch (buf.h_errno_val)
- {
- case NO_DATA:
- ugh = builddiag("no %s record for %s", typename, name_buf);
- break;
- case HOST_NOT_FOUND:
- ugh = builddiag("no host %s for %s record", name_buf, typename);
- break;
- default:
- ugh = builddiag("failure querying DNS for %s of %s: %s"
- , typename, name_buf, hstrerror(buf.h_errno_val));
- break;
- }
- }
- else if (buf.result > (int) sizeof(buf.ans))
- {
- ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
- , (long)buf.result);
- }
- else
- {
- ugh = process_dns_answer(cr, buf.ans, buf.result);
- if (ugh != NULL)
- ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
- , typename, name_buf, ugh);
+ passert(cr->gateways_from_dns == NULL);
+ adns_in_flight--;
+ if (buf.result == -1)
+ {
+ /* newer resolvers support statp->res_h_errno as well as h_errno.
+ * That might be better, but older resolvers don't.
+ * See resolver(3), if you have it.
+ * The undocumented(!) h_errno values are defined in
+ * /usr/include/netdb.h.
+ */
+ switch (buf.h_errno_val)
+ {
+ case NO_DATA:
+ ugh = builddiag("no %s record for %s", typename, name_buf);
+ break;
+ case HOST_NOT_FOUND:
+ ugh = builddiag("no host %s for %s record", name_buf, typename);
+ break;
+ default:
+ ugh = builddiag("failure querying DNS for %s of %s: %s"
+ , typename, name_buf, hstrerror(buf.h_errno_val));
+ break;
+ }
+ }
+ else if (buf.result > (int) sizeof(buf.ans))
+ {
+ ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
+ , (long)buf.result);
+ }
+ else
+ {
+ ugh = process_dns_answer(cr, buf.ans, buf.result);
+ if (ugh != NULL)
+ ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
+ , typename, name_buf, ugh);
+ }
+ DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
+ DBG_log(BLANK_FORMAT);
+ if (ugh == NULL)
+ DBG_log("asynch DNS answer %lu for %s of %s"
+ , cr->query.serial, typename, name_buf);
+ else
+ DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh);
+ );
+
+ passert(GLOBALS_ARE_RESET());
+ cr->cont_fn(cr, ugh);
+ reset_globals();
+ release_adns_continuation(cr);
+
+ /* shift out answer that we've consumed */
+ buflen -= buf.len;
+ memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen);
}
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
- DBG_log(BLANK_FORMAT);
- if (ugh == NULL)
- DBG_log("asynch DNS answer %lu for %s of %s"
- , cr->query.serial, typename, name_buf);
- else
- DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh);
- );
-
- passert(GLOBALS_ARE_RESET());
- cr->cont_fn(cr, ugh);
- reset_globals();
- release_adns_continuation(cr);
-
- /* shift out answer that we've consumed */
- buflen -= buf.len;
- memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen);
- }
#else /* USE_LWRES */
- for (;;)
- {
- err_t ugh;
- char *nlp = memchr(buf, '\n', buflen);
+ for (;;)
+ {
+ err_t ugh;
+ char *nlp = memchr(buf, '\n', buflen);
- if (nlp == NULL)
- break;
+ if (nlp == NULL)
+ break;
- /* we've got a line */
- *nlp++ = '\0';
+ /* we've got a line */
+ *nlp++ = '\0';
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS
- , DBG_log("lwdns: %s", buf));
+ DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS
+ , DBG_log("lwdns: %s", buf));
- /* process lwdnsq_answer may modify buf, so make a copy. */
- buf_copy[0]='\0';
- strncat(buf_copy, buf, sizeof(buf_copy));
+ /* process lwdnsq_answer may modify buf, so make a copy. */
+ buf_copy[0]='\0';
+ strncat(buf_copy, buf, sizeof(buf_copy));
- ugh = process_lwdnsq_answer(buf_copy);
- if (ugh != NULL)
- plog("failure processing lwdnsq output: %s; record: %s"
- , ugh, buf);
+ ugh = process_lwdnsq_answer(buf_copy);
+ if (ugh != NULL)
+ plog("failure processing lwdnsq output: %s; record: %s"
+ , ugh, buf);
- passert(GLOBALS_ARE_RESET());
- reset_globals();
+ passert(GLOBALS_ARE_RESET());
+ reset_globals();
- /* shift out answer that we've consumed */
- buflen -= nlp - buf;
- memmove(buf, nlp, buflen);
- }
+ /* shift out answer that we've consumed */
+ buflen -= nlp - buf;
+ memmove(buf, nlp, buflen);
+ }
#endif /* USE_LWRES */
}
diff --git a/src/pluto/dnskey.h b/src/pluto/dnskey.h
index f69c226c8..976c715bf 100644
--- a/src/pluto/dnskey.h
+++ b/src/pluto/dnskey.h
@@ -10,14 +10,12 @@
* 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: dnskey.h 3252 2007-10-06 21:24:50Z andreas $
*/
extern int
- adns_qfd, /* file descriptor for sending queries to adns */
- adns_afd; /* file descriptor for receiving answers from adns */
-extern const char *pluto_adns_option; /* path from --pluto_adns */
+ adns_qfd, /* file descriptor for sending queries to adns */
+ adns_afd; /* file descriptor for receiving answers from adns */
+extern const char *pluto_adns_option; /* path from --pluto_adns */
extern void init_adns(void);
extern void stop_adns(void);
extern void handle_adns_answer(void);
@@ -30,55 +28,55 @@ extern void send_unsent_ADNS_queries(void);
* Freed by call to release_adns_continuation.
*/
-struct adns_continuation; /* forward declaration (not far!) */
+struct adns_continuation; /* forward declaration (not far!) */
typedef void (*cont_fn_t)(struct adns_continuation *cr, err_t ugh);
struct adns_continuation {
- unsigned long qtid; /* query transaction id number */
- int type; /* T_TXT or T_KEY, selecting rr type of interest */
- cont_fn_t cont_fn; /* function to carry on suspended work */
- struct id id; /* subject of query */
- bool sgw_specified;
- struct id sgw_id; /* peer, if constrained */
- lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
- struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */
+ unsigned long qtid; /* query transaction id number */
+ int type; /* T_TXT or T_KEY, selecting rr type of interest */
+ cont_fn_t cont_fn; /* function to carry on suspended work */
+ struct id id; /* subject of query */
+ bool sgw_specified;
+ struct id sgw_id; /* peer, if constrained */
+ lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
+ struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */
#ifdef USE_KEYRR
- struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */
+ struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */
#endif
- struct adns_continuation *previous, *next;
- struct pubkey *last_info; /* the last structure we accumulated */
+ struct adns_continuation *previous, *next;
+ struct pubkey *last_info; /* the last structure we accumulated */
#ifdef USE_LWRES
- bool used; /* have we called the cont_fn yet? */
- struct {
- u_char name_buf[NS_MAXDNAME + 2];
- } query;
+ bool used; /* have we called the cont_fn yet? */
+ struct {
+ u_char name_buf[NS_MAXDNAME + 2];
+ } query;
#else /* ! USE_LWRES */
- struct adns_query query;
+ struct adns_query query;
#endif /* ! USE_LWRES */
};
-extern err_t start_adns_query(const struct id *id /* domain to query */
- , const struct id *sgw_id /* if non-null, any accepted gw_info must match */
- , int type /* T_TXT or T_KEY, selecting rr type of interest */
- , cont_fn_t cont_fn /* continuation function */
- , struct adns_continuation *cr);
+extern err_t start_adns_query(const struct id *id /* domain to query */
+ , const struct id *sgw_id /* if non-null, any accepted gw_info must match */
+ , int type /* T_TXT or T_KEY, selecting rr type of interest */
+ , cont_fn_t cont_fn /* continuation function */
+ , struct adns_continuation *cr);
/* Gateway info gleaned from reverse DNS of client */
struct gw_info {
- unsigned refcnt; /* reference counted! */
- unsigned pref; /* preference: lower is better */
-#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
- struct id client_id; /* id of client of peer */
- struct id gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
- bool gw_key_present;
- struct pubkey *key;
- struct gw_info *next;
+ unsigned refcnt; /* reference counted! */
+ unsigned pref; /* preference: lower is better */
+#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
+ struct id client_id; /* id of client of peer */
+ struct id gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
+ bool gw_key_present;
+ struct pubkey *key;
+ struct gw_info *next;
};
extern void gw_addref(struct gw_info *gw)
- , gw_delref(struct gw_info **gwp);
+ , gw_delref(struct gw_info **gwp);
extern void reset_adns_restart_count(void);
diff --git a/src/pluto/dsa.c b/src/pluto/dsa.c
deleted file mode 100644
index c5982fbf4..000000000
--- a/src/pluto/dsa.c
+++ /dev/null
@@ -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 --git a/src/pluto/dsa.h b/src/pluto/dsa.h
deleted file mode 100644
index 1456d65b6..000000000
--- a/src/pluto/dsa.h
+++ /dev/null
@@ -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 --git a/src/pluto/elgamal.c b/src/pluto/elgamal.c
deleted file mode 100644
index 0c099bb90..000000000
--- a/src/pluto/elgamal.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/* elgamal.c - ElGamal Public Key encryption
- * Copyright (C) 1998 Free Software Foundation, Inc.
- *
- * For a description of the algorithm, see:
- * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
- * ISBN 0-471-11709-9. Pages 476 ff.
- *
- * 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 "util.h" */
-/* #include "mpi.h" */
-/* #include "cipher.h" */
-#endif
-
-#include "elgamal.h"
-
-typedef struct {
- MPI p; /* prime */
- MPI g; /* group generator */
- MPI y; /* g^x mod p */
-} ELG_public_key;
-
-
-typedef struct {
- MPI p; /* prime */
- MPI g; /* group generator */
- MPI y; /* g^x mod p */
- MPI x; /* secret exponent */
-} ELG_secret_key;
-
-
-static void test_keys( ELG_secret_key *sk, unsigned nbits );
-static MPI gen_k( MPI p );
-static void generate( ELG_secret_key *sk, unsigned nbits, MPI **factors );
-static int check_secret_key( ELG_secret_key *sk );
-static void encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey );
-static void decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey );
-static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey);
-static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey);
-
-
-static void
-progress( int c )
-{
- fputc( c, stderr );
-}
-
-
-static void
-test_keys( ELG_secret_key *sk, unsigned nbits )
-{
- ELG_public_key pk;
- MPI test = mpi_alloc( 0 );
- MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
- MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
- MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
-
- pk.p = sk->p;
- pk.g = sk->g;
- pk.y = sk->y;
-
- /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/
- { char *p = get_random_bits( nbits, 0, 0 );
- mpi_set_buffer( test, p, (nbits+7)/8, 0 );
- m_free(p);
- }
-
- encrypt( out1_a, out1_b, test, &pk );
- decrypt( out2, out1_a, out1_b, sk );
- if( mpi_cmp( test, out2 ) )
- log_fatal("ElGamal operation: encrypt, decrypt failed\n");
-
- sign( out1_a, out1_b, test, sk );
- if( !verify( out1_a, out1_b, test, &pk ) )
- log_fatal("ElGamal operation: sign, verify failed\n");
-
- mpi_free( test );
- mpi_free( out1_a );
- mpi_free( out1_b );
- mpi_free( out2 );
-}
-
-
-/****************
- * generate a random secret exponent k from prime p, so
- * that k is relatively prime to p-1
- */
-static MPI
-gen_k( MPI p )
-{
- MPI k = mpi_alloc_secure( 0 );
- MPI temp = mpi_alloc( mpi_get_nlimbs(p) );
- MPI p_1 = mpi_copy(p);
- unsigned int nbits = mpi_get_nbits(p);
- unsigned int nbytes = (nbits+7)/8;
- char *rndbuf = NULL;
-
- if( DBG_CIPHER )
- log_debug("choosing a random k ");
- mpi_sub_ui( p_1, p, 1);
- 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 );
-
- for(;;) {
- /* make sure that the number is of the exact lenght */
- 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, p_1 ) < 0) ) { /* check: k < (p-1) */
- if( DBG_CIPHER )
- progress('+');
- break; /* no */
- }
- if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
- if( DBG_CIPHER )
- progress('-');
- break; /* no */
- }
- if( mpi_gcd( temp, k, p_1 ) )
- goto found; /* okay, k is relatively prime to (p-1) */
- mpi_add_ui( k, k, 1 );
- }
- }
- found:
- m_free(rndbuf);
- if( DBG_CIPHER )
- progress('\n');
- mpi_free(p_1);
- mpi_free(temp);
-
- return k;
-}
-
-/****************
- * Generate a key pair with a key of size NBITS
- * Returns: 2 structures filles with all needed values
- * and an array with n-1 factors of (p-1)
- */
-static void
-generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
-{
- MPI p; /* the prime */
- MPI p_min1;
- MPI g;
- MPI x; /* the secret exponent */
- MPI y;
- MPI temp;
- unsigned qbits;
- byte *rndbuf;
-
- p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
- temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
- if( nbits < 512 )
- qbits = 120;
- else if( nbits <= 1024 )
- qbits = 160;
- else if( nbits <= 2048 )
- qbits = 200;
- else
- qbits = 240;
- g = mpi_alloc(1);
- p = generate_elg_prime( 0, nbits, qbits, g, ret_factors );
- mpi_sub_ui(p_min1, p, 1);
-
-
- /* select a random number which has these properties:
- * 0 < x < p-1
- * This must be a very good random number because this is the
- * secret part. The prime is public and may be shared anyway,
- * so a random generator level of 1 is used for the prime.
- */
- x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB );
- if( DBG_CIPHER )
- log_debug("choosing a random x ");
- rndbuf = NULL;
- do {
- if( DBG_CIPHER )
- progress('.');
- if( rndbuf ) { /* change only some of the higher bits */
- if( nbits < 16 ) {/* should never happen ... */
- m_free(rndbuf);
- rndbuf = get_random_bits( nbits, 2, 1 );
- }
- else {
- char *r = get_random_bits( 16, 2, 1 );
- memcpy(rndbuf, r, 16/8 );
- m_free(r);
- }
- }
- else
- rndbuf = get_random_bits( nbits, 2, 1 );
- mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 );
- mpi_clear_highbit( x, nbits+1 );
- } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
- m_free(rndbuf);
-
- y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
- mpi_powm( y, g, x, p );
-
- if( DBG_CIPHER ) {
- progress('\n');
- log_mpidump("elg p= ", p );
- log_mpidump("elg g= ", g );
- log_mpidump("elg y= ", y );
- log_mpidump("elg x= ", x );
- }
-
- /* copy the stuff to the key structures */
- sk->p = p;
- sk->g = g;
- sk->y = y;
- sk->x = x;
-
- /* now we can test our keys (this should never fail!) */
- test_keys( sk, nbits - 64 );
-
- mpi_free( p_min1 );
- mpi_free( temp );
-}
-
-
-/****************
- * Test whether the secret key is valid.
- * Returns: if this is a valid key.
- */
-static int
-check_secret_key( ELG_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;
-}
-
-
-static void
-encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey )
-{
- MPI k;
-
- /* Note: maybe we should change the interface, so that it
- * is possible to check that input is < p and return an
- * error code.
- */
-
- k = gen_k( pkey->p );
- mpi_powm( a, pkey->g, k, pkey->p );
- /* b = (y^k * input) mod p
- * = ((y^k mod p) * (input mod p)) mod p
- * and because input is < p
- * = ((y^k mod p) * input) mod p
- */
- mpi_powm( b, pkey->y, k, pkey->p );
- mpi_mulm( b, b, input, pkey->p );
- #if 0
- if( DBG_CIPHER ) {
- log_mpidump("elg encrypted y= ", pkey->y);
- log_mpidump("elg encrypted p= ", pkey->p);
- log_mpidump("elg encrypted k= ", k);
- log_mpidump("elg encrypted M= ", input);
- log_mpidump("elg encrypted a= ", a);
- log_mpidump("elg encrypted b= ", b);
- }
- #endif
- mpi_free(k);
-}
-
-
-
-
-static void
-decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey )
-{
- MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
-
- /* output = b/(a^x) mod p */
-
- mpi_powm( t1, a, skey->x, skey->p );
- mpi_invm( t1, t1, skey->p );
- mpi_mulm( output, b, t1, skey->p );
- #if 0
- if( DBG_CIPHER ) {
- log_mpidump("elg decrypted x= ", skey->x);
- log_mpidump("elg decrypted p= ", skey->p);
- log_mpidump("elg decrypted a= ", a);
- log_mpidump("elg decrypted b= ", b);
- log_mpidump("elg decrypted M= ", output);
- }
- #endif
- mpi_free(t1);
-}
-
-
-/****************
- * Make an Elgamal signature out of INPUT
- */
-
-static void
-sign(MPI a, MPI b, MPI input, ELG_secret_key *skey )
-{
- MPI k;
- MPI t = mpi_alloc( mpi_get_nlimbs(a) );
- MPI inv = mpi_alloc( mpi_get_nlimbs(a) );
- MPI p_1 = mpi_copy(skey->p);
-
- /*
- * b = (t * inv) mod (p-1)
- * b = (t * inv(k,(p-1),(p-1)) mod (p-1)
- * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1)
- *
- */
- mpi_sub_ui(p_1, p_1, 1);
- k = gen_k( skey->p );
- mpi_powm( a, skey->g, k, skey->p );
- mpi_mul(t, skey->x, a );
- mpi_subm(t, input, t, p_1 );
- while( mpi_is_neg(t) )
- mpi_add(t, t, p_1);
- mpi_invm(inv, k, p_1 );
- mpi_mulm(b, t, inv, p_1 );
-
- #if 0
- if( DBG_CIPHER ) {
- log_mpidump("elg sign p= ", skey->p);
- log_mpidump("elg sign g= ", skey->g);
- log_mpidump("elg sign y= ", skey->y);
- log_mpidump("elg sign x= ", skey->x);
- log_mpidump("elg sign k= ", k);
- log_mpidump("elg sign M= ", input);
- log_mpidump("elg sign a= ", a);
- log_mpidump("elg sign b= ", b);
- }
- #endif
- mpi_free(k);
- mpi_free(t);
- mpi_free(inv);
- mpi_free(p_1);
-}
-
-
-/****************
- * Returns true if the signature composed of A and B is valid.
- */
-static int
-verify(MPI a, MPI b, MPI input, ELG_public_key *pkey )
-{
- int rc;
- MPI t1;
- MPI t2;
- MPI base[4];
- MPI exp[4];
-
- if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) )
- return 0; /* assertion 0 < a < p failed */
-
- t1 = mpi_alloc( mpi_get_nlimbs(a) );
- t2 = mpi_alloc( mpi_get_nlimbs(a) );
-
- #if 0
- /* t1 = (y^a mod p) * (a^b mod p) mod p */
- mpi_powm( t1, pkey->y, a, pkey->p );
- mpi_powm( t2, a, b, pkey->p );
- mpi_mulm( t1, t1, t2, pkey->p );
-
- /* t2 = g ^ input mod p */
- mpi_powm( t2, pkey->g, input, pkey->p );
-
- rc = !mpi_cmp( t1, t2 );
- #elif 0
- /* t1 = (y^a mod p) * (a^b mod p) mod p */
- base[0] = pkey->y; exp[0] = a;
- base[1] = a; exp[1] = b;
- base[2] = NULL; exp[2] = NULL;
- mpi_mulpowm( t1, base, exp, pkey->p );
-
- /* t2 = g ^ input mod p */
- mpi_powm( t2, pkey->g, input, pkey->p );
-
- rc = !mpi_cmp( t1, t2 );
- #else
- /* t1 = g ^ - input * y ^ a * a ^ b mod p */
- mpi_invm(t2, pkey->g, pkey->p );
- base[0] = t2 ; exp[0] = input;
- base[1] = pkey->y; exp[1] = a;
- base[2] = a; exp[2] = b;
- base[3] = NULL; exp[3] = NULL;
- mpi_mulpowm( t1, base, exp, pkey->p );
- rc = !mpi_cmp_ui( t1, 1 );
-
- #endif
-
- mpi_free(t1);
- mpi_free(t2);
- return rc;
-}
-
-/*********************************************
- ************** interface ******************
- *********************************************/
-
-int
-elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
-{
- ELG_secret_key sk;
-
- if( !is_ELGAMAL(algo) )
- return G10ERR_PUBKEY_ALGO;
-
- generate( &sk, nbits, retfactors );
- skey[0] = sk.p;
- skey[1] = sk.g;
- skey[2] = sk.y;
- skey[3] = sk.x;
- return 0;
-}
-
-
-int
-elg_check_secret_key( int algo, MPI *skey )
-{
- ELG_secret_key sk;
-
- if( !is_ELGAMAL(algo) )
- return G10ERR_PUBKEY_ALGO;
- if( !skey[0] || !skey[1] || !skey[2] || !skey[3] )
- return G10ERR_BAD_MPI;
-
- sk.p = skey[0];
- sk.g = skey[1];
- sk.y = skey[2];
- sk.x = skey[3];
- if( !check_secret_key( &sk ) )
- return G10ERR_BAD_SECKEY;
-
- return 0;
-}
-
-
-
-int
-elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
-{
- ELG_public_key pk;
-
- if( !is_ELGAMAL(algo) )
- return G10ERR_PUBKEY_ALGO;
- if( !data || !pkey[0] || !pkey[1] || !pkey[2] )
- return G10ERR_BAD_MPI;
-
- pk.p = pkey[0];
- pk.g = pkey[1];
- pk.y = pkey[2];
- resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) );
- resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) );
- encrypt( resarr[0], resarr[1], data, &pk );
- return 0;
-}
-
-int
-elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
-{
- ELG_secret_key sk;
-
- if( !is_ELGAMAL(algo) )
- return G10ERR_PUBKEY_ALGO;
- if( !data[0] || !data[1]
- || !skey[0] || !skey[1] || !skey[2] || !skey[3] )
- return G10ERR_BAD_MPI;
-
- sk.p = skey[0];
- sk.g = skey[1];
- sk.y = skey[2];
- sk.x = skey[3];
- *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) );
- decrypt( *result, data[0], data[1], &sk );
- return 0;
-}
-
-int
-elg_sign( int algo, MPI *resarr, MPI data, MPI *skey )
-{
- ELG_secret_key sk;
-
- if( !is_ELGAMAL(algo) )
- return G10ERR_PUBKEY_ALGO;
- if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] )
- return G10ERR_BAD_MPI;
-
- sk.p = skey[0];
- sk.g = skey[1];
- sk.y = skey[2];
- sk.x = skey[3];
- 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
-elg_verify( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED)
-{
- ELG_public_key pk;
-
- if( !is_ELGAMAL(algo) )
- return G10ERR_PUBKEY_ALGO;
- if( !data[0] || !data[1] || !hash
- || !pkey[0] || !pkey[1] || !pkey[2] )
- return G10ERR_BAD_MPI;
-
- pk.p = pkey[0];
- pk.g = pkey[1];
- pk.y = pkey[2];
- if( !verify( data[0], data[1], hash, &pk ) )
- return G10ERR_BAD_SIGN;
- return 0;
-}
-
-
-
-unsigned
-elg_get_nbits( int algo, MPI *pkey )
-{
- if( !is_ELGAMAL(algo) )
- 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
- * NOTE: This function allows signing also for ELG-E, which is not
- * okay but a bad hack to allow to work with old gpg keys. The real check
- * is done in the gnupg ocde depending on the packet version.
- */
-const char *
-elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
- int *use )
-{
- *npkey = 3;
- *nskey = 4;
- *nenc = 2;
- *nsig = 2;
-
- switch( algo ) {
- case PUBKEY_ALGO_ELGAMAL:
- *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
- return "ELG";
- case PUBKEY_ALGO_ELGAMAL_E:
- *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
- return "ELG-E";
- default: *use = 0; return NULL;
- }
-}
-
-
diff --git a/src/pluto/elgamal.h b/src/pluto/elgamal.h
deleted file mode 100644
index f104c2a52..000000000
--- a/src/pluto/elgamal.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* elgamal.h
- * 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_ELGAMAL_H
-#define G10_ELGAMAL_H
-
-int elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
-int elg_check_secret_key( int algo, MPI *skey );
-int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey );
-int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
-int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey );
-int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI), void *opaquev );
-unsigned elg_get_nbits( int algo, MPI *pkey );
-const char *elg_get_info( int algo, int *npkey, int *nskey,
- int *nenc, int *nsig, int *use );
-
-
-#endif /*G10_ELGAMAL_H*/
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
index c8a98cd9b..6f7f1215f 100644
--- a/src/pluto/fetch.c
+++ b/src/pluto/fetch.c
@@ -1,6 +1,6 @@
/* Dynamic fetching of X.509 CRLs
* Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com>
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,8 +11,6 @@
* 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: fetch.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -25,24 +23,17 @@
#include <pthread.h>
#endif
-#ifdef LIBCURL
-#include <curl/curl.h>
-#endif
-
#include <freeswan.h>
-#ifdef LIBLDAP
-#ifndef LDAP_DEPRECATED
-#define LDAP_DEPRECATED 1
-#endif
-#include <ldap.h>
-#endif
+#include <library.h>
+#include <debug.h>
+#include <asn1/asn1.h>
+#include <asn1/pem.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "id.h"
-#include "asn1.h"
#include "pem.h"
#include "x509.h"
#include "ca.h"
@@ -52,13 +43,13 @@
#include "fetch.h"
fetch_req_t empty_fetch_req = {
- NULL , /* next */
- 0 , /* installed */
- 0 , /* trials */
+ NULL , /* next */
+ 0 , /* installed */
+ 0 , /* trials */
{ NULL, 0}, /* issuer */
{ NULL, 0}, /* authKeyID */
{ NULL, 0}, /* authKeySerialNumber */
- NULL /* distributionPoints */
+ NULL /* distributionPoints */
};
/* chained list of crl fetch requests */
@@ -79,189 +70,174 @@ static pthread_mutex_t ocsp_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t fetch_wake_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t fetch_wake_cond = PTHREAD_COND_INITIALIZER;
-/*
+/**
* lock access to my certs and keys
*/
-void
-lock_certs_and_keys(const char *who)
+void lock_certs_and_keys(const char *who)
{
- pthread_mutex_lock(&certs_and_keys_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("certs and keys locked by '%s'", who)
- )
+ pthread_mutex_lock(&certs_and_keys_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("certs and keys locked by '%s'", who)
+ )
}
-/*
- * unlock access to my certs and keys
+/**
+ * Unlock access to my certs and keys
*/
-void
-unlock_certs_and_keys(const char *who)
+void unlock_certs_and_keys(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("certs and keys unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&certs_and_keys_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("certs and keys unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&certs_and_keys_mutex);
}
-/*
- * lock access to the chained authcert list
+/**
+ * Lock access to the chained authcert list
*/
-void
-lock_authcert_list(const char *who)
+void lock_authcert_list(const char *who)
{
- pthread_mutex_lock(&authcert_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("authcert list locked by '%s'", who)
- )
+ pthread_mutex_lock(&authcert_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("authcert list locked by '%s'", who)
+ )
}
-/*
- * unlock access to the chained authcert list
+/**
+ * Unlock access to the chained authcert list
*/
-void
-unlock_authcert_list(const char *who)
+void unlock_authcert_list(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("authcert list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&authcert_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("authcert list unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&authcert_list_mutex);
}
-/*
- * lock access to the chained crl list
+/**
+ * Lock access to the chained crl list
*/
-void
-lock_crl_list(const char *who)
+void lock_crl_list(const char *who)
{
- pthread_mutex_lock(&crl_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("crl list locked by '%s'", who)
- )
+ pthread_mutex_lock(&crl_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("crl list locked by '%s'", who)
+ )
}
-/*
- * unlock access to the chained crl list
+/**
+ * Unlock access to the chained crl list
*/
-void
-unlock_crl_list(const char *who)
+void unlock_crl_list(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("crl list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&crl_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("crl list unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&crl_list_mutex);
}
-/*
- * lock access to the ocsp cache
+/**
+ * Lock access to the ocsp cache
*/
-extern void
-lock_ocsp_cache(const char *who)
+extern void lock_ocsp_cache(const char *who)
{
- pthread_mutex_lock(&ocsp_cache_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp cache locked by '%s'", who)
- )
+ pthread_mutex_lock(&ocsp_cache_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("ocsp cache locked by '%s'", who)
+ )
}
-/*
- * unlock access to the ocsp cache
+/**
+ * Unlock access to the ocsp cache
*/
-extern void
-unlock_ocsp_cache(const char *who)
+extern void unlock_ocsp_cache(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp cache unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&ocsp_cache_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("ocsp cache unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&ocsp_cache_mutex);
}
-/*
- * lock access to the ca info list
+/**
+ * Lock access to the ca info list
*/
-extern void
-lock_ca_info_list(const char *who)
+extern void lock_ca_info_list(const char *who)
{
- pthread_mutex_lock(&ca_info_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("ca info list locked by '%s'", who)
- )
+ pthread_mutex_lock(&ca_info_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("ca info list locked by '%s'", who)
+ )
}
-/*
- * unlock access to the ca info list
+/**
+ * Unlock access to the ca info list
*/
-extern void
-unlock_ca_info_list(const char *who)
+extern void unlock_ca_info_list(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("ca info list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&ca_info_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("ca info list unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&ca_info_list_mutex);
}
-/*
- * lock access to the chained crl fetch request list
+/**
+ * Lock access to the chained crl fetch request list
*/
-static void
-lock_crl_fetch_list(const char *who)
+static void lock_crl_fetch_list(const char *who)
{
- pthread_mutex_lock(&crl_fetch_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("crl fetch request list locked by '%s'", who)
- )
+ pthread_mutex_lock(&crl_fetch_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("crl fetch request list locked by '%s'", who)
+ )
}
-/*
- * unlock access to the chained crl fetch request list
+/**
+ * Unlock access to the chained crl fetch request list
*/
-static void
-unlock_crl_fetch_list(const char *who)
+static void unlock_crl_fetch_list(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("crl fetch request list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&crl_fetch_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("crl fetch request list unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&crl_fetch_list_mutex);
}
-/*
- * lock access to the chained ocsp fetch request list
+/**
+ * Lock access to the chained ocsp fetch request list
*/
-static void
-lock_ocsp_fetch_list(const char *who)
+static void lock_ocsp_fetch_list(const char *who)
{
- pthread_mutex_lock(&ocsp_fetch_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp fetch request list locked by '%s'", who)
- )
+ pthread_mutex_lock(&ocsp_fetch_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("ocsp fetch request list locked by '%s'", who)
+ )
}
-/*
- * unlock access to the chained ocsp fetch request list
+/**
+ * Unlock access to the chained ocsp fetch request list
*/
-static void
-unlock_ocsp_fetch_list(const char *who)
+static void unlock_ocsp_fetch_list(const char *who)
{
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp fetch request list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&ocsp_fetch_list_mutex);
+ DBG(DBG_CONTROLMORE,
+ DBG_log("ocsp fetch request list unlocked by '%s'", who)
+ )
+ pthread_mutex_unlock(&ocsp_fetch_list_mutex);
}
-/*
- * wakes up the sleeping fetch thread
+/**
+ * Wakes up the sleeping fetch thread
*/
-void
-wake_fetch_thread(const char *who)
+void wake_fetch_thread(const char *who)
{
- if (crl_check_interval > 0)
- {
- DBG(DBG_CONTROLMORE,
- DBG_log("fetch thread wake call by '%s'", who)
- )
- pthread_mutex_lock(&fetch_wake_mutex);
- pthread_cond_signal(&fetch_wake_cond);
- pthread_mutex_unlock(&fetch_wake_mutex);
- }
+ if (crl_check_interval > 0)
+ {
+ DBG(DBG_CONTROLMORE,
+ DBG_log("fetch thread wake call by '%s'", who)
+ )
+ pthread_mutex_lock(&fetch_wake_mutex);
+ pthread_cond_signal(&fetch_wake_cond);
+ pthread_mutex_unlock(&fetch_wake_mutex);
+ }
}
#else /* !THREADS */
#define lock_crl_fetch_list(who) /* do nothing */
@@ -270,817 +246,506 @@ wake_fetch_thread(const char *who)
#define unlock_ocsp_fetch_list(who) /* do nothing */
#endif /* !THREADS */
-/*
- * free the dynamic memory used to store fetch requests
+/**
+ * Free the dynamic memory used to store fetch requests
*/
-static void
-free_fetch_request(fetch_req_t *req)
+static void free_fetch_request(fetch_req_t *req)
{
- pfree(req->issuer.ptr);
- pfreeany(req->authKeySerialNumber.ptr);
- pfreeany(req->authKeyID.ptr);
- free_generalNames(req->distributionPoints, TRUE);
- pfree(req);
-}
-
-/* writes data into a dynamically resizeable chunk_t
- * needed for libcurl responses
- */
-size_t
-write_buffer(void *ptr, size_t size, size_t nmemb, void *data)
-{
- size_t realsize = size * nmemb;
- chunk_t *mem = (chunk_t*)data;
-
- mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize);
- if (mem->ptr) {
- memcpy(&(mem->ptr[mem->len]), ptr, realsize);
- mem->len += realsize;
- }
- return realsize;
+ free(req->issuer.ptr);
+ free(req->authKeySerialNumber.ptr);
+ free(req->authKeyID.ptr);
+ free_generalNames(req->distributionPoints, TRUE);
+ free(req);
}
#ifdef THREADS
-/*
- * fetches a binary blob from a url with libcurl
+/**
+ * Fetch an ASN.1 blob coded in PEM or DER format from a URL
*/
-static err_t
-fetch_curl(char *url, chunk_t *blob)
+bool fetch_asn1_blob(char *url, chunk_t *blob)
{
-#ifdef LIBCURL
- char errorbuffer[CURL_ERROR_SIZE] = "";
- chunk_t response = empty_chunk;
- CURLcode res;
-
- /* get it with libcurl */
- CURL *curl = curl_easy_init();
-
- if (curl != NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("Trying cURL '%s'", url)
- )
-
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT);
-
- res = curl_easy_perform(curl);
-
- if (res == CURLE_OK)
- {
- blob->len = response.len;
- blob->ptr = alloc_bytes(response.len, "curl blob");
- memcpy(blob->ptr, response.ptr, response.len);
- }
- else
+ DBG1(" fetching crl from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, blob, FETCH_END) != SUCCESS)
{
- plog("fetching uri (%s) with libcurl failed: %s", url, errorbuffer);
+ DBG1("crl fetching failed");
+ return FALSE;
}
- curl_easy_cleanup(curl);
- /* not using freeanychunk because of realloc (no leak detective) */
- curl_free(response.ptr);
- }
- return strlen(errorbuffer) > 0 ? "libcurl error" : NULL;
-#else /* !LIBCURL */
- return "warning: not compiled with libcurl support";
-#endif /* !LIBCURL */
-}
-
-#ifdef LIBLDAP
-/*
- * parses the result returned by an ldap query
- */
-static err_t
-parse_ldap_result(LDAP * ldap, LDAPMessage *result, chunk_t *blob)
-{
- err_t ugh = NULL;
-
- LDAPMessage * entry = ldap_first_entry(ldap, result);
- if (entry != NULL)
- {
- BerElement *ber = NULL;
- char *attr;
-
- attr = ldap_first_attribute(ldap, entry, &ber);
-
- if (attr != NULL)
+ if (is_asn1(*blob))
{
- struct berval **values = ldap_get_values_len(ldap, entry, attr);
-
- if (values != NULL)
- {
- if (values[0] != NULL)
- {
- blob->len = values[0]->bv_len;
- blob->ptr = alloc_bytes(blob->len, "ldap blob");
- memcpy(blob->ptr, values[0]->bv_val, blob->len);
- if (values[1] != NULL)
- {
- plog("warning: more than one value was fetched from LDAP URL");
- }
- }
- else
- {
- ugh = "no values in attribute";
- }
- ldap_value_free_len(values);
- }
- else
- {
- ugh = ldap_err2string(ldap_result2error(ldap, entry, 0));
- }
- ldap_memfree(attr);
+ DBG2(" fetched blob coded in DER format");
}
else
{
- ugh = ldap_err2string(ldap_result2error(ldap, entry, 0));
- }
- ber_free(ber, 0);
- }
- else
- {
- ugh = ldap_err2string(ldap_result2error(ldap, result, 0));
- }
- return ugh;
-}
-
-/*
- * fetches a binary blob from an ldap url
- */
-static err_t
-fetch_ldap_url(char *url, chunk_t *blob)
-{
- LDAPURLDesc *lurl;
- err_t ugh = NULL;
- int rc;
-
- DBG(DBG_CONTROL,
- DBG_log("Trying LDAP URL '%s'", url)
- )
-
- rc = ldap_url_parse(url, &lurl);
-
- if (rc == LDAP_SUCCESS)
- {
- LDAP *ldap = ldap_init(lurl->lud_host, lurl->lud_port);
-
- if (ldap != NULL)
- {
- int ldap_version = LDAP_VERSION3;
- struct timeval timeout;
+ bool pgp = FALSE;
- timeout.tv_sec = FETCH_CMD_TIMEOUT;
- timeout.tv_usec = 0;
- ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
- ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);
-
- rc = ldap_simple_bind_s(ldap, NULL, NULL);
-
- if (rc == LDAP_SUCCESS)
- {
- LDAPMessage *result;
-
- timeout.tv_sec = FETCH_CMD_TIMEOUT;
- timeout.tv_usec = 0;
-
- rc = ldap_search_st(ldap, lurl->lud_dn
- , lurl->lud_scope
- , lurl->lud_filter
- , lurl->lud_attrs
- , 0, &timeout, &result);
-
- if (rc == LDAP_SUCCESS)
+ if (pem_to_bin(blob, chunk_empty, &pgp) != SUCCESS)
{
- ugh = parse_ldap_result(ldap, result, blob);
- ldap_msgfree(result);
+ free(blob->ptr);
+ return FALSE;
+ }
+ if (is_asn1(*blob))
+ {
+ DBG2(" fetched blob coded in PEM format");
}
else
{
- ugh = ldap_err2string(rc);
+ DBG1("crl fetched successfully but data coded in unknown format");
+ free(blob->ptr);
+ return FALSE;
}
- }
- else
- {
- ugh = ldap_err2string(rc);
- }
- ldap_unbind_s(ldap);
- }
- else
- {
- ugh = "ldap init";
- }
- ldap_free_urldesc(lurl);
- }
- else
- {
- ugh = ldap_err2string(rc);
- }
- return ugh;
-}
-#else /* !LIBLDAP */
-static err_t
-fetch_ldap_url(char *url, chunk_t *blob)
-{
- return "LDAP URL fetching not activated in pluto source code";
-}
-#endif /* !LIBLDAP */
-
-/*
- * fetch an ASN.1 blob coded in PEM or DER format from a URL
- */
-static err_t
-fetch_asn1_blob(char *url, chunk_t *blob)
-{
- err_t ugh = NULL;
-
- if (strlen(url) >= 4 && strncasecmp(url, "ldap", 4) == 0)
- {
- ugh = fetch_ldap_url(url, blob);
- }
- else
- {
- ugh = fetch_curl(url, blob);
- }
- if (ugh != NULL)
- return ugh;
-
- if (is_asn1(*blob))
- {
- DBG(DBG_PARSING,
- DBG_log(" fetched blob coded in DER format")
- )
- }
- else
- {
- bool pgp = FALSE;
-
- ugh = pemtobin(blob, NULL, "", &pgp);
- if (ugh == NULL)
- {
- if (is_asn1(*blob))
- {
- DBG(DBG_PARSING,
- DBG_log(" fetched blob coded in PEM format")
- )
- }
- else
- {
- ugh = "blob coded in unknown format";
- pfree(blob->ptr);
- }
- }
- else
- {
- pfree(blob->ptr);
}
- }
- return ugh;
+ return TRUE;
}
-/*
- * complete a distributionPoint URI with ca information
+/**
+ * Complete a distributionPoint URI with ca information
*/
-static char*
-complete_uri(chunk_t distPoint, const char *ldaphost)
+static char* complete_uri(chunk_t distPoint, const char *ldaphost)
{
- char *uri;
- char *ptr = distPoint.ptr;
- size_t len = distPoint.len;
+ char *uri;
+ char *ptr = distPoint.ptr;
+ size_t len = distPoint.len;
- char *symbol = memchr(ptr, ':', len);
+ char *symbol = memchr(ptr, ':', len);
- if (symbol != NULL)
- {
- size_t type_len = symbol - ptr;
-
- if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0)
+ if (symbol != NULL)
{
- ptr = symbol + 1;
- len -= (type_len + 1);
-
- if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
- {
- len -= 2;
- symbol = memchr(ptr, '/', len);
+ size_t type_len = symbol - ptr;
- if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL)
+ if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0)
{
- uri = alloc_bytes(distPoint.len+strlen(ldaphost)+1, "uri");
-
- /* insert the ldaphost into the uri */
- sprintf(uri, "%.*s%s%.*s"
- , (int)(distPoint.len - len), distPoint.ptr
- , ldaphost
- , (int)len, symbol);
- return uri;
+ ptr = symbol + 1;
+ len -= (type_len + 1);
+
+ if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
+ {
+ len -= 2;
+ symbol = memchr(ptr, '/', len);
+
+ if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL)
+ {
+ uri = malloc(distPoint.len + strlen(ldaphost) + 1);
+
+ /* insert the ldaphost into the uri */
+ sprintf(uri, "%.*s%s%.*s"
+ , (int)(distPoint.len - len), distPoint.ptr
+ , ldaphost
+ , (int)len, symbol);
+ return uri;
+ }
+ }
}
- }
}
- }
-
- /* default action: copy distributionPoint without change */
- uri = alloc_bytes(distPoint.len+1, "uri");
- sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr);
- return uri;
+
+ /* default action: copy distributionPoint without change */
+ uri = malloc(distPoint.len + 1);
+ sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr);
+ return uri;
}
-/*
- * try to fetch the crls defined by the fetch requests
+/**
+ * Try to fetch the crls defined by the fetch requests
*/
-static void
-fetch_crls(bool cache_crls)
+static void fetch_crls(bool cache_crls)
{
- fetch_req_t *req;
- fetch_req_t **reqp;
-
- lock_crl_fetch_list("fetch_crls");
- req = crl_fetch_reqs;
- reqp = &crl_fetch_reqs;
-
- while (req != NULL)
- {
- bool valid_crl = FALSE;
- chunk_t blob = empty_chunk;
- generalName_t *gn = req->distributionPoints;
- const char *ldaphost;
- ca_info_t *ca;
+ fetch_req_t *req;
+ fetch_req_t **reqp;
- lock_ca_info_list("fetch_crls");
+ lock_crl_fetch_list("fetch_crls");
+ req = crl_fetch_reqs;
+ reqp = &crl_fetch_reqs;
- ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID);
- ldaphost = (ca == NULL)? NULL : ca->ldaphost;
-
- while (gn != NULL)
+ while (req != NULL)
{
- char *uri = complete_uri(gn->name, ldaphost);
+ bool valid_crl = FALSE;
+ chunk_t blob = chunk_empty;
+ generalName_t *gn = req->distributionPoints;
+ const char *ldaphost;
+ ca_info_t *ca;
- err_t ugh = fetch_asn1_blob(uri, &blob);
- pfree(uri);
+ lock_ca_info_list("fetch_crls");
- if (ugh != NULL)
- {
- plog("fetch failed: %s", ugh);
- }
- else
- {
- chunk_t crl_uri;
+ ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID);
+ ldaphost = (ca == NULL)? NULL : ca->ldaphost;
- clonetochunk(crl_uri, gn->name.ptr, gn->name.len, "crl uri");
- if (insert_crl(blob, crl_uri, cache_crls))
+ while (gn != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("we have a valid crl")
- )
- valid_crl = TRUE;
- break;
+ char *uri = complete_uri(gn->name, ldaphost);
+
+ if (fetch_asn1_blob(uri, &blob))
+ {
+ chunk_t crl_uri = chunk_clone(gn->name);
+
+ if (insert_crl(blob, crl_uri, cache_crls))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("we have a valid crl")
+ )
+ valid_crl = TRUE;
+ free(uri);
+ break;
+ }
+ }
+ free(uri);
+ gn = gn->next;
}
- }
- gn = gn->next;
- }
- unlock_ca_info_list("fetch_crls");
+ unlock_ca_info_list("fetch_crls");
- if (valid_crl)
- {
- /* delete fetch request */
- fetch_req_t *req_free = req;
+ if (valid_crl)
+ {
+ /* delete fetch request */
+ fetch_req_t *req_free = req;
- req = req->next;
- *reqp = req;
- free_fetch_request(req_free);
- }
- else
- {
- /* try again next time */
- req->trials++;
- reqp = &req->next;
- req = req->next;
+ req = req->next;
+ *reqp = req;
+ free_fetch_request(req_free);
+ }
+ else
+ {
+ /* try again next time */
+ req->trials++;
+ reqp = &req->next;
+ req = req->next;
+ }
}
- }
- unlock_crl_fetch_list("fetch_crls");
+ unlock_crl_fetch_list("fetch_crls");
}
-static void
-fetch_ocsp_status(ocsp_location_t* location)
+static void fetch_ocsp_status(ocsp_location_t* location)
{
-#ifdef LIBCURL
- chunk_t request;
- chunk_t response = empty_chunk;
-
- CURL* curl;
- CURLcode res;
-
- request = build_ocsp_request(location);
+ chunk_t request, response;
+ char *uri;
- DBG(DBG_CONTROL,
- DBG_log("sending ocsp request to location '%.*s'"
- , (int)location->uri.len, location->uri.ptr)
- )
- DBG(DBG_RAW,
- DBG_dump_chunk("OCSP request", request)
- )
-
- /* send via http post using libcurl */
- curl = curl_easy_init();
-
- if (curl != NULL)
- {
- char errorbuffer[CURL_ERROR_SIZE];
- struct curl_slist *headers = NULL;
- char* uri = alloc_bytes(location->uri.len+1, "ocsp uri");
+ request = build_ocsp_request(location);
+ response = chunk_empty;
/* we need a null terminated string for curl */
+ uri = malloc(location->uri.len + 1);
memcpy(uri, location->uri.ptr, location->uri.len);
*(uri + location->uri.len) = '\0';
- /* set content type header */
- headers = curl_slist_append(headers, "Content-Type: application/ocsp-request");
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-
- curl_easy_setopt(curl, CURLOPT_URL, uri);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*)request.ptr);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request.len);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT);
-
- res = curl_easy_perform(curl);
-
- if (res == CURLE_OK)
+ DBG1(" requesting ocsp status from '%s' ...", uri);
+ if (lib->fetcher->fetch(lib->fetcher, uri, &response,
+ FETCH_REQUEST_DATA, request,
+ FETCH_REQUEST_TYPE, "application/ocsp-request",
+ FETCH_END) == SUCCESS)
{
- DBG(DBG_CONTROL,
- DBG_log("received ocsp response")
- )
- DBG(DBG_RAW,
- DBG_dump_chunk("OCSP response:\n", response)
- )
- parse_ocsp(location, response);
+ parse_ocsp(location, response);
}
else
{
- plog("failed to fetch ocsp status from '%s': %s", uri, errorbuffer);
+ DBG1("ocsp request to %s failed", uri);
}
- curl_slist_free_all(headers);
- curl_easy_cleanup(curl);
- pfree(uri);
- /* not using freeanychunk because of realloc (no leak detective) */
- curl_free(response.ptr);
- }
- freeanychunk(location->nonce);
- freeanychunk(request);
-
- /* increment the trial counter of the unresolved fetch requests */
- {
- ocsp_certinfo_t *certinfo = location->certinfo;
-
- while (certinfo != NULL)
+
+ free(uri);
+ free(request.ptr);
+ chunk_free(&location->nonce);
+
+ /* increment the trial counter of the unresolved fetch requests */
{
- certinfo->trials++;
- certinfo = certinfo->next;
+ ocsp_certinfo_t *certinfo = location->certinfo;
+
+ while (certinfo != NULL)
+ {
+ certinfo->trials++;
+ certinfo = certinfo->next;
+ }
}
- }
- return;
-#else /* !LIBCURL */
- plog("ocsp error: pluto wasn't compiled with libcurl support");
-#endif /* !LIBCURL */
}
-/*
- * try to fetch the necessary ocsp information
+/**
+ * Try to fetch the necessary ocsp information
*/
-static void
-fetch_ocsp(void)
+static void fetch_ocsp(void)
{
- ocsp_location_t *location;
+ ocsp_location_t *location;
- lock_ocsp_fetch_list("fetch_ocsp");
- location = ocsp_fetch_reqs;
+ lock_ocsp_fetch_list("fetch_ocsp");
+ location = ocsp_fetch_reqs;
- /* fetch the ocps status for all locations */
- while (location != NULL)
- {
- if (location->certinfo != NULL)
- fetch_ocsp_status(location);
- location = location->next;
- }
+ /* fetch the ocps status for all locations */
+ while (location != NULL)
+ {
+ if (location->certinfo != NULL)
+ {
+ fetch_ocsp_status(location);
+ }
+ location = location->next;
+ }
- unlock_ocsp_fetch_list("fetch_ocsp");
+ unlock_ocsp_fetch_list("fetch_ocsp");
}
-static void*
-fetch_thread(void *arg)
+static void* fetch_thread(void *arg)
{
- struct timespec wait_interval;
+ struct timespec wait_interval;
- DBG(DBG_CONTROL,
- DBG_log("fetch thread started")
- )
+ DBG(DBG_CONTROL,
+ DBG_log("fetch thread started")
+ )
- pthread_mutex_lock(&fetch_wake_mutex);
+ pthread_mutex_lock(&fetch_wake_mutex);
- while(1)
- {
- int status;
+ while(1)
+ {
+ int status;
- wait_interval.tv_nsec = 0;
- wait_interval.tv_sec = time(NULL) + crl_check_interval;
+ wait_interval.tv_nsec = 0;
+ wait_interval.tv_sec = time(NULL) + crl_check_interval;
- DBG(DBG_CONTROL,
- DBG_log("next regular crl check in %ld seconds", crl_check_interval)
- )
- status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
- , &wait_interval);
+ DBG(DBG_CONTROL,
+ DBG_log("next regular crl check in %ld seconds", crl_check_interval)
+ )
+ status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
+ , &wait_interval);
- if (status == ETIMEDOUT)
- {
- DBG(DBG_CONTROL,
- DBG_log(" ");
- DBG_log("*time to check crls and the ocsp cache")
- )
- check_ocsp();
- check_crls();
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("fetch thread was woken up")
- )
+ if (status == ETIMEDOUT)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log(" ");
+ DBG_log("*time to check crls and the ocsp cache")
+ )
+ check_ocsp();
+ check_crls();
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("fetch thread was woken up")
+ )
+ }
+ fetch_ocsp();
+ fetch_crls(cache_crls);
}
- fetch_ocsp();
- fetch_crls(cache_crls);
- }
}
#endif /* THREADS*/
-/*
- * initializes curl and starts the fetching thread
+/**
+ * Initializes curl and starts the fetching thread
*/
-void
-init_fetch(void)
+void init_fetch(void)
{
-#if defined(LIBCURL) || defined (THREADS)
- int status;
-#endif
-
-#ifdef LIBCURL
- /* init curl */
- status = curl_global_init(CURL_GLOBAL_NOTHING);
- if (status != CURLE_OK)
- {
- plog("libcurl could not be initialized, status = %d", status);
- }
-#endif /* LIBCURL */
-
- if (crl_check_interval > 0)
- {
-#ifdef THREADS
- status = pthread_create( &thread, NULL, fetch_thread, NULL);
- if (status != 0)
+ if (crl_check_interval > 0)
{
- plog("fetching thread could not be started, status = %d", status);
- }
+#ifdef THREADS
+ int status = pthread_create( &thread, NULL, fetch_thread, NULL);
+
+ if (status != 0)
+ {
+ plog("fetching thread could not be started, status = %d", status);
+ }
#else /* !THREADS */
- plog("warning: not compiled with pthread support");
+ plog("warning: not compiled with pthread support");
#endif /* !THREADS */
- }
+ }
}
-void
-free_crl_fetch(void)
+void free_crl_fetch(void)
{
lock_crl_fetch_list("free_crl_fetch");
- while (crl_fetch_reqs != NULL)
- {
- fetch_req_t *req = crl_fetch_reqs;
- crl_fetch_reqs = req->next;
- free_fetch_request(req);
- }
-
- unlock_crl_fetch_list("free_crl_fetch");
-
-#ifdef LIBCURL
- if (crl_check_interval > 0)
- {
- /* cleanup curl */
- curl_global_cleanup();
- }
-#endif /* LIBCURL */
+ while (crl_fetch_reqs != NULL)
+ {
+ fetch_req_t *req = crl_fetch_reqs;
+ crl_fetch_reqs = req->next;
+ free_fetch_request(req);
+ }
+
+ unlock_crl_fetch_list("free_crl_fetch");
}
-/*
- * free the chained list of ocsp requests
+/**
+ * Free the chained list of ocsp requests
*/
-void
-free_ocsp_fetch(void)
+void free_ocsp_fetch(void)
{
- lock_ocsp_fetch_list("free_ocsp_fetch");
- free_ocsp_locations(&ocsp_fetch_reqs);
- unlock_ocsp_fetch_list("free_ocsp_fetch");
+ lock_ocsp_fetch_list("free_ocsp_fetch");
+ free_ocsp_locations(&ocsp_fetch_reqs);
+ unlock_ocsp_fetch_list("free_ocsp_fetch");
}
-/*
- * add additional distribution points
+/**
+ * Add additional distribution points
*/
-void
-add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints)
+void add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints)
{
- while (newPoints != NULL)
- {
- /* skip empty distribution point */
- if (newPoints->name.len > 0)
- {
- bool add = TRUE;
- generalName_t *gn = *distributionPoints;
-
- while (gn != NULL)
- {
- if (gn->kind == newPoints->kind
- && gn->name.len == newPoints->name.len
- && memcmp(gn->name.ptr, newPoints->name.ptr, gn->name.len) == 0)
- {
- /* skip if the distribution point is already present */
- add = FALSE;
- break;
- }
- gn = gn->next;
- }
-
- if (add)
- {
- /* clone additional distribution point */
- gn = clone_thing(*newPoints, "generalName");
- clonetochunk(gn->name, newPoints->name.ptr, newPoints->name.len
- , "crl uri");
-
- /* insert additional CRL distribution point */
- gn->next = *distributionPoints;
- *distributionPoints = gn;
- }
+ while (newPoints != NULL)
+ {
+ /* skip empty distribution point */
+ if (newPoints->name.len > 0)
+ {
+ bool add = TRUE;
+ generalName_t *gn = *distributionPoints;
+
+ while (gn != NULL)
+ {
+ if (gn->kind == newPoints->kind
+ && gn->name.len == newPoints->name.len
+ && memeq(gn->name.ptr, newPoints->name.ptr, gn->name.len))
+ {
+ /* skip if the distribution point is already present */
+ add = FALSE;
+ break;
+ }
+ gn = gn->next;
+ }
+
+ if (add)
+ {
+ /* clone additional distribution point */
+ gn = clone_thing(*newPoints);
+ gn->name = chunk_clone(newPoints->name);
+
+ /* insert additional CRL distribution point */
+ gn->next = *distributionPoints;
+ *distributionPoints = gn;
+ }
+ }
+ newPoints = newPoints->next;
}
- newPoints = newPoints->next;
- }
}
-fetch_req_t*
-build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber
-, chunk_t authKeyID, const generalName_t *gn)
+fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber,
+ chunk_t authKeyID, const generalName_t *gn)
{
- fetch_req_t *req = alloc_thing(fetch_req_t, "fetch request");
- *req = empty_fetch_req;
-
- /* note current time */
- req->installed = time(NULL);
-
- /* clone fields */
- clonetochunk(req->issuer, issuer.ptr, issuer.len, "issuer");
- if (authKeySerialNumber.ptr != NULL)
- {
- clonetochunk(req->authKeySerialNumber, authKeySerialNumber.ptr
- , authKeySerialNumber.len, "authKeySerialNumber");
- }
- if (authKeyID.ptr != NULL)
- {
- clonetochunk(req->authKeyID, authKeyID.ptr, authKeyID.len, "authKeyID");
- }
-
- /* copy distribution points */
- add_distribution_points(gn, &req->distributionPoints);
-
- return req;
+ fetch_req_t *req = malloc_thing(fetch_req_t);
+ *req = empty_fetch_req;
+
+ /* note current time */
+ req->installed = time(NULL);
+
+ /* clone fields */
+ req->issuer = chunk_clone(issuer);
+ req->authKeySerialNumber = chunk_clone(authKeySerialNumber);
+ req->authKeyID = chunk_clone(authKeyID);
+
+ /* copy distribution points */
+ add_distribution_points(gn, &req->distributionPoints);
+
+ return req;
}
-/*
- * add a crl fetch request to the chained list
+/**
+ * Add a crl fetch request to the chained list
*/
-void
-add_crl_fetch_request(fetch_req_t *req)
+void add_crl_fetch_request(fetch_req_t *req)
{
- fetch_req_t *r;
+ fetch_req_t *r;
- lock_crl_fetch_list("add_crl_fetch_request");
- r = crl_fetch_reqs;
+ lock_crl_fetch_list("add_crl_fetch_request");
+ r = crl_fetch_reqs;
- while (r != NULL)
- {
- if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID)
- : (same_dn(req->issuer, r->issuer)
- && same_serial(req->authKeySerialNumber, r->authKeySerialNumber)))
+ while (r != NULL)
{
- /* there is already a fetch request */
- DBG(DBG_CONTROL,
- DBG_log("crl fetch request already exists")
- )
+ if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID)
+ : (same_dn(req->issuer, r->issuer)
+ && same_serial(req->authKeySerialNumber, r->authKeySerialNumber)))
+ {
+ /* there is already a fetch request */
+ DBG(DBG_CONTROL,
+ DBG_log("crl fetch request already exists")
+ )
- /* there might be new distribution points */
- add_distribution_points(req->distributionPoints, &r->distributionPoints);
+ /* there might be new distribution points */
+ add_distribution_points(req->distributionPoints, &r->distributionPoints);
- unlock_crl_fetch_list("add_crl_fetch_request");
- free_fetch_request(req);
- return;
+ unlock_crl_fetch_list("add_crl_fetch_request");
+ free_fetch_request(req);
+ return;
+ }
+ r = r->next;
}
- r = r->next;
- }
- /* insert new fetch request at the head of the queue */
- req->next = crl_fetch_reqs;
- crl_fetch_reqs = req;
+ /* insert new fetch request at the head of the queue */
+ req->next = crl_fetch_reqs;
+ crl_fetch_reqs = req;
- DBG(DBG_CONTROL,
- DBG_log("crl fetch request added")
- )
- unlock_crl_fetch_list("add_crl_fetch_request");
+ DBG(DBG_CONTROL,
+ DBG_log("crl fetch request added")
+ )
+ unlock_crl_fetch_list("add_crl_fetch_request");
}
-/*
- * add an ocsp fetch request to the chained list
+/**
+ * Add an ocsp fetch request to the chained list
*/
-void
-add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
+void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
{
- ocsp_certinfo_t certinfo;
+ ocsp_certinfo_t certinfo;
- certinfo.serialNumber = serialNumber;
+ certinfo.serialNumber = serialNumber;
- lock_ocsp_fetch_list("add_ocsp_fetch_request");
- add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE);
- unlock_ocsp_fetch_list("add_ocsp_fetch_request");
+ lock_ocsp_fetch_list("add_ocsp_fetch_request");
+ add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE);
+ unlock_ocsp_fetch_list("add_ocsp_fetch_request");
}
-/*
- * list all distribution points
+/**
+ * List all distribution points
*/
-void
-list_distribution_points(const generalName_t *gn)
+void list_distribution_points(const generalName_t *gn)
{
- bool first_gn = TRUE;
-
- while (gn != NULL)
- {
- whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: "
- :" ", (int)gn->name.len, gn->name.ptr);
- first_gn = FALSE;
- gn = gn->next;
- }
+ bool first_gn = TRUE;
+
+ while (gn != NULL)
+ {
+ whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: "
+ :" ", (int)gn->name.len, gn->name.ptr);
+ first_gn = FALSE;
+ gn = gn->next;
+ }
}
-/*
- * list all fetch requests in the chained list
+/**
+ * List all fetch requests in the chained list
*/
-void
-list_crl_fetch_requests(bool utc)
+void list_crl_fetch_requests(bool utc)
{
- fetch_req_t *req;
-
- lock_crl_fetch_list("list_crl_fetch_requests");
- req = crl_fetch_reqs;
-
- if (req != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of CRL fetch requests:");
- whack_log(RC_COMMENT, " ");
- }
-
- while (req != NULL)
- {
- u_char buf[BUF_LEN];
-
- whack_log(RC_COMMENT, "%s, trials: %d"
- , timetoa(&req->installed, utc), req->trials);
- dntoa(buf, BUF_LEN, req->issuer);
- whack_log(RC_COMMENT, " issuer: '%s'", buf);
- if (req->authKeyID.ptr != NULL)
+ fetch_req_t *req;
+
+ lock_crl_fetch_list("list_crl_fetch_requests");
+ req = crl_fetch_reqs;
+
+ if (req != NULL)
{
- datatot(req->authKeyID.ptr, req->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of CRL fetch requests:");
+ whack_log(RC_COMMENT, " ");
}
- if (req->authKeySerialNumber.ptr != NULL)
+
+ while (req != NULL)
{
- datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ u_char buf[BUF_LEN];
+
+ whack_log(RC_COMMENT, "%T, trials: %d"
+ , &req->installed, utc, req->trials);
+ dntoa(buf, BUF_LEN, req->issuer);
+ whack_log(RC_COMMENT, " issuer: '%s'", buf);
+ if (req->authKeyID.ptr != NULL)
+ {
+ datatot(req->authKeyID.ptr, req->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authkey: %s", buf);
+ }
+ if (req->authKeySerialNumber.ptr != NULL)
+ {
+ datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " aserial: %s", buf);
+ }
+ list_distribution_points(req->distributionPoints);
+ req = req->next;
}
- list_distribution_points(req->distributionPoints);
- req = req->next;
- }
- unlock_crl_fetch_list("list_crl_fetch_requests");
+ unlock_crl_fetch_list("list_crl_fetch_requests");
}
-void
-list_ocsp_fetch_requests(bool utc)
+void list_ocsp_fetch_requests(bool utc)
{
- lock_ocsp_fetch_list("list_ocsp_fetch_requests");
- list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE);
- unlock_ocsp_fetch_list("list_ocsp_fetch_requests");
+ lock_ocsp_fetch_list("list_ocsp_fetch_requests");
+ list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE);
+ unlock_ocsp_fetch_list("list_ocsp_fetch_requests");
}
diff --git a/src/pluto/fetch.h b/src/pluto/fetch.h
index 67be12d47..f7b4eb074 100644
--- a/src/pluto/fetch.h
+++ b/src/pluto/fetch.h
@@ -11,31 +11,29 @@
* 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: fetch.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include "x509.h"
-#define FETCH_CMD_TIMEOUT 10 /* seconds */
+#define FETCH_CMD_TIMEOUT 10 /* seconds */
-struct ocsp_location; /* forward declaration of ocsp_location defined in ocsp.h */
+struct ocsp_location; /* forward declaration of ocsp_location defined in ocsp.h */
typedef enum {
- FETCH_GET = 1,
- FETCH_POST = 2
+ FETCH_GET = 1,
+ FETCH_POST = 2
} fetch_request_t;
typedef struct fetch_req fetch_req_t;
struct fetch_req {
- fetch_req_t *next;
- time_t installed;
- int trials;
- chunk_t issuer;
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- generalName_t *distributionPoints;
+ fetch_req_t *next;
+ time_t installed;
+ int trials;
+ chunk_t issuer;
+ chunk_t authKeyID;
+ chunk_t authKeySerialNumber;
+ generalName_t *distributionPoints;
};
#ifdef THREADS
@@ -67,9 +65,9 @@ extern void init_fetch(void);
extern void free_crl_fetch(void);
extern void free_ocsp_fetch(void);
extern void add_distribution_points(const generalName_t *newPoints
- , generalName_t **distributionPoints);
+ , generalName_t **distributionPoints);
extern fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber
- , chunk_t authKeyID, const generalName_t *gn);
+ , chunk_t authKeyID, const generalName_t *gn);
extern void add_crl_fetch_request(fetch_req_t *req);
extern void add_ocsp_fetch_request(struct ocsp_location *location, chunk_t serialNumber);
extern void list_distribution_points(const generalName_t *gn);
diff --git a/src/pluto/foodgroups.c b/src/pluto/foodgroups.c
index 5b2836bce..ed9853fc4 100644
--- a/src/pluto/foodgroups.c
+++ b/src/pluto/foodgroups.c
@@ -10,8 +10,6 @@
* 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: foodgroups.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <string.h>
@@ -49,8 +47,8 @@ static size_t fg_path_space = 0;
*/
struct fg_groups {
- struct fg_groups *next;
- struct connection *connection;
+ struct fg_groups *next;
+ struct connection *connection;
};
static struct fg_groups *groups = NULL;
@@ -66,10 +64,10 @@ static struct fg_groups *groups = NULL;
*/
struct fg_targets {
- struct fg_targets *next;
- struct fg_groups *group;
- ip_subnet subnet;
- char *name; /* name of instance of group conn */
+ struct fg_targets *next;
+ struct fg_groups *group;
+ ip_subnet subnet;
+ char *name; /* name of instance of group conn */
};
static struct fg_targets *targets = NULL;
@@ -83,24 +81,24 @@ struct fg_targets *new_targets;
static int
ipcmp(ip_address *a, ip_address *b)
{
- if (addrtypeof(a) != addrtypeof(b))
- {
- return addrtypeof(a) < addrtypeof(b)? -1 : 1;
- }
- else if (sameaddr(a, b))
- {
- return 0;
- }
- else
- {
- const struct sockaddr *sa = sockaddrof(a)
- , *sb = sockaddrof(b);
-
- passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */
- return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr)
- < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr))
- ? -1 : 1;
- }
+ if (addrtypeof(a) != addrtypeof(b))
+ {
+ return addrtypeof(a) < addrtypeof(b)? -1 : 1;
+ }
+ else if (sameaddr(a, b))
+ {
+ return 0;
+ }
+ else
+ {
+ const struct sockaddr *sa = sockaddrof(a)
+ , *sb = sockaddrof(b);
+
+ passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */
+ return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr)
+ < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr))
+ ? -1 : 1;
+ }
}
/* subnetcmp compares the two ip_subnet values a and b.
@@ -110,353 +108,353 @@ ipcmp(ip_address *a, ip_address *b)
static int
subnetcmp(const ip_subnet *a, const ip_subnet *b)
{
- ip_address neta, maska, netb, maskb;
- int r;
-
- networkof(a, &neta);
- maskof(a, &maska);
- networkof(b, &netb);
- maskof(b, &maskb);
- r = ipcmp(&neta, &netb);
- if (r == 0)
- r = ipcmp(&maska, &maskb);
- return r;
+ ip_address neta, maska, netb, maskb;
+ int r;
+
+ networkof(a, &neta);
+ maskof(a, &maska);
+ networkof(b, &netb);
+ maskof(b, &maskb);
+ r = ipcmp(&neta, &netb);
+ if (r == 0)
+ r = ipcmp(&maska, &maskb);
+ return r;
}
static void
read_foodgroup(struct fg_groups *g)
{
- const char *fgn = g->connection->name;
- const ip_subnet *lsn = &g->connection->spd.this.client;
- size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1;
- struct file_lex_position flp_space;
-
- if (plen > fg_path_space)
- {
- pfreeany(fg_path);
- fg_path_space = plen + 10;
- fg_path = alloc_bytes(fg_path_space, "policy group path");
- }
- snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn);
- if (!lexopen(&flp_space, fg_path, TRUE))
- {
- DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path));
- }
- else
- {
- plog("loading group \"%s\"", fg_path);
- for (;;)
+ const char *fgn = g->connection->name;
+ const ip_subnet *lsn = &g->connection->spd.this.client;
+ size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1;
+ struct file_lex_position flp_space;
+
+ if (plen > fg_path_space)
+ {
+ free(fg_path);
+ fg_path_space = plen + 10;
+ fg_path = malloc(fg_path_space);
+ }
+ snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn);
+ if (!lexopen(&flp_space, fg_path, TRUE))
+ {
+ DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path));
+ }
+ else
{
- switch (flp->bdry)
- {
- case B_none:
+ plog("loading group \"%s\"", fg_path);
+ for (;;)
{
- /* !!! this test is not sufficient for distinguishing address families.
- * We need a notation to specify that a FQDN is to be resolved to IPv6.
- */
- const struct af_info *afi = strchr(tok, ':') == NULL
- ? &af_inet4_info: &af_inet6_info;
- ip_subnet sn;
- err_t ugh;
-
- if (strchr(tok, '/') == NULL)
- {
- /* no /, so treat as /32 or V6 equivalent */
- ip_address t;
-
- ugh = ttoaddr(tok, 0, afi->af, &t);
- if (ugh == NULL)
- ugh = addrtosubnet(&t, &sn);
- }
- else
- {
- ugh = ttosubnet(tok, 0, afi->af, &sn);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\""
- , flp->filename, flp->lino, ugh, tok);
- }
- else if (afi->af != AF_INET)
- {
- loglog(RC_LOG_SERIOUS
- , "\"%s\" line %d: unsupported Address Family \"%s\""
- , flp->filename, flp->lino, tok);
- }
- else
- {
- /* Find where new entry ought to go in new_targets. */
- struct fg_targets **pp;
- int r;
-
- for (pp = &new_targets; ; pp = &(*pp)->next)
- {
- if (*pp == NULL)
- {
- r = -1; /* end of list is infinite */
- break;
- }
- r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client);
- if (r == 0)
- r = subnetcmp(&sn, &(*pp)->subnet);
- if (r <= 0)
- break;
- }
-
- if (r == 0)
+ switch (flp->bdry)
{
- char source[SUBNETTOT_BUF];
-
- subnettot(lsn, 0, source, sizeof(source));
- loglog(RC_LOG_SERIOUS
- , "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\""
- , flp->filename
- , flp->lino
- , tok
- , source
- , (*pp)->group->connection->name);
+ case B_none:
+ {
+ /* !!! this test is not sufficient for distinguishing address families.
+ * We need a notation to specify that a FQDN is to be resolved to IPv6.
+ */
+ const struct af_info *afi = strchr(tok, ':') == NULL
+ ? &af_inet4_info: &af_inet6_info;
+ ip_subnet sn;
+ err_t ugh;
+
+ if (strchr(tok, '/') == NULL)
+ {
+ /* no /, so treat as /32 or V6 equivalent */
+ ip_address t;
+
+ ugh = ttoaddr(tok, 0, afi->af, &t);
+ if (ugh == NULL)
+ ugh = addrtosubnet(&t, &sn);
+ }
+ else
+ {
+ ugh = ttosubnet(tok, 0, afi->af, &sn);
+ }
+
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\""
+ , flp->filename, flp->lino, ugh, tok);
+ }
+ else if (afi->af != AF_INET)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "\"%s\" line %d: unsupported Address Family \"%s\""
+ , flp->filename, flp->lino, tok);
+ }
+ else
+ {
+ /* Find where new entry ought to go in new_targets. */
+ struct fg_targets **pp;
+ int r;
+
+ for (pp = &new_targets; ; pp = &(*pp)->next)
+ {
+ if (*pp == NULL)
+ {
+ r = -1; /* end of list is infinite */
+ break;
+ }
+ r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client);
+ if (r == 0)
+ r = subnetcmp(&sn, &(*pp)->subnet);
+ if (r <= 0)
+ break;
+ }
+
+ if (r == 0)
+ {
+ char source[SUBNETTOT_BUF];
+
+ subnettot(lsn, 0, source, sizeof(source));
+ loglog(RC_LOG_SERIOUS
+ , "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\""
+ , flp->filename
+ , flp->lino
+ , tok
+ , source
+ , (*pp)->group->connection->name);
+ }
+ else
+ {
+ struct fg_targets *f = malloc_thing(struct fg_targets);
+
+ f->next = *pp;
+ f->group = g;
+ f->subnet = sn;
+ f->name = NULL;
+ *pp = f;
+ }
+ }
+ }
+ (void)shift(); /* next */
+ continue;
+
+ case B_record:
+ flp->bdry = B_none; /* eat the Record Boundary */
+ (void)shift(); /* get real first token */
+ continue;
+
+ case B_file:
+ break; /* done */
}
- else
- {
- struct fg_targets *f = alloc_thing(struct fg_targets, "fg_target");
-
- f->next = *pp;
- f->group = g;
- f->subnet = sn;
- f->name = NULL;
- *pp = f;
- }
- }
+ break; /* if we reach here, out of loop */
}
- (void)shift(); /* next */
- continue;
-
- case B_record:
- flp->bdry = B_none; /* eat the Record Boundary */
- (void)shift(); /* get real first token */
- continue;
-
- case B_file:
- break; /* done */
- }
- break; /* if we reach here, out of loop */
+ lexclose();
}
- lexclose();
- }
}
static void
free_targets(void)
{
- while (targets != NULL)
- {
- struct fg_targets *t = targets;
-
- targets = t->next;
- pfreeany(t->name);
- pfree(t);
- }
+ while (targets != NULL)
+ {
+ struct fg_targets *t = targets;
+
+ targets = t->next;
+ free(t->name);
+ free(t);
+ }
}
void
load_groups(void)
{
- passert(new_targets == NULL);
+ passert(new_targets == NULL);
- /* for each group, add config file targets into new_targets */
- {
- struct fg_groups *g;
+ /* for each group, add config file targets into new_targets */
+ {
+ struct fg_groups *g;
- for (g = groups; g != NULL; g = g->next)
- if (oriented(*g->connection))
- read_foodgroup(g);
- }
+ for (g = groups; g != NULL; g = g->next)
+ if (oriented(*g->connection))
+ read_foodgroup(g);
+ }
- /* dump new_targets */
- DBG(DBG_CONTROL,
- {
- struct fg_targets *t;
-
- for (t = new_targets; t != NULL; t = t->next)
- {
- char asource[SUBNETTOT_BUF];
- char atarget[SUBNETTOT_BUF];
-
- subnettot(&t->group->connection->spd.this.client
- , 0, asource, sizeof(asource));
- subnettot(&t->subnet, 0, atarget, sizeof(atarget));
- DBG_log("%s->%s %s"
- , asource, atarget
- , t->group->connection->name);
- }
- });
-
- /* determine and deal with differences between targets and new_targets.
- * structured like a merge.
- */
- {
- struct fg_targets *op = targets
- , *np = new_targets;
-
- while (op != NULL && np != NULL)
- {
- int r = subnetcmp(&op->group->connection->spd.this.client
- , &np->group->connection->spd.this.client);
-
- if (r == 0)
- r = subnetcmp(&op->subnet, &np->subnet);
-
- if (r == 0 && op->group == np->group)
- {
- /* unchanged -- steal name & skip over */
- np->name = op->name;
- op->name = NULL;
- op = op->next;
- np = np->next;
- }
- else
- {
- /* note: following cases overlap! */
- if (r <= 0)
+ /* dump new_targets */
+ DBG(DBG_CONTROL,
{
- remove_group_instance(op->group->connection, op->name);
- op = op->next;
- }
- if (r >= 0)
+ struct fg_targets *t;
+
+ for (t = new_targets; t != NULL; t = t->next)
+ {
+ char asource[SUBNETTOT_BUF];
+ char atarget[SUBNETTOT_BUF];
+
+ subnettot(&t->group->connection->spd.this.client
+ , 0, asource, sizeof(asource));
+ subnettot(&t->subnet, 0, atarget, sizeof(atarget));
+ DBG_log("%s->%s %s"
+ , asource, atarget
+ , t->group->connection->name);
+ }
+ });
+
+ /* determine and deal with differences between targets and new_targets.
+ * structured like a merge.
+ */
+ {
+ struct fg_targets *op = targets
+ , *np = new_targets;
+
+ while (op != NULL && np != NULL)
{
- np->name = add_group_instance(np->group->connection, &np->subnet);
- np = np->next;
+ int r = subnetcmp(&op->group->connection->spd.this.client
+ , &np->group->connection->spd.this.client);
+
+ if (r == 0)
+ r = subnetcmp(&op->subnet, &np->subnet);
+
+ if (r == 0 && op->group == np->group)
+ {
+ /* unchanged -- steal name & skip over */
+ np->name = op->name;
+ op->name = NULL;
+ op = op->next;
+ np = np->next;
+ }
+ else
+ {
+ /* note: following cases overlap! */
+ if (r <= 0)
+ {
+ remove_group_instance(op->group->connection, op->name);
+ op = op->next;
+ }
+ if (r >= 0)
+ {
+ np->name = add_group_instance(np->group->connection, &np->subnet);
+ np = np->next;
+ }
+ }
}
- }
+ for (; op != NULL; op = op->next)
+ remove_group_instance(op->group->connection, op->name);
+ for (; np != NULL; np = np->next)
+ np->name = add_group_instance(np->group->connection, &np->subnet);
+
+ /* update: new_targets replaces targets */
+ free_targets();
+ targets = new_targets;
+ new_targets = NULL;
}
- for (; op != NULL; op = op->next)
- remove_group_instance(op->group->connection, op->name);
- for (; np != NULL; np = np->next)
- np->name = add_group_instance(np->group->connection, &np->subnet);
-
- /* update: new_targets replaces targets */
- free_targets();
- targets = new_targets;
- new_targets = NULL;
- }
}
void
add_group(struct connection *c)
{
- struct fg_groups *g = alloc_thing(struct fg_groups, "policy group");
+ struct fg_groups *g = malloc_thing(struct fg_groups);
- g->next = groups;
- groups = g;
+ g->next = groups;
+ groups = g;
- g->connection = c;
+ g->connection = c;
}
static struct fg_groups *
find_group(const struct connection *c)
{
- struct fg_groups *g;
+ struct fg_groups *g;
- for (g = groups; g != NULL && g->connection != c; g = g->next)
- ;
- return g;
+ for (g = groups; g != NULL && g->connection != c; g = g->next)
+ ;
+ return g;
}
void
route_group(struct connection *c)
{
- /* it makes no sense to route a connection that is ISAKMP-only */
- if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
- {
- loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection");
- }
- else
- {
- struct fg_groups *g = find_group(c);
- struct fg_targets *t;
-
- passert(g != NULL);
- g->connection->policy |= POLICY_GROUTED;
- for (t = targets; t != NULL; t = t->next)
+ /* it makes no sense to route a connection that is ISAKMP-only */
+ if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
+ {
+ loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection");
+ }
+ else
{
- if (t->group == g)
- {
- struct connection *ci = con_by_name(t->name, FALSE);
+ struct fg_groups *g = find_group(c);
+ struct fg_targets *t;
- if (ci != NULL)
+ passert(g != NULL);
+ g->connection->policy |= POLICY_GROUTED;
+ for (t = targets; t != NULL; t = t->next)
{
- set_cur_connection(ci);
- if (!trap_connection(ci))
- whack_log(RC_ROUTE, "could not route");
- set_cur_connection(c);
+ if (t->group == g)
+ {
+ struct connection *ci = con_by_name(t->name, FALSE);
+
+ if (ci != NULL)
+ {
+ set_cur_connection(ci);
+ if (!trap_connection(ci))
+ whack_log(RC_ROUTE, "could not route");
+ set_cur_connection(c);
+ }
+ }
}
- }
}
- }
}
void
unroute_group(struct connection *c)
{
- struct fg_groups *g = find_group(c);
- struct fg_targets *t;
-
- passert(g != NULL);
- g->connection->policy &= ~POLICY_GROUTED;
- for (t = targets; t != NULL; t = t->next)
- {
- if (t->group == g)
+ struct fg_groups *g = find_group(c);
+ struct fg_targets *t;
+
+ passert(g != NULL);
+ g->connection->policy &= ~POLICY_GROUTED;
+ for (t = targets; t != NULL; t = t->next)
{
- struct connection *ci = con_by_name(t->name, FALSE);
-
- if (ci != NULL)
- {
- set_cur_connection(ci);
- unroute_connection(ci);
- set_cur_connection(c);
- }
+ if (t->group == g)
+ {
+ struct connection *ci = con_by_name(t->name, FALSE);
+
+ if (ci != NULL)
+ {
+ set_cur_connection(ci);
+ unroute_connection(ci);
+ set_cur_connection(c);
+ }
+ }
}
- }
}
void
delete_group(const struct connection *c)
{
- struct fg_groups *g;
-
- /* find and remove from groups */
- {
- struct fg_groups **pp;
+ struct fg_groups *g;
- for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next)
- ;
+ /* find and remove from groups */
+ {
+ struct fg_groups **pp;
- *pp = g->next;
- }
+ for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next)
+ ;
- /* find and remove from targets */
- {
- struct fg_targets **pp;
+ *pp = g->next;
+ }
- for (pp = &targets; *pp != NULL; )
+ /* find and remove from targets */
{
- struct fg_targets *t = *pp;
-
- if (t->group == g)
- {
- *pp = t->next;
- remove_group_instance(t->group->connection, t->name);
- pfree(t);
- /* pp is ready for next iteration */
- }
- else
- {
- pp = &t->next;
- }
+ struct fg_targets **pp;
+
+ for (pp = &targets; *pp != NULL; )
+ {
+ struct fg_targets *t = *pp;
+
+ if (t->group == g)
+ {
+ *pp = t->next;
+ remove_group_instance(t->group->connection, t->name);
+ free(t);
+ /* pp is ready for next iteration */
+ }
+ else
+ {
+ pp = &t->next;
+ }
+ }
}
- }
- pfree(g);
+ free(g);
}
diff --git a/src/pluto/foodgroups.h b/src/pluto/foodgroups.h
index d66f85423..b6d3386ae 100644
--- a/src/pluto/foodgroups.h
+++ b/src/pluto/foodgroups.h
@@ -10,11 +10,9 @@
* 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: foodgroups.h 3252 2007-10-06 21:24:50Z andreas $
*/
-struct connection; /* forward declaration */
+struct connection; /* forward declaration */
extern void add_group(struct connection *c);
extern void route_group(struct connection *c);
extern void unroute_group(struct connection *c);
diff --git a/src/pluto/gcryptfix.c b/src/pluto/gcryptfix.c
deleted file mode 100644
index b8007046d..000000000
--- a/src/pluto/gcryptfix.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Routines to make gcrypt routines feel at home in Pluto.
- * Copyright (C) 1999 D. Hugh Redelmeier.
- *
- * 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: gcryptfix.c 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#include <stdlib.h>
-
-#include <gmp.h>
-#include <freeswan.h>
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "rnd.h"
-#include "gcryptfix.h" /* includes <gmp.h> "defs.h" "rnd.h" */
-
-MPI
-mpi_alloc( unsigned nlimbs UNUSED )
-{
- MPI n = alloc_bytes(sizeof *n, "mpi_alloc");
-
- mpz_init(n);
- return n;
-}
-
-MPI
-mpi_alloc_secure( unsigned nlimbs )
-{
- return mpi_alloc(nlimbs);
-}
-
-MPI
-mpi_alloc_set_ui( unsigned long u)
-{
- MPI n = alloc_bytes(sizeof *n, "mpi_copy");
-
- mpz_init_set_ui(n, u);
- return n;
-}
-
-MPI
-mpi_copy( MPI a )
-{
- MPI n = alloc_bytes(sizeof *n, "mpi_copy");
-
- mpz_init_set(n, a);
- return n;
-}
-
-void
-mpi_free( MPI a )
-{
- mpz_clear(a);
- pfree(a);
-}
-
-int
-mpi_divisible_ui(MPI dividend, ulong divisor )
-{
- ulong rem;
- mpz_t remtoo;
-
- mpz_init(remtoo);
- rem = mpz_mod_ui(remtoo, dividend, divisor);
- mpz_clear(remtoo);
- return rem == 0;
-}
-
-unsigned
-mpi_trailing_zeros( MPI a )
-{
- return mpz_scan1(a, 0);
-}
-
-unsigned
-mpi_get_nbits( MPI a )
-{
- return mpz_sizeinbase(a, 2);
-}
-
-int
-mpi_test_bit( MPI a, unsigned n )
-{
- /* inspired by gmp/mpz/clrbit.c */
- mp_size_t li = n / mp_bits_per_limb;
-
- if (li >= a->_mp_size)
- return 0;
- return (a->_mp_d[li] & ((mp_limb_t) 1 << (n % mp_bits_per_limb))) != 0;
-}
-
-void
-mpi_set_bit( MPI a, unsigned n )
-{
- mpz_setbit(a, n);
-}
-
-void
-mpi_clear_bit( MPI a, unsigned n )
-{
- mpz_clrbit(a, n);
-}
-
-void
-mpi_clear_highbit( MPI a, unsigned n )
-{
- /* This seems whacky, but what do I know. */
- mpz_fdiv_r_2exp(a, a, n);
-}
-
-void
-mpi_set_highbit( MPI a, unsigned n )
-{
- /* This seems whacky, but what do I know. */
- mpz_fdiv_r_2exp(a, a, n+1);
- mpz_setbit(a, n);
-}
-
-void
-mpi_set_buffer( MPI a, const u_char *buffer, unsigned nbytes, int sign )
-{
- /* this is a lot like n_to_mpz */
- size_t i;
-
- passert(sign == 0); /* we won't hit any negative numbers */
- mpz_init_set_ui(a, 0);
-
- for (i = 0; i != nbytes; i++)
- {
- mpz_mul_ui(a, a, 1 << BITS_PER_BYTE);
- mpz_add_ui(a, a, buffer[i]);
- }
-}
-
-u_char *
-get_random_bits(size_t nbits, int level UNUSED, int secure UNUSED)
-{
- size_t nbytes = (nbits+7)/8;
- u_char *b = alloc_bytes(nbytes, "random bytes");
-
- get_rnd_bytes(b, nbytes);
- return b;
-}
-/**************** from gnupg-1.0.0/mpi/mpi-mpow.c
- * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M
- */
-#define barrett_mulm( w, u, v, m, y, k, r1, r2 ) mpi_mulm( (w), (u), (v), (m) )
-
-static int
-build_index( MPI *exparray, int k, int i, int t )
-{
- int j, bitno;
- int index = 0;
-
- bitno = t-i;
- for(j=k-1; j >= 0; j-- ) {
- index <<= 1;
- if( mpi_test_bit( exparray[j], bitno ) )
- index |= 1;
- }
- /*log_debug("t=%d i=%d index=%d\n", t, i, index );*/
- return index;
-}
-
-void
-mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m)
-{
- int k; /* number of elements */
- int t; /* bit size of largest exponent */
- int i, j, idx;
- MPI *G; /* table with precomputed values of size 2^k */
- MPI tmp;
- #ifdef USE_BARRETT
- MPI barrett_y, barrett_r1, barrett_r2;
- int barrett_k;
- #endif
-
- for(k=0; basearray[k]; k++ )
- ;
- passert(k);
- for(t=0, i=0; (tmp=exparray[i]); i++ ) {
- /*log_mpidump("exp: ", tmp );*/
- j = mpi_get_nbits(tmp);
- if( j > t )
- t = j;
- }
- /*log_mpidump("mod: ", m );*/
- passert(i==k);
- passert(t);
- passert( k < 10 );
-
-#ifdef PLUTO
- m_alloc_ptrs_clear(G, 1<<k);
-#else
- G = m_alloc_clear( (1<<k) * sizeof *G );
-#endif
-
- #ifdef USE_BARRETT
- barrett_y = init_barrett( m, &barrett_k, &barrett_r1, &barrett_r2 );
- #endif
- /* and calculate */
- tmp = mpi_alloc( mpi_get_nlimbs(m)+1 );
- mpi_set_ui( res, 1 );
- for(i = 1; i <= t; i++ ) {
- barrett_mulm(tmp, res, res, m, barrett_y, barrett_k,
- barrett_r1, barrett_r2 );
- idx = build_index( exparray, k, i, t );
- passert( idx >= 0 && idx < (1<<k) );
- if( !G[idx] ) {
- if( !idx )
- G[0] = mpi_alloc_set_ui( 1 );
- else {
- for(j=0; j < k; j++ ) {
- if( (idx & (1<<j) ) ) {
- if( !G[idx] )
- G[idx] = mpi_copy( basearray[j] );
- else
- barrett_mulm( G[idx], G[idx], basearray[j],
- m, barrett_y, barrett_k, barrett_r1, barrett_r2 );
- }
- }
- if( !G[idx] )
- G[idx] = mpi_alloc(0);
- }
- }
- barrett_mulm(res, tmp, G[idx], m, barrett_y, barrett_k, barrett_r1, barrett_r2 );
- }
-
- /* cleanup */
- mpi_free(tmp);
- #ifdef USE_BARRETT
- mpi_free(barrett_y);
- mpi_free(barrett_r1);
- mpi_free(barrett_r2);
- #endif
- for(i=0; i < (1<<k); i++ )
- mpi_free(G[i]);
- m_free(G);
-}
-
-void
-log_mpidump( const char *text UNUSED, MPI a )
-{
- /* Print number in hex -- helpful to see if they match bytes.
- * Humans are not going to do arithmetic with the large numbers!
- * Much code adapted from mpz_to_n.
- */
- u_char buf[8048]; /* this ought to be big enough */
- size_t len = (mpz_sizeinbase(a, 16) + 1) / 2; /* bytes */
- MP_INT temp1, temp2;
- int i;
-
- passert(len <= sizeof(buf));
-
- mpz_init(&temp1);
- mpz_init(&temp2);
-
- mpz_set(&temp1, a);
-
- for (i = len-1; i >= 0; i--)
- {
- buf[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE);
- mpz_set(&temp1, &temp2);
- }
-
- passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */
- mpz_clear(&temp1);
- mpz_clear(&temp2);
-
-#ifdef DEBUG
- DBG_dump(text, buf, len);
-#endif /* DEBUG */
-}
diff --git a/src/pluto/gcryptfix.h b/src/pluto/gcryptfix.h
deleted file mode 100644
index db2587c59..000000000
--- a/src/pluto/gcryptfix.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Definitions to make gcrypt routines feel at home in Pluto.
- * Copyright (C) 1999 D. Hugh Redelmeier.
- *
- * 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: gcryptfix.h 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#define DBG_CIPHER 1 /* some day we'll do this right */
-
-/* Simulate MPI routines with gmp routines.
- * gmp's MP_INT is a stuct; MPI's MPI is a pointer to an analogous struct.
- * gmp's mpz_t is an array of one of these structs to enable magic pointer
- * conversions to make the notation convenient (but confusing).
- */
-typedef u_char byte;
-typedef MP_INT *MPI;
-
-#define BITS_PER_MPI_LIMB mp_bits_per_limb
-
-extern MPI mpi_alloc( unsigned nlimbs );
-extern MPI mpi_alloc_secure( unsigned nlimbs );
-#define mpi_alloc_like(n) mpi_alloc(mpi_get_nlimbs(n))
-extern MPI mpi_alloc_set_ui( unsigned long u);
-#define mpi_set_ui(w, u) mpz_set_ui(w, u)
-#define mpi_set(w, u) mpz_set(w, u)
-extern void mpi_free( MPI a );
-extern MPI mpi_copy( MPI a );
-extern unsigned mpi_get_nbits( MPI a );
-#define mpi_get_nlimbs(a) ((a)->_mp_alloc) /* dirty, but useless */
-extern void mpi_set_buffer( MPI a, const u_char *buffer, unsigned nbytes, int sign );
-extern unsigned mpi_trailing_zeros( MPI a );
-extern int mpi_test_bit( MPI a, unsigned n );
-extern void mpi_set_bit( MPI a, unsigned n );
-extern void mpi_clear_bit( MPI a, unsigned n );
-extern void mpi_clear_highbit( MPI a, unsigned n );
-extern void mpi_set_highbit( MPI a, unsigned n );
-#define mpi_cmp_ui(u, v) mpz_cmp_ui((u), (v))
-#define mpi_cmp(u, v) mpz_cmp((u), (v))
-#define mpi_is_neg(n) (mpz_sgn(n) < 0)
-#define mpi_add(w, u, v) mpz_add((w), (u), (v))
-#define mpi_add_ui(w, u, v) mpz_add_ui((w), (u), (v))
-#define mpi_sub_ui(w, u, v) mpz_sub_ui((w), (u), (v))
-#define mpi_subm( w, u, v, m) { mpz_sub( (w), (u), (v)) ; mpz_fdiv_r((w), (w), (m)); }
-#define mpi_mul( w, u, v) mpz_mul( (w), (u), (v))
-#define mpi_mul_ui( w, u, v) mpz_mul_ui( (w), (u), (v))
-#define mpi_mulm( w, u, v, m) { mpz_mul( (w), (u), (v)) ; mpz_fdiv_r((w), (w), (m)); }
-#define mpi_fdiv_q(quot, dividend, divisor) mpz_fdiv_q((quot), (dividend), (divisor))
-#define mpi_fdiv_r( rem, dividend, divisor ) mpz_fdiv_r( (rem), (dividend), (divisor) )
-#define mpi_fdiv_r_ui( rem, dividend, divisor ) mpz_fdiv_r_ui( (rem), (dividend), (divisor) )
-#define mpi_tdiv_q_2exp( w, u, count ) mpz_tdiv_q_2exp( (w), (u), (count) )
-extern int mpi_divisible_ui(MPI dividend, ulong divisor );
-#define mpi_powm( res, base, exp, mod) mpz_powm( res, base, exp, mod)
-extern void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod);
-#define mpi_gcd( g, a, b ) ( mpz_gcd( (g), (a), (b) ), !mpi_cmp_ui( (g), 1))
-#define mpi_invm( x, a, n ) mpz_invert( (x), (a), (n) )
-
-#ifdef DEBUG
-# define log_debug(f...) DBG_log(f)
-#else
-# define log_debug(f...) do ; while (0) /* do nothing, carefully */
-#endif
-#define log_fatal(f...) exit_log(f) /* overreaction? */
-extern void log_mpidump( const char *text, MPI a );
-
-#define assert(p) passert(p)
-#define BUG() passert(FALSE)
-
-#define m_alloc_ptrs_clear(pp, n) { \
- int c = (n); \
- (pp) = alloc_bytes((n) * sizeof(*(pp)), "m_alloc_ptrs_clear"); \
- while (c > 0) (pp)[--c] = NULL; \
- }
-
-extern u_char *get_random_bits(size_t nbits, int level, int secure);
-#define m_alloc(sz) alloc_bytes((sz), "m_alloc") /* not initialized */
-#define m_free(n) pfree(n) /* always freeing something from get_random_bits */
-
-/* declarations from gnupg-1.0.0/include/cipher.h */
-/*-- primegen.c --*/
-MPI generate_secret_prime( unsigned nbits );
-MPI generate_public_prime( unsigned nbits );
-MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
- MPI g, MPI **factors );
-
-#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not for v3)*/
-#define PUBKEY_ALGO_DSA 17
-#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */
-
-#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E)
-
-#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */
-#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */
-
-/* from gnupg-1.0.0/include/errors.h */
-
-#define G10ERR_PUBKEY_ALGO 4 /* Unknown pubkey algorithm */
-#define G10ERR_BAD_SECKEY 7 /* Bad secret key */
-#define G10ERR_BAD_SIGN 8 /* Bad signature */
-#define G10ERR_BAD_MPI 30
-
-/*-- smallprime.c --*/
-extern ushort small_prime_numbers[];
diff --git a/src/pluto/id.c b/src/pluto/id.c
index 8db322a5e..f34775e68 100644
--- a/src/pluto/id.c
+++ b/src/pluto/id.c
@@ -10,8 +10,6 @@
* 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: id.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdlib.h>
@@ -22,13 +20,12 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
-#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
-# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
+#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
+# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
#endif
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "constants.h"
#include "defs.h"
@@ -38,10 +35,10 @@
#include "packet.h"
#include "whack.h"
-const struct id empty_id; /* ID_NONE */
+const struct id empty_id; /* ID_ANY */
enum myid_state myid_state = MYID_UNKNOWN;
-struct id myids[MYID_SPECIFIED+1]; /* %myid */
+struct id myids[MYID_SPECIFIED+1]; /* %myid */
char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */
/* initialize id module
@@ -50,100 +47,117 @@ char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */
void
init_id(void)
{
- passert(empty_id.kind == ID_NONE);
- myid_state = MYID_UNKNOWN;
- {
+ passert(empty_id.kind == ID_ANY);
+ myid_state = MYID_UNKNOWN;
+ {
+ enum myid_state s;
+
+ for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
+ {
+ myids[s] = empty_id;
+ myid_str[s] = NULL;
+ }
+ }
+ set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
+ set_myid(MYID_IP, getenv("defaultrouteaddr"));
+ set_myFQDN();
+}
+
+/*
+ * free id module
+ */
+void
+free_id(void)
+{
enum myid_state s;
for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
{
- myids[s] = empty_id;
- myid_str[s] = NULL;
+ free_id_content(&myids[s]);
+ free(myid_str[s]);
}
- }
- set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
- set_myid(MYID_IP, getenv("defaultrouteaddr"));
- set_myFQDN();
}
static void
calc_myid_str(enum myid_state s)
{
- /* preformat the ID name */
- char buf[BUF_LEN];
+ /* preformat the ID name */
+ char buf[BUF_LEN];
- idtoa(&myids[s], buf, BUF_LEN);
- replace(myid_str[s], clone_str(buf, "myid string"));
+ idtoa(&myids[s], buf, BUF_LEN);
+ replace(myid_str[s], clone_str(buf));
}
void
set_myid(enum myid_state s, char *idstr)
{
- if (idstr != NULL)
- {
- struct id id;
- err_t ugh = atoid(idstr, &id, FALSE);
-
- if (ugh != NULL)
- {
- loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr);
- }
- else
+ if (idstr != NULL)
{
- free_id_content(&myids[s]);
- unshare_id_content(&id);
- myids[s] = id;
- if (s == MYID_SPECIFIED)
- myid_state = MYID_SPECIFIED;
-
- calc_myid_str(s);
+ struct id id;
+ err_t ugh = atoid(idstr, &id, FALSE);
+
+ if (ugh != NULL)
+ {
+ loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr);
+ }
+ else
+ {
+ free_id_content(&myids[s]);
+ unshare_id_content(&id);
+ myids[s] = id;
+ if (s == MYID_SPECIFIED)
+ myid_state = MYID_SPECIFIED;
+
+ calc_myid_str(s);
+ }
}
- }
}
void
set_myFQDN(void)
{
- char FQDN[HOST_NAME_MAX + 1];
- int r = gethostname(FQDN, sizeof(FQDN));
-
- free_id_content(&myids[MYID_HOSTNAME]);
- myids[MYID_HOSTNAME] = empty_id;
- if (r != 0)
- {
- log_errno((e, "gethostname() failed in set_myFQDN"));
- }
- else
- {
- FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
+ char FQDN[HOST_NAME_MAX + 1];
+ int r = gethostname(FQDN, sizeof(FQDN));
+ free_id_content(&myids[MYID_HOSTNAME]);
+ myids[MYID_HOSTNAME] = empty_id;
+ if (r != 0)
{
- size_t len = strlen(FQDN);
-
- if (len > 0 && FQDN[len-1] == '.')
- {
- /* nuke trailing . */
- FQDN[len-1]='\0';
- }
+ log_errno((e, "gethostname() failed in set_myFQDN"));
}
-
- if (!strcaseeq(FQDN, "localhost.localdomain"))
+ else
{
- clonetochunk(myids[MYID_HOSTNAME].name, FQDN, strlen(FQDN), "my FQDN");
- myids[MYID_HOSTNAME].kind = ID_FQDN;
- calc_myid_str(MYID_HOSTNAME);
+ FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
+
+ {
+ size_t len = strlen(FQDN);
+
+ if (len > 0 && FQDN[len-1] == '.')
+ {
+ /* nuke trailing . */
+ FQDN[len-1]='\0';
+ }
+ }
+
+ if (!strcaseeq(FQDN, "localhost.localdomain"))
+ {
+ chunk_t myid_name = { FQDN, strlen(FQDN) };
+
+ myids[MYID_HOSTNAME].name = chunk_clone(myid_name);
+ myids[MYID_HOSTNAME].kind = ID_FQDN;
+ calc_myid_str(MYID_HOSTNAME);
+ }
}
- }
}
void
show_myid_status(void)
{
- char idstr[BUF_LEN];
+ char idstr[BUF_LEN];
- (void)idtoa(&myids[myid_state], idstr, sizeof(idstr));
- whack_log(RC_COMMENT, "%%myid = %s", idstr);
+ (void)idtoa(&myids[myid_state], idstr, sizeof(idstr));
+ whack_log(RC_COMMENT, "%%myid = %s", idstr);
}
/* Convert textual form of id into a (temporary) struct id.
@@ -152,86 +166,86 @@ show_myid_status(void)
err_t
atoid(char *src, struct id *id, bool myid_ok)
{
- err_t ugh = NULL;
-
- *id = empty_id;
-
- if (myid_ok && streq("%myid", src))
- {
- id->kind = ID_MYID;
- }
- else if (strchr(src, '=') != NULL)
- {
- /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */
- id->kind = ID_DER_ASN1_DN;
- id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */
- id->name.len = 0;
- /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN
- * discard optional @ character in front of DN
- */
- ugh = atodn((*src == '@')?src+1:src, &id->name);
- }
- else if (strchr(src, '@') == NULL)
- {
- if (streq(src, "%any") || streq(src, "0.0.0.0"))
+ err_t ugh = NULL;
+
+ *id = empty_id;
+
+ if (myid_ok && streq("%myid", src))
{
- /* any ID will be accepted */
- id->kind = ID_NONE;
+ id->kind = ID_MYID;
}
- else
+ else if (strchr(src, '=') != NULL)
{
- /* !!! this test is not sufficient for distinguishing address families.
- * We need a notation to specify that a FQDN is to be resolved to IPv6.
- */
- const struct af_info *afi = strchr(src, ':') == NULL
- ? &af_inet4_info: &af_inet6_info;
-
- id->kind = afi->id_addr;
- ugh = ttoaddr(src, 0, afi->af, &id->ip_addr);
+ /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */
+ id->kind = ID_DER_ASN1_DN;
+ id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */
+ id->name.len = 0;
+ /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN
+ * discard optional @ character in front of DN
+ */
+ ugh = atodn((*src == '@')?src+1:src, &id->name);
}
- }
- else
- {
- if (*src == '@')
+ else if (strchr(src, '@') == NULL)
{
- if (*(src+1) == '#')
- {
- /* if there is a second specifier (#) on the line
- * we interprete this as ID_KEY_ID
- */
- id->kind = ID_KEY_ID;
- id->name.ptr = src;
- /* discard @~, convert from hex to bin */
- ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
- }
- else if (*(src+1) == '~')
- {
- /* if there is a second specifier (~) on the line
- * we interprete this as a binary ID_DER_ASN1_DN
- */
- id->kind = ID_DER_ASN1_DN;
- id->name.ptr = src;
- /* discard @~, convert from hex to bin */
- ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
- }
- else
- {
- id->kind = ID_FQDN;
- id->name.ptr = src+1; /* discard @ */
- id->name.len = strlen(src)-1;
- }
+ if (streq(src, "%any") || streq(src, "0.0.0.0"))
+ {
+ /* any ID will be accepted */
+ id->kind = ID_ANY;
+ }
+ else
+ {
+ /* !!! this test is not sufficient for distinguishing address families.
+ * We need a notation to specify that a FQDN is to be resolved to IPv6.
+ */
+ const struct af_info *afi = strchr(src, ':') == NULL
+ ? &af_inet4_info: &af_inet6_info;
+
+ id->kind = afi->id_addr;
+ ugh = ttoaddr(src, 0, afi->af, &id->ip_addr);
+ }
}
else
{
- /* We leave in @, as per DOI 4.6.2.4
- * (but DNS wants . instead).
- */
- id->kind = ID_USER_FQDN;
- id->name.ptr = src;
- id->name.len = strlen(src);
+ if (*src == '@')
+ {
+ if (*(src+1) == '#')
+ {
+ /* if there is a second specifier (#) on the line
+ * we interprete this as ID_KEY_ID
+ */
+ id->kind = ID_KEY_ID;
+ id->name.ptr = src;
+ /* discard @~, convert from hex to bin */
+ ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
+ }
+ else if (*(src+1) == '~')
+ {
+ /* if there is a second specifier (~) on the line
+ * we interprete this as a binary ID_DER_ASN1_DN
+ */
+ id->kind = ID_DER_ASN1_DN;
+ id->name.ptr = src;
+ /* discard @~, convert from hex to bin */
+ ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
+ }
+ else
+ {
+ id->kind = ID_FQDN;
+ id->name.ptr = src+1; /* discard @ */
+ id->name.len = strlen(src)-1;
+ }
+ }
+ else
+ {
+ /* We leave in @, as per DOI 4.6.2.4
+ * (but DNS wants . instead).
+ */
+ id->kind = ID_USER_FQDN;
+ id->name.ptr = src;
+ id->name.len = strlen(src);
+ }
}
- }
- return ugh;
+ return ugh;
}
@@ -241,72 +255,72 @@ atoid(char *src, struct id *id, bool myid_ok)
int
keyidtoa(char *dst, size_t dstlen, chunk_t keyid)
{
- int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen);
- return (((size_t)n < dstlen)? n : dstlen) - 1;
+ int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen);
+ return (((size_t)n < dstlen)? n : dstlen) - 1;
}
void
iptoid(const ip_address *ip, struct id *id)
{
- *id = empty_id;
-
- switch (addrtypeof(ip))
- {
- case AF_INET:
- id->kind = ID_IPV4_ADDR;
- break;
- case AF_INET6:
- id->kind = ID_IPV6_ADDR;
- break;
- default:
- bad_case(addrtypeof(ip));
- }
- id->ip_addr = *ip;
+ *id = empty_id;
+
+ switch (addrtypeof(ip))
+ {
+ case AF_INET:
+ id->kind = ID_IPV4_ADDR;
+ break;
+ case AF_INET6:
+ id->kind = ID_IPV6_ADDR;
+ break;
+ default:
+ bad_case(addrtypeof(ip));
+ }
+ id->ip_addr = *ip;
}
int
idtoa(const struct id *id, char *dst, size_t dstlen)
{
- int n;
-
- id = resolve_myid(id);
- switch (id->kind)
- {
- case ID_NONE:
- n = snprintf(dst, dstlen, "(none)");
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1;
- break;
- case ID_FQDN:
- 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);
- break;
- case ID_DER_ASN1_DN:
- n = dntoa(dst, dstlen, id->name);
- break;
- case ID_KEY_ID:
- n = keyidtoa(dst, dstlen, id->name);
- break;
- default:
- n = snprintf(dst, dstlen, "unknown id kind %d", id->kind);
- break;
- }
-
- /* "Sanitize" string so that log isn't endangered:
- * replace unprintable characters with '?'.
- */
- if (n > 0)
- {
- for ( ; *dst != '\0'; dst++)
- if (!isprint(*dst))
- *dst = '?';
- }
-
- return n;
+ int n;
+
+ id = resolve_myid(id);
+ switch (id->kind)
+ {
+ case ID_ANY:
+ n = snprintf(dst, dstlen, "(none)");
+ break;
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1;
+ break;
+ case ID_FQDN:
+ 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);
+ break;
+ case ID_DER_ASN1_DN:
+ n = dntoa(dst, dstlen, id->name);
+ break;
+ case ID_KEY_ID:
+ n = keyidtoa(dst, dstlen, id->name);
+ break;
+ default:
+ n = snprintf(dst, dstlen, "unknown id kind %d", id->kind);
+ break;
+ }
+
+ /* "Sanitize" string so that log isn't endangered:
+ * replace unprintable characters with '?'.
+ */
+ if (n > 0)
+ {
+ for ( ; *dst != '\0'; dst++)
+ if (!isprint(*dst))
+ *dst = '?';
+ }
+
+ return n;
}
/* Replace the shell metacharacters ', \, ", `, and $ in a character string
@@ -315,26 +329,26 @@ idtoa(const struct id *id, char *dst, size_t dstlen)
void
escape_metachar(const char *src, char *dst, size_t dstlen)
{
- while (*src != '\0' && dstlen > 4)
- {
- switch (*src)
+ while (*src != '\0' && dstlen > 4)
{
- case '\'':
- case '\\':
- case '"':
- case '`':
- case '$':
- sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
- dst += 4;
- dstlen -= 4;
- break;
- default:
- *dst++ = *src;
- dstlen--;
+ switch (*src)
+ {
+ case '\'':
+ case '\\':
+ case '"':
+ case '`':
+ case '$':
+ sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
+ dst += 4;
+ dstlen -= 4;
+ break;
+ default:
+ *dst++ = *src;
+ dstlen--;
+ }
+ src++;
}
- src++;
- }
- *dst = '\0';
+ *dst = '\0';
}
@@ -344,126 +358,126 @@ escape_metachar(const char *src, char *dst, size_t dstlen)
void
unshare_id_content(struct id *id)
{
- switch (id->kind)
- {
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
- break;
- case ID_MYID:
- case ID_NONE:
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- break;
- default:
- bad_case(id->kind);
- }
+ switch (id->kind)
+ {
+ case ID_FQDN:
+ case ID_USER_FQDN:
+ case ID_DER_ASN1_DN:
+ case ID_KEY_ID:
+ id->name = chunk_clone(id->name);
+ break;
+ case ID_MYID:
+ case ID_ANY:
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ break;
+ default:
+ bad_case(id->kind);
+ }
}
void
free_id_content(struct id *id)
{
- switch (id->kind)
- {
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- freeanychunk(id->name);
- break;
- case ID_MYID:
- case ID_NONE:
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- break;
- default:
- bad_case(id->kind);
- }
+ switch (id->kind)
+ {
+ case ID_FQDN:
+ case ID_USER_FQDN:
+ case ID_DER_ASN1_DN:
+ case ID_KEY_ID:
+ free(id->name.ptr);
+ break;
+ case ID_MYID:
+ case ID_ANY:
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ break;
+ default:
+ bad_case(id->kind);
+ }
}
/* compare two struct id values */
bool
same_id(const struct id *a, const struct id *b)
{
- a = resolve_myid(a);
- b = resolve_myid(b);
- if (a->kind != b->kind)
- return FALSE;
- switch (a->kind)
- {
- case ID_NONE:
- return TRUE; /* kind of vacuous */
-
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- return sameaddr(&a->ip_addr, &b->ip_addr);
-
- case ID_FQDN:
- case ID_USER_FQDN:
- /* assumptions:
- * - case should be ignored
- * - trailing "." should be ignored (even if the only character?)
- */
+ a = resolve_myid(a);
+ b = resolve_myid(b);
+ if (a->kind != b->kind)
+ return FALSE;
+ switch (a->kind)
{
- size_t al = a->name.len
- , bl = b->name.len;
-
- while (al > 0 && a->name.ptr[al - 1] == '.')
- al--;
- while (bl > 0 && b->name.ptr[bl - 1] == '.')
- bl--;
- return al == bl
- && strncasecmp(a->name.ptr, b->name.ptr, al) == 0;
- }
+ case ID_ANY:
+ return TRUE; /* kind of vacuous */
+
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ return sameaddr(&a->ip_addr, &b->ip_addr);
+
+ case ID_FQDN:
+ case ID_USER_FQDN:
+ /* assumptions:
+ * - case should be ignored
+ * - trailing "." should be ignored (even if the only character?)
+ */
+ {
+ size_t al = a->name.len
+ , bl = b->name.len;
+
+ while (al > 0 && a->name.ptr[al - 1] == '.')
+ al--;
+ while (bl > 0 && b->name.ptr[bl - 1] == '.')
+ bl--;
+ return al == bl
+ && strncasecmp(a->name.ptr, b->name.ptr, al) == 0;
+ }
- case ID_DER_ASN1_DN:
- return same_dn(a->name, b->name);
+ case ID_DER_ASN1_DN:
+ return same_dn(a->name, b->name);
- case ID_KEY_ID:
- return a->name.len == b->name.len
- && memcmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
+ case ID_KEY_ID:
+ return a->name.len == b->name.len
+ && memeq(a->name.ptr, b->name.ptr, a->name.len);
- default:
- bad_case(a->kind);
- }
- return FALSE;
+ default:
+ bad_case(a->kind);
+ }
+ return FALSE;
}
/* compare two struct id values, DNs can contain wildcards */
bool
match_id(const struct id *a, const struct id *b, int *wildcards)
{
- if (b->kind == ID_NONE)
- {
- *wildcards = MAX_WILDCARDS;
- return TRUE;
- }
- if (a->kind != b->kind)
- return FALSE;
- if (a->kind == ID_DER_ASN1_DN)
- return match_dn(a->name, b->name, wildcards);
- else
- {
- *wildcards = 0;
- return same_id(a, b);
- }
+ if (b->kind == ID_ANY)
+ {
+ *wildcards = MAX_WILDCARDS;
+ return TRUE;
+ }
+ if (a->kind != b->kind)
+ return FALSE;
+ if (a->kind == ID_DER_ASN1_DN)
+ return match_dn(a->name, b->name, wildcards);
+ else
+ {
+ *wildcards = 0;
+ return same_id(a, b);
+ }
}
/* count the numer of wildcards in an id */
int
id_count_wildcards(const struct id *id)
{
- switch (id->kind)
- {
- case ID_NONE:
- return MAX_WILDCARDS;
- case ID_DER_ASN1_DN:
- return dn_count_wildcards(id->name);
- default:
- return 0;
- }
+ switch (id->kind)
+ {
+ case ID_ANY:
+ return MAX_WILDCARDS;
+ case ID_DER_ASN1_DN:
+ return dn_count_wildcards(id->name);
+ default:
+ return 0;
+ }
}
/* build an ID payload
@@ -474,31 +488,31 @@ id_count_wildcards(const struct id *id)
void
build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
{
- const struct id *id = resolve_myid(&end->id);
-
- zero(hd);
- hd->isaiid_idtype = id->kind;
- switch (id->kind)
- {
- case ID_NONE:
- hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr;
- tl->len = addrbytesptr(&end->host_addr
- , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
- break;
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- *tl = id->name;
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- tl->len = addrbytesptr(&id->ip_addr
- , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
- break;
- default:
- bad_case(id->kind);
- }
+ const struct id *id = resolve_myid(&end->id);
+
+ zero(hd);
+ hd->isaiid_idtype = id->kind;
+ switch (id->kind)
+ {
+ case ID_ANY:
+ hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr;
+ tl->len = addrbytesptr(&end->host_addr
+ , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
+ break;
+ case ID_FQDN:
+ case ID_USER_FQDN:
+ case ID_DER_ASN1_DN:
+ case ID_KEY_ID:
+ *tl = id->name;
+ break;
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ tl->len = addrbytesptr(&id->ip_addr
+ , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
+ break;
+ default:
+ bad_case(id->kind);
+ }
}
/*
diff --git a/src/pluto/id.h b/src/pluto/id.h
index 185c17f20..dc2dcdfa6 100644
--- a/src/pluto/id.h
+++ b/src/pluto/id.h
@@ -10,8 +10,6 @@
* 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: id.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _ID_H
@@ -20,25 +18,25 @@
#include "defs.h"
struct id {
- int kind; /* ID_* value */
- ip_address ip_addr; /* ID_IPV4_ADDR, ID_IPV6_ADDR */
- chunk_t name; /* ID_FQDN, ID_USER_FQDN (with @) */
- /* ID_KEY_ID, ID_DER_ASN_DN */
+ int kind; /* ID_* value */
+ ip_address ip_addr; /* ID_IPV4_ADDR, ID_IPV6_ADDR */
+ chunk_t name; /* ID_FQDN, ID_USER_FQDN (with @) */
+ /* ID_KEY_ID, ID_DER_ASN_DN */
};
extern void init_id(void);
-
-extern const struct id empty_id; /* ID_NONE */
+extern void free_id(void);
+extern const struct id empty_id; /* ID_NONE */
enum myid_state {
- MYID_UNKNOWN, /* not yet figured out */
- MYID_HOSTNAME, /* our current hostname */
- MYID_IP, /* our default IP address */
- MYID_SPECIFIED /* as specified by ipsec.conf */
+ MYID_UNKNOWN, /* not yet figured out */
+ MYID_HOSTNAME, /* our current hostname */
+ MYID_IP, /* our default IP address */
+ MYID_SPECIFIED /* as specified by ipsec.conf */
};
extern enum myid_state myid_state;
-extern struct id myids[MYID_SPECIFIED+1]; /* %myid */
+extern struct id myids[MYID_SPECIFIED+1]; /* %myid */
extern char *myid_str[MYID_SPECIFIED+1]; /* strings */
extern void set_myid(enum myid_state s, char *);
extern void show_myid_status(void);
@@ -49,19 +47,19 @@ extern err_t atoid(char *src, struct id *id, bool myid_ok);
extern int keyidtoa(char *dst, size_t dstlen, chunk_t keyid);
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 512
+#define IDTOA_BUF 512
extern void escape_metachar(const char *src, char *dst, size_t dstlen);
-struct end; /* forward declaration of tag (defined in connections.h) */
+struct end; /* forward declaration of tag (defined in connections.h) */
extern void unshare_id_content(struct id *id);
extern void free_id_content(struct id *id);
extern bool same_id(const struct id *a, const struct id *b);
-#define MAX_WILDCARDS 15
+#define MAX_WILDCARDS 15
extern bool match_id(const struct id *a, const struct id *b, int *wildcards);
extern int id_count_wildcards(const struct id *id);
#define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR)
-struct isakmp_ipsec_id; /* forward declaration of tag (defined in packet.h) */
+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);
+ build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end);
#endif /* _ID_H */
diff --git a/src/pluto/ike_alg.c b/src/pluto/ike_alg.c
index 6759059fa..f833f85b5 100644
--- a/src/pluto/ike_alg.c
+++ b/src/pluto/ike_alg.c
@@ -1,5 +1,6 @@
/* IKE modular algorithm handling interface
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +11,6 @@
* 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: ike_alg.c 3686 2008-03-28 11:48:14Z martin $
*/
#include <stdio.h>
@@ -21,16 +20,19 @@
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <library.h>
+#include <debug.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/prfs/prf.h>
#include "constants.h"
#include "defs.h"
-#include "sha1.h"
-#include "md5.h"
#include "crypto.h"
-
#include "state.h"
#include "packet.h"
+#include "keys.h"
#include "log.h"
#include "whack.h"
#include "spdb.h"
@@ -42,7 +44,7 @@
#define return_on(var, val) do { var=val;goto return_out; } while(0);
-/*
+/**
* IKE algorithm list handling - registration and lookup
*/
@@ -50,540 +52,371 @@
static struct ike_alg *ike_alg_base[IKE_ALG_MAX+1] = {NULL, NULL};
-/*
- * return ike_algo object by {type, id}
+/**
+ * Return ike_algo object by {type, id}
*/
-static struct ike_alg *
-ike_alg_find(u_int algo_type, u_int algo_id, u_int keysize __attribute__((unused)))
+static struct ike_alg *ike_alg_find(u_int algo_type, u_int algo_id,
+ u_int keysize __attribute__((unused)))
{
- struct ike_alg *e = ike_alg_base[algo_type];
+ struct ike_alg *e = ike_alg_base[algo_type];
- while (e != NULL && algo_id > e->algo_id)
- {
- e = e->algo_next;
- }
- return (e != NULL && e->algo_id == algo_id) ? e : NULL;
+ while (e != NULL && algo_id > e->algo_id)
+ {
+ e = e->algo_next;
+ }
+ return (e != NULL && e->algo_id == algo_id) ? e : NULL;
}
-/*
+/**
* "raw" ike_alg list adding function
*/
-int
-ike_alg_add(struct ike_alg* a)
+int ike_alg_add(struct ike_alg* a)
{
- if (a->algo_type > IKE_ALG_MAX)
- {
- plog("ike_alg: Not added, invalid algorithm type");
- return -EINVAL;
- }
-
- if (ike_alg_find(a->algo_type, a->algo_id, 0) != NULL)
- {
- plog("ike_alg: Not added, algorithm already exists");
- return -EEXIST;
- }
-
- {
- struct ike_alg **ep = &ike_alg_base[a->algo_type];
- struct ike_alg *e = *ep;
-
- while (e != NULL && a->algo_id > e->algo_id)
+ if (a->algo_type > IKE_ALG_MAX)
{
- ep = &e->algo_next;
- e = *ep;
+ plog("ike_alg: Not added, invalid algorithm type");
+ return -EINVAL;
}
- *ep = a;
- a->algo_next = e;
- return 0;
- }
-}
-/*
- * get IKE hash algorithm
- */
-struct hash_desc *ike_alg_get_hasher(u_int alg)
-{
- return (struct hash_desc *) ike_alg_find(IKE_ALG_HASH, alg, 0);
-}
+ if (ike_alg_find(a->algo_type, a->algo_id, 0) != NULL)
+ {
+ plog("ike_alg: Not added, algorithm already exists");
+ return -EEXIST;
+ }
-/*
- * get IKE encryption algorithm
- */
-struct encrypt_desc *ike_alg_get_encrypter(u_int alg)
-{
- return (struct encrypt_desc *) ike_alg_find(IKE_ALG_ENCRYPT, alg, 0);
-}
+ {
+ struct ike_alg **ep = &ike_alg_base[a->algo_type];
+ struct ike_alg *e = *ep;
-/*
- * check if IKE hash algorithm is present
- */
-bool
-ike_alg_hash_present(u_int halg)
-{
- return ike_alg_get_hasher(halg) != NULL;
+ while (e != NULL && a->algo_id > e->algo_id)
+ {
+ ep = &e->algo_next;
+ e = *ep;
+ }
+ *ep = a;
+ a->algo_next = e;
+ return 0;
+ }
}
-/*
- * check if IKE encryption algorithm is present
+/**
+ * Get IKE hash algorithm
*/
-bool
-ike_alg_enc_present(u_int ealg)
+struct hash_desc *ike_alg_get_hasher(u_int alg)
{
- return ike_alg_get_encrypter(ealg) != NULL;
+ return (struct hash_desc *) ike_alg_find(IKE_ALG_HASH, alg, 0);
}
-/*
- * Validate and register IKE hash algorithm object
+/**
+ * Get IKE encryption algorithm
*/
-int
-ike_alg_register_hash(struct hash_desc *hash_desc)
+struct encrypt_desc *ike_alg_get_crypter(u_int alg)
{
- const char *alg_name = NULL;
- int ret = 0;
-
- if (hash_desc->algo_id > OAKLEY_HASH_MAX)
- {
- plog ("ike_alg: hash alg=%d > max=%d"
- , hash_desc->algo_id, OAKLEY_HASH_MAX);
- return_on(ret,-EINVAL);
- }
-
- if (hash_desc->hash_ctx_size > sizeof (union hash_ctx))
- {
- plog ("ike_alg: hash alg=%d has ctx_size=%d > hash_ctx=%d"
- , hash_desc->algo_id
- , (int)hash_desc->hash_ctx_size
- , (int)sizeof (union hash_ctx));
- return_on(ret,-EOVERFLOW);
- }
-
- if (!(hash_desc->hash_init && hash_desc->hash_update && hash_desc->hash_final))
- {
- plog ("ike_alg: hash alg=%d needs hash_init(), hash_update() and hash_final()"
- , hash_desc->algo_id);
- return_on(ret,-EINVAL);
- }
-
- alg_name = enum_name(&oakley_hash_names, hash_desc->algo_id);
- if (!alg_name)
- {
- plog ("ike_alg: hash alg=%d not found in constants.c:oakley_hash_names"
- , hash_desc->algo_id);
- alg_name = "<NULL>";
- }
-
-return_out:
- if (ret == 0)
- ret = ike_alg_add((struct ike_alg *)hash_desc);
-
- plog("ike_alg: Activating %s hash: %s"
- ,alg_name, ret == 0 ? "Ok" : "FAILED");
-
- return ret;
+ return (struct encrypt_desc *) ike_alg_find(IKE_ALG_ENCRYPT, alg, 0);
}
-/*
- * Validate and register IKE encryption algorithm object
+/**
+ * Get IKE dh group
*/
-int
-ike_alg_register_enc(struct encrypt_desc *enc_desc)
+struct dh_desc *ike_alg_get_dh_group(u_int alg)
{
- int ret = ike_alg_add((struct ike_alg *)enc_desc);
-
- const char *alg_name = enum_name(&oakley_enc_names, enc_desc->algo_id);
-
- char alg_number[20];
-
- /* algorithm is not listed in oakley_enc_names */
- if (alg_name == NULL)
- {
- snprintf(alg_number, sizeof(alg_number), "OAKLEY_ID_%d"
- , enc_desc->algo_id);
- alg_name = alg_number;
- }
-
- plog("ike_alg: Activating %s encryption: %s"
- , alg_name, ret == 0 ? "Ok" : "FAILED");
-
- return ret;
+ return (struct dh_desc *) ike_alg_find(IKE_ALG_DH_GROUP, alg, 0);
}
-/*
+/**
* Get pfsgroup for this connection
*/
-const struct oakley_group_desc *
-ike_alg_pfsgroup(struct connection *c, lset_t policy)
+const struct dh_desc *ike_alg_pfsgroup(struct connection *c, lset_t policy)
{
- const struct oakley_group_desc * ret = NULL;
+ const struct dh_desc *ret = NULL;
- if ((policy & POLICY_PFS)
- && c->alg_info_esp
- && c->alg_info_esp->esp_pfsgroup)
- ret = lookup_group(c->alg_info_esp->esp_pfsgroup);
- return ret;
+ if ((policy & POLICY_PFS) &&
+ c->alg_info_esp && c->alg_info_esp->esp_pfsgroup)
+ {
+ ret = ike_alg_get_dh_group(c->alg_info_esp->esp_pfsgroup);
+ }
+ return ret;
}
-/*
+/**
* Create an OAKLEY proposal based on alg_info and policy
*/
-struct db_context *
-ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
+struct db_context *ike_alg_db_new(struct connection *c, lset_t policy)
{
- struct db_context *db_ctx = NULL;
- struct ike_info *ike_info;
- struct encrypt_desc *enc_desc;
- u_int ealg, halg, modp, eklen = 0;
- int i;
-
- bool is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY;
-
- if (!ai)
- {
- whack_log(RC_LOG_SERIOUS, "no IKE algorithms "
- "for this connection "
- "(check ike algorithm string)");
- goto fail;
- }
- policy &= POLICY_ID_AUTH_MASK;
- db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5);
-
- /* for each group */
- ALG_INFO_IKE_FOREACH(ai, ike_info, i)
- {
- ealg = ike_info->ike_ealg;
- halg = ike_info->ike_halg;
- modp = ike_info->ike_modp;
- eklen= ike_info->ike_eklen;
-
- if (!ike_alg_enc_present(ealg))
- {
- DBG_log("ike_alg: ike enc ealg=%d not present"
- , ealg);
- continue;
- }
-
- if (!ike_alg_hash_present(halg))
- {
- DBG_log("ike_alg: ike hash halg=%d not present"
- , halg);
- continue;
- }
+ struct alg_info_ike *ai = c->alg_info_ike;
+ struct db_context *db_ctx = NULL;
+ struct ike_info *ike_info;
+ struct encrypt_desc *enc_desc;
+ u_int ealg, halg, modp, eklen = 0;
+ int i;
- enc_desc = ike_alg_get_encrypter(ealg);
- passert(enc_desc != NULL);
+ bool is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY;
- if (eklen
- && (eklen < enc_desc->keyminlen || eklen > enc_desc->keymaxlen))
+ if (!ai)
{
- DBG_log("ike_alg: ealg=%d (specified) keylen:%d, not valid min=%d, max=%d"
- , ealg
- , eklen
- , enc_desc->keyminlen
- , enc_desc->keymaxlen
- );
- continue;
+ whack_log(RC_LOG_SERIOUS, "no IKE algorithms "
+ "for this connection "
+ "(check ike algorithm string)");
+ goto fail;
}
+ policy &= POLICY_ID_AUTH_MASK;
+ db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5);
- if (policy & POLICY_RSASIG)
+ /* for each group */
+ ALG_INFO_IKE_FOREACH(ai, ike_info, i)
{
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
+ ealg = ike_info->ike_ealg;
+ halg = ike_info->ike_halg;
+ modp = ike_info->ike_modp;
+ eklen= ike_info->ike_eklen;
- if (policy & POLICY_PSK)
- {
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
+ if (!ike_alg_get_crypter(ealg))
+ {
+ plog("ike alg: crypter %s not present",
+ enum_show(&oakley_enc_names, ealg));
+ continue;
+ }
+ if (!ike_alg_get_hasher(halg))
+ {
+ plog("ike alg: hasher %s not present",
+ enum_show(&oakley_hash_names, halg));
+ continue;
+ }
+ if (!ike_alg_get_dh_group(modp))
+ {
+ plog("ike alg: dh group %s not present",
+ enum_show(&oakley_group_names, modp));
+ continue;
+ }
+ enc_desc = ike_alg_get_crypter(ealg);
- if (policy & POLICY_XAUTH_RSASIG)
- {
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
- , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
+ if (policy & POLICY_PUBKEY)
+ {
+ int auth_method = 0;
+ private_key_t *key = get_private_key(c);
+
+ if (key == NULL)
+ {
+ plog("ike alg: unable to locate my private key");
+ continue;
+ }
+ switch (key->get_type(key))
+ {
+ case KEY_RSA:
+ auth_method = OAKLEY_RSA_SIG;
+ break;
+ case KEY_ECDSA:
+ switch (key->get_keysize(key))
+ {
+ case 32:
+ auth_method = OAKLEY_ECDSA_256;
+ break;
+ case 48:
+ auth_method = OAKLEY_ECDSA_384;
+ break;
+ case 66:
+ auth_method = OAKLEY_ECDSA_521;
+ break;
+ default:
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ {
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ }
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, auth_method);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
- if (policy & POLICY_XAUTH_PSK)
- {
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
- , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ if (policy & POLICY_PSK)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ {
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ }
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
+
+ if (policy & POLICY_XAUTH_RSASIG)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ {
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ }
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
+ , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
+
+ if (policy & POLICY_XAUTH_PSK)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ {
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ }
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
+ , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
}
- }
fail:
- return db_ctx;
+ return db_ctx;
}
-/*
+/**
* Show registered IKE algorithms
*/
-void
-ike_alg_list(void)
+void ike_alg_list(void)
{
- u_int i;
- struct ike_alg *a;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered IKE Encryption Algorithms:");
- whack_log(RC_COMMENT, " ");
-
- for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next)
- {
- struct encrypt_desc *desc = (struct encrypt_desc*)a;
-
- whack_log(RC_COMMENT, "#%-5d %s, blocksize: %d, keylen: %d-%d-%d"
- , a->algo_id
- , enum_name(&oakley_enc_names, a->algo_id)
- , (int)desc->enc_blocksize*BITS_PER_BYTE
- , desc->keyminlen
- , desc->keydeflen
- , desc->keymaxlen
- );
- }
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered IKE Hash Algorithms:");
- whack_log(RC_COMMENT, " ");
-
- for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next)
- {
- whack_log(RC_COMMENT, "#%-5d %s, hashsize: %d"
- , a->algo_id
- , enum_name(&oakley_hash_names, a->algo_id)
- , (int)((struct hash_desc *)a)->hash_digest_size*BITS_PER_BYTE
- );
- }
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered IKE DH Groups:");
- whack_log(RC_COMMENT, " ");
-
- for (i = 0; i < elemsof(oakley_group); i++)
- {
- const struct oakley_group_desc *gdesc=oakley_group + i;
-
- whack_log(RC_COMMENT, "#%-5d %s, groupsize: %d"
- , gdesc->group
- , enum_name(&oakley_group_names, gdesc->group)
- , (int)gdesc->bytes*BITS_PER_BYTE
- );
- }
-}
-
-/* Show IKE algorithms for
- * - this connection (result from ike= string)
- * - newest SA
- */
-void
-ike_alg_show_connection(struct connection *c, const char *instance)
-{
- char buf[256];
- struct state *st;
-
- if (c->alg_info_ike)
- {
- alg_info_snprint(buf, sizeof(buf)-1, (struct alg_info *)c->alg_info_ike);
- whack_log(RC_COMMENT
- , "\"%s\"%s: IKE algorithms wanted: %s"
- , c->name
- , instance
- , buf
- );
-
- alg_info_snprint_ike(buf, sizeof(buf)-1, c->alg_info_ike);
- whack_log(RC_COMMENT
- , "\"%s\"%s: IKE algorithms found: %s"
- , c->name
- , instance
- , buf
- );
- }
-
- st = state_with_serialno(c->newest_isakmp_sa);
- if (st)
- whack_log(RC_COMMENT
- , "\"%s\"%s: IKE algorithm newest: %s_%d-%s-%s"
- , c->name
- , instance
- , enum_show(&oakley_enc_names, st->st_oakley.encrypt)
- +7 /* strlen("OAKLEY_") */
- /* , st->st_oakley.encrypter->keydeflen */
- , st->st_oakley.enckeylen
- , enum_show(&oakley_hash_names, st->st_oakley.hash)
- +7 /* strlen("OAKLEY_") */
- , enum_show(&oakley_group_names, st->st_oakley.group->group)
- +13 /* strlen("OAKLEY_GROUP_") */
- );
-}
-
-/*
- * Apply a suite of testvectors to a hash algorithm
- */
-static bool
-ike_hash_test(const struct hash_desc *desc)
-{
- bool hash_results = TRUE;
- bool hmac_results = TRUE;
-
- if (desc->hash_testvectors == NULL)
- {
- plog(" %s hash self-test not available", enum_name(&oakley_hash_names, desc->algo_id));
- }
- else
- {
- int i;
+ char buf[BUF_LEN];
+ char *pos;
+ int n, len;
+ struct ike_alg *a;
+
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of registered IKEv1 Algorithms:");
+ whack_log(RC_COMMENT, " ");
+
+ pos = buf;
+ *pos = '\0';
+ len = BUF_LEN;
+ for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next)
+ {
+ n = snprintf(pos, len, " %s", enum_name(&oakley_enc_names, a->algo_id));
+ pos += n;
+ len -= n;
+ if (len <= 0)
+ {
+ break;
+ }
+ }
+ whack_log(RC_COMMENT, " encryption:%s", buf);
- for (i = 0; desc->hash_testvectors[i].msg_digest != NULL; i++)
+ pos = buf;
+ *pos = '\0';
+ len = BUF_LEN;
+ for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next)
{
- u_char digest[MAX_DIGEST_LEN];
- bool result;
-
- union hash_ctx ctx;
-
- desc->hash_init(&ctx);
- desc->hash_update(&ctx, desc->hash_testvectors[i].msg
- ,desc->hash_testvectors[i].msg_size);
- desc->hash_final(digest, &ctx);
- result = memcmp(digest, desc->hash_testvectors[i].msg_digest
- , desc->hash_digest_size) == 0;
- DBG(DBG_CRYPT,
- DBG_log(" hash testvector %d: %s", i, result ? "ok":"failed")
- )
- hash_results &= result;
+ n = snprintf(pos, len, " %s", enum_name(&oakley_hash_names, a->algo_id));
+ pos += n;
+ len -= n;
+ if (len <= 0)
+ {
+ break;
+ }
}
- plog(" %s hash self-test %s", enum_name(&oakley_hash_names, desc->algo_id)
- , hash_results ? "passed":"failed");
- }
-
- if (desc->hmac_testvectors == NULL)
- {
- plog(" %s hmac self-test not available", enum_name(&oakley_hash_names, desc->algo_id));
- }
- else
- {
- int i;
+ whack_log(RC_COMMENT, " integrity: %s", buf);
- for (i = 0; desc->hmac_testvectors[i].hmac != NULL; i++)
+ pos = buf;
+ *pos = '\0';
+ len = BUF_LEN;
+ for (a = ike_alg_base[IKE_ALG_DH_GROUP]; a != NULL; a = a->algo_next)
{
- u_char digest[MAX_DIGEST_LEN];
- bool result;
-
- struct hmac_ctx ctx;
-
- hmac_init(&ctx, desc, desc->hmac_testvectors[i].key
- , desc->hmac_testvectors[i].key_size);
- hmac_update(&ctx, desc->hmac_testvectors[i].msg
- ,desc->hmac_testvectors[i].msg_size);
- hmac_final(digest, &ctx);
- result = memcmp(digest, desc->hmac_testvectors[i].hmac
- , desc->hash_digest_size) == 0;
- DBG(DBG_CRYPT,
- DBG_log(" hmac testvector %d: %s", i, result ? "ok":"failed")
- )
- hmac_results &= result;
+ n = snprintf(pos, len, " %s", enum_name(&oakley_group_names, a->algo_id));
+ pos += n;
+ len -= n;
+ if (len <= 0)
+ {
+ break;
+ }
}
- plog(" %s hmac self-test %s", enum_name(&oakley_hash_names, desc->algo_id)
- , hmac_results ? "passed":"failed");
- }
- return hash_results && hmac_results;
+ whack_log(RC_COMMENT, " dh-group: %s", buf);
}
-/*
- * Apply test vectors to registered encryption and hash algorithms
+/**
+ * Show IKE algorithms for this connection (result from ike= string)
+ * and newest SA
*/
-bool
-ike_alg_test(void)
+void ike_alg_show_connection(struct connection *c, const char *instance)
{
- bool all_results = TRUE;
- struct ike_alg *a;
-
- plog("Testing registered IKE encryption algorithms:");
-
- for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next)
- {
- plog(" %s self-test not available", enum_name(&oakley_enc_names, a->algo_id));
- }
-
- plog("Testing registered IKE hash algorithms:");
-
- for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next)
- {
- struct hash_desc *desc = (struct hash_desc*)a;
+ struct state *st = state_with_serialno(c->newest_isakmp_sa);
- all_results &= ike_hash_test(desc);
- }
-
- if (all_results)
- plog("All crypto self-tests passed");
- else
- plog("Some crypto self-tests failed");
- return all_results;
+ if (st)
+ {
+ if (st->st_oakley.encrypt == OAKLEY_3DES_CBC)
+ {
+ whack_log(RC_COMMENT,
+ "\"%s\"%s: IKE proposal: %s/%s/%s",
+ c->name, instance,
+ enum_show(&oakley_enc_names, st->st_oakley.encrypt),
+ enum_show(&oakley_hash_names, st->st_oakley.hash),
+ enum_show(&oakley_group_names, st->st_oakley.group->algo_id)
+ );
+ }
+ else
+ {
+ whack_log(RC_COMMENT,
+ "\"%s\"%s: IKE proposal: %s_%u/%s/%s",
+ c->name, instance,
+ enum_show(&oakley_enc_names, st->st_oakley.encrypt),
+ st->st_oakley.enckeylen,
+ enum_show(&oakley_hash_names, st->st_oakley.hash),
+ enum_show(&oakley_group_names, st->st_oakley.group->algo_id)
+ );
+ }
+ }
}
-/*
+/**
* ML: make F_STRICT logic consider enc,hash/auth,modp algorithms
*/
-bool
-ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group
-, struct alg_info_ike *alg_info_ike)
+bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group,
+ struct alg_info_ike *alg_info_ike)
{
- /*
- * simple test to discard low key_len, will accept it only
- * if specified in "esp" string
- */
- bool ealg_insecure = (key_len < 128);
-
- if (ealg_insecure
- || (alg_info_ike && alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT))
- {
- int i;
- struct ike_info *ike_info;
-
- if (alg_info_ike)
+ /*
+ * simple test to discard low key_len, will accept it only
+ * if specified in "esp" string
+ */
+ bool ealg_insecure = (key_len < 128);
+
+ if (ealg_insecure
+ || (alg_info_ike && alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT))
{
- ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i)
- {
- if (ike_info->ike_ealg == ealg
- && (ike_info->ike_eklen == 0 || key_len == 0 || ike_info->ike_eklen == key_len)
- && ike_info->ike_halg == aalg
- && ike_info->ike_modp == group)
+ int i;
+ struct ike_info *ike_info;
+
+ if (alg_info_ike)
{
- if (ealg_insecure)
- loglog(RC_LOG_SERIOUS, "You should NOT use insecure IKE algorithms (%s)!"
- , enum_name(&oakley_enc_names, ealg));
- return TRUE;
+ ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i)
+ {
+ if (ike_info->ike_ealg == ealg
+ && (ike_info->ike_eklen == 0 || key_len == 0 || ike_info->ike_eklen == key_len)
+ && ike_info->ike_halg == aalg
+ && ike_info->ike_modp == group)
+ {
+ if (ealg_insecure)
+ loglog(RC_LOG_SERIOUS, "You should NOT use insecure IKE algorithms (%s)!"
+ , enum_name(&oakley_enc_names, ealg));
+ return TRUE;
+ }
+ }
}
- }
+ plog("Oakley Transform [%s (%d), %s, %s] refused due to %s"
+ , enum_name(&oakley_enc_names, ealg), key_len
+ , enum_name(&oakley_hash_names, aalg)
+ , enum_name(&oakley_group_names, group)
+ , ealg_insecure ?
+ "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag"
+ );
+ return FALSE;
}
- plog("Oakley Transform [%s (%d), %s, %s] refused due to %s"
- , enum_name(&oakley_enc_names, ealg), key_len
- , enum_name(&oakley_hash_names, aalg)
- , enum_name(&oakley_group_names, group)
- , ealg_insecure ?
- "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag"
- );
- return FALSE;
- }
- return TRUE;
+ return TRUE;
}
diff --git a/src/pluto/ike_alg.h b/src/pluto/ike_alg.h
index dbf4076c5..458d14c3a 100644
--- a/src/pluto/ike_alg.h
+++ b/src/pluto/ike_alg.h
@@ -10,85 +10,63 @@
* 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: ike_alg.h 3252 2007-10-06 21:24:50Z andreas $
*/
-
+
#ifndef _IKE_ALG_H
#define _IKE_ALG_H
+#include <freeswan.h>
+
#include "connections.h"
struct ike_alg {
- u_int16_t algo_type;
- u_int16_t algo_id;
- struct ike_alg *algo_next;
+ u_int16_t algo_type;
+ u_int16_t algo_id;
+ struct ike_alg *algo_next;
};
struct encrypt_desc {
- u_int16_t algo_type;
- u_int16_t algo_id;
- struct ike_alg *algo_next;
+ u_int16_t algo_type;
+ u_int16_t algo_id;
+ struct ike_alg *algo_next;
- size_t enc_ctxsize;
- size_t enc_blocksize;
- u_int keydeflen;
- u_int keymaxlen;
- u_int keyminlen;
- void (*do_crypt)(u_int8_t *dat, size_t datasize, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc);
+ size_t enc_blocksize;
+ u_int keydeflen;
+ u_int keymaxlen;
+ u_int keyminlen;
};
-typedef struct hash_testvector hash_testvector_t;
+struct hash_desc {
+ u_int16_t algo_type;
+ u_int16_t algo_id;
+ struct ike_alg *algo_next;
-struct hash_testvector {
- const size_t msg_size;
- const u_char *msg;
- const u_char *msg_digest;
+ size_t hash_digest_size;
};
-typedef struct hmac_testvector hmac_testvector_t;
-
-struct hmac_testvector {
- const size_t key_size;
- const u_char *key;
- const size_t msg_size;
- const u_char *msg;
- const u_char *hmac;
-};
-struct hash_desc {
- u_int16_t algo_type;
- u_int16_t algo_id;
- struct ike_alg *algo_next;
+struct dh_desc {
+ u_int16_t algo_type;
+ u_int16_t algo_id;
+ struct ike_alg *algo_next;
- size_t hash_ctx_size;
- size_t hash_block_size;
- size_t hash_digest_size;
- const hash_testvector_t *hash_testvectors;
- const hmac_testvector_t *hmac_testvectors;
- void (*hash_init)(void *ctx);
- void (*hash_update)(void *ctx, const u_int8_t *in, size_t datasize);
- void (*hash_final)(u_int8_t *out, void *ctx);
+ size_t ke_size;
};
-#define IKE_ALG_ENCRYPT 0
-#define IKE_ALG_HASH 1
-#define IKE_ALG_MAX IKE_ALG_HASH
+#define IKE_ALG_ENCRYPT 0
+#define IKE_ALG_HASH 1
+#define IKE_ALG_DH_GROUP 2
+#define IKE_ALG_MAX IKE_ALG_DH_GROUP
extern int ike_alg_add(struct ike_alg *a);
extern struct hash_desc *ike_alg_get_hasher(u_int alg);
-extern struct encrypt_desc *ike_alg_get_encrypter(u_int alg);
-extern bool ike_alg_enc_present(u_int ealg);
-extern bool ike_alg_hash_present(u_int halg);
-extern int ike_alg_register_hash(struct hash_desc *a);
-extern int ike_alg_register_enc(struct encrypt_desc *e);
-extern const struct oakley_group_desc* ike_alg_pfsgroup(struct connection *c
- , lset_t policy);
-extern struct db_context * ike_alg_db_new(struct alg_info_ike *ai, lset_t policy);
+extern struct encrypt_desc *ike_alg_get_crypter(u_int alg);
+extern struct dh_desc *ike_alg_get_dh_group(u_int alg);
+extern const struct dh_desc* ike_alg_pfsgroup(struct connection *c, lset_t policy);
+extern struct db_context * ike_alg_db_new(struct connection *c, lset_t policy);
extern void ike_alg_list(void);
extern void ike_alg_show_connection(struct connection *c, const char *instance);
-extern bool ike_alg_test(void);
extern bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group
- , struct alg_info_ike *alg_info_ike);
+ , struct alg_info_ike *alg_info_ike);
extern int ike_alg_init(void);
#endif /* _IKE_ALG_H */
diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c
index 9721ac583..929768ee9 100644
--- a/src/pluto/ipsec_doi.c
+++ b/src/pluto/ipsec_doi.c
@@ -1,6 +1,7 @@
/* IPsec DOI and Oakley resolution routines
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,8 +12,6 @@
* 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: ipsec_doi.c 5052 2009-03-30 03:47:14Z andreas $
*/
#include <stdio.h>
@@ -24,16 +23,22 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
-#include <sys/time.h> /* for gettimeofday */
+#include <sys/time.h> /* for gettimeofday */
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <library.h>
+#include <asn1/asn1.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/rngs/rng.h>
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
#include "constants.h"
#include "defs.h"
-#include "mp_defs.h"
#include "state.h"
#include "id.h"
#include "x509.h"
@@ -44,25 +49,20 @@
#include "connections.h"
#include "keys.h"
#include "packet.h"
-#include "demux.h" /* needs packet.h */
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
+#include "demux.h" /* needs packet.h */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "kernel.h"
#include "log.h"
#include "cookie.h"
#include "server.h"
#include "spdb.h"
#include "timer.h"
-#include "rnd.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "whack.h"
#include "fetch.h"
#include "pkcs7.h"
-#include "asn1.h"
-
-#include "sha1.h"
-#include "md5.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
+#include "crypto.h"
#include "vendor.h"
#include "alg_info.h"
#include "ike_alg.h"
@@ -74,115 +74,84 @@
* are we sending Pluto's Vendor ID?
*/
#ifdef VENDORID
-#define SEND_PLUTO_VID 1
+#define SEND_PLUTO_VID 1
#else /* !VENDORID */
-#define SEND_PLUTO_VID 0
+#define SEND_PLUTO_VID 0
#endif /* !VENDORID */
/*
* are we sending an XAUTH VID?
*/
#ifdef XAUTH_VID
-#define SEND_XAUTH_VID 1
+#define SEND_XAUTH_VID 1
#else /* !XAUTH_VID */
-#define SEND_XAUTH_VID 0
+#define SEND_XAUTH_VID 0
#endif /* !XAUTH_VID */
/*
* are we sending a Cisco Unity VID?
*/
#ifdef CISCO_QUIRKS
-#define SEND_CISCO_UNITY_VID 1
+#define SEND_CISCO_UNITY_VID 1
#else /* !CISCO_QUIRKS */
-#define SEND_CISCO_UNITY_VID 0
+#define SEND_CISCO_UNITY_VID 0
#endif /* !CISCO_QUIRKS */
/* 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; }
+ { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; }
/* create output HDR as replica of input HDR */
void
echo_hdr(struct msg_digest *md, bool enc, u_int8_t np)
{
- struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */
-
- r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */
- if (enc)
- r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION;
- /* some day, we may have to set r_hdr.isa_version */
- r_hdr.isa_np = np;
- if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
- impossible(); /* surely must have room and be well-formed */
+ struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */
+
+ r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */
+ if (enc)
+ r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION;
+ /* some day, we may have to set r_hdr.isa_version */
+ r_hdr.isa_np = np;
+ if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+ impossible(); /* surely must have room and be well-formed */
}
/* 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).
*/
-static void
-compute_dh_shared(struct state *st, const chunk_t g
-, const struct oakley_group_desc *group)
+static void compute_dh_shared(struct state *st, const chunk_t g)
{
- MP_INT mp_g, mp_shared;
- struct timeval tv0, tv1;
- unsigned long tv_diff;
-
- gettimeofday(&tv0, NULL);
- passert(st->st_sec_in_use);
- n_to_mpz(&mp_g, g.ptr, g.len);
- mpz_init(&mp_shared);
- mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus);
- mpz_clear(&mp_g);
- freeanychunk(st->st_shared); /* happens in odd error cases */
- st->st_shared = mpz_to_n(&mp_shared, group->bytes);
- mpz_clear(&mp_shared);
- gettimeofday(&tv1, NULL);
- tv_diff=(tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec);
- DBG(DBG_CRYPT,
- DBG_log("compute_dh_shared(): time elapsed (%s): %ld usec"
- , enum_show(&oakley_group_names, st->st_oakley.group->group)
- , tv_diff);
- );
- /* if took more than 200 msec ... */
- if (tv_diff > 200000) {
- loglog(RC_LOG_SERIOUS, "WARNING: compute_dh_shared(): for %s took "
- "%ld usec"
- , enum_show(&oakley_group_names, st->st_oakley.group->group)
- , tv_diff);
- }
-
- DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
+ passert(st->st_dh);
+ st->st_dh->set_other_public_value(st->st_dh, g);
+ st->st_dh->get_shared_secret(st->st_dh, &st->st_shared);
+ DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
}
/* 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.
*/
-static bool
-build_and_ship_KE(struct state *st, chunk_t *g
-, const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np)
+static bool build_and_ship_KE(struct state *st, chunk_t *g,
+ const struct dh_desc *group,
+ pb_stream *outs, u_int8_t np)
{
- 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);
+ if (st->st_dh == NULL)
+ {
+ st->st_dh = lib->crypto->create_dh(lib->crypto, group->algo_id);
+ if (st->st_dh == NULL)
+ {
+ plog("Diffie Hellman group %N is not available",
+ diffie_hellman_group_names, group->algo_id);
+ return FALSE;
+ }
+ }
+ st->st_dh->get_my_public_value(st->st_dh, g);
DBG(DBG_CRYPT,
- DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
- DBG_dump_chunk("Public DH value sent:\n", *g));
- }
- return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
+ DBG_dump_chunk("Public DH value sent:\n", *g)
+ )
+ return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
}
/* accept_ke
@@ -194,21 +163,22 @@ build_and_ship_KE(struct state *st, chunk_t *g
* Diffie-Hellman group enforced, if necessary, by pre-pending the
* value with zeros.
*/
-static notification_t
-accept_KE(chunk_t *dest, const char *val_name
-, const struct oakley_group_desc *gr
-, pb_stream *pbs)
+static notification_t accept_KE(chunk_t *dest, const char *val_name,
+ const struct dh_desc *gr,
+ pb_stream *pbs)
{
- if (pbs_left(pbs) != gr->bytes)
- {
- loglog(RC_LOG_SERIOUS, "KE has %u byte DH public value; %u required"
- , (unsigned) pbs_left(pbs), (unsigned) gr->bytes);
- /* XXX Could send notification back */
- return INVALID_KEY_INFORMATION;
- }
- clonereplacechunk(*dest, pbs->cur, pbs_left(pbs), val_name);
- DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest);
- return NOTHING_WRONG;
+ if (pbs_left(pbs) != gr->ke_size)
+ {
+ loglog(RC_LOG_SERIOUS, "KE has %u byte DH public value; %u required"
+ , (unsigned) pbs_left(pbs), gr->ke_size);
+ /* XXX Could send notification back */
+ return INVALID_KEY_INFORMATION;
+ }
+ free(dest->ptr);
+ *dest = chunk_create(pbs->cur, pbs_left(pbs));
+ *dest = chunk_clone(*dest);
+ DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest);
+ return NOTHING_WRONG;
}
/* accept_PFS_KE
@@ -216,652 +186,663 @@ accept_KE(chunk_t *dest, const char *val_name
* Check and accept optional Quick Mode KE payload for PFS.
* Extends ACCEPT_PFS to check whether KE is allowed or required.
*/
-static notification_t
-accept_PFS_KE(struct msg_digest *md, chunk_t *dest
-, const char *val_name, const char *msg_name)
+static notification_t accept_PFS_KE(struct msg_digest *md, chunk_t *dest,
+ const char *val_name, const char *msg_name)
{
- struct state *st = md->st;
- struct payload_digest *const ke_pd = md->chain[ISAKMP_NEXT_KE];
+ struct state *st = md->st;
+ struct payload_digest *const ke_pd = md->chain[ISAKMP_NEXT_KE];
- if (ke_pd == NULL)
- {
- if (st->st_pfs_group != NULL)
- {
- loglog(RC_LOG_SERIOUS, "missing KE payload in %s message", msg_name);
- return INVALID_KEY_INFORMATION;
- }
- }
- else
- {
- if (st->st_pfs_group == NULL)
+ if (ke_pd == NULL)
{
- loglog(RC_LOG_SERIOUS, "%s message KE payload requires a GROUP_DESCRIPTION attribute in SA"
- , msg_name);
- return INVALID_KEY_INFORMATION;
+ if (st->st_pfs_group != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "missing KE payload in %s message", msg_name);
+ return INVALID_KEY_INFORMATION;
+ }
}
- if (ke_pd->next != NULL)
+ else
{
- loglog(RC_LOG_SERIOUS, "%s message contains several KE payloads; we accept at most one", msg_name);
- return INVALID_KEY_INFORMATION; /* ??? */
+ if (st->st_pfs_group == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s message KE payload requires a GROUP_DESCRIPTION attribute in SA"
+ , msg_name);
+ return INVALID_KEY_INFORMATION;
+ }
+ if (ke_pd->next != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s message contains several KE payloads; we accept at most one", msg_name);
+ return INVALID_KEY_INFORMATION; /* ??? */
+ }
+ return accept_KE(dest, val_name, st->st_pfs_group, &ke_pd->pbs);
}
- return accept_KE(dest, val_name, st->st_pfs_group, &ke_pd->pbs);
- }
- return NOTHING_WRONG;
+ return NOTHING_WRONG;
}
-static bool
-build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np
-, const char *name)
+static bool build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np,
+ const char *name)
{
- freeanychunk(*n);
- setchunk(*n, alloc_bytes(DEFAULT_NONCE_SIZE, name), DEFAULT_NONCE_SIZE);
- get_rnd_bytes(n->ptr, DEFAULT_NONCE_SIZE);
- return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name);
+ rng_t *rng;
+
+ free(n->ptr);
+ *n = chunk_create(malloc(DEFAULT_NONCE_SIZE), DEFAULT_NONCE_SIZE);
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ rng->get_bytes(rng, DEFAULT_NONCE_SIZE, n->ptr);
+ rng->destroy(rng);
+ return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name);
}
-static bool
-collect_rw_ca_candidates(struct msg_digest *md, generalName_t **top)
+static bool collect_rw_ca_candidates(struct msg_digest *md, generalName_t **top)
{
- struct connection *d = find_host_connection(&md->iface->addr
- , pluto_port, (ip_address*)NULL, md->sender_port, LEMPTY);
+ struct connection *d = find_host_connection(&md->iface->addr
+ , pluto_port, (ip_address*)NULL, md->sender_port, LEMPTY);
- for (; d != NULL; d = d->hp_next)
- {
- /* must be a road warrior connection */
- if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO)
- && d->spd.that.ca.ptr != NULL)
+ for (; d != NULL; d = d->hp_next)
{
- generalName_t *gn;
- bool new_entry = TRUE;
-
- for (gn = *top; gn != NULL; gn = gn->next)
- {
- if (same_dn(gn->name, d->spd.that.ca))
+ /* must be a road warrior connection */
+ if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO)
+ && d->spd.that.ca.ptr != NULL)
{
- new_entry = FALSE;
- break;
+ generalName_t *gn;
+ bool new_entry = TRUE;
+
+ for (gn = *top; gn != NULL; gn = gn->next)
+ {
+ if (same_dn(gn->name, d->spd.that.ca))
+ {
+ new_entry = FALSE;
+ break;
+ }
+ }
+ if (new_entry)
+ {
+ gn = malloc_thing(generalName_t);
+ gn->kind = GN_DIRECTORY_NAME;
+ gn->name = d->spd.that.ca;
+ gn->next = *top;
+ *top = gn;
+ }
}
- }
- if (new_entry)
- {
- gn = alloc_thing(generalName_t, "generalName");
- gn->kind = GN_DIRECTORY_NAME;
- gn->name = d->spd.that.ca;
- gn->next = *top;
- *top = gn;
- }
- }
- }
- return *top != NULL;
+ }
+ return *top != NULL;
}
-static bool
-build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs, u_int8_t np)
+static bool build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs,
+ u_int8_t np)
{
- pb_stream cr_pbs;
- struct isakmp_cr cr_hd;
- cr_hd.isacr_np = np;
- cr_hd.isacr_type = type;
+ pb_stream cr_pbs;
+ struct isakmp_cr cr_hd;
+ cr_hd.isacr_np = np;
+ cr_hd.isacr_type = type;
- /* build CR header */
- if (!out_struct(&cr_hd, &isakmp_ipsec_cert_req_desc, outs, &cr_pbs))
- return FALSE;
+ /* build CR header */
+ if (!out_struct(&cr_hd, &isakmp_ipsec_cert_req_desc, outs, &cr_pbs))
+ return FALSE;
- if (ca.ptr != NULL)
- {
- /* build CR body containing the distinguished name of the CA */
- if (!out_chunk(ca, &cr_pbs, "CA"))
- return FALSE;
- }
- close_output_pbs(&cr_pbs);
- return TRUE;
+ if (ca.ptr != NULL)
+ {
+ /* build CR body containing the distinguished name of the CA */
+ if (!out_chunk(ca, &cr_pbs, "CA"))
+ return FALSE;
+ }
+ close_output_pbs(&cr_pbs);
+ return TRUE;
}
/* Send a notification to the peer. We could decide
* whether to send the notification, based on the type and the
* destination, if we care to.
*/
-static void
-send_notification(struct state *sndst, u_int16_t type, struct state *encst,
- msgid_t msgid, u_char *icookie, u_char *rcookie,
- u_char *spi, size_t spisize, u_char protoid)
+static void send_notification(struct state *sndst, u_int16_t type,
+ struct state *encst, msgid_t msgid,
+ u_char *icookie, u_char *rcookie,
+ u_char *spi, size_t spisize, u_char protoid)
{
- u_char buffer[1024];
- pb_stream pbs, r_hdr_pbs;
- u_char *r_hashval = NULL; /* where in reply to jam hash value */
- u_char *r_hash_start = NULL; /* start of what is to be hashed */
-
- passert((sndst) && (sndst->st_connection));
-
- plog("sending %snotification %s to %s:%u"
- , encst ? "encrypted " : ""
- , enum_name(&notification_names, type)
- , ip_str(&sndst->st_connection->spd.that.host_addr)
- , (unsigned)sndst->st_connection->spd.that.host_port);
-
- memset(buffer, 0, sizeof(buffer));
- init_pbs(&pbs, buffer, sizeof(buffer), "ISAKMP notify");
-
- /* HDR* */
- {
- struct isakmp_hdr hdr;
-
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = encst ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_N;
- hdr.isa_xchg = ISAKMP_XCHG_INFO;
- hdr.isa_msgid = msgid;
- hdr.isa_flags = encst ? ISAKMP_FLAG_ENCRYPTION : 0;
- if (icookie)
- memcpy(hdr.isa_icookie, icookie, COOKIE_SIZE);
- if (rcookie)
- memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE);
- if (!out_struct(&hdr, &isakmp_hdr_desc, &pbs, &r_hdr_pbs))
- impossible();
- }
-
- /* HASH -- value to be filled later */
- if (encst)
- {
- pb_stream hash_pbs;
- if (!out_generic(ISAKMP_NEXT_N, &isakmp_hash_desc, &r_hdr_pbs,
- &hash_pbs))
- impossible();
- r_hashval = hash_pbs.cur; /* remember where to plant value */
- if (!out_zero(
- encst->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH"))
- impossible();
- close_output_pbs(&hash_pbs);
- r_hash_start = r_hdr_pbs.cur; /* hash from after HASH */
- }
-
- /* Notification Payload */
- {
- pb_stream not_pbs;
- struct isakmp_notification isan;
-
- isan.isan_doi = ISAKMP_DOI_IPSEC;
- isan.isan_np = ISAKMP_NEXT_NONE;
- isan.isan_type = type;
- isan.isan_spisize = spisize;
- isan.isan_protoid = protoid;
-
- if (!out_struct(&isan, &isakmp_notification_desc, &r_hdr_pbs, &not_pbs)
- || !out_raw(spi, spisize, &not_pbs, "spi"))
- impossible();
- close_output_pbs(&not_pbs);
- }
-
- /* calculate hash value and patch into Hash Payload */
- if (encst)
- {
- struct hmac_ctx ctx;
- hmac_init_chunk(&ctx, encst->st_oakley.hasher, encst->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);
+ u_char buffer[1024];
+ pb_stream pbs, r_hdr_pbs;
+ u_char *r_hashval = NULL; /* where in reply to jam hash value */
+ u_char *r_hash_start = NULL; /* start of what is to be hashed */
- DBG(DBG_CRYPT,
- DBG_log("HASH computed:");
- DBG_dump("", r_hashval, ctx.hmac_digest_size);
- )
- }
+ passert((sndst) && (sndst->st_connection));
- /* Encrypt message (preserve st_iv and st_new_iv) */
- if (encst)
- {
- u_char old_iv[MAX_DIGEST_LEN];
- u_char new_iv[MAX_DIGEST_LEN];
+ plog("sending %snotification %s to %s:%u"
+ , encst ? "encrypted " : ""
+ , enum_name(&notification_names, type)
+ , ip_str(&sndst->st_connection->spd.that.host_addr)
+ , (unsigned)sndst->st_connection->spd.that.host_port);
+
+ memset(buffer, 0, sizeof(buffer));
+ init_pbs(&pbs, buffer, sizeof(buffer), "ISAKMP notify");
+
+ /* HDR* */
+ {
+ struct isakmp_hdr hdr;
+
+ hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+ hdr.isa_np = encst ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_N;
+ hdr.isa_xchg = ISAKMP_XCHG_INFO;
+ hdr.isa_msgid = msgid;
+ hdr.isa_flags = encst ? ISAKMP_FLAG_ENCRYPTION : 0;
+ if (icookie)
+ memcpy(hdr.isa_icookie, icookie, COOKIE_SIZE);
+ if (rcookie)
+ memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE);
+ if (!out_struct(&hdr, &isakmp_hdr_desc, &pbs, &r_hdr_pbs))
+ impossible();
+ }
- u_int old_iv_len = encst->st_iv_len;
- u_int new_iv_len = encst->st_new_iv_len;
-
- if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN)
- impossible();
-
- memcpy(old_iv, encst->st_iv, old_iv_len);
- memcpy(new_iv, encst->st_new_iv, new_iv_len);
-
- if (!IS_ISAKMP_SA_ESTABLISHED(encst->st_state))
- {
- memcpy(encst->st_ph1_iv, encst->st_new_iv, encst->st_new_iv_len);
- encst->st_ph1_iv_len = encst->st_new_iv_len;
- }
- init_phase2_iv(encst, &msgid);
- if (!encrypt_message(&r_hdr_pbs, encst))
- impossible();
-
- /* restore preserved st_iv and st_new_iv */
- memcpy(encst->st_iv, old_iv, old_iv_len);
- memcpy(encst->st_new_iv, new_iv, new_iv_len);
- encst->st_iv_len = old_iv_len;
- encst->st_new_iv_len = new_iv_len;
- }
- else
- {
- close_output_pbs(&r_hdr_pbs);
- }
-
- /* Send packet (preserve st_tpacket) */
- {
- chunk_t saved_tpacket = sndst->st_tpacket;
-
- setchunk(sndst->st_tpacket, pbs.start, pbs_offset(&pbs));
- send_packet(sndst, "ISAKMP notify");
- sndst->st_tpacket = saved_tpacket;
- }
+ /* HASH -- value to be filled later */
+ if (encst)
+ {
+ pb_stream hash_pbs;
+ if (!out_generic(ISAKMP_NEXT_N, &isakmp_hash_desc, &r_hdr_pbs,
+ &hash_pbs))
+ impossible();
+ r_hashval = hash_pbs.cur; /* remember where to plant value */
+ if (!out_zero(
+ encst->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH"))
+ impossible();
+ close_output_pbs(&hash_pbs);
+ r_hash_start = r_hdr_pbs.cur; /* hash from after HASH */
+ }
+
+ /* Notification Payload */
+ {
+ pb_stream not_pbs;
+ struct isakmp_notification isan;
+
+ isan.isan_doi = ISAKMP_DOI_IPSEC;
+ isan.isan_np = ISAKMP_NEXT_NONE;
+ isan.isan_type = type;
+ isan.isan_spisize = spisize;
+ isan.isan_protoid = protoid;
+
+ if (!out_struct(&isan, &isakmp_notification_desc, &r_hdr_pbs, &not_pbs)
+ || !out_raw(spi, spisize, &not_pbs, "spi"))
+ impossible();
+ close_output_pbs(&not_pbs);
+ }
+
+ /* calculate hash value and patch into Hash Payload */
+ if (encst)
+ {
+ chunk_t msgid_chunk = chunk_from_thing(msgid);
+ chunk_t msg_chunk = { r_hash_start, r_hdr_pbs.cur-r_hash_start };
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(encst->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, encst->st_skeyid_a);
+ prf->get_bytes(prf, msgid_chunk, NULL);
+ prf->get_bytes(prf, msg_chunk, r_hashval);
+
+ DBG(DBG_CRYPT,
+ DBG_log("HASH computed:");
+ DBG_dump("", r_hashval, prf->get_block_size(prf));
+ )
+ prf->destroy(prf);
+ }
+
+ /* Encrypt message (preserve st_iv and st_new_iv) */
+ if (encst)
+ {
+ u_char old_iv[MAX_DIGEST_LEN];
+ u_char new_iv[MAX_DIGEST_LEN];
+
+ u_int old_iv_len = encst->st_iv_len;
+ u_int new_iv_len = encst->st_new_iv_len;
+
+ if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN)
+ impossible();
+
+ memcpy(old_iv, encst->st_iv, old_iv_len);
+ memcpy(new_iv, encst->st_new_iv, new_iv_len);
+
+ if (!IS_ISAKMP_SA_ESTABLISHED(encst->st_state))
+ {
+ memcpy(encst->st_ph1_iv, encst->st_new_iv, encst->st_new_iv_len);
+ encst->st_ph1_iv_len = encst->st_new_iv_len;
+ }
+ init_phase2_iv(encst, &msgid);
+ if (!encrypt_message(&r_hdr_pbs, encst))
+ impossible();
+
+ /* restore preserved st_iv and st_new_iv */
+ memcpy(encst->st_iv, old_iv, old_iv_len);
+ memcpy(encst->st_new_iv, new_iv, new_iv_len);
+ encst->st_iv_len = old_iv_len;
+ encst->st_new_iv_len = new_iv_len;
+ }
+ else
+ {
+ close_output_pbs(&r_hdr_pbs);
+ }
+
+ /* Send packet (preserve st_tpacket) */
+ {
+ chunk_t saved_tpacket = sndst->st_tpacket;
+
+ sndst->st_tpacket = chunk_create(pbs.start, pbs_offset(&pbs));
+ send_packet(sndst, "ISAKMP notify");
+ sndst->st_tpacket = saved_tpacket;
+ }
}
-void
-send_notification_from_state(struct state *st, enum state_kind state,
- u_int16_t type)
+void send_notification_from_state(struct state *st, enum state_kind state,
+ u_int16_t type)
{
- struct state *p1st;
-
- passert(st);
-
- if (state == STATE_UNDEFINED)
- state = st->st_state;
-
- if (IS_QUICK(state))
- {
- p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
- if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)))
- {
- loglog(RC_LOG_SERIOUS,
- "no Phase1 state for Quick mode notification");
- return;
- }
- send_notification(st, type, p1st, generate_msgid(p1st),
- st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
- }
- else if (IS_ISAKMP_ENCRYPTED(state) && st->st_enc_key.ptr != NULL)
- {
- send_notification(st, type, st, generate_msgid(st),
- st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
- }
- else
- {
- /* no ISAKMP SA established - don't encrypt notification */
- send_notification(st, type, NULL, 0,
- st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
- }
+ struct state *p1st;
+
+ passert(st);
+
+ if (state == STATE_UNDEFINED)
+ state = st->st_state;
+
+ if (IS_QUICK(state))
+ {
+ p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
+ if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)))
+ {
+ loglog(RC_LOG_SERIOUS,
+ "no Phase1 state for Quick mode notification");
+ return;
+ }
+ send_notification(st, type, p1st, generate_msgid(p1st),
+ st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
+ }
+ else if (IS_ISAKMP_ENCRYPTED(state) && st->st_enc_key.ptr != NULL)
+ {
+ send_notification(st, type, st, generate_msgid(st),
+ st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
+ }
+ else
+ {
+ /* no ISAKMP SA established - don't encrypt notification */
+ send_notification(st, type, NULL, 0,
+ st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
+ }
}
-void
-send_notification_from_md(struct msg_digest *md, u_int16_t type)
+void send_notification_from_md(struct msg_digest *md, u_int16_t type)
{
- /**
- * Create a dummy state to be able to use send_packet in
- * send_notification
- *
- * we need to set:
- * st_connection->that.host_addr
- * st_connection->that.host_port
- * st_connection->interface
- */
- struct state st;
- struct connection cnx;
-
- passert(md);
-
- memset(&st, 0, sizeof(st));
- memset(&cnx, 0, sizeof(cnx));
- st.st_connection = &cnx;
- cnx.spd.that.host_addr = md->sender;
- cnx.spd.that.host_port = md->sender_port;
- cnx.interface = md->iface;
-
- send_notification(&st, type, NULL, 0,
- md->hdr.isa_icookie, md->hdr.isa_rcookie, NULL, 0, PROTO_ISAKMP);
+ /**
+ * Create a dummy state to be able to use send_packet in
+ * send_notification
+ *
+ * we need to set:
+ * st_connection->that.host_addr
+ * st_connection->that.host_port
+ * st_connection->interface
+ */
+ struct state st;
+ struct connection cnx;
+
+ passert(md);
+
+ memset(&st, 0, sizeof(st));
+ memset(&cnx, 0, sizeof(cnx));
+ st.st_connection = &cnx;
+ cnx.spd.that.host_addr = md->sender;
+ cnx.spd.that.host_port = md->sender_port;
+ cnx.interface = md->iface;
+
+ send_notification(&st, type, NULL, 0,
+ md->hdr.isa_icookie, md->hdr.isa_rcookie, NULL, 0, PROTO_ISAKMP);
}
/* Send a Delete Notification to announce deletion of ISAKMP SA or
* inbound IPSEC SAs. Does nothing if no such SAs are being deleted.
* Delete Notifications cannot announce deletion of outbound IPSEC/ISAKMP SAs.
*/
-void
-send_delete(struct state *st)
+void send_delete(struct state *st)
{
- pb_stream reply_pbs;
- pb_stream r_hdr_pbs;
- msgid_t msgid;
- u_char buffer[8192];
- struct state *p1st;
- ip_said said[EM_MAXRELSPIS];
- ip_said *ns = said;
- u_char
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
- bool isakmp_sa = FALSE;
-
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
- if (p1st == NULL)
+ pb_stream reply_pbs;
+ pb_stream r_hdr_pbs;
+ msgid_t msgid;
+ u_char buffer[8192];
+ struct state *p1st;
+ ip_said said[EM_MAXRELSPIS];
+ ip_said *ns = said;
+ u_char
+ *r_hashval, /* where in reply to jam hash value */
+ *r_hash_start; /* start of what is to be hashed */
+ bool isakmp_sa = FALSE;
+
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ {
+ p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
+ if (p1st == NULL)
+ {
+ DBG(DBG_CONTROL, DBG_log("no Phase 1 state for Delete"));
+ return;
+ }
+
+ if (st->st_ah.present)
+ {
+ ns->spi = st->st_ah.our_spi;
+ ns->dst = st->st_connection->spd.this.host_addr;
+ ns->proto = PROTO_IPSEC_AH;
+ ns++;
+ }
+ if (st->st_esp.present)
+ {
+ ns->spi = st->st_esp.our_spi;
+ ns->dst = st->st_connection->spd.this.host_addr;
+ ns->proto = PROTO_IPSEC_ESP;
+ ns++;
+ }
+
+ passert(ns != said); /* there must be some SAs to delete */
+ }
+ else if (IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ p1st = st;
+ isakmp_sa = TRUE;
+ }
+ else
{
- DBG(DBG_CONTROL, DBG_log("no Phase 1 state for Delete"));
- return;
+ return; /* nothing to do */
}
- if (st->st_ah.present)
+ msgid = generate_msgid(p1st);
+
+ zero(buffer);
+ init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
+
+ /* HDR* */
{
- ns->spi = st->st_ah.our_spi;
- ns->dst = st->st_connection->spd.this.host_addr;
- ns->proto = PROTO_IPSEC_AH;
- ns++;
+ 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))
+ impossible();
}
- if (st->st_esp.present)
+
+ /* HASH -- value to be filled later */
{
- ns->spi = st->st_esp.our_spi;
- ns->dst = st->st_connection->spd.this.host_addr;
- ns->proto = PROTO_IPSEC_ESP;
- ns++;
- }
-
- passert(ns != said); /* there must be some SAs to delete */
- }
- else if (IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- p1st = st;
- isakmp_sa = TRUE;
- }
- else
- {
- return; /* nothing to do */
- }
-
- msgid = generate_msgid(p1st);
-
- zero(buffer);
- init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
-
- /* 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))
- impossible();
- }
-
- /* HASH -- value to be filled later */
- {
- pb_stream hash_pbs;
-
- if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
- impossible();
- r_hashval = hash_pbs.cur; /* remember where to plant value */
- if (!out_zero(p1st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH(1)"))
- impossible();
- close_output_pbs(&hash_pbs);
- r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */
- }
-
- /* Delete Payloads */
- if (isakmp_sa)
- {
- pb_stream del_pbs;
- struct isakmp_delete isad;
- u_char isakmp_spi[2*COOKIE_SIZE];
-
- isad.isad_doi = ISAKMP_DOI_IPSEC;
- isad.isad_np = ISAKMP_NEXT_NONE;
- isad.isad_spisize = (2 * COOKIE_SIZE);
- isad.isad_protoid = PROTO_ISAKMP;
- isad.isad_nospi = 1;
-
- memcpy(isakmp_spi, st->st_icookie, COOKIE_SIZE);
- memcpy(isakmp_spi+COOKIE_SIZE, st->st_rcookie, COOKIE_SIZE);
-
- if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)
- || !out_raw(&isakmp_spi, (2*COOKIE_SIZE), &del_pbs, "delete payload"))
- impossible();
- close_output_pbs(&del_pbs);
- }
- else
- {
- while (ns != said)
- {
-
- pb_stream del_pbs;
- struct isakmp_delete isad;
-
- ns--;
- isad.isad_doi = ISAKMP_DOI_IPSEC;
- isad.isad_np = ns == said? ISAKMP_NEXT_NONE : ISAKMP_NEXT_D;
- isad.isad_spisize = sizeof(ipsec_spi_t);
- isad.isad_protoid = ns->proto;
-
- isad.isad_nospi = 1;
- if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)
- || !out_raw(&ns->spi, sizeof(ipsec_spi_t), &del_pbs, "delete payload"))
- impossible();
- close_output_pbs(&del_pbs);
- }
- }
-
- /* calculate hash value and patch into Hash Payload */
- {
- 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);
+ pb_stream hash_pbs;
+
+ if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
+ impossible();
+ r_hashval = hash_pbs.cur; /* remember where to plant value */
+ if (!out_zero(p1st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH(1)"))
+ impossible();
+ close_output_pbs(&hash_pbs);
+ r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */
+ }
- DBG(DBG_CRYPT,
- DBG_log("HASH(1) computed:");
- DBG_dump("", r_hashval, ctx.hmac_digest_size);
- )
- }
-
- /* Do a dance to avoid needing a new state object.
- * We use the Phase 1 State. This is the one with right
- * IV, for one thing.
- * The tricky bits are:
- * - we need to preserve (save/restore) st_iv (but not st_iv_new)
- * - we need to preserve (save/restore) st_tpacket.
- */
- {
- u_char old_iv[MAX_DIGEST_LEN];
- chunk_t saved_tpacket = p1st->st_tpacket;
-
- memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
- init_phase2_iv(p1st, &msgid);
-
- if (!encrypt_message(&r_hdr_pbs, p1st))
- impossible();
-
- setchunk(p1st->st_tpacket, reply_pbs.start, pbs_offset(&reply_pbs));
- send_packet(p1st, "delete notify");
- p1st->st_tpacket = saved_tpacket;
-
- /* get back old IV for this state */
- memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);
- }
+ /* Delete Payloads */
+ if (isakmp_sa)
+ {
+ pb_stream del_pbs;
+ struct isakmp_delete isad;
+ u_char isakmp_spi[2*COOKIE_SIZE];
+
+ isad.isad_doi = ISAKMP_DOI_IPSEC;
+ isad.isad_np = ISAKMP_NEXT_NONE;
+ isad.isad_spisize = (2 * COOKIE_SIZE);
+ isad.isad_protoid = PROTO_ISAKMP;
+ isad.isad_nospi = 1;
+
+ memcpy(isakmp_spi, st->st_icookie, COOKIE_SIZE);
+ memcpy(isakmp_spi+COOKIE_SIZE, st->st_rcookie, COOKIE_SIZE);
+
+ if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)
+ || !out_raw(&isakmp_spi, (2*COOKIE_SIZE), &del_pbs, "delete payload"))
+ impossible();
+ close_output_pbs(&del_pbs);
+ }
+ else
+ {
+ while (ns != said)
+ {
+
+ pb_stream del_pbs;
+ struct isakmp_delete isad;
+
+ ns--;
+ isad.isad_doi = ISAKMP_DOI_IPSEC;
+ isad.isad_np = ns == said? ISAKMP_NEXT_NONE : ISAKMP_NEXT_D;
+ isad.isad_spisize = sizeof(ipsec_spi_t);
+ isad.isad_protoid = ns->proto;
+
+ isad.isad_nospi = 1;
+ if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)
+ || !out_raw(&ns->spi, sizeof(ipsec_spi_t), &del_pbs, "delete payload"))
+ impossible();
+ close_output_pbs(&del_pbs);
+ }
+ }
+
+ /* calculate hash value and patch into Hash Payload */
+ {
+ chunk_t msgid_chunk = chunk_from_thing(msgid);
+ chunk_t msg_chunk = { r_hash_start, r_hdr_pbs.cur-r_hash_start };
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(p1st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, p1st->st_skeyid_a);
+ prf->get_bytes(prf, msgid_chunk, NULL);
+ prf->get_bytes(prf, msg_chunk, r_hashval);
+
+ DBG(DBG_CRYPT,
+ DBG_log("HASH(1) computed:");
+ DBG_dump("", r_hashval, prf->get_block_size(prf));
+ )
+
+ prf->destroy(prf);
+ }
+
+ /* Do a dance to avoid needing a new state object.
+ * We use the Phase 1 State. This is the one with right
+ * IV, for one thing.
+ * The tricky bits are:
+ * - we need to preserve (save/restore) st_iv (but not st_iv_new)
+ * - we need to preserve (save/restore) st_tpacket.
+ */
+ {
+ u_char old_iv[MAX_DIGEST_LEN];
+ chunk_t saved_tpacket = p1st->st_tpacket;
+
+ memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
+ init_phase2_iv(p1st, &msgid);
+
+ if (!encrypt_message(&r_hdr_pbs, p1st))
+ impossible();
+
+ p1st->st_tpacket = chunk_create(reply_pbs.start, pbs_offset(&reply_pbs));
+ send_packet(p1st, "delete notify");
+ p1st->st_tpacket = saved_tpacket;
+
+ /* get back old IV for this state */
+ memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);
+ }
}
-void
-accept_delete(struct state *st, struct msg_digest *md, struct payload_digest *p)
+void accept_delete(struct state *st, struct msg_digest *md,
+ struct payload_digest *p)
{
- struct isakmp_delete *d = &(p->payload.delete);
- size_t sizespi;
- int i;
-
- if (!md->encrypted)
- {
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: not encrypted");
- return;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- /* can't happen (if msg is encrypt), but just to be sure */
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
- "ISAKMP SA not established");
- return;
- }
-
- if (d->isad_nospi == 0)
- {
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: no SPI");
- return;
- }
-
- switch (d->isad_protoid)
- {
- case PROTO_ISAKMP:
- sizespi = 2 * COOKIE_SIZE;
- break;
- case PROTO_IPSEC_AH:
- case PROTO_IPSEC_ESP:
- sizespi = sizeof(ipsec_spi_t);
- break;
- case PROTO_IPCOMP:
- /* nothing interesting to delete */
- return;
- default:
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: unknown Protocol ID (%s)"
- , enum_show(&protocol_names, d->isad_protoid));
- return;
- }
-
- if (d->isad_spisize != sizespi)
- {
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: bad SPI size (%d) for %s"
- , d->isad_spisize, enum_show(&protocol_names, d->isad_protoid));
- return;
- }
-
- if (pbs_left(&p->pbs) != d->isad_nospi * sizespi)
- {
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: invalid payload size");
- return;
- }
-
- for (i = 0; i < d->isad_nospi; i++)
- {
- u_char *spi = p->pbs.cur + (i * sizespi);
-
- if (d->isad_protoid == PROTO_ISAKMP)
- {
- /**
- * ISAKMP
- */
- struct state *dst = find_state(spi /*iCookie*/
- , spi+COOKIE_SIZE /*rCookie*/
- , &st->st_connection->spd.that.host_addr
- , MAINMODE_MSGID);
-
- if (dst == NULL)
- {
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
- "ISAKMP SA not found (maybe expired)");
- }
- else if (!same_peer_ids(st->st_connection, dst->st_connection, NULL))
- {
- /* we've not authenticated the relevant identities */
+ struct isakmp_delete *d = &(p->payload.delete);
+ size_t sizespi;
+ int i;
+
+ if (!md->encrypted)
+ {
+ loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: not encrypted");
+ return;
+ }
+
+ if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ /* can't happen (if msg is encrypt), but just to be sure */
loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
- "ISAKMP SA used to convey Delete has different IDs from ISAKMP SA it deletes");
- }
- else
- {
- struct connection *oldc;
-
- oldc = cur_connection;
- set_cur_connection(dst->st_connection);
+ "ISAKMP SA not established");
+ return;
+ }
- if (nat_traversal_enabled)
- nat_traversal_change_port_lookup(md, dst);
+ if (d->isad_nospi == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: no SPI");
+ return;
+ }
- loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
- "deleting ISAKMP State #%lu", dst->st_serialno);
- delete_state(dst);
- set_cur_connection(oldc);
- }
+ switch (d->isad_protoid)
+ {
+ case PROTO_ISAKMP:
+ sizespi = 2 * COOKIE_SIZE;
+ break;
+ case PROTO_IPSEC_AH:
+ case PROTO_IPSEC_ESP:
+ sizespi = sizeof(ipsec_spi_t);
+ break;
+ case PROTO_IPCOMP:
+ /* nothing interesting to delete */
+ return;
+ default:
+ loglog(RC_LOG_SERIOUS
+ , "ignoring Delete SA payload: unknown Protocol ID (%s)"
+ , enum_show(&protocol_names, d->isad_protoid));
+ return;
}
- else
+
+ if (d->isad_spisize != sizespi)
{
- /**
- * IPSEC (ESP/AH)
- */
- bool bogus;
- struct state *dst = find_phase2_state_to_delete(st
- , d->isad_protoid
- , *(ipsec_spi_t *)spi /* network order */
- , &bogus);
-
- if (dst == NULL)
- {
loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: %s SA(0x%08lx) not found (%s)"
- , enum_show(&protocol_names, d->isad_protoid)
- , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)
- , bogus ? "our SPI - bogus implementation" : "maybe expired");
- }
- else
- {
- struct connection *rc = dst->st_connection;
- struct connection *oldc;
-
- oldc = cur_connection;
- set_cur_connection(rc);
-
- if (nat_traversal_enabled)
- nat_traversal_change_port_lookup(md, dst);
-
- if (rc->newest_ipsec_sa == dst->st_serialno
- && (rc->policy & POLICY_UP))
- {
- /* Last IPSec SA for a permanent connection that we
- * have initiated. Replace it in a few seconds.
- *
- * Useful if the other peer is rebooting.
- */
-#define DELETE_SA_DELAY EVENT_RETRANSMIT_DELAY_0
- if (dst->st_event != NULL
- && dst->st_event->ev_type == EVENT_SA_REPLACE
- && dst->st_event->ev_time <= DELETE_SA_DELAY + now())
- {
- /* Patch from Angus Lees to ignore retransmited
- * Delete SA.
+ , "ignoring Delete SA payload: bad SPI size (%d) for %s"
+ , d->isad_spisize, enum_show(&protocol_names, d->isad_protoid));
+ return;
+ }
+
+ if (pbs_left(&p->pbs) != d->isad_nospi * sizespi)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ignoring Delete SA payload: invalid payload size");
+ return;
+ }
+
+ for (i = 0; i < d->isad_nospi; i++)
+ {
+ u_char *spi = p->pbs.cur + (i * sizespi);
+
+ if (d->isad_protoid == PROTO_ISAKMP)
+ {
+ /**
+ * ISAKMP
*/
- loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
- "already replacing IPSEC State #%lu in %d seconds"
- , dst->st_serialno, (int)(dst->st_event->ev_time - now()));
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
- "replace IPSEC State #%lu in %d seconds"
- , dst->st_serialno, DELETE_SA_DELAY);
- dst->st_margin = DELETE_SA_DELAY;
- delete_event(dst);
- event_schedule(EVENT_SA_REPLACE, DELETE_SA_DELAY, dst);
- }
+ struct state *dst = find_state(spi /*iCookie*/
+ , spi+COOKIE_SIZE /*rCookie*/
+ , &st->st_connection->spd.that.host_addr
+ , MAINMODE_MSGID);
+
+ if (dst == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
+ "ISAKMP SA not found (maybe expired)");
+ }
+ else if (!same_peer_ids(st->st_connection, dst->st_connection, NULL))
+ {
+ /* we've not authenticated the relevant identities */
+ loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
+ "ISAKMP SA used to convey Delete has different IDs from ISAKMP SA it deletes");
+ }
+ else
+ {
+ struct connection *oldc;
+
+ oldc = cur_connection;
+ set_cur_connection(dst->st_connection);
+
+ if (nat_traversal_enabled)
+ nat_traversal_change_port_lookup(md, dst);
+
+ loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
+ "deleting ISAKMP State #%lu", dst->st_serialno);
+ delete_state(dst);
+ set_cur_connection(oldc);
+ }
}
else
{
- loglog(RC_LOG_SERIOUS, "received Delete SA(0x%08lx) payload: "
- "deleting IPSEC State #%lu"
- , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)
- , dst->st_serialno);
- delete_state(dst);
- }
+ /**
+ * IPSEC (ESP/AH)
+ */
+ bool bogus;
+ struct state *dst = find_phase2_state_to_delete(st
+ , d->isad_protoid
+ , *(ipsec_spi_t *)spi /* network order */
+ , &bogus);
- /* reset connection */
- set_cur_connection(oldc);
- }
+ if (dst == NULL)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ignoring Delete SA payload: %s SA(0x%08lx) not found (%s)"
+ , enum_show(&protocol_names, d->isad_protoid)
+ , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)
+ , bogus ? "our SPI - bogus implementation" : "maybe expired");
+ }
+ else
+ {
+ struct connection *rc = dst->st_connection;
+ struct connection *oldc;
+
+ oldc = cur_connection;
+ set_cur_connection(rc);
+
+ if (nat_traversal_enabled)
+ nat_traversal_change_port_lookup(md, dst);
+
+ if (rc->newest_ipsec_sa == dst->st_serialno
+ && (rc->policy & POLICY_UP))
+ {
+ /* Last IPSec SA for a permanent connection that we
+ * have initiated. Replace it in a few seconds.
+ *
+ * Useful if the other peer is rebooting.
+ */
+#define DELETE_SA_DELAY EVENT_RETRANSMIT_DELAY_0
+ if (dst->st_event != NULL
+ && dst->st_event->ev_type == EVENT_SA_REPLACE
+ && dst->st_event->ev_time <= DELETE_SA_DELAY + now())
+ {
+ /* Patch from Angus Lees to ignore retransmited
+ * Delete SA.
+ */
+ loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
+ "already replacing IPSEC State #%lu in %d seconds"
+ , dst->st_serialno, (int)(dst->st_event->ev_time - now()));
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
+ "replace IPSEC State #%lu in %d seconds"
+ , dst->st_serialno, DELETE_SA_DELAY);
+ dst->st_margin = DELETE_SA_DELAY;
+ delete_event(dst);
+ event_schedule(EVENT_SA_REPLACE, DELETE_SA_DELAY, dst);
+ }
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "received Delete SA(0x%08lx) payload: "
+ "deleting IPSEC State #%lu"
+ , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)
+ , dst->st_serialno);
+ delete_state(dst);
+ }
+
+ /* reset connection */
+ set_cur_connection(oldc);
+ }
+ }
}
- }
}
/* The whole message must be a multiple of 4 octets.
@@ -869,14 +850,13 @@ accept_delete(struct state *st, struct msg_digest *md, struct payload_digest *p)
* rfc2408 3.6 Transform Payload.
* Note: it talks about 4 BYTE boundaries!
*/
-void
-close_message(pb_stream *pbs)
+void close_message(pb_stream *pbs)
{
- size_t padding = pad_up(pbs_offset(pbs), 4);
+ size_t padding = pad_up(pbs_offset(pbs), 4);
- if (padding != 0)
- (void) out_zero(padding, pbs, "message padding");
- close_output_pbs(pbs);
+ if (padding != 0)
+ (void) out_zero(padding, pbs, "message padding");
+ close_output_pbs(pbs);
}
/* Initiate an Oakley Main Mode exchange.
@@ -885,225 +865,220 @@ close_message(pb_stream *pbs)
*/
static stf_status
main_outI1(int whack_sock, struct connection *c, struct state *predecessor
- , lset_t policy, unsigned long try)
+ , lset_t policy, unsigned long try)
{
- struct state *st = new_state();
- pb_stream reply; /* not actually a reply, but you know what I mean */
- pb_stream rbody;
-
- int vids_to_send = 0;
-
- /* set up new state */
- st->st_connection = c;
- set_cur_state(st); /* we must reset before exit */
- st->st_policy = policy & ~POLICY_IPSEC_MASK;
- st->st_whack_sock = whack_sock;
- st->st_try = try;
- st->st_state = STATE_MAIN_I1;
-
- /* determine how many Vendor ID payloads we will be sending */
- if (SEND_PLUTO_VID)
- vids_to_send++;
- if (SEND_CISCO_UNITY_VID)
- vids_to_send++;
- if (c->spd.this.cert.type == CERT_PGP)
- vids_to_send++;
- if (SEND_XAUTH_VID)
- vids_to_send++;
- /* always send DPD Vendor ID */
- vids_to_send++;
- if (nat_traversal_enabled)
- vids_to_send++;
+ struct state *st = new_state();
+ pb_stream reply; /* not actually a reply, but you know what I mean */
+ pb_stream rbody;
+
+ int vids_to_send = 0;
+
+ /* set up new state */
+ st->st_connection = c;
+ set_cur_state(st); /* we must reset before exit */
+ st->st_policy = policy & ~POLICY_IPSEC_MASK;
+ st->st_whack_sock = whack_sock;
+ st->st_try = try;
+ st->st_state = STATE_MAIN_I1;
+
+ /* determine how many Vendor ID payloads we will be sending */
+ if (SEND_PLUTO_VID)
+ vids_to_send++;
+ if (SEND_CISCO_UNITY_VID)
+ vids_to_send++;
+ if (c->spd.this.cert.type == CERT_PGP)
+ vids_to_send++;
+ if (SEND_XAUTH_VID)
+ vids_to_send++;
+ /* always send DPD Vendor ID */
+ vids_to_send++;
+ if (nat_traversal_enabled)
+ vids_to_send++;
get_cookie(TRUE, st->st_icookie, COOKIE_SIZE, &c->spd.that.host_addr);
- insert_state(st); /* needs cookies, connection, and msgid (0) */
+ insert_state(st); /* needs cookies, connection, and msgid (0) */
- if (HAS_IPSEC_POLICY(policy))
- add_pending(dup_any(whack_sock), st, c, policy, 1
- , predecessor == NULL? SOS_NOBODY : predecessor->st_serialno);
+ if (HAS_IPSEC_POLICY(policy))
+ add_pending(dup_any(whack_sock), st, c, policy, 1
+ , predecessor == NULL? SOS_NOBODY : predecessor->st_serialno);
- if (predecessor == NULL)
- plog("initiating Main Mode");
- else
- plog("initiating Main Mode to replace #%lu", predecessor->st_serialno);
+ if (predecessor == NULL)
+ plog("initiating Main Mode");
+ else
+ plog("initiating Main Mode to replace #%lu", predecessor->st_serialno);
- /* set up reply */
- init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
+ /* set up reply */
+ init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
- /* HDR out */
- {
- struct isakmp_hdr hdr;
+ /* HDR out */
+ {
+ struct isakmp_hdr hdr;
- zero(&hdr); /* default to 0 */
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_SA;
- hdr.isa_xchg = ISAKMP_XCHG_IDPROT;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- /* R-cookie, flags and MessageID are left zero */
+ zero(&hdr); /* default to 0 */
+ hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+ hdr.isa_np = ISAKMP_NEXT_SA;
+ hdr.isa_xchg = ISAKMP_XCHG_IDPROT;
+ memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
+ /* R-cookie, flags and MessageID are left zero */
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
-
- /* SA out */
- {
- u_char *sa_start = rbody.cur;
- if (!out_sa(&rbody, &oakley_sadb, st, TRUE
- , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
+ /* SA out */
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
+ u_char *sa_start = rbody.cur;
- /* save initiator SA for later HASH */
- passert(st->st_p1isa.ptr == NULL); /* no leak! (MUST be first time) */
- clonetochunk(st->st_p1isa, sa_start, rbody.cur - sa_start
- , "sa in main_outI1");
- }
+ if (!out_sa(&rbody, &oakley_sadb, st, TRUE
+ , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
- /* if enabled send Pluto Vendor ID */
- if (SEND_PLUTO_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_STRONGSWAN))
+ /* save initiator SA for later HASH */
+ passert(st->st_p1isa.ptr == NULL); /* no leak! (MUST be first time) */
+ st->st_p1isa = chunk_create(sa_start, rbody.cur - sa_start);
+ st->st_p1isa = chunk_clone(st->st_p1isa);
+ }
+
+ /* if enabled send Pluto Vendor ID */
+ if (SEND_PLUTO_VID)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody, VID_STRONGSWAN))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* if enabled send Cisco Unity Vendor ID */
- if (SEND_CISCO_UNITY_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_CISCO_UNITY))
+ /* if enabled send Cisco Unity Vendor ID */
+ if (SEND_CISCO_UNITY_VID)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody, VID_CISCO_UNITY))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* if we have an OpenPGP certificate we assume an
- * OpenPGP peer and have to send the Vendor ID
- */
- if (c->spd.this.cert.type == CERT_PGP)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_OPENPGP))
+ /* if we have an OpenPGP certificate we assume an
+ * OpenPGP peer and have to send the Vendor ID
+ */
+ if (c->spd.this.cert.type == CERT_PGP)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody, VID_OPENPGP))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* Announce our ability to do eXtended AUTHentication to the peer */
- if (SEND_XAUTH_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_MISC_XAUTH))
+ /* Announce our ability to do eXtended AUTHentication to the peer */
+ if (SEND_XAUTH_VID)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody, VID_MISC_XAUTH))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* Announce our ability to do Dead Peer Detection to the peer */
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_MISC_DPD))
+ /* Announce our ability to do Dead Peer Detection to the peer */
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody, VID_MISC_DPD))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- if (nat_traversal_enabled)
- {
- /* Add supported NAT-Traversal VID */
- if (!nat_traversal_add_vid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody))
+ if (nat_traversal_enabled)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ /* Add supported NAT-Traversal VID */
+ if (!nat_traversal_add_vid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
-
- close_message(&rbody);
- close_output_pbs(&reply);
- clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply)
- , "reply packet for main_outI1");
+ close_message(&rbody);
+ close_output_pbs(&reply);
+ st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply));
+ st->st_tpacket = chunk_clone(st->st_tpacket);
- /* Transmit */
+ /* Transmit */
- send_packet(st, "main_outI1");
+ send_packet(st, "main_outI1");
- /* Set up a retransmission event, half a minute henceforth */
- delete_event(st);
- event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
+ /* Set up a retransmission event, half a minute henceforth */
+ delete_event(st);
+ event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
- if (predecessor != NULL)
- {
- update_pending(predecessor, st);
- whack_log(RC_NEW_STATE + STATE_MAIN_I1
- , "%s: initiate, replacing #%lu"
- , enum_name(&state_names, st->st_state)
- , predecessor->st_serialno);
- }
- else
- {
- whack_log(RC_NEW_STATE + STATE_MAIN_I1
- , "%s: initiate", enum_name(&state_names, st->st_state));
- }
- reset_cur_state();
- return STF_OK;
+ if (predecessor != NULL)
+ {
+ update_pending(predecessor, st);
+ whack_log(RC_NEW_STATE + STATE_MAIN_I1
+ , "%s: initiate, replacing #%lu"
+ , enum_name(&state_names, st->st_state)
+ , predecessor->st_serialno);
+ }
+ else
+ {
+ whack_log(RC_NEW_STATE + STATE_MAIN_I1
+ , "%s: initiate", enum_name(&state_names, st->st_state));
+ }
+ reset_cur_state();
+ return STF_OK;
}
-void
-ipsecdoi_initiate(int whack_sock
-, struct connection *c
-, lset_t policy
-, unsigned long try
-, so_serial_t replacing)
+void ipsecdoi_initiate(int whack_sock, struct connection *c, lset_t policy,
+ unsigned long try, so_serial_t replacing)
{
- /* If there's already an ISAKMP SA established, use that and
- * go directly to Quick Mode. We are even willing to use one
- * that is still being negotiated, but only if we are the Initiator
- * (thus we can be sure that the IDs are not going to change;
- * other issues around intent might matter).
- * Note: there is no way to initiate with a Road Warrior.
- */
- struct state *st = find_phase1_state(c
- , ISAKMP_SA_ESTABLISHED_STATES | PHASE1_INITIATOR_STATES);
-
- if (st == NULL)
- {
- (void) main_outI1(whack_sock, c, NULL, policy, try);
- }
- else if (HAS_IPSEC_POLICY(policy))
- {
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ /* If there's already an ISAKMP SA established, use that and
+ * go directly to Quick Mode. We are even willing to use one
+ * that is still being negotiated, but only if we are the Initiator
+ * (thus we can be sure that the IDs are not going to change;
+ * other issues around intent might matter).
+ * Note: there is no way to initiate with a Road Warrior.
+ */
+ struct state *st = find_phase1_state(c
+ , ISAKMP_SA_ESTABLISHED_STATES | PHASE1_INITIATOR_STATES);
+
+ if (st == NULL)
+ {
+ (void) main_outI1(whack_sock, c, NULL, policy, try);
+ }
+ else if (HAS_IPSEC_POLICY(policy))
{
- /* leave our Phase 2 negotiation pending */
- add_pending(whack_sock, st, c, policy, try, replacing);
+ if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ /* leave our Phase 2 negotiation pending */
+ add_pending(whack_sock, st, c, policy, try, replacing);
+ }
+ else
+ {
+ /* ??? we assume that peer_nexthop_sin isn't important:
+ * we already have it from when we negotiated the ISAKMP SA!
+ * It isn't clear what to do with the error return.
+ */
+ (void) quick_outI1(whack_sock, st, c, policy, try, replacing);
+ }
}
else
{
- /* ??? we assume that peer_nexthop_sin isn't important:
- * we already have it from when we negotiated the ISAKMP SA!
- * It isn't clear what to do with the error return.
- */
- (void) quick_outI1(whack_sock, st, c, policy, try, replacing);
- }
- }
- else
- {
- close_any(whack_sock);
- }
+ close_any(whack_sock);
+ }
}
/* Replace SA with a fresh one that is similar
@@ -1115,221 +1090,264 @@ ipsecdoi_initiate(int whack_sock
* - duplicate whack fd, if live.
* Does not delete the old state -- someone else will do that.
*/
-void
-ipsecdoi_replace(struct state *st, unsigned long try)
+void ipsecdoi_replace(struct state *st, unsigned long try)
{
- int whack_sock = dup_any(st->st_whack_sock);
- lset_t policy = st->st_policy;
-
- if (IS_PHASE1(st->st_state))
- {
- passert(!HAS_IPSEC_POLICY(policy));
- (void) main_outI1(whack_sock, st->st_connection, st, policy, try);
- }
- else
- {
- /* Add features of actual old state to policy. This ensures
- * that rekeying doesn't downgrade security. I admit that
- * this doesn't capture everything.
- */
- if (st->st_pfs_group != NULL)
- policy |= POLICY_PFS;
- if (st->st_ah.present)
- {
- policy |= POLICY_AUTHENTICATE;
- if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- policy |= POLICY_TUNNEL;
- }
- if (st->st_esp.present && st->st_esp.attrs.transid != ESP_NULL)
+ int whack_sock = dup_any(st->st_whack_sock);
+ lset_t policy = st->st_policy;
+
+ if (IS_PHASE1(st->st_state))
{
- policy |= POLICY_ENCRYPT;
- if (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- policy |= POLICY_TUNNEL;
+ passert(!HAS_IPSEC_POLICY(policy));
+ (void) main_outI1(whack_sock, st->st_connection, st, policy, try);
}
- if (st->st_ipcomp.present)
+ else
{
- policy |= POLICY_COMPRESS;
- if (st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- policy |= POLICY_TUNNEL;
+ /* Add features of actual old state to policy. This ensures
+ * that rekeying doesn't downgrade security. I admit that
+ * this doesn't capture everything.
+ */
+ if (st->st_pfs_group != NULL)
+ policy |= POLICY_PFS;
+ if (st->st_ah.present)
+ {
+ policy |= POLICY_AUTHENTICATE;
+ if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ policy |= POLICY_TUNNEL;
+ }
+ if (st->st_esp.present && st->st_esp.attrs.transid != ESP_NULL)
+ {
+ policy |= POLICY_ENCRYPT;
+ if (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ policy |= POLICY_TUNNEL;
+ }
+ if (st->st_ipcomp.present)
+ {
+ policy |= POLICY_COMPRESS;
+ if (st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ policy |= POLICY_TUNNEL;
+ }
+ passert(HAS_IPSEC_POLICY(policy));
+ ipsecdoi_initiate(whack_sock, st->st_connection, policy, try
+ , st->st_serialno);
}
- passert(HAS_IPSEC_POLICY(policy));
- ipsecdoi_initiate(whack_sock, st->st_connection, policy, try
- , st->st_serialno);
- }
}
/* SKEYID for preshared keys.
* See draft-ietf-ipsec-ike-01.txt 4.1
*/
-static bool
-skeyid_preshared(struct state *st)
+static bool skeyid_preshared(struct state *st)
{
- const chunk_t *pss = get_preshared_secret(st->st_connection);
+ const chunk_t *pss = get_preshared_secret(st->st_connection);
- if (pss == NULL)
- {
- loglog(RC_LOG_SERIOUS, "preshared secret disappeared!");
- return FALSE;
- }
- else
- {
- struct hmac_ctx ctx;
-
- hmac_init_chunk(&ctx, st->st_oakley.hasher, *pss);
- hmac_update_chunk(&ctx, st->st_ni);
- hmac_update_chunk(&ctx, st->st_nr);
- hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_preshared()", &ctx);
- return TRUE;
- }
+ if (pss == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "preshared secret disappeared!");
+ return FALSE;
+ }
+ else
+ {
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ if (prf == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
+ pseudo_random_function_names, prf_alg);
+ return FALSE;
+ }
+ free(st->st_skeyid.ptr);
+ prf->set_key(prf, *pss);
+ prf->allocate_bytes(prf, st->st_ni, NULL);
+ prf->allocate_bytes(prf, st->st_nr, &st->st_skeyid);
+ prf->destroy(prf);
+ return TRUE;
+ }
}
static bool
skeyid_digisig(struct state *st)
{
- struct hmac_ctx ctx;
- chunk_t nir;
-
- /* We need to hmac_init with the concatenation of Ni_b and Nr_b,
- * so we have to build a temporary concatentation.
- */
- nir.len = st->st_ni.len + st->st_nr.len;
- nir.ptr = alloc_bytes(nir.len, "Ni + Nr in skeyid_digisig");
- memcpy(nir.ptr, st->st_ni.ptr, st->st_ni.len);
- memcpy(nir.ptr+st->st_ni.len, st->st_nr.ptr, st->st_nr.len);
- hmac_init_chunk(&ctx, st->st_oakley.hasher, nir);
- pfree(nir.ptr);
-
- hmac_update_chunk(&ctx, st->st_shared);
- hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_digisig()", &ctx);
- return TRUE;
+ chunk_t nir;
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ if (prf == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
+ pseudo_random_function_names, prf_alg);
+ return FALSE;
+ }
+ free(st->st_skeyid.ptr);
+ nir = chunk_cat("cc", st->st_ni, st->st_nr);
+ prf->set_key(prf, nir);
+ prf->allocate_bytes(prf, st->st_shared, &st->st_skeyid);
+ prf->destroy(prf);
+ free(nir.ptr);
+ return TRUE;
}
/* Generate the SKEYID_* and new IV
* See draft-ietf-ipsec-ike-01.txt 4.1
*/
-static bool
-generate_skeyids_iv(struct state *st)
+static bool generate_skeyids_iv(struct state *st)
{
- /* Generate the SKEYID */
- switch (st->st_oakley.auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- if (!skeyid_preshared(st))
- return FALSE;
- break;
+ /* Generate the SKEYID */
+ switch (st->st_oakley.auth)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ if (!skeyid_preshared(st))
+ {
+ return FALSE;
+ }
+ break;
- case OAKLEY_RSA_SIG:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- if (!skeyid_digisig(st))
- return FALSE;
- break;
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ if (!skeyid_digisig(st))
+ {
+ return FALSE;
+ }
+ break;
- case OAKLEY_DSS_SIG:
- /* XXX */
+ case OAKLEY_DSS_SIG:
+ /* XXX */
- case OAKLEY_RSA_ENC:
- case OAKLEY_RSA_ENC_REV:
- case OAKLEY_ELGAMAL_ENC:
- case OAKLEY_ELGAMAL_ENC_REV:
- /* XXX */
+ case OAKLEY_RSA_ENC:
+ case OAKLEY_RSA_ENC_REV:
+ case OAKLEY_ELGAMAL_ENC:
+ case OAKLEY_ELGAMAL_ENC_REV:
+ /* XXX */
- default:
- bad_case(st->st_oakley.auth);
- }
-
- /* generate SKEYID_* from SKEYID */
- {
- struct hmac_ctx ctx;
-
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid);
-
- /* SKEYID_D */
- hmac_update_chunk(&ctx, st->st_shared);
- hmac_update(&ctx, st->st_icookie, COOKIE_SIZE);
- hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE);
- hmac_update(&ctx, "\0", 1);
- hmac_final_chunk(st->st_skeyid_d, "st_skeyid_d in generate_skeyids_iv()", &ctx);
-
- /* SKEYID_A */
- hmac_reinit(&ctx);
- hmac_update_chunk(&ctx, st->st_skeyid_d);
- hmac_update_chunk(&ctx, st->st_shared);
- hmac_update(&ctx, st->st_icookie, COOKIE_SIZE);
- hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE);
- hmac_update(&ctx, "\1", 1);
- hmac_final_chunk(st->st_skeyid_a, "st_skeyid_a in generate_skeyids_iv()", &ctx);
-
- /* SKEYID_E */
- hmac_reinit(&ctx);
- hmac_update_chunk(&ctx, st->st_skeyid_a);
- hmac_update_chunk(&ctx, st->st_shared);
- hmac_update(&ctx, st->st_icookie, COOKIE_SIZE);
- hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE);
- hmac_update(&ctx, "\2", 1);
- hmac_final_chunk(st->st_skeyid_e, "st_skeyid_e in generate_skeyids_iv()", &ctx);
- }
-
- /* generate IV */
- {
- union hash_ctx hash_ctx;
- const struct hash_desc *h = st->st_oakley.hasher;
-
- st->st_new_iv_len = h->hash_digest_size;
- passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
+ default:
+ bad_case(st->st_oakley.auth);
+ }
+
+ /* generate SKEYID_* from SKEYID */
+ {
+ char buf_skeyid_d[] = { 0x00 };
+ char buf_skeyid_a[] = { 0x01 };
+ char buf_skeyid_e[] = { 0x02 };
+ chunk_t seed_skeyid_d = chunk_from_buf(buf_skeyid_d);
+ chunk_t seed_skeyid_a = chunk_from_buf(buf_skeyid_a);
+ chunk_t seed_skeyid_e = chunk_from_buf(buf_skeyid_e);
+ chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
+ chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE };
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid);
+
+ /* SKEYID_D */
+ free(st->st_skeyid_d.ptr);
+ prf->allocate_bytes(prf, st->st_shared, NULL);
+ prf->allocate_bytes(prf, icookie, NULL);
+ prf->allocate_bytes(prf, rcookie, NULL);
+ prf->allocate_bytes(prf, seed_skeyid_d, &st->st_skeyid_d);
+
+ /* SKEYID_A */
+ free(st->st_skeyid_a.ptr);
+ prf->allocate_bytes(prf, st->st_skeyid_d, NULL);
+ prf->allocate_bytes(prf, st->st_shared, NULL);
+ prf->allocate_bytes(prf, icookie, NULL);
+ prf->allocate_bytes(prf, rcookie, NULL);
+ prf->allocate_bytes(prf, seed_skeyid_a, &st->st_skeyid_a);
+
+ /* SKEYID_E */
+ free(st->st_skeyid_e.ptr);
+ prf->allocate_bytes(prf, st->st_skeyid_a, NULL);
+ prf->allocate_bytes(prf, st->st_shared, NULL);
+ prf->allocate_bytes(prf, icookie, NULL);
+ prf->allocate_bytes(prf, rcookie, NULL);
+ prf->allocate_bytes(prf, seed_skeyid_e, &st->st_skeyid_e);
+
+ prf->destroy(prf);
+ }
+
+ /* generate IV */
+ {
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+
+ hash_alg = oakley_to_hash_algorithm(st->st_oakley.hash);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ st->st_new_iv_len = hasher->get_hash_size(hasher);
+ passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
+
+ DBG(DBG_CRYPT,
+ DBG_dump_chunk("DH_i:", st->st_gi);
+ DBG_dump_chunk("DH_r:", st->st_gr);
+ );
+
+ hasher->get_hash(hasher, st->st_gi, NULL);
+ hasher->get_hash(hasher, st->st_gr, st->st_new_iv);
+ hasher->destroy(hasher);
+ }
+
+ /* Oakley Keying Material
+ * Derived from Skeyid_e: if it is not big enough, generate more
+ * using the PRF.
+ * See RFC 2409 "IKE" Appendix B
+ */
+ {
+ size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE;
+
+ /* free any existing key */
+ free(st->st_enc_key.ptr);
+
+ if (keysize > st->st_skeyid_e.len)
+ {
+ u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN];
+ char seed_buf[] = { 0x00 };
+ chunk_t seed = chunk_from_buf(seed_buf);
+ size_t prf_block_size, i;
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid_e);
+ prf_block_size = prf->get_block_size(prf);
+
+ for (i = 0;;)
+ {
+ prf->get_bytes(prf, seed, &keytemp[i]);
+ i += prf_block_size;
+ if (i >= keysize)
+ {
+ break;
+ }
+ seed = chunk_create(&keytemp[i-prf_block_size], prf_block_size);
+ }
+ prf->destroy(prf);
+ st->st_enc_key = chunk_create(keytemp, keysize);
+ }
+ else
+ {
+ st->st_enc_key = chunk_create(st->st_skeyid_e.ptr, keysize);
+ }
+ st->st_enc_key = chunk_clone(st->st_enc_key);
+ }
- DBG(DBG_CRYPT,
- DBG_dump_chunk("DH_i:", st->st_gi);
- DBG_dump_chunk("DH_r:", st->st_gr);
- );
- h->hash_init(&hash_ctx);
- h->hash_update(&hash_ctx, st->st_gi.ptr, st->st_gi.len);
- h->hash_update(&hash_ctx, st->st_gr.ptr, st->st_gr.len);
- h->hash_final(st->st_new_iv, &hash_ctx);
- }
-
- /* Oakley Keying Material
- * Derived from Skeyid_e: if it is not big enough, generate more
- * using the PRF.
- * See RFC 2409 "IKE" Appendix B
- */
- {
- /* const size_t keysize = st->st_oakley.encrypter->keydeflen/BITS_PER_BYTE; */
- const size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE;
- u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN];
- u_char *k = st->st_skeyid_e.ptr;
-
- if (keysize > st->st_skeyid_e.len)
- {
- struct hmac_ctx ctx;
- size_t i = 0;
-
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_e);
- hmac_update(&ctx, "\0", 1);
- for (;;)
- {
- hmac_final(&keytemp[i], &ctx);
- i += ctx.hmac_digest_size;
- if (i >= keysize)
- break;
- hmac_reinit(&ctx);
- hmac_update(&ctx, &keytemp[i - ctx.hmac_digest_size], ctx.hmac_digest_size);
- }
- k = keytemp;
- }
- clonereplacechunk(st->st_enc_key, k, keysize, "st_enc_key");
- }
-
- DBG(DBG_CRYPT,
- DBG_dump_chunk("Skeyid: ", st->st_skeyid);
- DBG_dump_chunk("Skeyid_d:", st->st_skeyid_d);
- DBG_dump_chunk("Skeyid_a:", st->st_skeyid_a);
- DBG_dump_chunk("Skeyid_e:", st->st_skeyid_e);
- DBG_dump_chunk("enc key:", st->st_enc_key);
- DBG_dump("IV:", st->st_new_iv, st->st_new_iv_len));
- return TRUE;
+ DBG(DBG_CRYPT,
+ DBG_dump_chunk("Skeyid: ", st->st_skeyid);
+ DBG_dump_chunk("Skeyid_d:", st->st_skeyid_d);
+ DBG_dump_chunk("Skeyid_a:", st->st_skeyid_a);
+ DBG_dump_chunk("Skeyid_e:", st->st_skeyid_e);
+ DBG_dump_chunk("enc key:", st->st_enc_key);
+ DBG_dump("IV:", st->st_new_iv, st->st_new_iv_len));
+ return TRUE;
}
/* Generate HASH_I or HASH_R for ISAKMP Phase I.
@@ -1338,288 +1356,126 @@ generate_skeyids_iv(struct state *st)
* If the hashi argument is TRUE, generate HASH_I; if FALSE generate HASH_R.
* If hashus argument is TRUE, we're generating a hash for our end.
* See RFC2409 IKE 5.
- *
- * Generating the SIG_I and SIG_R for DSS is an odd perversion of this:
- * Most of the logic is the same, but SHA-1 is used in place of HMAC-whatever.
- * The extensive common logic is embodied in main_mode_hash_body().
- * See draft-ietf-ipsec-ike-01.txt 4.1 and 6.1.1.2
*/
-
-typedef void (*hash_update_t)(union hash_ctx *, const u_char *, size_t) ;
-static void
-main_mode_hash_body(struct state *st
-, bool hashi /* Initiator? */
-, const pb_stream *idpl /* ID payload, as PBS */
-, union hash_ctx *ctx
-, void (*hash_update_void)(void *, const u_char *input, size_t))
+ static void main_mode_hash(struct state *st, chunk_t *hash, bool hashi,
+ const pb_stream *idpl)
{
-#define HASH_UPDATE_T (union hash_ctx *, const u_char *input, unsigned int len)
- hash_update_t hash_update=(hash_update_t) hash_update_void;
-#if 0 /* if desperate to debug hashing */
-# define hash_update(ctx, input, len) { \
- DBG_dump("hash input", input, len); \
- (hash_update)(ctx, input, len); \
+ chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
+ chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE };
+ chunk_t sa_body = { st->st_p1isa.ptr + sizeof(struct isakmp_generic),
+ st->st_p1isa.len - sizeof(struct isakmp_generic) };
+ chunk_t id_body = { idpl->start + sizeof(struct isakmp_generic),
+ pbs_offset(idpl) - sizeof(struct isakmp_generic) };
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ switch (st->st_oakley.auth)
+ {
+ case OAKLEY_ECDSA_256:
+ prf_alg = PRF_HMAC_SHA2_256;
+ break;
+ case OAKLEY_ECDSA_384:
+ prf_alg = PRF_HMAC_SHA2_384;
+ break;
+ case OAKLEY_ECDSA_521:
+ prf_alg = PRF_HMAC_SHA2_512;
+ break;
+ default:
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
}
-#endif
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid);
-# define hash_update_chunk(ctx, ch) hash_update((ctx), (ch).ptr, (ch).len)
-
- if (hashi)
- {
- hash_update_chunk(ctx, st->st_gi);
- hash_update_chunk(ctx, st->st_gr);
- hash_update(ctx, st->st_icookie, COOKIE_SIZE);
- hash_update(ctx, st->st_rcookie, COOKIE_SIZE);
- }
- else
- {
- hash_update_chunk(ctx, st->st_gr);
- hash_update_chunk(ctx, st->st_gi);
- hash_update(ctx, st->st_rcookie, COOKIE_SIZE);
- hash_update(ctx, st->st_icookie, COOKIE_SIZE);
- }
-
- DBG(DBG_CRYPT, DBG_log("hashing %lu bytes of SA"
- , (unsigned long) (st->st_p1isa.len - sizeof(struct isakmp_generic))));
-
- /* SA_b */
- hash_update(ctx, st->st_p1isa.ptr + sizeof(struct isakmp_generic)
- , st->st_p1isa.len - sizeof(struct isakmp_generic));
-
- /* Hash identification payload, without generic payload header.
- * We used to reconstruct ID Payload for this purpose, but now
- * we use the bytes as they appear on the wire to avoid
- * "spelling problems".
- */
- hash_update(ctx
- , idpl->start + sizeof(struct isakmp_generic)
- , pbs_offset(idpl) - sizeof(struct isakmp_generic));
-
-# undef hash_update_chunk
-# undef hash_update
-}
-
-static size_t /* length of hash */
-main_mode_hash(struct state *st
-, u_char *hash_val /* resulting bytes */
-, bool hashi /* Initiator? */
-, const pb_stream *idpl) /* ID payload, as PBS; cur must be at end */
-{
- struct hmac_ctx ctx;
-
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid);
- main_mode_hash_body(st, hashi, idpl, &ctx.hash_ctx, ctx.h->hash_update);
- hmac_final(hash_val, &ctx);
- return ctx.hmac_digest_size;
-}
-
-#if 0 /* only needed for DSS */
-static void
-main_mode_sha1(struct state *st
-, u_char *hash_val /* resulting bytes */
-, size_t *hash_len /* length of hash */
-, bool hashi /* Initiator? */
-, const pb_stream *idpl) /* ID payload, as PBS */
-{
- union hash_ctx ctx;
-
- SHA1Init(&ctx.ctx_sha1);
- SHA1Update(&ctx.ctx_sha1, st->st_skeyid.ptr, st->st_skeyid.len);
- *hash_len = SHA1_DIGEST_SIZE;
- main_mode_hash_body(st, hashi, idpl, &ctx
- , (void (*)(union hash_ctx *, const u_char *, unsigned int))&SHA1Update);
- SHA1Final(hash_val, &ctx.ctx_sha1);
-}
-#endif
-
-/* Create an RSA signature of a hash.
- * Poorly specified in draft-ietf-ipsec-ike-01.txt 6.1.1.2.
- * Use PKCS#1 version 1.5 encryption of hash (called
- * RSAES-PKCS1-V1_5) in PKCS#2.
- */
-static size_t
-RSA_sign_hash(struct connection *c
-, u_char sig_val[RSA_MAX_OCTETS]
-, const u_char *hash_val, size_t hash_len)
-{
- size_t sz = 0;
- smartcard_t *sc = c->spd.this.sc;
-
- if (sc == NULL) /* no smartcard */
- {
- const struct RSA_private_key *k = get_RSA_private_key(c);
-
- if (k == NULL)
- return 0; /* failure: no key to use */
-
- sz = k->pub.k;
- passert(RSA_MIN_OCTETS <= sz && 4 + hash_len < sz && sz <= RSA_MAX_OCTETS);
- sign_hash(k, hash_val, hash_len, sig_val, sz);
- }
- else if (sc->valid) /* if valid pin then sign hash on the smartcard */
- {
- lock_certs_and_keys("RSA_sign_hash");
- if (!scx_establish_context(sc) || !scx_login(sc))
+ if (hashi)
{
- scx_release_context(sc);
- unlock_certs_and_keys("RSA_sign_hash");
- return 0;
+ prf->get_bytes(prf, st->st_gi, NULL);
+ prf->get_bytes(prf, st->st_gr, NULL);
+ prf->get_bytes(prf, icookie, NULL);
+ prf->get_bytes(prf, rcookie, NULL);
}
-
- sz = scx_get_keylength(sc);
- if (sz == 0)
+ else
{
- plog("failed to get keylength from smartcard");
- scx_release_context(sc);
- unlock_certs_and_keys("RSA_sign_hash");
- return 0;
+ prf->get_bytes(prf, st->st_gr, NULL);
+ prf->get_bytes(prf, st->st_gi, NULL);
+ prf->get_bytes(prf, rcookie, NULL);
+ prf->get_bytes(prf, icookie, NULL);
}
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
+ DBG(DBG_CRYPT,
+ DBG_log("hashing %u bytes of SA", sa_body.len)
)
- sz = scx_sign_hash(sc, hash_val, hash_len, sig_val, sz) ? sz : 0;
- if (!pkcs11_keep_state)
- scx_release_context(sc);
- unlock_certs_and_keys("RSA_sign_hash");
- }
- return sz;
+ prf->get_bytes(prf, sa_body, NULL);
+
+ /* Hash identification payload, without generic payload header.
+ * We used to reconstruct ID Payload for this purpose, but now
+ * we use the bytes as they appear on the wire to avoid
+ * "spelling problems".
+ */
+ prf->get_bytes(prf, id_body, hash->ptr);
+ hash->len = prf->get_block_size(prf);
+ prf->destroy(prf);
}
-/* Check a Main Mode RSA Signature against computed hash using RSA public key k.
- *
- * As a side effect, on success, the public key is copied into the
- * state object to record the authenticator.
- *
- * Can fail because wrong public key is used or because hash disagrees.
- * We distinguish because diagnostics should also.
- *
- * The result is NULL if the Signature checked out.
- * Otherwise, the first character of the result indicates
- * how far along failure occurred. A greater character signifies
- * greater progress.
- *
- * Classes:
- * 0 reserved for caller
- * 1 SIG length doesn't match key length -- wrong key
- * 2-8 malformed ECB after decryption -- probably wrong key
- * 9 decrypted hash != computed hash -- probably correct key
- *
- * Although the math should be the same for generating and checking signatures,
- * it is not: the knowledge of the private key allows more efficient (i.e.
- * different) computation for encryption.
+/* Create a public key signature of a hash.
+ * Poorly specified in draft-ietf-ipsec-ike-01.txt 6.1.1.2.
+ * Use PKCS#1 version 1.5 encryption of hash (called
+ * RSAES-PKCS1-V1_5) in PKCS#2.
*/
-static err_t
-try_RSA_signature(const u_char hash_val[MAX_DIGEST_LEN], size_t hash_len
-, const pb_stream *sig_pbs, pubkey_t *kr
-, struct state *st)
+static size_t sign_hash(signature_scheme_t scheme, struct connection *c,
+ u_char sig_val[RSA_MAX_OCTETS], chunk_t hash)
{
- const u_char *sig_val = sig_pbs->cur;
- size_t sig_len = pbs_left(sig_pbs);
- u_char s[RSA_MAX_OCTETS]; /* for decrypted sig_val */
- u_char *hash_in_s = &s[sig_len - hash_len];
- const struct RSA_public_key *k = &kr->u.rsa;
-
- /* decrypt the signature -- reversing RSA_sign_hash */
- if (sig_len != k->k)
- {
- /* XXX notification: INVALID_KEY_INFORMATION */
- return "1" "SIG length does not match public key length";
- }
-
- /* actual exponentiation; see PKCS#1 v2.0 5.1 */
- {
- chunk_t temp_s;
- mpz_t c;
-
- n_to_mpz(c, sig_val, sig_len);
- mpz_powm(c, c, &k->e, &k->n);
-
- temp_s = mpz_to_n(c, sig_len); /* back to octets */
- memcpy(s, temp_s.ptr, sig_len);
- pfree(temp_s.ptr);
- mpz_clear(c);
- }
-
- /* sanity check on signature: see if it matches
- * PKCS#1 v1.5 8.1 encryption-block formatting
- */
- {
- err_t ugh = NULL;
+ size_t sz = 0;
+ smartcard_t *sc = c->spd.this.sc;
- if (s[0] != 0x00)
- ugh = "2" "no leading 00";
- else if (hash_in_s[-1] != 0x00)
- ugh = "3" "00 separator not present";
- else if (s[1] == 0x01)
+ if (sc == NULL) /* no smartcard */
{
- const u_char *p;
+ chunk_t sig;
+ private_key_t *private = get_private_key(c);
- for (p = &s[2]; p != hash_in_s - 1; p++)
- {
- if (*p != 0xFF)
+ if (private == NULL)
{
- ugh = "4" "invalid Padding String";
- break;
+ return 0; /* failure: no key to use */
}
- }
+ if (!private->sign(private, scheme, hash, &sig))
+ {
+ return 0;
+ }
+ memcpy(sig_val, sig.ptr, sig.len);
+ sz = sig.len;
+ free(sig.ptr);
}
- else if (s[1] == 0x02)
+ else if (sc->valid) /* if valid pin then sign hash on the smartcard */
{
- const u_char *p;
+ lock_certs_and_keys("sign_hash");
+ if (!scx_establish_context(sc) || !scx_login(sc))
+ {
+ scx_release_context(sc);
+ unlock_certs_and_keys("sign_hash");
+ return 0;
+ }
- for (p = &s[2]; p != hash_in_s - 1; p++)
- {
- if (*p == 0x00)
+ sz = scx_get_keylength(sc);
+ if (sz == 0)
{
- ugh = "5" "invalid Padding String";
- break;
+ plog("failed to get keylength from smartcard");
+ scx_release_context(sc);
+ unlock_certs_and_keys("sign_hash");
+ return 0;
}
- }
- }
- else
- ugh = "6" "Block Type not 01 or 02";
- if (ugh != NULL)
- {
- /* note: it might be a good idea to make sure that
- * an observer cannot tell what kind of failure happened.
- * I don't know what this means in practice.
- */
- /* We probably selected the wrong public key for peer:
- * SIG Payload decrypted into malformed ECB
- */
- /* XXX notification: INVALID_KEY_INFORMATION */
- return ugh;
- }
- }
-
- /* We have the decoded hash: see if it matches. */
- if (memcmp(hash_val, hash_in_s, hash_len) != 0)
- {
- /* good: header, hash, signature, and other payloads well-formed
- * good: we could find an RSA Sig key for the peer.
- * bad: hash doesn't match
- * Guess: sides disagree about key to be used.
- */
- DBG_cond_dump(DBG_CRYPT, "decrypted SIG", s, sig_len);
- DBG_cond_dump(DBG_CRYPT, "computed HASH", hash_val, hash_len);
- /* XXX notification: INVALID_HASH_INFORMATION */
- return "9" "authentication failure: received SIG does not match computed HASH, but message is well-formed";
- }
-
- /* Success: copy successful key into state.
- * There might be an old one if we previously aborted this
- * state transition.
- */
- unreference_key(&st->st_peer_pubkey);
- st->st_peer_pubkey = reference_key(kr);
-
- return NULL; /* happy happy */
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("signing hash with private key from smartcard (slot: %d, id: %s)"
+ , (int)sc->slot, sc->id)
+ )
+ sz = scx_sign_hash(sc, hash.ptr, hash.len, sig_val, sz) ? sz : 0;
+ if (!pkcs11_keep_state)
+ scx_release_context(sc);
+ unlock_certs_and_keys("sign_hash");
+ }
+ return sz;
}
-/* Check signature against all RSA public keys we can find.
+/* Check signature against all public keys we can find.
* If we need keys from DNS KEY records, and they haven't been fetched,
* return STF_SUSPEND to ask for asynch DNS lookup.
*
@@ -1630,227 +1486,195 @@ try_RSA_signature(const u_char hash_val[MAX_DIGEST_LEN], size_t hash_len
* If only we had coroutines.
*/
struct tac_state {
- /* RSA_check_signature's args that take_a_crack needs */
- struct state *st;
- const u_char *hash_val;
- size_t hash_len;
- const pb_stream *sig_pbs;
-
- /* state carried between calls */
- err_t best_ugh; /* most successful failure */
- int tried_cnt; /* number of keys tried */
- char tried[50]; /* keyids of tried public keys */
- char *tn; /* roof of tried[] */
+ struct state *st;
+ chunk_t hash;
+ chunk_t sig;
+ int tried_cnt; /* number of keys tried */
};
-static bool
-take_a_crack(struct tac_state *s
-, pubkey_t *kr
-, const char *story USED_BY_DEBUG)
+static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
{
- err_t ugh = try_RSA_signature(s->hash_val, s->hash_len, s->sig_pbs
- , kr, s->st);
- const struct RSA_public_key *k = &kr->u.rsa;
-
- s->tried_cnt++;
- if (ugh == NULL)
- {
- DBG(DBG_CRYPT | DBG_CONTROL
- , DBG_log("an RSA Sig check passed with *%s [%s]"
- , k->keyid, story));
- return TRUE;
- }
- else
- {
- DBG(DBG_CRYPT
- , DBG_log("an RSA Sig check failure %s with *%s [%s]"
- , ugh + 1, k->keyid, story));
- if (s->best_ugh == NULL || s->best_ugh[0] < ugh[0])
- s->best_ugh = ugh;
- if (ugh[0] > '0'
- && s->tn - s->tried + KEYID_BUF + 2 < (ptrdiff_t)sizeof(s->tried))
- {
- strcpy(s->tn, " *");
- strcpy(s->tn + 2, k->keyid);
- s->tn += strlen(s->tn);
+ public_key_t *pub_key = kr->public_key;
+ identification_t *keyid = pub_key->get_id(pub_key, ID_PUBKEY_INFO_SHA1);
+ signature_scheme_t scheme;
+
+ s->tried_cnt++;
+ scheme = oakley_to_signature_scheme(s->st->st_oakley.auth);
+
+ if (pub_key->verify(pub_key, scheme, s->hash, s->sig))
+ {
+ DBG(DBG_CRYPT | DBG_CONTROL,
+ DBG_log("%s check passed with keyid %Y",
+ enum_show(&oakley_auth_names, s->st->st_oakley.auth), keyid)
+ )
+ unreference_key(&s->st->st_peer_pubkey);
+ s->st->st_peer_pubkey = reference_key(kr);
+ return TRUE;
+ }
+ else
+ {
+ DBG(DBG_CRYPT,
+ DBG_log("%s check failed with keyid %Y",
+ enum_show(&oakley_auth_names, s->st->st_oakley.auth), keyid)
+ )
+ return FALSE;
}
- return FALSE;
- }
}
-static stf_status
-RSA_check_signature(const struct id* peer
-, struct state *st
-, const u_char hash_val[MAX_DIGEST_LEN]
-, size_t hash_len
-, const pb_stream *sig_pbs
+static stf_status check_signature(key_type_t key_type, const struct id* peer,
+ struct state *st, chunk_t hash,
+ const pb_stream *sig_pbs,
#ifdef USE_KEYRR
-, const pubkey_list_t *keys_from_dns
+ const pubkey_list_t *keys_from_dns,
#endif /* USE_KEYRR */
-, const struct gw_info *gateways_from_dns
-)
+ const struct gw_info *gateways_from_dns)
{
- const struct connection *c = st->st_connection;
- struct tac_state s;
- err_t dns_ugh = NULL;
-
- s.st = st;
- s.hash_val = hash_val;
- s.hash_len = hash_len;
- s.sig_pbs = sig_pbs;
-
- s.best_ugh = NULL;
- s.tried_cnt = 0;
- s.tn = s.tried;
-
- /* try all gateway records hung off c */
- if (c->policy & POLICY_OPPO)
- {
- struct gw_info *gw;
-
- for (gw = c->gw_info; gw != NULL; gw = gw->next)
- {
- /* only consider entries that have a key and are for our peer */
- if (gw->gw_key_present
- && same_id(&gw->gw_id, &c->spd.that.id)
- && take_a_crack(&s, gw->key, "key saved from DNS TXT"))
- return STF_OK;
- }
- }
+ const struct connection *c = st->st_connection;
+ struct tac_state s;
- /* try all appropriate Public keys */
- {
- pubkey_list_t *p, **pp;
+ s.st = st;
+ s.hash = hash;
+ s.sig = chunk_create(sig_pbs->cur, pbs_left(sig_pbs));
+ s.tried_cnt = 0;
- pp = &pubkeys;
+ /* try all gateway records hung off c */
+ if (c->policy & POLICY_OPPO)
+ {
+ struct gw_info *gw;
- for (p = pubkeys; p != NULL; p = *pp)
+ for (gw = c->gw_info; gw != NULL; gw = gw->next)
+ {
+ /* only consider entries that have a key and are for our peer */
+ if (gw->gw_key_present && same_id(&gw->gw_id, &c->spd.that.id)&&
+ take_a_crack(&s, gw->key))
+ {
+ return STF_OK;
+ }
+ }
+ }
+
+ /* try all appropriate Public keys */
{
- pubkey_t *key = p->key;
+ pubkey_list_t *p, **pp;
- if (key->alg == PUBKEY_ALG_RSA && same_id(peer, &key->id))
- {
- time_t now = time(NULL);
+ pp = &pubkeys;
- /* check if found public key has expired */
- if (key->until_time != UNDEFINED_TIME && key->until_time < now)
+ for (p = pubkeys; p != NULL; p = *pp)
{
- loglog(RC_LOG_SERIOUS,
- "cached RSA public key has expired and has been deleted");
- *pp = free_public_keyentry(p);
- continue; /* continue with next public key */
- }
+ pubkey_t *key = p->key;
+ key_type_t type = key->public_key->get_type(key->public_key);
- if (take_a_crack(&s, key, "preloaded key"))
- return STF_OK;
- }
- pp = &p->next;
- }
+ if (type == key_type && same_id(peer, &key->id))
+ {
+ time_t now = time(NULL);
+
+ /* check if found public key has expired */
+ if (key->until_time != UNDEFINED_TIME && key->until_time < now)
+ {
+ loglog(RC_LOG_SERIOUS,
+ "cached public key has expired and has been deleted");
+ *pp = free_public_keyentry(p);
+ continue; /* continue with next public key */
+ }
+
+ if (take_a_crack(&s, key))
+ {
+ return STF_OK;
+ }
+ }
+ pp = &p->next;
+ }
}
- /* if no key was found (evidenced by best_ugh == NULL)
- * and that side of connection is key_from_DNS_on_demand
- * then go search DNS for keys for peer.
- */
- if (s.best_ugh == NULL && c->spd.that.key_from_DNS_on_demand)
- {
- if (gateways_from_dns != NULL)
+ /* if no key was found and that side of connection is
+ * key_from_DNS_on_demand then go search DNS for keys for peer.
+ */
+ if (s.tried_cnt == 0 && c->spd.that.key_from_DNS_on_demand)
{
- /* TXT keys */
- const struct gw_info *gwp;
+ if (gateways_from_dns != NULL)
+ {
+ /* TXT keys */
+ const struct gw_info *gwp;
- for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
- if (gwp->gw_key_present
- && take_a_crack(&s, gwp->key, "key from DNS TXT"))
- return STF_OK;
- }
+ for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ if (gwp->gw_key_present && take_a_crack(&s, gwp->key))
+ {
+ return STF_OK;
+ }
+ }
+ }
#ifdef USE_KEYRR
- else if (keys_from_dns != NULL)
- {
- /* KEY keys */
- const pubkey_list_t *kr;
+ else if (keys_from_dns != NULL)
+ {
+ /* KEY keys */
+ const pubkey_list_t *kr;
- for (kr = keys_from_dns; kr != NULL; kr = kr->next)
- if (kr->key->alg == PUBKEY_ALG_RSA
- && take_a_crack(&s, kr->key, "key from DNS KEY"))
- return STF_OK;
- }
+ for (kr = keys_from_dns; kr != NULL; kr = kr->next)
+ {
+ if (kr->key->alg == PUBKEY_ALG_RSA && take_a_crack(&s, kr->key))
+ {
+ return STF_OK;
+ }
+ }
+ }
#endif /* USE_KEYRR */
- else
- {
- /* nothing yet: ask for asynch DNS lookup */
- return STF_SUSPEND;
+ else
+ {
+ /* nothing yet: ask for asynch DNS lookup */
+ return STF_SUSPEND;
+ }
}
- }
-
- /* no acceptable key was found: diagnose */
- {
- char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
- (void) idtoa(peer, id_buf, sizeof(id_buf));
-
- if (s.best_ugh == NULL)
+ /* no acceptable key was found: diagnose */
{
- if (dns_ugh == NULL)
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
- , id_buf);
- else
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
- "; DNS search for KEY failed (%s)"
- , id_buf, dns_ugh);
+ char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
- /* ??? is this the best code there is? */
- return STF_FAIL + INVALID_KEY_INFORMATION;
- }
+ idtoa(peer, id_buf, sizeof(id_buf));
- if (s.best_ugh[0] == '9')
- {
- loglog(RC_LOG_SERIOUS, "%s", s.best_ugh + 1);
- /* XXX Could send notification back */
- return STF_FAIL + INVALID_HASH_INFORMATION;
- }
- else
- {
- if (s.tried_cnt == 1)
- {
- loglog(RC_LOG_SERIOUS
- , "Signature check (on %s) failed (wrong key?); tried%s"
- , id_buf, s.tried);
- DBG(DBG_CONTROL,
- DBG_log("public key for %s failed:"
- " decrypted SIG payload into a malformed ECB (%s)"
- , id_buf, s.best_ugh + 1));
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "Signature check (on %s) failed:"
- " tried%s keys but none worked."
- , id_buf, s.tried);
- DBG(DBG_CONTROL,
- DBG_log("all %d public keys for %s failed:"
- " best decrypted SIG payload into a malformed ECB (%s)"
- , s.tried_cnt, id_buf, s.best_ugh + 1));
- }
- return STF_FAIL + INVALID_KEY_INFORMATION;
+ if (s.tried_cnt == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "no public key known for '%s'", id_buf);
+ }
+ else if (s.tried_cnt == 1)
+ {
+ loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
+ " wrong key?; tried %d", id_buf, s.tried_cnt);
+ DBG(DBG_CONTROL,
+ DBG_log("public key for '%s' failed: "
+ "decrypted SIG payload into a malformed ECB", id_buf)
+ )
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
+ "tried %d keys but none worked.", id_buf, s.tried_cnt);
+ DBG(DBG_CONTROL,
+ DBG_log("all %d public keys for '%s' failed: "
+ "best decrypted SIG payload into a malformed ECB",
+ s.tried_cnt, id_buf)
+ )
+ }
+ return STF_FAIL + INVALID_KEY_INFORMATION;
}
- }
}
-static notification_t
-accept_nonce(struct msg_digest *md, chunk_t *dest, const char *name)
+static notification_t accept_nonce(struct msg_digest *md, chunk_t *dest,
+ const char *name)
{
- pb_stream *nonce_pbs = &md->chain[ISAKMP_NEXT_NONCE]->pbs;
- size_t len = pbs_left(nonce_pbs);
-
- if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len)
- {
- loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"
- , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
- return PAYLOAD_MALFORMED; /* ??? */
- }
- clonereplacechunk(*dest, nonce_pbs->cur, len, "nonce");
- return NOTHING_WRONG;
+ pb_stream *nonce_pbs = &md->chain[ISAKMP_NEXT_NONCE]->pbs;
+ size_t len = pbs_left(nonce_pbs);
+
+ if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len)
+ {
+ loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"
+ , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
+ return PAYLOAD_MALFORMED; /* ??? */
+ }
+ free(dest->ptr);
+ *dest = chunk_create(nonce_pbs->cur, len);
+ *dest = chunk_clone(*dest);
+ return NOTHING_WRONG;
}
/* encrypt message, sans fixed part of header
@@ -1861,36 +1685,51 @@ accept_nonce(struct msg_digest *md, chunk_t *dest, const char *name)
bool
encrypt_message(pb_stream *pbs, struct state *st)
{
- const struct encrypt_desc *e = st->st_oakley.encrypter;
- u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr);
- size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr);
-
- DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len);
-
- /* Pad up to multiple of encryption blocksize.
- * See the description associated with the definition of
- * struct isakmp_hdr in packet.h.
- */
- {
- size_t padding = pad_up(enc_len, e->enc_blocksize);
-
- if (padding != 0)
+ u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr);
+ size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr);
+ chunk_t data, iv;
+ char *new_iv;
+ size_t crypter_block_size;
+ encryption_algorithm_t enc_alg;
+ crypter_t *crypter;
+
+ DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len);
+ enc_alg = oakley_to_encryption_algorithm(st->st_oakley.encrypt);
+ crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, st->st_enc_key.len);
+ crypter_block_size = crypter->get_block_size(crypter);
+
+ /* Pad up to multiple of encryption blocksize.
+ * See the description associated with the definition of
+ * struct isakmp_hdr in packet.h.
+ */
{
- if (!out_zero(padding, pbs, "encryption padding"))
- return FALSE;
- enc_len += padding;
+ size_t padding = pad_up(enc_len, crypter_block_size);
+
+ if (padding != 0)
+ {
+ if (!out_zero(padding, pbs, "encryption padding"))
+ return FALSE;
+ enc_len += padding;
+ }
}
- }
- DBG(DBG_CRYPT, DBG_log("encrypting using %s", enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
+ DBG(DBG_CRYPT, DBG_log("encrypting using %s", enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
+ data = chunk_create(enc_start, enc_len);
- /* e->crypt(TRUE, enc_start, enc_len, st); */
- crypto_cbc_encrypt(e, TRUE, enc_start, enc_len, st);
+ /* form iv by truncation */
+ st->st_new_iv_len = crypter_block_size;
+ iv = chunk_create(st->st_new_iv, st->st_new_iv_len);
- update_iv(st);
- DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len);
- close_message(pbs);
- return TRUE;
+ crypter->set_key(crypter, st->st_enc_key);
+ crypter->encrypt(crypter, data, iv, NULL);
+ crypter->destroy(crypter);
+
+ new_iv = data.ptr + data.len - crypter_block_size;
+ memcpy(st->st_new_iv, new_iv, crypter_block_size);
+ update_iv(st);
+ DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len);
+ close_message(pbs);
+ return TRUE;
}
/* Compute HASH(1), HASH(2) of Quick Mode.
@@ -1899,31 +1738,33 @@ encrypt_message(pb_stream *pbs, struct state *st)
* Used by: quick_outI1, quick_inI1_outR1 (twice), quick_inR1_outI2
* (see RFC 2409 "IKE" 5.5, pg. 18 or draft-ietf-ipsec-ike-01.txt 6.2 pg 25)
*/
-static size_t
-quick_mode_hash12(u_char *dest, const u_char *start, const u_char *roof
-, const struct state *st, const msgid_t *msgid, bool hash2)
+static size_t quick_mode_hash12(u_char *dest, u_char *start, u_char *roof,
+ const struct state *st, const msgid_t *msgid,
+ bool hash2)
{
- struct hmac_ctx ctx;
-
-#if 0 /* if desperate to debug hashing */
-# define hmac_update(ctx, ptr, len) { \
- DBG_dump("hash input", (ptr), (len)); \
- (hmac_update)((ctx), (ptr), (len)); \
- }
- DBG_dump("hash key", st->st_skeyid_a.ptr, st->st_skeyid_a.len);
-#endif
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
- hmac_update(&ctx, (const void *) msgid, sizeof(msgid_t));
- if (hash2)
- hmac_update_chunk(&ctx, st->st_ni); /* include Ni_b in the hash */
- hmac_update(&ctx, start, roof-start);
- hmac_final(dest, &ctx);
-
- DBG(DBG_CRYPT,
- DBG_log("HASH(%d) computed:", hash2 + 1);
- DBG_dump("", dest, ctx.hmac_digest_size));
- return ctx.hmac_digest_size;
-# undef hmac_update
+ chunk_t msgid_chunk = chunk_from_thing(*msgid);
+ chunk_t msg_chunk = { start, roof - start };
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+ size_t prf_block_size;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid_a);
+ prf->get_bytes(prf, msgid_chunk, NULL);
+ if (hash2)
+ {
+ prf->get_bytes(prf, st->st_ni, NULL); /* include Ni_b in the hash */
+ }
+ prf->get_bytes(prf, msg_chunk, dest);
+ prf_block_size = prf->get_block_size(prf);
+ prf->destroy(prf);
+
+ DBG(DBG_CRYPT,
+ DBG_log("HASH(%d) computed:", hash2 + 1);
+ DBG_dump("", dest, prf_block_size)
+ )
+ return prf_block_size;
}
/* Compute HASH(3) in Quick Mode (part of Quick I2 message).
@@ -1932,44 +1773,54 @@ quick_mode_hash12(u_char *dest, const u_char *start, const u_char *roof
* NOTE: this hash (unlike HASH(1) and HASH(2)) ONLY covers the
* Message ID and Nonces. This is a mistake.
*/
-static size_t
-quick_mode_hash3(u_char *dest, struct state *st)
+static size_t quick_mode_hash3(u_char *dest, struct state *st)
{
- struct hmac_ctx ctx;
-
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
- hmac_update(&ctx, "\0", 1);
- hmac_update(&ctx, (u_char *) &st->st_msgid, sizeof(st->st_msgid));
- hmac_update_chunk(&ctx, st->st_ni);
- hmac_update_chunk(&ctx, st->st_nr);
- hmac_final(dest, &ctx);
- DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, ctx.hmac_digest_size);
- return ctx.hmac_digest_size;
+ char seed_buf[] = { 0x00 };
+ chunk_t seed_chunk = chunk_from_buf(seed_buf);
+ chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+ size_t prf_block_size;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid_a);
+ prf->get_bytes(prf, seed_chunk, NULL );
+ prf->get_bytes(prf, msgid_chunk, NULL);
+ prf->get_bytes(prf, st->st_ni, NULL);
+ prf->get_bytes(prf, st->st_nr, dest);
+ prf_block_size = prf->get_block_size(prf);
+ prf->destroy(prf);
+
+ DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, prf_block_size);
+ return prf_block_size;
}
/* Compute Phase 2 IV.
* Uses Phase 1 IV from st_iv; puts result in st_new_iv.
*/
-void
-init_phase2_iv(struct state *st, const msgid_t *msgid)
+void init_phase2_iv(struct state *st, const msgid_t *msgid)
{
- const struct hash_desc *h = st->st_oakley.hasher;
- union hash_ctx ctx;
+ chunk_t iv_chunk = { st->st_ph1_iv, st->st_ph1_iv_len };
+ chunk_t msgid_chunk = chunk_from_thing(*msgid);
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
- DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:"
- , st->st_ph1_iv, st->st_ph1_iv_len);
+ hash_alg = oakley_to_hash_algorithm(st->st_oakley.hash);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- st->st_new_iv_len = h->hash_digest_size;
- passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
+ DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:",
+ st->st_ph1_iv, st->st_ph1_iv_len);
- h->hash_init(&ctx);
- h->hash_update(&ctx, st->st_ph1_iv, st->st_ph1_iv_len);
- passert(*msgid != 0);
- h->hash_update(&ctx, (const u_char *)msgid, sizeof(*msgid));
- h->hash_final(st->st_new_iv, &ctx);
+ st->st_new_iv_len = hasher->get_hash_size(hasher);
+ passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
+
+ hasher->get_hash(hasher, iv_chunk, NULL);
+ hasher->get_hash(hasher, msgid_chunk, st->st_new_iv);
+ hasher->destroy(hasher);
- DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:"
- , st->st_new_iv, st->st_new_iv_len);
+ DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:",
+ st->st_new_iv, st->st_new_iv_len);
}
/* Initiate quick mode.
@@ -1978,474 +1829,467 @@ init_phase2_iv(struct state *st, const msgid_t *msgid)
* Note: this is not called from demux.c
*/
-static bool
-emit_subnet_id(ip_subnet *net
-, u_int8_t np, u_int8_t protoid, u_int16_t port, pb_stream *outs)
+static bool emit_subnet_id(ip_subnet *net, u_int8_t np, u_int8_t protoid,
+ u_int16_t port, pb_stream *outs)
{
- struct isakmp_ipsec_id id;
- pb_stream id_pbs;
- ip_address ta;
- const unsigned char *tbp;
- size_t tal;
-
- id.isaiid_np = np;
- id.isaiid_idtype = subnetishost(net)
- ? aftoinfo(subnettypeof(net))->id_addr
- : aftoinfo(subnettypeof(net))->id_subnet;
- id.isaiid_protoid = protoid;
- id.isaiid_port = port;
-
- if (!out_struct(&id, &isakmp_ipsec_identification_desc, outs, &id_pbs))
- return FALSE;
-
- networkof(net, &ta);
- tal = addrbytesptr(&ta, &tbp);
- if (!out_raw(tbp, tal, &id_pbs, "client network"))
- return FALSE;
+ struct isakmp_ipsec_id id;
+ pb_stream id_pbs;
+ ip_address ta;
+ const unsigned char *tbp;
+ size_t tal;
+
+ id.isaiid_np = np;
+ id.isaiid_idtype = subnetishost(net)
+ ? aftoinfo(subnettypeof(net))->id_addr
+ : aftoinfo(subnettypeof(net))->id_subnet;
+ id.isaiid_protoid = protoid;
+ id.isaiid_port = port;
+
+ if (!out_struct(&id, &isakmp_ipsec_identification_desc, outs, &id_pbs))
+ return FALSE;
- if (!subnetishost(net))
- {
- maskof(net, &ta);
+ networkof(net, &ta);
tal = addrbytesptr(&ta, &tbp);
- if (!out_raw(tbp, tal, &id_pbs, "client mask"))
- return FALSE;
- }
+ if (!out_raw(tbp, tal, &id_pbs, "client network"))
+ return FALSE;
+
+ if (!subnetishost(net))
+ {
+ maskof(net, &ta);
+ tal = addrbytesptr(&ta, &tbp);
+ if (!out_raw(tbp, tal, &id_pbs, "client mask"))
+ return FALSE;
+ }
- close_output_pbs(&id_pbs);
- return TRUE;
+ close_output_pbs(&id_pbs);
+ return TRUE;
}
-stf_status
-quick_outI1(int whack_sock
-, struct state *isakmp_sa
-, struct connection *c
-, lset_t policy
-, unsigned long try
-, so_serial_t replacing)
+stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
+ struct connection *c, lset_t policy, unsigned long try,
+ so_serial_t replacing)
{
- struct state *st = duplicate_state(isakmp_sa);
- pb_stream reply; /* not really a reply */
- pb_stream rbody;
- u_char /* set by START_HASH_PAYLOAD: */
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
- bool has_client = c->spd.this.has_client || c->spd.that.has_client ||
- c->spd.this.protocol || c->spd.that.protocol ||
- c->spd.this.port || c->spd.that.port;
-
- bool send_natoa = FALSE;
- u_int8_t np = ISAKMP_NEXT_NONE;
-
- st->st_whack_sock = whack_sock;
- st->st_connection = c;
- set_cur_state(st); /* we must reset before exit */
- st->st_policy = policy;
- st->st_try = try;
-
- st->st_myuserprotoid = c->spd.this.protocol;
- st->st_peeruserprotoid = c->spd.that.protocol;
- st->st_myuserport = c->spd.this.port;
- st->st_peeruserport = c->spd.that.port;
-
- st->st_msgid = generate_msgid(isakmp_sa);
- st->st_state = STATE_QUICK_I1;
-
- insert_state(st); /* needs cookies, connection, and msgid */
-
- if (replacing == SOS_NOBODY)
- plog("initiating Quick Mode %s {using isakmp#%lu}"
- , prettypolicy(policy)
- , isakmp_sa->st_serialno);
- else
- plog("initiating Quick Mode %s to replace #%lu {using isakmp#%lu}"
- , prettypolicy(policy)
- , replacing
- , isakmp_sa->st_serialno);
-
- if (isakmp_sa->nat_traversal & NAT_T_DETECTED)
- {
- /* Duplicate nat_traversal status in new state */
- st->nat_traversal = isakmp_sa->nat_traversal;
-
- if (isakmp_sa->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
- has_client = TRUE;
-
- nat_traversal_change_port_lookup(NULL, st);
- }
- else
- st->nat_traversal = 0;
-
- /* are we going to send a NAT-OA payload? */
- if ((st->nat_traversal & NAT_T_WITH_NATOA)
- && !(st->st_policy & POLICY_TUNNEL)
- && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)))
- {
- send_natoa = TRUE;
- np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
- ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS;
- }
-
- /* set up reply */
- init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
-
- /* HDR* out */
- {
- 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_QUICK;
- hdr.isa_msgid = st->st_msgid;
- hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* HASH(1) -- create and note space to be filled later */
- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA);
-
- /* SA out */
-
- /*
- * See if pfs_group has been specified for this conn,
- * if not, fallback to old use-same-as-P1 behaviour
- */
+ struct state *st = duplicate_state(isakmp_sa);
+ pb_stream reply; /* not really a reply */
+ pb_stream rbody;
+ u_char /* set by START_HASH_PAYLOAD: */
+ *r_hashval, /* where in reply to jam hash value */
+ *r_hash_start; /* start of what is to be hashed */
+ bool has_client = c->spd.this.has_client || c->spd.that.has_client ||
+ c->spd.this.protocol || c->spd.that.protocol ||
+ c->spd.this.port || c->spd.that.port;
+
+ bool send_natoa = FALSE;
+ u_int8_t np = ISAKMP_NEXT_NONE;
+
+ st->st_whack_sock = whack_sock;
+ st->st_connection = c;
+ set_cur_state(st); /* we must reset before exit */
+ st->st_policy = policy;
+ st->st_try = try;
+
+ st->st_myuserprotoid = c->spd.this.protocol;
+ st->st_peeruserprotoid = c->spd.that.protocol;
+ st->st_myuserport = c->spd.this.port;
+ st->st_peeruserport = c->spd.that.port;
+
+ st->st_msgid = generate_msgid(isakmp_sa);
+ st->st_state = STATE_QUICK_I1;
+
+ insert_state(st); /* needs cookies, connection, and msgid */
+
+ if (replacing == SOS_NOBODY)
+ plog("initiating Quick Mode %s {using isakmp#%lu}"
+ , prettypolicy(policy)
+ , isakmp_sa->st_serialno);
+ else
+ plog("initiating Quick Mode %s to replace #%lu {using isakmp#%lu}"
+ , prettypolicy(policy)
+ , replacing
+ , isakmp_sa->st_serialno);
+
+ if (isakmp_sa->nat_traversal & NAT_T_DETECTED)
+ {
+ /* Duplicate nat_traversal status in new state */
+ st->nat_traversal = isakmp_sa->nat_traversal;
+
+ if (isakmp_sa->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
+ has_client = TRUE;
+
+ nat_traversal_change_port_lookup(NULL, st);
+ }
+ else
+ st->nat_traversal = 0;
+
+ /* are we going to send a NAT-OA payload? */
+ if ((st->nat_traversal & NAT_T_WITH_NATOA)
+ && !(st->st_policy & POLICY_TUNNEL)
+ && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)))
+ {
+ send_natoa = TRUE;
+ np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
+ ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS;
+ }
+
+ /* set up reply */
+ init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
+
+ /* HDR* out */
+ {
+ 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_QUICK;
+ hdr.isa_msgid = st->st_msgid;
+ hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
+ memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
+ memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
+ if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
+ }
+
+ /* HASH(1) -- create and note space to be filled later */
+ START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA);
+
+ /* SA out */
+
+ /*
+ * See if pfs_group has been specified for this conn,
+ * if not, fallback to old use-same-as-P1 behaviour
+ */
#ifndef NO_IKE_ALG
- if (st->st_connection)
- st->st_pfs_group = ike_alg_pfsgroup(st->st_connection, policy);
- if (!st->st_pfs_group)
+ if (st->st_connection)
+ st->st_pfs_group = ike_alg_pfsgroup(st->st_connection, policy);
+ if (!st->st_pfs_group)
#endif
- /* If PFS specified, use the same group as during Phase 1:
- * since no negotiation is possible, we pick one that is
- * very likely supported.
- */
- st->st_pfs_group = policy & POLICY_PFS? isakmp_sa->st_oakley.group : NULL;
-
- /* Emit SA payload based on a subset of the policy bits.
- * POLICY_COMPRESS is considered iff we can do IPcomp.
- */
- {
- lset_t pm = POLICY_ENCRYPT | POLICY_AUTHENTICATE;
-
- if (can_do_IPcomp)
- pm |= POLICY_COMPRESS;
-
- if (!out_sa(&rbody
- , &ipsec_sadb[(st->st_policy & pm) >> POLICY_IPSEC_SHIFT]
- , st, FALSE, ISAKMP_NEXT_NONCE))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Ni out */
- if (!build_and_ship_nonce(&st->st_ni, &rbody
- , policy & POLICY_PFS? ISAKMP_NEXT_KE : has_client? ISAKMP_NEXT_ID : np
- , "Ni"))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
+ /* If PFS specified, use the same group as during Phase 1:
+ * since no negotiation is possible, we pick one that is
+ * very likely supported.
+ */
+ st->st_pfs_group = policy & POLICY_PFS? isakmp_sa->st_oakley.group : NULL;
+
+ /* Emit SA payload based on a subset of the policy bits.
+ * POLICY_COMPRESS is considered iff we can do IPcomp.
+ */
+ {
+ lset_t pm = POLICY_ENCRYPT | POLICY_AUTHENTICATE;
+
+ if (can_do_IPcomp)
+ pm |= POLICY_COMPRESS;
+
+ if (!out_sa(&rbody
+ , &ipsec_sadb[(st->st_policy & pm) >> POLICY_IPSEC_SHIFT]
+ , st, FALSE, ISAKMP_NEXT_NONCE))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
+ }
+
+ /* Ni out */
+ if (!build_and_ship_nonce(&st->st_ni, &rbody
+ , policy & POLICY_PFS? ISAKMP_NEXT_KE : has_client? ISAKMP_NEXT_ID : np
+ , "Ni"))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
- /* [ KE ] out (for PFS) */
+ /* [ KE ] out (for PFS) */
- if (st->st_pfs_group != NULL)
- {
- if (!build_and_ship_KE(st, &st->st_gi, st->st_pfs_group
- , &rbody, has_client? ISAKMP_NEXT_ID : np))
+ if (st->st_pfs_group != NULL)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!build_and_ship_KE(st, &st->st_gi, st->st_pfs_group
+ , &rbody, has_client? ISAKMP_NEXT_ID : np))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* [ IDci, IDcr ] out */
- if (has_client)
- {
- /* IDci (we are initiator), then IDcr (peer is responder) */
- if (!emit_subnet_id(&c->spd.this.client
- , ISAKMP_NEXT_ID, st->st_myuserprotoid, st->st_myuserport, &rbody)
- || !emit_subnet_id(&c->spd.that.client
- , np, st->st_peeruserprotoid, st->st_peeruserport, &rbody))
+ /* [ IDci, IDcr ] out */
+ if (has_client)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ /* IDci (we are initiator), then IDcr (peer is responder) */
+ if (!emit_subnet_id(&c->spd.this.client
+ , ISAKMP_NEXT_ID, st->st_myuserprotoid, st->st_myuserport, &rbody)
+ || !emit_subnet_id(&c->spd.that.client
+ , np, st->st_peeruserprotoid, st->st_peeruserport, &rbody))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* Send NAT-OA if our address is NATed */
- if (send_natoa)
- {
- if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &rbody, st))
+ /* Send NAT-OA if our address is NATed */
+ if (send_natoa)
{
- reset_cur_state();
- return STF_INTERNAL_ERROR;
+ if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &rbody, st))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* finish computing HASH(1), inserting it in output */
- (void) quick_mode_hash12(r_hashval, r_hash_start, rbody.cur
- , st, &st->st_msgid, FALSE);
+ /* finish computing HASH(1), inserting it in output */
+ (void) quick_mode_hash12(r_hashval, r_hash_start, rbody.cur
+ , st, &st->st_msgid, FALSE);
- /* encrypt message, except for fixed part of header */
+ /* encrypt message, except for fixed part of header */
+
+ init_phase2_iv(isakmp_sa, &st->st_msgid);
+ st->st_new_iv_len = isakmp_sa->st_new_iv_len;
+ memcpy(st->st_new_iv, isakmp_sa->st_new_iv, st->st_new_iv_len);
- init_phase2_iv(isakmp_sa, &st->st_msgid);
- st->st_new_iv_len = isakmp_sa->st_new_iv_len;
- memcpy(st->st_new_iv, isakmp_sa->st_new_iv, st->st_new_iv_len);
+ if (!encrypt_message(&rbody, st))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
- if (!encrypt_message(&rbody, st))
- {
+ /* save packet, now that we know its size */
+ st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply));
+ st->st_tpacket = chunk_clone(st->st_tpacket);
+
+ /* send the packet */
+
+ send_packet(st, "quick_outI1");
+
+ delete_event(st);
+ event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
+
+ if (replacing == SOS_NOBODY)
+ whack_log(RC_NEW_STATE + STATE_QUICK_I1
+ , "%s: initiate"
+ , enum_name(&state_names, st->st_state));
+ else
+ whack_log(RC_NEW_STATE + STATE_QUICK_I1
+ , "%s: initiate to replace #%lu"
+ , enum_name(&state_names, st->st_state)
+ , replacing);
reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
-
- /* save packet, now that we know its size */
- clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply)
- , "reply packet from quick_outI1");
-
- /* send the packet */
-
- send_packet(st, "quick_outI1");
-
- delete_event(st);
- event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
-
- if (replacing == SOS_NOBODY)
- whack_log(RC_NEW_STATE + STATE_QUICK_I1
- , "%s: initiate"
- , enum_name(&state_names, st->st_state));
- else
- whack_log(RC_NEW_STATE + STATE_QUICK_I1
- , "%s: initiate to replace #%lu"
- , enum_name(&state_names, st->st_state)
- , replacing);
- reset_cur_state();
- return STF_OK;
+ return STF_OK;
}
/*
* Decode the CERT payload of Phase 1.
*/
-static void
-decode_cert(struct msg_digest *md)
+static void decode_cert(struct msg_digest *md)
{
- struct payload_digest *p;
-
- for (p = md->chain[ISAKMP_NEXT_CERT]; p != NULL; p = p->next)
- {
- struct isakmp_cert *const cert = &p->payload.cert;
- chunk_t blob;
- time_t valid_until;
- blob.ptr = p->pbs.cur;
- blob.len = pbs_left(&p->pbs);
- if (cert->isacert_type == CERT_X509_SIGNATURE)
- {
- x509cert_t cert = empty_x509cert;
- if (parse_x509cert(blob, 0, &cert))
- {
- if (verify_x509cert(&cert, strict_crl_policy, &valid_until))
+ struct payload_digest *p;
+
+ for (p = md->chain[ISAKMP_NEXT_CERT]; p != NULL; p = p->next)
+ {
+ struct isakmp_cert *const cert = &p->payload.cert;
+ chunk_t blob;
+ time_t valid_until;
+ blob.ptr = p->pbs.cur;
+ blob.len = pbs_left(&p->pbs);
+ if (cert->isacert_type == CERT_X509_SIGNATURE)
+ {
+ x509cert_t cert = empty_x509cert;
+ if (parse_x509cert(blob, 0, &cert))
+ {
+ if (verify_x509cert(&cert, strict_crl_policy, &valid_until))
+ {
+ DBG(DBG_PARSING,
+ DBG_log("Public key validated")
+ )
+ add_x509_public_key(&cert, valid_until, DAL_SIGNED);
+ }
+ else
+ {
+ plog("X.509 certificate rejected");
+ }
+ DESTROY_IF(cert.public_key);
+ free_generalNames(cert.subjectAltName, FALSE);
+ free_generalNames(cert.crlDistributionPoints, FALSE);
+ }
+ else
+ plog("Syntax error in X.509 certificate");
+ }
+ else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509)
{
- DBG(DBG_PARSING,
- DBG_log("Public key validated")
- )
- add_x509_public_key(&cert, valid_until, DAL_SIGNED);
+ x509cert_t *cert = NULL;
+
+ if (pkcs7_parse_signedData(blob, NULL, &cert, NULL, NULL))
+ store_x509certs(&cert, strict_crl_policy);
+ else
+ plog("Syntax error in PKCS#7 wrapped X.509 certificates");
}
else
{
- plog("X.509 certificate rejected");
+ loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload",
+ enum_show(&cert_type_names, cert->isacert_type));
+ DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob);
}
- free_generalNames(cert.subjectAltName, FALSE);
- free_generalNames(cert.crlDistributionPoints, FALSE);
- }
- else
- plog("Syntax error in X.509 certificate");
- }
- else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509)
- {
- x509cert_t *cert = NULL;
-
- if (pkcs7_parse_signedData(blob, NULL, &cert, NULL, NULL))
- store_x509certs(&cert, strict_crl_policy);
- else
- plog("Syntax error in PKCS#7 wrapped X.509 certificates");
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload",
- enum_show(&cert_type_names, cert->isacert_type));
- DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob);
}
- }
}
/*
* Decode the CR payload of Phase 1.
*/
-static void
-decode_cr(struct msg_digest *md, struct connection *c)
+static void decode_cr(struct msg_digest *md, struct connection *c)
{
- struct payload_digest *p;
+ struct payload_digest *p;
- for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next)
- {
- struct isakmp_cr *const cr = &p->payload.cr;
- chunk_t ca_name;
-
- ca_name.len = pbs_left(&p->pbs);
- ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL;
+ for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next)
+ {
+ struct isakmp_cr *const cr = &p->payload.cr;
+ chunk_t ca_name;
+
+ ca_name.len = pbs_left(&p->pbs);
+ ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL;
- DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name);
+ DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name);
- if (cr->isacr_type == CERT_X509_SIGNATURE)
- {
- char buf[BUF_LEN];
+ if (cr->isacr_type == CERT_X509_SIGNATURE)
+ {
+ char buf[BUF_LEN];
- if (ca_name.len > 0)
- {
- generalName_t *gn;
-
- if (!is_asn1(ca_name))
- continue;
-
- gn = alloc_thing(generalName_t, "generalName");
- clonetochunk(ca_name, ca_name.ptr,ca_name.len, "ca name");
- gn->kind = GN_DIRECTORY_NAME;
- gn->name = ca_name;
- gn->next = c->requested_ca;
- c->requested_ca = gn;
- }
- c->got_certrequest = TRUE;
-
- DBG(DBG_PARSING | DBG_CONTROL,
- dntoa_or_null(buf, BUF_LEN, ca_name, "%any");
- DBG_log("requested CA: '%s'", buf);
- )
+ if (ca_name.len > 0)
+ {
+ generalName_t *gn;
+
+ if (!is_asn1(ca_name))
+ continue;
+
+ gn = malloc_thing(generalName_t);
+ ca_name = chunk_clone(ca_name);
+ gn->kind = GN_DIRECTORY_NAME;
+ gn->name = ca_name;
+ gn->next = c->requested_ca;
+ c->requested_ca = gn;
+ }
+ c->got_certrequest = TRUE;
+
+ DBG(DBG_PARSING | DBG_CONTROL,
+ dntoa_or_null(buf, BUF_LEN, ca_name, "%any");
+ DBG_log("requested CA: '%s'", buf);
+ )
+ }
+ else
+ loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload",
+ enum_show(&cert_type_names, cr->isacr_type));
}
- else
- loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload",
- enum_show(&cert_type_names, cr->isacr_type));
- }
}
/* Decode the ID payload of Phase 1 (main_inI3_outR3 and main_inR3)
* Note: we may change connections as a result.
* We must be called before SIG or HASH are decoded since we
- * may change the peer's RSA key or ID.
+ * may change the peer's public key or ID.
*/
-static bool
-decode_peer_id(struct msg_digest *md, struct id *peer)
+static bool decode_peer_id(struct msg_digest *md, struct id *peer)
{
- struct state *const st = md->st;
- struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID];
- const pb_stream *const id_pbs = &id_pld->pbs;
- struct isakmp_id *const id = &id_pld->payload.id;
-
- /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
- * It talks about the protocol ID and Port fields of the ID
- * Payload, but they don't exist as such in Phase 1.
- * We use more appropriate names.
- * isaid_doi_specific_a is in place of Protocol ID.
- * isaid_doi_specific_b is in place of Port.
- * Besides, there is no good reason for allowing these to be
- * other than 0 in Phase 1.
- */
- if ((st->nat_traversal & NAT_T_WITH_PORT_FLOATING)
- && id->isaid_doi_specific_a == IPPROTO_UDP
- && (id->isaid_doi_specific_b == 0 || id->isaid_doi_specific_b == NAT_T_IKE_FLOAT_PORT))
- {
- DBG_log("protocol/port in Phase 1 ID Payload is %d/%d. "
- "accepted with port_floating NAT-T",
- id->isaid_doi_specific_a, id->isaid_doi_specific_b);
- }
- else if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0)
- && !(id->isaid_doi_specific_a == IPPROTO_UDP && id->isaid_doi_specific_b == IKE_UDP_PORT))
- {
- loglog(RC_LOG_SERIOUS, "protocol/port in Phase 1 ID Payload must be 0/0 or %d/%d"
- " but are %d/%d"
- , IPPROTO_UDP, IKE_UDP_PORT
- , id->isaid_doi_specific_a, id->isaid_doi_specific_b);
- return FALSE;
- }
-
- peer->kind = id->isaid_idtype;
-
- switch (peer->kind)
- {
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- /* failure mode for initaddr is probably inappropriate address length */
+ struct state *const st = md->st;
+ struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID];
+ const pb_stream *const id_pbs = &id_pld->pbs;
+ struct isakmp_id *const id = &id_pld->payload.id;
+
+ /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
+ * It talks about the protocol ID and Port fields of the ID
+ * Payload, but they don't exist as such in Phase 1.
+ * We use more appropriate names.
+ * isaid_doi_specific_a is in place of Protocol ID.
+ * isaid_doi_specific_b is in place of Port.
+ * Besides, there is no good reason for allowing these to be
+ * other than 0 in Phase 1.
+ */
+ if ((st->nat_traversal & NAT_T_WITH_PORT_FLOATING)
+ && id->isaid_doi_specific_a == IPPROTO_UDP
+ && (id->isaid_doi_specific_b == 0 || id->isaid_doi_specific_b == NAT_T_IKE_FLOAT_PORT))
{
- err_t ugh = initaddr(id_pbs->cur, pbs_left(id_pbs)
- , peer->kind == ID_IPV4_ADDR? AF_INET : AF_INET6
- , &peer->ip_addr);
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s"
- , enum_show(&ident_names, peer->kind), ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
+ DBG_log("protocol/port in Phase 1 ID Payload is %d/%d. "
+ "accepted with port_floating NAT-T",
+ id->isaid_doi_specific_a, id->isaid_doi_specific_b);
}
- break;
-
- case ID_USER_FQDN:
- if (memchr(id_pbs->cur, '@', pbs_left(id_pbs)) == NULL)
+ else if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0)
+ && !(id->isaid_doi_specific_a == IPPROTO_UDP && id->isaid_doi_specific_b == IKE_UDP_PORT))
{
- loglog(RC_LOG_SERIOUS, "peer's ID_USER_FQDN contains no @");
- return FALSE;
+ loglog(RC_LOG_SERIOUS, "protocol/port in Phase 1 ID Payload must be 0/0 or %d/%d"
+ " but are %d/%d"
+ , IPPROTO_UDP, IKE_UDP_PORT
+ , id->isaid_doi_specific_a, id->isaid_doi_specific_b);
+ return FALSE;
}
- /* FALLTHROUGH */
- case ID_FQDN:
- if (memchr(id_pbs->cur, '\0', pbs_left(id_pbs)) != NULL)
+
+ peer->kind = id->isaid_idtype;
+
+ switch (peer->kind)
{
- loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NUL"
- , enum_show(&ident_names, peer->kind));
- return FALSE;
- }
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ /* failure mode for initaddr is probably inappropriate address length */
+ {
+ err_t ugh = initaddr(id_pbs->cur, pbs_left(id_pbs)
+ , peer->kind == ID_IPV4_ADDR? AF_INET : AF_INET6
+ , &peer->ip_addr);
+
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s"
+ , enum_show(&ident_names, peer->kind), ugh);
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+ }
+ break;
+
+ case ID_USER_FQDN:
+ if (memchr(id_pbs->cur, '@', pbs_left(id_pbs)) == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "peer's ID_USER_FQDN contains no @");
+ return FALSE;
+ }
+ /* FALLTHROUGH */
+ 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));
+ return FALSE;
+ }
- /* ??? ought to do some more sanity check, but what? */
+ /* ??? ought to do some more sanity check, but what? */
- setchunk(peer->name, id_pbs->cur, pbs_left(id_pbs));
- break;
+ peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
+ break;
- case ID_KEY_ID:
- setchunk(peer->name, id_pbs->cur, pbs_left(id_pbs));
- DBG(DBG_PARSING,
- DBG_dump_chunk("KEY ID:", peer->name));
- break;
+ case ID_KEY_ID:
+ peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
+ DBG(DBG_PARSING,
+ DBG_dump_chunk("KEY ID:", peer->name));
+ break;
- case ID_DER_ASN1_DN:
- setchunk(peer->name, id_pbs->cur, pbs_left(id_pbs));
- DBG(DBG_PARSING,
- DBG_dump_chunk("DER ASN1 DN:", peer->name));
- break;
+ case ID_DER_ASN1_DN:
+ peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
+ DBG(DBG_PARSING,
+ DBG_dump_chunk("DER ASN1 DN:", peer->name));
+ break;
- default:
- /* XXX Could send notification back */
- loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload"
- , enum_show(&ident_names, peer->kind));
- return FALSE;
- }
+ default:
+ /* XXX Could send notification back */
+ loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload"
+ , enum_show(&ident_names, peer->kind));
+ return FALSE;
+ }
- {
- char buf[BUF_LEN];
+ {
+ char buf[BUF_LEN];
- idtoa(peer, buf, sizeof(buf));
- plog("Peer ID is %s: '%s'",
- enum_show(&ident_names, id->isaid_idtype), buf);
- }
+ idtoa(peer, buf, sizeof(buf));
+ plog("Peer ID is %s: '%s'",
+ enum_show(&ident_names, id->isaid_idtype), buf);
+ }
- /* check for certificates */
- decode_cert(md);
- return TRUE;
+ /* check for certificates */
+ decode_cert(md);
+ return TRUE;
}
/* Now that we've decoded the ID payload, let's see if we
@@ -2454,111 +2298,111 @@ decode_peer_id(struct msg_digest *md, struct id *peer)
* - if the initiation was explicit, we'd be ignoring user's intent
* - if opportunistic, we'll lose our HOLD info
*/
-static bool
-switch_connection(struct msg_digest *md, struct id *peer, bool initiator)
+static bool switch_connection(struct msg_digest *md, struct id *peer,
+ bool initiator)
{
- struct state *const st = md->st;
- struct connection *c = st->st_connection;
-
- chunk_t peer_ca = (st->st_peer_pubkey != NULL)
- ? st->st_peer_pubkey->issuer : empty_chunk;
+ struct state *const st = md->st;
+ struct connection *c = st->st_connection;
- DBG(DBG_CONTROL,
- char buf[BUF_LEN];
+ chunk_t peer_ca = (st->st_peer_pubkey != NULL)
+ ? st->st_peer_pubkey->issuer : chunk_empty;
- dntoa_or_null(buf, BUF_LEN, peer_ca, "%none");
- DBG_log("peer CA: '%s'", buf);
- )
+ DBG(DBG_CONTROL,
+ char buf[BUF_LEN];
- if (initiator)
- {
- int pathlen;
+ dntoa_or_null(buf, BUF_LEN, peer_ca, "%none");
+ DBG_log("peer CA: '%s'", buf);
+ )
- if (!same_id(&c->spd.that.id, peer))
+ if (initiator)
{
- char expect[BUF_LEN]
- , found[BUF_LEN];
+ int pathlen;
- idtoa(&c->spd.that.id, expect, sizeof(expect));
- idtoa(peer, found, sizeof(found));
- loglog(RC_LOG_SERIOUS
- , "we require peer to have ID '%s', but peer declares '%s'"
- , expect, found);
- return FALSE;
- }
+ if (!same_id(&c->spd.that.id, peer))
+ {
+ char expect[BUF_LEN]
+ , found[BUF_LEN];
+
+ idtoa(&c->spd.that.id, expect, sizeof(expect));
+ idtoa(peer, found, sizeof(found));
+ loglog(RC_LOG_SERIOUS
+ , "we require peer to have ID '%s', but peer declares '%s'"
+ , expect, found);
+ return FALSE;
+ }
- DBG(DBG_CONTROL,
- char buf[BUF_LEN];
+ DBG(DBG_CONTROL,
+ char buf[BUF_LEN];
- dntoa_or_null(buf, BUF_LEN, c->spd.that.ca, "%none");
- DBG_log("required CA: '%s'", buf);
- )
+ dntoa_or_null(buf, BUF_LEN, c->spd.that.ca, "%none");
+ DBG_log("required CA: '%s'", buf);
+ )
- if (!trusted_ca(peer_ca, c->spd.that.ca, &pathlen))
- {
- loglog(RC_LOG_SERIOUS
- , "we don't accept the peer's CA");
- return FALSE;
+ if (!trusted_ca(peer_ca, c->spd.that.ca, &pathlen))
+ {
+ loglog(RC_LOG_SERIOUS
+ , "we don't accept the peer's CA");
+ return FALSE;
+ }
}
- }
- else
- {
- struct connection *r;
+ else
+ {
+ struct connection *r;
- /* check for certificate requests */
- decode_cr(md, c);
+ /* check for certificate requests */
+ decode_cr(md, c);
- r = refine_host_connection(st, peer, peer_ca);
+ r = refine_host_connection(st, peer, peer_ca);
- /* delete the collected certificate requests */
- free_generalNames(c->requested_ca, TRUE);
- c->requested_ca = NULL;
+ /* delete the collected certificate requests */
+ free_generalNames(c->requested_ca, TRUE);
+ c->requested_ca = NULL;
- if (r == NULL)
- {
- char buf[BUF_LEN];
+ if (r == NULL)
+ {
+ char buf[BUF_LEN];
- idtoa(peer, buf, sizeof(buf));
- loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%s'", buf);
- return FALSE;
- }
+ idtoa(peer, buf, sizeof(buf));
+ loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%s'", buf);
+ return FALSE;
+ }
- DBG(DBG_CONTROL,
- char buf[BUF_LEN];
+ DBG(DBG_CONTROL,
+ char buf[BUF_LEN];
- dntoa_or_null(buf, BUF_LEN, r->spd.this.ca, "%none");
- DBG_log("offered CA: '%s'", buf);
- )
+ dntoa_or_null(buf, BUF_LEN, r->spd.this.ca, "%none");
+ DBG_log("offered CA: '%s'", buf);
+ )
- if (r != c)
- {
- /* apparently, r is an improvement on c -- replace */
+ if (r != c)
+ {
+ /* apparently, r is an improvement on c -- replace */
- DBG(DBG_CONTROL
- , DBG_log("switched from \"%s\" to \"%s\"", c->name, r->name));
- if (r->kind == CK_TEMPLATE)
- {
- /* instantiate it, filling in peer's ID */
- r = rw_instantiate(r, &c->spd.that.host_addr
- , c->spd.that.host_port, NULL, peer);
- }
+ DBG(DBG_CONTROL
+ , DBG_log("switched from \"%s\" to \"%s\"", c->name, r->name));
+ if (r->kind == CK_TEMPLATE)
+ {
+ /* instantiate it, filling in peer's ID */
+ r = rw_instantiate(r, &c->spd.that.host_addr
+ , c->spd.that.host_port, NULL, peer);
+ }
- /* copy certificate request info */
- r->got_certrequest = c->got_certrequest;
+ /* copy certificate request info */
+ r->got_certrequest = c->got_certrequest;
- st->st_connection = r; /* kill reference to c */
- set_cur_connection(r);
- connection_discard(c);
- }
- else if (c->spd.that.has_id_wildcards)
- {
- free_id_content(&c->spd.that.id);
- c->spd.that.id = *peer;
- c->spd.that.has_id_wildcards = FALSE;
- unshare_id_content(&c->spd.that.id);
+ st->st_connection = r; /* kill reference to c */
+ set_cur_connection(r);
+ connection_discard(c);
+ }
+ else if (c->spd.that.has_id_wildcards)
+ {
+ free_id_content(&c->spd.that.id);
+ c->spd.that.id = *peer;
+ c->spd.that.has_id_wildcards = FALSE;
+ unshare_id_content(&c->spd.that.id);
+ }
}
- }
- return TRUE;
+ return TRUE;
}
/* Decode the variable part of an ID packet (during Quick Mode).
@@ -2566,227 +2410,218 @@ switch_connection(struct msg_digest *md, struct id *peer, bool initiator)
* Rejects 0.0.0.0/32 or IPv6 equivalent because
* (1) it is wrong and (2) we use this value for inband signalling.
*/
-static bool
-decode_net_id(struct isakmp_ipsec_id *id
-, pb_stream *id_pbs
-, ip_subnet *net
-, const char *which)
+static bool decode_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
+ ip_subnet *net, const char *which)
{
- const struct af_info *afi = NULL;
+ const struct af_info *afi = NULL;
- /* Note: the following may be a pointer into static memory
- * that may be recycled, but only if the type is not known.
- * That case is disposed of very early -- in the first switch.
- */
- const char *idtypename = enum_show(&ident_names, id->isaiid_idtype);
+ /* Note: the following may be a pointer into static memory
+ * that may be recycled, but only if the type is not known.
+ * That case is disposed of very early -- in the first switch.
+ */
+ const char *idtypename = enum_show(&ident_names, id->isaiid_idtype);
- switch (id->isaiid_idtype)
- {
- case ID_IPV4_ADDR:
- case ID_IPV4_ADDR_SUBNET:
- case ID_IPV4_ADDR_RANGE:
- afi = &af_inet4_info;
- break;
- case ID_IPV6_ADDR:
- case ID_IPV6_ADDR_SUBNET:
- case ID_IPV6_ADDR_RANGE:
- afi = &af_inet6_info;
- break;
- case ID_FQDN:
- return TRUE;
- default:
- /* XXX support more */
- loglog(RC_LOG_SERIOUS, "unsupported ID type %s"
- , idtypename);
- /* XXX Could send notification back */
- return FALSE;
- }
-
- switch (id->isaiid_idtype)
- {
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
+ switch (id->isaiid_idtype)
{
- ip_address temp_address;
- err_t ugh;
-
- ugh = initaddr(id_pbs->cur, pbs_left(id_pbs), afi->af, &temp_address);
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s has wrong length in Quick I1 (%s)"
- , which, idtypename, ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
- if (isanyaddr(&temp_address))
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s is invalid (%s) in Quick I1"
- , which, idtypename, ip_str(&temp_address));
- /* XXX Could send notification back */
- return FALSE;
- }
- happy(addrtosubnet(&temp_address, net));
- DBG(DBG_PARSING | DBG_CONTROL
- , DBG_log("%s is %s", which, ip_str(&temp_address)));
- break;
+ case ID_IPV4_ADDR:
+ case ID_IPV4_ADDR_SUBNET:
+ case ID_IPV4_ADDR_RANGE:
+ afi = &af_inet4_info;
+ break;
+ case ID_IPV6_ADDR:
+ case ID_IPV6_ADDR_SUBNET:
+ case ID_IPV6_ADDR_RANGE:
+ afi = &af_inet6_info;
+ break;
+ case ID_FQDN:
+ return TRUE;
+ default:
+ /* XXX support more */
+ loglog(RC_LOG_SERIOUS, "unsupported ID type %s"
+ , idtypename);
+ /* XXX Could send notification back */
+ return FALSE;
}
- case ID_IPV4_ADDR_SUBNET:
- case ID_IPV6_ADDR_SUBNET:
+ switch (id->isaiid_idtype)
{
- ip_address temp_address, temp_mask;
- err_t ugh;
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ {
+ ip_address temp_address;
+ err_t ugh;
- if (pbs_left(id_pbs) != 2 * afi->ia_sz)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1"
- , which, idtypename);
- /* XXX Could send notification back */
- return FALSE;
- }
- ugh = initaddr(id_pbs->cur
- , afi->ia_sz, afi->af, &temp_address);
- if (ugh == NULL)
- ugh = initaddr(id_pbs->cur + afi->ia_sz
- , afi->ia_sz, afi->af, &temp_mask);
- if (ugh == NULL)
- ugh = initsubnet(&temp_address, masktocount(&temp_mask)
- , '0', net);
- if (ugh == NULL && subnetisnone(net))
- ugh = "contains only anyaddr";
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s bad subnet in Quick I1 (%s)"
- , which, idtypename, ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
- DBG(DBG_PARSING | DBG_CONTROL,
+ ugh = initaddr(id_pbs->cur, pbs_left(id_pbs), afi->af, &temp_address);
+
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID payload %s has wrong length in Quick I1 (%s)"
+ , which, idtypename, ugh);
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+ if (isanyaddr(&temp_address))
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID payload %s is invalid (%s) in Quick I1"
+ , which, idtypename, ip_str(&temp_address));
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+ happy(addrtosubnet(&temp_address, net));
+ DBG(DBG_PARSING | DBG_CONTROL
+ , DBG_log("%s is %s", which, ip_str(&temp_address)));
+ break;
+ }
+
+ case ID_IPV4_ADDR_SUBNET:
+ case ID_IPV6_ADDR_SUBNET:
{
- char temp_buff[SUBNETTOT_BUF];
+ ip_address temp_address, temp_mask;
+ err_t ugh;
- subnettot(net, 0, temp_buff, sizeof(temp_buff));
- DBG_log("%s is subnet %s", which, temp_buff);
- });
- break;
- }
+ if (pbs_left(id_pbs) != 2 * afi->ia_sz)
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1"
+ , which, idtypename);
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+ ugh = initaddr(id_pbs->cur
+ , afi->ia_sz, afi->af, &temp_address);
+ if (ugh == NULL)
+ ugh = initaddr(id_pbs->cur + afi->ia_sz
+ , afi->ia_sz, afi->af, &temp_mask);
+ if (ugh == NULL)
+ ugh = initsubnet(&temp_address, masktocount(&temp_mask)
+ , '0', net);
+ if (ugh == NULL && subnetisnone(net))
+ ugh = "contains only anyaddr";
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID payload %s bad subnet in Quick I1 (%s)"
+ , which, idtypename, ugh);
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+ DBG(DBG_PARSING | DBG_CONTROL,
+ {
+ char temp_buff[SUBNETTOT_BUF];
- case ID_IPV4_ADDR_RANGE:
- case ID_IPV6_ADDR_RANGE:
- {
- ip_address temp_address_from, temp_address_to;
- err_t ugh;
+ subnettot(net, 0, temp_buff, sizeof(temp_buff));
+ DBG_log("%s is subnet %s", which, temp_buff);
+ });
+ break;
+ }
- if (pbs_left(id_pbs) != 2 * afi->ia_sz)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1"
- , which, idtypename);
- /* XXX Could send notification back */
- return FALSE;
- }
- ugh = initaddr(id_pbs->cur, afi->ia_sz, afi->af, &temp_address_from);
- if (ugh == NULL)
- ugh = initaddr(id_pbs->cur + afi->ia_sz
- , afi->ia_sz, afi->af, &temp_address_to);
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s malformed (%s) in Quick I1"
- , which, idtypename, ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
-
- ugh = rangetosubnet(&temp_address_from, &temp_address_to, net);
- if (ugh == NULL && subnetisnone(net))
- ugh = "contains only anyaddr";
- if (ugh != NULL)
- {
- char temp_buff1[ADDRTOT_BUF], temp_buff2[ADDRTOT_BUF];
-
- addrtot(&temp_address_from, 0, temp_buff1, sizeof(temp_buff1));
- addrtot(&temp_address_to, 0, temp_buff2, sizeof(temp_buff2));
- loglog(RC_LOG_SERIOUS, "%s ID payload in Quick I1, %s"
- " %s - %s unacceptable: %s"
- , which, idtypename, temp_buff1, temp_buff2, ugh);
- return FALSE;
- }
- DBG(DBG_PARSING | DBG_CONTROL,
+ case ID_IPV4_ADDR_RANGE:
+ case ID_IPV6_ADDR_RANGE:
{
- char temp_buff[SUBNETTOT_BUF];
+ ip_address temp_address_from, temp_address_to;
+ err_t ugh;
- subnettot(net, 0, temp_buff, sizeof(temp_buff));
- DBG_log("%s is subnet %s (received as range)"
- , which, temp_buff);
- });
- break;
+ if (pbs_left(id_pbs) != 2 * afi->ia_sz)
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1"
+ , which, idtypename);
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+ ugh = initaddr(id_pbs->cur, afi->ia_sz, afi->af, &temp_address_from);
+ if (ugh == NULL)
+ ugh = initaddr(id_pbs->cur + afi->ia_sz
+ , afi->ia_sz, afi->af, &temp_address_to);
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID payload %s malformed (%s) in Quick I1"
+ , which, idtypename, ugh);
+ /* XXX Could send notification back */
+ return FALSE;
+ }
+
+ ugh = rangetosubnet(&temp_address_from, &temp_address_to, net);
+ if (ugh == NULL && subnetisnone(net))
+ ugh = "contains only anyaddr";
+ if (ugh != NULL)
+ {
+ char temp_buff1[ADDRTOT_BUF], temp_buff2[ADDRTOT_BUF];
+
+ addrtot(&temp_address_from, 0, temp_buff1, sizeof(temp_buff1));
+ addrtot(&temp_address_to, 0, temp_buff2, sizeof(temp_buff2));
+ loglog(RC_LOG_SERIOUS, "%s ID payload in Quick I1, %s"
+ " %s - %s unacceptable: %s"
+ , which, idtypename, temp_buff1, temp_buff2, ugh);
+ return FALSE;
+ }
+ DBG(DBG_PARSING | DBG_CONTROL,
+ {
+ char temp_buff[SUBNETTOT_BUF];
+
+ subnettot(net, 0, temp_buff, sizeof(temp_buff));
+ DBG_log("%s is subnet %s (received as range)"
+ , which, temp_buff);
+ });
+ break;
+ }
}
- }
- /* set the port selector */
- setportof(htons(id->isaiid_port), &net->addr);
+ /* set the port selector */
+ setportof(htons(id->isaiid_port), &net->addr);
- DBG(DBG_PARSING | DBG_CONTROL,
- DBG_log("%s protocol/port is %d/%d", which, id->isaiid_protoid, id->isaiid_port)
- )
+ DBG(DBG_PARSING | DBG_CONTROL,
+ DBG_log("%s protocol/port is %d/%d", which, id->isaiid_protoid, id->isaiid_port)
+ )
- return TRUE;
+ return TRUE;
}
/* like decode, but checks that what is received matches what was sent */
-static bool
-
-check_net_id(struct isakmp_ipsec_id *id
-, pb_stream *id_pbs
-, u_int8_t *protoid
-, u_int16_t *port
-, ip_subnet *net
-, const char *which)
+static bool check_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
+ u_int8_t *protoid, u_int16_t *port, ip_subnet *net,
+ const char *which)
{
- ip_subnet net_temp;
+ ip_subnet net_temp;
- if (!decode_net_id(id, id_pbs, &net_temp, which))
- return FALSE;
+ if (!decode_net_id(id, id_pbs, &net_temp, which))
+ return FALSE;
- if (!samesubnet(net, &net_temp)
- || *protoid != id->isaiid_protoid || *port != id->isaiid_port)
- {
- loglog(RC_LOG_SERIOUS, "%s ID returned doesn't match my proposal", which);
- return FALSE;
- }
- return TRUE;
+ if (!samesubnet(net, &net_temp)
+ || *protoid != id->isaiid_protoid || *port != id->isaiid_port)
+ {
+ loglog(RC_LOG_SERIOUS, "%s ID returned doesn't match my proposal", which);
+ return FALSE;
+ }
+ return TRUE;
}
/*
* look for the existence of a non-expiring preloaded public key
*/
-static bool
-has_preloaded_public_key(struct state *st)
+static bool has_preloaded_public_key(struct state *st)
{
- struct connection *c = st->st_connection;
+ struct connection *c = st->st_connection;
- /* do not consider rw connections since
- * the peer's identity must be known
- */
- if (c->kind == CK_PERMANENT)
- {
- pubkey_list_t *p;
-
- /* look for a matching RSA public key */
- for (p = pubkeys; p != NULL; p = p->next)
+ /* do not consider rw connections since
+ * the peer's identity must be known
+ */
+ if (c->kind == CK_PERMANENT)
{
- pubkey_t *key = p->key;
+ pubkey_list_t *p;
- if (key->alg == PUBKEY_ALG_RSA &&
- same_id(&c->spd.that.id, &key->id) &&
- key->until_time == UNDEFINED_TIME)
- {
- /* found a preloaded public key */
- return TRUE;
- }
+ /* look for a matching RSA public key */
+ for (p = pubkeys; p != NULL; p = p->next)
+ {
+ pubkey_t *key = p->key;
+ key_type_t type = key->public_key->get_type(key->public_key);
+
+ if (type == KEY_RSA && same_id(&c->spd.that.id, &key->id) &&
+ key->until_time == UNDEFINED_TIME)
+ {
+ /* found a preloaded public key */
+ return TRUE;
+ }
+ }
}
- }
- return FALSE;
+ return FALSE;
}
/*
@@ -2794,161 +2629,181 @@ has_preloaded_public_key(struct state *st)
* RFC 2409 "IKE" section 5.5
* specifies how this is to be done.
*/
-static void
-compute_proto_keymat(struct state *st
-, u_int8_t protoid
-, struct ipsec_proto_info *pi)
+static void compute_proto_keymat(struct state *st, u_int8_t protoid,
+ struct ipsec_proto_info *pi)
{
- size_t needed_len = 0; /* bytes of keying material needed */
-
- /* Add up the requirements for keying material
- * (It probably doesn't matter if we produce too much!)
- */
- switch (protoid)
- {
- case PROTO_IPSEC_ESP:
- switch (pi->attrs.transid)
- {
- case ESP_NULL:
- needed_len = 0;
- break;
- case ESP_DES:
- needed_len = DES_CBC_BLOCK_SIZE;
- break;
- case ESP_3DES:
- needed_len = DES_CBC_BLOCK_SIZE * 3;
- break;
- default:
+ size_t needed_len = 0; /* bytes of keying material needed */
+
+ /* Add up the requirements for keying material
+ * (It probably doesn't matter if we produce too much!)
+ */
+ switch (protoid)
+ {
+ case PROTO_IPSEC_ESP:
+ switch (pi->attrs.transid)
+ {
+ case ESP_NULL:
+ needed_len = 0;
+ break;
+ case ESP_DES:
+ needed_len = DES_CBC_BLOCK_SIZE;
+ break;
+ case ESP_3DES:
+ needed_len = DES_CBC_BLOCK_SIZE * 3;
+ break;
+ default:
#ifndef NO_KERNEL_ALG
- if((needed_len=kernel_alg_esp_enc_keylen(pi->attrs.transid))>0) {
- /* XXX: check key_len "coupling with kernel.c's */
- if (pi->attrs.key_len) {
- needed_len=pi->attrs.key_len/8;
- DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
- "key_len=%d from peer",
- (int)needed_len));
- }
- break;
- }
+ if((needed_len=kernel_alg_esp_enc_keylen(pi->attrs.transid))>0) {
+ /* XXX: check key_len "coupling with kernel.c's */
+ if (pi->attrs.key_len) {
+ needed_len=pi->attrs.key_len/8;
+ DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
+ "key_len=%d from peer",
+ (int)needed_len));
+ }
+ break;
+ }
#endif
- bad_case(pi->attrs.transid);
- }
+ bad_case(pi->attrs.transid);
+ }
#ifndef NO_KERNEL_ALG
- DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
- "needed_len (after ESP enc)=%d",
- (int)needed_len));
- if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL)) {
- needed_len += kernel_alg_esp_auth_keylen(pi->attrs.auth);
- } else
+ DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
+ "needed_len (after ESP enc)=%d",
+ (int)needed_len));
+ if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL)) {
+ needed_len += kernel_alg_esp_auth_keylen(pi->attrs.auth);
+ } else
#endif
- switch (pi->attrs.auth)
- {
- case AUTH_ALGORITHM_NONE:
- break;
- case AUTH_ALGORITHM_HMAC_MD5:
- needed_len += HMAC_MD5_KEY_LEN;
- break;
- case AUTH_ALGORITHM_HMAC_SHA1:
- needed_len += HMAC_SHA1_KEY_LEN;
- break;
- case AUTH_ALGORITHM_DES_MAC:
- default:
- bad_case(pi->attrs.auth);
- }
- DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
- "needed_len (after ESP auth)=%d",
- (int)needed_len));
- break;
-
- case PROTO_IPSEC_AH:
- switch (pi->attrs.transid)
- {
- case AH_MD5:
- needed_len = HMAC_MD5_KEY_LEN;
- break;
- case AH_SHA:
- needed_len = HMAC_SHA1_KEY_LEN;
- break;
- default:
- bad_case(pi->attrs.transid);
- }
- break;
-
- default:
- bad_case(protoid);
- }
-
- pi->keymat_len = needed_len;
-
- /* Allocate space for the keying material.
- * Although only needed_len bytes are desired, we
- * must round up to a multiple of ctx.hmac_digest_size
- * so that our buffer isn't overrun.
- */
- {
- struct hmac_ctx ctx_me, ctx_peer;
- size_t needed_space; /* space needed for keying material (rounded up) */
- size_t i;
-
- hmac_init_chunk(&ctx_me, st->st_oakley.hasher, st->st_skeyid_d);
- ctx_peer = ctx_me; /* duplicate initial conditions */
-
- needed_space = needed_len + pad_up(needed_len, ctx_me.hmac_digest_size);
- replace(pi->our_keymat, alloc_bytes(needed_space, "keymat in compute_keymat()"));
- replace(pi->peer_keymat, alloc_bytes(needed_space, "peer_keymat in quick_inI1_outR1()"));
-
- for (i = 0;; )
- {
- if (st->st_shared.ptr != NULL)
- {
- /* PFS: include the g^xy */
- hmac_update_chunk(&ctx_me, st->st_shared);
- hmac_update_chunk(&ctx_peer, st->st_shared);
- }
- hmac_update(&ctx_me, &protoid, sizeof(protoid));
- hmac_update(&ctx_peer, &protoid, sizeof(protoid));
-
- hmac_update(&ctx_me, (u_char *)&pi->our_spi, sizeof(pi->our_spi));
- hmac_update(&ctx_peer, (u_char *)&pi->attrs.spi, sizeof(pi->attrs.spi));
-
- hmac_update_chunk(&ctx_me, st->st_ni);
- hmac_update_chunk(&ctx_peer, st->st_ni);
-
- hmac_update_chunk(&ctx_me, st->st_nr);
- hmac_update_chunk(&ctx_peer, st->st_nr);
-
- hmac_final(pi->our_keymat + i, &ctx_me);
- hmac_final(pi->peer_keymat + i, &ctx_peer);
-
- i += ctx_me.hmac_digest_size;
- if (i >= needed_space)
- break;
+ switch (pi->attrs.auth)
+ {
+ case AUTH_ALGORITHM_NONE:
+ break;
+ case AUTH_ALGORITHM_HMAC_MD5:
+ needed_len += HMAC_MD5_KEY_LEN;
+ break;
+ case AUTH_ALGORITHM_HMAC_SHA1:
+ needed_len += HMAC_SHA1_KEY_LEN;
+ break;
+ case AUTH_ALGORITHM_DES_MAC:
+ default:
+ bad_case(pi->attrs.auth);
+ }
+ DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
+ "needed_len (after ESP auth)=%d",
+ (int)needed_len));
+ break;
+
+ case PROTO_IPSEC_AH:
+ switch (pi->attrs.transid)
+ {
+ case AH_MD5:
+ needed_len = HMAC_MD5_KEY_LEN;
+ break;
+ case AH_SHA:
+ needed_len = HMAC_SHA1_KEY_LEN;
+ break;
+ default:
+ bad_case(pi->attrs.transid);
+ }
+ break;
+
+ default:
+ bad_case(protoid);
+ }
+
+ pi->keymat_len = needed_len;
+
+ /* Allocate space for the keying material. Although only needed_len bytes
+ * are desired, we must round up to a multiple of hash_size
+ * so that our buffer isn't overrun.
+ */
+ {
+ size_t needed_space; /* space needed for keying material (rounded up) */
+ size_t i, prf_block_size;
+ chunk_t protoid_chunk = chunk_from_thing(protoid);
+ chunk_t spi_our = chunk_from_thing(pi->our_spi);
+ chunk_t spi_peer = chunk_from_thing(pi->attrs.spi);
+ pseudo_random_function_t prf_alg;
+ prf_t *prf_our, *prf_peer;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf_our = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf_peer = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf_our->set_key(prf_our, st->st_skeyid_d);
+ prf_peer->set_key(prf_peer, st->st_skeyid_d);
+ prf_block_size = prf_our->get_block_size(prf_our);
+
+ needed_space = needed_len + pad_up(needed_len, prf_block_size);
+ replace(pi->our_keymat, malloc(needed_space));
+ replace(pi->peer_keymat, malloc(needed_space));
+
+ for (i = 0;; )
+ {
+ char *keymat_i_our = pi->our_keymat + i;
+ char *keymat_i_peer = pi->peer_keymat + i;
+ chunk_t keymat_our = { keymat_i_our, prf_block_size };
+ chunk_t keymat_peer = { keymat_i_peer, prf_block_size };
+
+ if (st->st_shared.ptr != NULL)
+ {
+ /* PFS: include the g^xy */
+ prf_our->get_bytes(prf_our, st->st_shared, NULL);
+ prf_peer->get_bytes(prf_peer, st->st_shared, NULL);
+ }
+ prf_our->get_bytes(prf_our, protoid_chunk, NULL);
+ prf_peer->get_bytes(prf_peer, protoid_chunk, NULL);
+
+ prf_our->get_bytes(prf_our, spi_our, NULL);
+ prf_peer->get_bytes(prf_peer, spi_peer, NULL);
- /* more keying material needed: prepare to go around again */
+ prf_our->get_bytes(prf_our, st->st_ni, NULL);
+ prf_peer->get_bytes(prf_peer, st->st_ni, NULL);
- hmac_reinit(&ctx_me);
- hmac_reinit(&ctx_peer);
+ prf_our->get_bytes(prf_our, st->st_nr, keymat_i_our);
+ prf_peer->get_bytes(prf_peer, st->st_nr, keymat_i_peer);
+
+ i += prf_block_size;
+ if (i >= needed_space)
+ {
+ break;
+ }
- hmac_update(&ctx_me, pi->our_keymat + i - ctx_me.hmac_digest_size
- , ctx_me.hmac_digest_size);
- hmac_update(&ctx_peer, pi->peer_keymat + i - ctx_peer.hmac_digest_size
- , ctx_peer.hmac_digest_size);
+ /* more keying material needed: prepare to go around again */
+ prf_our->get_bytes(prf_our, keymat_our, NULL);
+ prf_peer->get_bytes(prf_peer, keymat_peer, NULL);
+ }
+ prf_our->destroy(prf_our);
+ prf_peer->destroy(prf_peer);
}
- }
+ DBG(DBG_CRYPT,
+ DBG_dump("KEYMAT computed:\n", pi->our_keymat, pi->keymat_len);
+ DBG_dump("Peer KEYMAT computed:\n", pi->peer_keymat, pi->keymat_len));
+}
- DBG(DBG_CRYPT,
- DBG_dump("KEYMAT computed:\n", pi->our_keymat, pi->keymat_len);
- DBG_dump("Peer KEYMAT computed:\n", pi->peer_keymat, pi->keymat_len));
+static void compute_keymats(struct state *st)
+{
+ if (st->st_ah.present)
+ compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah);
+ if (st->st_esp.present)
+ compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp);
}
-static void
-compute_keymats(struct state *st)
+static bool uses_pubkey_auth(int auth)
{
- if (st->st_ah.present)
- compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah);
- if (st->st_esp.present)
- compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp);
+ switch (auth)
+ {
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ return TRUE;
+ default:
+ return FALSE;
+ }
}
/* State Transition Functions.
@@ -2973,261 +2828,272 @@ compute_keymats(struct state *st)
/* Handle a Main Mode Oakley first packet (responder side).
* HDR;SA --> HDR;SA
*/
-stf_status
-main_inI1_outR1(struct msg_digest *md)
+stf_status main_inI1_outR1(struct msg_digest *md)
{
- struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
- struct state *st;
- struct connection *c;
- struct isakmp_proposal proposal;
- pb_stream proposal_pbs;
- pb_stream r_sa_pbs;
- u_int32_t ipsecdoisit;
- lset_t policy = LEMPTY;
- int vids_to_send = 0;
-
- /* We preparse the peer's proposal in order to determine
- * the requested authentication policy (RSA or PSK)
- */
- RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa
- , &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
-
- backup_pbs(&proposal_pbs);
- RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
- , proposal.isap_notrans, &policy));
- restore_pbs(&proposal_pbs);
-
- /* We are only considering candidate connections that match
- * the requested authentication policy (RSA or PSK)
- */
- c = find_host_connection(&md->iface->addr, pluto_port
- , &md->sender, md->sender_port, policy);
-
- if (c == NULL && md->iface->ike_float)
- {
- c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT
- , &md->sender, md->sender_port, policy);
- }
-
- if (c == NULL)
- {
- /* See if a wildcarded connection can be found.
- * We cannot pick the right connection, so we're making a guess.
- * All Road Warrior connections are fair game:
- * we pick the first we come across (if any).
- * If we don't find any, we pick the first opportunistic
- * with the smallest subnet that includes the peer.
- * There is, of course, no necessary relationship between
- * an Initiator's address and that of its client,
- * but Food Groups kind of assumes one.
+ struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
+ struct state *st;
+ struct connection *c;
+ struct isakmp_proposal proposal;
+ pb_stream proposal_pbs;
+ pb_stream r_sa_pbs;
+ u_int32_t ipsecdoisit;
+ lset_t policy = LEMPTY;
+ int vids_to_send = 0;
+
+ /* We preparse the peer's proposal in order to determine
+ * the requested authentication policy (RSA or PSK)
+ */
+ RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa
+ , &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
+
+ backup_pbs(&proposal_pbs);
+ RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
+ , proposal.isap_notrans, &policy));
+ restore_pbs(&proposal_pbs);
+
+ /* We are only considering candidate connections that match
+ * the requested authentication policy (RSA or PSK)
*/
+ c = find_host_connection(&md->iface->addr, pluto_port
+ , &md->sender, md->sender_port, policy);
+
+ if (c == NULL && md->iface->ike_float)
{
- struct connection *d;
+ c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT
+ , &md->sender, md->sender_port, policy);
+ }
- d = find_host_connection(&md->iface->addr
- , pluto_port, (ip_address*)NULL, md->sender_port, policy);
+ if (c == NULL)
+ {
+ /* See if a wildcarded connection can be found.
+ * We cannot pick the right connection, so we're making a guess.
+ * All Road Warrior connections are fair game:
+ * we pick the first we come across (if any).
+ * If we don't find any, we pick the first opportunistic
+ * with the smallest subnet that includes the peer.
+ * There is, of course, no necessary relationship between
+ * an Initiator's address and that of its client,
+ * but Food Groups kind of assumes one.
+ */
+ {
+ struct connection *d;
+
+ d = find_host_connection(&md->iface->addr
+ , pluto_port, (ip_address*)NULL, md->sender_port, policy);
+
+ for (; d != NULL; d = d->hp_next)
+ {
+ if (d->kind == CK_GROUP)
+ {
+ /* ignore */
+ }
+ else
+ {
+ if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO))
+ {
+ /* must be Road Warrior: we have a winner */
+ c = d;
+ break;
+ }
+
+ /* Opportunistic or Shunt: pick tightest match */
+ if (addrinsubnet(&md->sender, &d->spd.that.client)
+ && (c == NULL || !subnetinsubnet(&c->spd.that.client, &d->spd.that.client)))
+ c = d;
+ }
+ }
+ }
- for (; d != NULL; d = d->hp_next)
- {
- if (d->kind == CK_GROUP)
+ if (c == NULL)
{
- /* ignore */
+ loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u"
+ " but no connection has been authorized%s%s"
+ , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr))
+ , (policy != LEMPTY) ? " with policy=" : ""
+ , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : "");
+ /* XXX notification is in order! */
+ return STF_IGNORE;
+ }
+ else if (c->kind != CK_TEMPLATE)
+ {
+ loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u"
+ " but \"%s\" forbids connection"
+ , ip_str(&md->iface->addr), pluto_port, c->name);
+ /* XXX notification is in order! */
+ return STF_IGNORE;
}
else
{
- if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO))
- {
- /* must be Road Warrior: we have a winner */
- c = d;
- break;
- }
-
- /* Opportunistic or Shunt: pick tightest match */
- if (addrinsubnet(&md->sender, &d->spd.that.client)
- && (c == NULL || !subnetinsubnet(&c->spd.that.client, &d->spd.that.client)))
- c = d;
+ /* Create a temporary connection that is a copy of this one.
+ * His ID isn't declared yet.
+ */
+ c = rw_instantiate(c, &md->sender, md->sender_port, NULL, NULL);
}
- }
+ }
+ else if (c->kind == CK_TEMPLATE)
+ {
+ /* Create an instance
+ * This is a rare case: wildcard peer ID but static peer IP address
+ */
+ c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id);
}
- if (c == NULL)
+ /* Set up state */
+ md->st = st = new_state();
+ st->st_connection = c;
+ set_cur_state(st); /* (caller will reset cur_state) */
+ st->st_try = 0; /* not our job to try again from start */
+ st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */
+
+ memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE);
+ get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender);
+
+ insert_state(st); /* needs cookies, connection, and msgid (0) */
+
+ st->st_doi = ISAKMP_DOI_IPSEC;
+ st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */
+
+ if ((c->kind == CK_INSTANCE) && (c->spd.that.host_port != pluto_port))
{
- loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u"
- " but no connection has been authorized%s%s"
- , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr))
- , (policy != LEMPTY) ? " with policy=" : ""
- , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : "");
- /* XXX notification is in order! */
- return STF_IGNORE;
+ plog("responding to Main Mode from unknown peer %s:%u"
+ , ip_str(&c->spd.that.host_addr), c->spd.that.host_port);
}
- else if (c->kind != CK_TEMPLATE)
+ else if (c->kind == CK_INSTANCE)
{
- loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u"
- " but \"%s\" forbids connection"
- , ip_str(&md->iface->addr), pluto_port, c->name);
- /* XXX notification is in order! */
- return STF_IGNORE;
+ plog("responding to Main Mode from unknown peer %s"
+ , ip_str(&c->spd.that.host_addr));
}
else
{
- /* Create a temporary connection that is a copy of this one.
- * His ID isn't declared yet.
- */
- c = rw_instantiate(c, &md->sender, md->sender_port, NULL, NULL);
+ plog("responding to Main Mode");
}
- }
- else if (c->kind == CK_TEMPLATE)
- {
- /* Create an instance
- * This is a rare case: wildcard peer ID but static peer IP address
- */
- c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id);
- }
-
- /* Set up state */
- md->st = st = new_state();
- st->st_connection = c;
- set_cur_state(st); /* (caller will reset cur_state) */
- st->st_try = 0; /* not our job to try again from start */
- st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */
-
- memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE);
- get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender);
-
- insert_state(st); /* needs cookies, connection, and msgid (0) */
-
- st->st_doi = ISAKMP_DOI_IPSEC;
- st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */
-
- if ((c->kind == CK_INSTANCE) && (c->spd.that.host_port != pluto_port))
- {
- plog("responding to Main Mode from unknown peer %s:%u"
- , ip_str(&c->spd.that.host_addr), c->spd.that.host_port);
- }
- else if (c->kind == CK_INSTANCE)
- {
- plog("responding to Main Mode from unknown peer %s"
- , ip_str(&c->spd.that.host_addr));
- }
- else
- {
- plog("responding to Main Mode");
- }
-
- /* parse_isakmp_sa also spits out a winning SA into our reply,
- * so we have to build our md->reply and emit HDR before calling it.
- */
-
- /* determine how many Vendor ID payloads we will be sending */
- if (SEND_PLUTO_VID)
- vids_to_send++;
- if (SEND_CISCO_UNITY_VID)
- vids_to_send++;
- if (md->openpgp)
- vids_to_send++;
- if (SEND_XAUTH_VID)
- vids_to_send++;
- /* always send DPD Vendor ID */
- vids_to_send++;
- if (md->nat_traversal_vid && nat_traversal_enabled)
- vids_to_send++;
-
- /* HDR out.
- * We can't leave this to comm_handle() because we must
- * fill in the cookie.
- */
- {
- struct isakmp_hdr r_hdr = md->hdr;
-
- r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */
- memcpy(r_hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- r_hdr.isa_np = ISAKMP_NEXT_SA;
- if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
- return STF_INTERNAL_ERROR;
- }
- /* start of SA out */
- {
- struct isakmp_sa r_sa = sa_pd->payload.sa;
+ /* parse_isakmp_sa also spits out a winning SA into our reply,
+ * so we have to build our md->reply and emit HDR before calling it.
+ */
- r_sa.isasa_np = vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE;
+ /* determine how many Vendor ID payloads we will be sending */
+ if (SEND_PLUTO_VID)
+ {
+ vids_to_send++;
+ }
+ if (SEND_CISCO_UNITY_VID)
+ {
+ vids_to_send++;
+ }
+ if (md->openpgp)
+ {
+ vids_to_send++;
+ }
+ if (SEND_XAUTH_VID)
+ {
+ vids_to_send++;
+ }
+ /* always send DPD Vendor ID */
+ vids_to_send++;
+ if (md->nat_traversal_vid && nat_traversal_enabled)
+ {
+ vids_to_send++;
+ }
- if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
- return STF_INTERNAL_ERROR;
- }
+ /* HDR out.
+ * We can't leave this to comm_handle() because we must
+ * fill in the cookie.
+ */
+ {
+ struct isakmp_hdr r_hdr = md->hdr;
- /* SA body in and out */
- RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs
- ,&proposal, &r_sa_pbs, st, FALSE));
+ r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */
+ memcpy(r_hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
+ r_hdr.isa_np = ISAKMP_NEXT_SA;
+ if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+ return STF_INTERNAL_ERROR;
+ }
- /* if enabled send Pluto Vendor ID */
- if (SEND_PLUTO_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_STRONGSWAN))
+ /* start of SA out */
{
- return STF_INTERNAL_ERROR;
+ struct isakmp_sa r_sa = sa_pd->payload.sa;
+
+ r_sa.isasa_np = vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE;
+
+ if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
+ return STF_INTERNAL_ERROR;
}
- }
- /* if enabled send Cisco Unity Vendor ID */
- if (SEND_CISCO_UNITY_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_CISCO_UNITY))
+ /* SA body in and out */
+ RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs
+ ,&proposal, &r_sa_pbs, st, FALSE));
+
+ /* if enabled send Pluto Vendor ID */
+ if (SEND_PLUTO_VID)
{
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_STRONGSWAN))
+ {
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /*
- * if the peer sent an OpenPGP Vendor ID we offer the same capability
- */
- if (md->openpgp)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_OPENPGP))
+ /* if enabled send Cisco Unity Vendor ID */
+ if (SEND_CISCO_UNITY_VID)
{
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_CISCO_UNITY))
+ {
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* Announce our ability to do eXtended AUTHentication to the peer */
- if (SEND_XAUTH_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_MISC_XAUTH))
+ /*
+ * if the peer sent an OpenPGP Vendor ID we offer the same capability
+ */
+ if (md->openpgp)
{
- return STF_INTERNAL_ERROR;
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_OPENPGP))
+ {
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- /* Announce our ability to do Dead Peer Detection to the peer */
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_MISC_DPD))
- {
- return STF_INTERNAL_ERROR;
- }
+ /* Announce our ability to do eXtended AUTHentication to the peer */
+ if (SEND_XAUTH_VID)
+ {
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_MISC_XAUTH))
+ {
+ return STF_INTERNAL_ERROR;
+ }
+ }
- if (md->nat_traversal_vid && nat_traversal_enabled)
- {
- /* reply if NAT-Traversal draft is supported */
- st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid);
+ /* Announce our ability to do Dead Peer Detection to the peer */
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_MISC_DPD))
+ {
+ return STF_INTERNAL_ERROR;
+ }
- if (st->nat_traversal
- && !out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, md->nat_traversal_vid))
+ if (md->nat_traversal_vid && nat_traversal_enabled)
{
- return STF_INTERNAL_ERROR;
+ /* reply if NAT-Traversal draft is supported */
+ st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid);
+
+ if (st->nat_traversal
+ && !out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, md->nat_traversal_vid))
+ {
+ return STF_INTERNAL_ERROR;
+ }
}
- }
- close_message(&md->rbody);
+ close_message(&md->rbody);
- /* save initiator SA for HASH */
- clonereplacechunk(st->st_p1isa, sa_pd->pbs.start, pbs_room(&sa_pd->pbs), "sa in main_inI1_outR1()");
+ /* save initiator SA for HASH */
+ free(st->st_p1isa.ptr);
+ st->st_p1isa = chunk_create(sa_pd->pbs.start, pbs_room(&sa_pd->pbs));
+ st->st_p1isa = chunk_clone(st->st_p1isa);
- return STF_OK;
+ return STF_OK;
}
/* STATE_MAIN_I1: HDR, SA --> auth dependent
@@ -3240,95 +3106,94 @@ main_inI1_outR1(struct msg_digest *md)
*
* We must verify that the proposal received matches one we sent.
*/
-stf_status
-main_inR1_outI2(struct msg_digest *md)
+stf_status main_inR1_outI2(struct msg_digest *md)
{
- struct state *const st = md->st;
+ struct state *const st = md->st;
- u_int8_t np = ISAKMP_NEXT_NONE;
+ u_int8_t np = ISAKMP_NEXT_NONE;
- /* verify echoed SA */
- {
- u_int32_t ipsecdoisit;
- pb_stream proposal_pbs;
- struct isakmp_proposal proposal;
- struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
-
- RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sapd->payload.sa
- ,&sapd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
- if (proposal.isap_notrans != 1)
- {
- loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u"
- , (unsigned)proposal.isap_notrans);
- RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX);
- }
- RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
- , &proposal_pbs, &proposal, NULL, st, TRUE));
- }
-
- if (nat_traversal_enabled && md->nat_traversal_vid)
- {
- st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid);
- plog("enabling possible NAT-traversal with method %s"
- , bitnamesof(natt_type_bitnames, st->nat_traversal));
- }
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
- ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS;
- }
-
- /**************** build output packet HDR;KE;Ni ****************/
-
- /* HDR out.
- * We can't leave this to comm_handle() because the isa_np
- * depends on the type of Auth (eventually).
- */
- echo_hdr(md, FALSE, ISAKMP_NEXT_KE);
-
- /* KE out */
- if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group
- , &md->rbody, ISAKMP_NEXT_NONCE))
- return STF_INTERNAL_ERROR;
+ /* verify echoed SA */
+ {
+ u_int32_t ipsecdoisit;
+ pb_stream proposal_pbs;
+ struct isakmp_proposal proposal;
+ struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
+
+ RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sapd->payload.sa
+ ,&sapd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
+ if (proposal.isap_notrans != 1)
+ {
+ loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u"
+ , (unsigned)proposal.isap_notrans);
+ RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX);
+ }
+ RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
+ , &proposal_pbs, &proposal, NULL, st, TRUE));
+ }
+
+ if (nat_traversal_enabled && md->nat_traversal_vid)
+ {
+ st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid);
+ plog("enabling possible NAT-traversal with method %s"
+ , bitnamesof(natt_type_bitnames, st->nat_traversal));
+ }
+ if (st->nat_traversal & NAT_T_WITH_NATD)
+ {
+ np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
+ ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS;
+ }
+
+ /**************** build output packet HDR;KE;Ni ****************/
+
+ /* HDR out.
+ * We can't leave this to comm_handle() because the isa_np
+ * depends on the type of Auth (eventually).
+ */
+ echo_hdr(md, FALSE, ISAKMP_NEXT_KE);
+
+ /* KE out */
+ if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group
+ , &md->rbody, ISAKMP_NEXT_NONCE))
+ return STF_INTERNAL_ERROR;
#ifdef DEBUG
- /* Ni out */
- if (!build_and_ship_nonce(&st->st_ni, &md->rbody
- , (cur_debugging & IMPAIR_BUST_MI2)? ISAKMP_NEXT_VID : np, "Ni"))
- return STF_INTERNAL_ERROR;
-
- if (cur_debugging & IMPAIR_BUST_MI2)
- {
- /* generate a pointless large VID payload to push message over MTU */
- pb_stream vid_pbs;
-
- if (!out_generic(np, &isakmp_vendor_id_desc, &md->rbody, &vid_pbs))
- return STF_INTERNAL_ERROR;
- if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID"))
- return STF_INTERNAL_ERROR;
- close_output_pbs(&vid_pbs);
- }
+ /* Ni out */
+ if (!build_and_ship_nonce(&st->st_ni, &md->rbody
+ , (cur_debugging & IMPAIR_BUST_MI2)? ISAKMP_NEXT_VID : np, "Ni"))
+ return STF_INTERNAL_ERROR;
+
+ if (cur_debugging & IMPAIR_BUST_MI2)
+ {
+ /* generate a pointless large VID payload to push message over MTU */
+ pb_stream vid_pbs;
+
+ if (!out_generic(np, &isakmp_vendor_id_desc, &md->rbody, &vid_pbs))
+ return STF_INTERNAL_ERROR;
+ if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID"))
+ return STF_INTERNAL_ERROR;
+ close_output_pbs(&vid_pbs);
+ }
#else
- /* Ni out */
- if (!build_and_ship_nonce(&st->st_ni, &md->rbody, np, "Ni"))
- return STF_INTERNAL_ERROR;
+ /* Ni out */
+ if (!build_and_ship_nonce(&st->st_ni, &md->rbody, np, "Ni"))
+ return STF_INTERNAL_ERROR;
#endif
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md))
- return STF_INTERNAL_ERROR;
- }
+ if (st->nat_traversal & NAT_T_WITH_NATD)
+ {
+ if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md))
+ return STF_INTERNAL_ERROR;
+ }
- /* finish message */
- close_message(&md->rbody);
+ /* 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) */
+ /* 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) */
- return STF_OK;
+ return STF_OK;
}
/* STATE_MAIN_R1:
@@ -3336,140 +3201,137 @@ main_inR1_outI2(struct msg_digest *md)
*
* 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
+ * --> 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
+ * 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)
+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;
-
- /* send CR if auth is RSA and no preloaded RSA public key exists*/
- bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
- || st->st_oakley.auth == XAUTHInitRSA
- || st->st_oakley.auth == XAUTHRespRSA;
- bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st);
+ struct state *const st = md->st;
+ pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+ /* send CR if auth is RSA or ECDSA and no preloaded public key exists*/
+ bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
+ bool send_cr = !no_cr_send && pubkey_auth && !has_preloaded_public_key(st);
- u_int8_t np = ISAKMP_NEXT_NONE;
+ u_int8_t np = ISAKMP_NEXT_NONE;
- /* KE in */
- RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs));
+ /* 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"));
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- nat_traversal_natd_lookup(md);
+ if (st->nat_traversal & NAT_T_WITH_NATD)
+ {
+ nat_traversal_natd_lookup(md);
- np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
- ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS;
- }
- if (st->nat_traversal)
- {
- nat_traversal_show_result(st->nat_traversal, md->sender_port);
- }
- if (st->nat_traversal & NAT_T_WITH_KA)
- {
- nat_traversal_new_ka_event();
- }
+ np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
+ ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS;
+ }
+ if (st->nat_traversal)
+ {
+ nat_traversal_show_result(st->nat_traversal, md->sender_port);
+ }
+ if (st->nat_traversal & NAT_T_WITH_KA)
+ {
+ nat_traversal_new_ka_event();
+ }
- /* decode certificate requests */
- st->st_connection->got_certrequest = FALSE;
- decode_cr(md, st->st_connection);
+ /* decode certificate requests */
+ st->st_connection->got_certrequest = FALSE;
+ decode_cr(md, st->st_connection);
- /**************** build output packet HDR;KE;Nr ****************/
+ /**************** build output packet HDR;KE;Nr ****************/
- /* 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;
+ /* KE out */
+ if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group
+ , &md->rbody, ISAKMP_NEXT_NONCE))
+ return STF_INTERNAL_ERROR;
#ifdef DEBUG
- /* Nr out */
- if (!build_and_ship_nonce(&st->st_nr, &md->rbody
- , (cur_debugging & IMPAIR_BUST_MR2)? ISAKMP_NEXT_VID
- : (send_cr? ISAKMP_NEXT_CR : np), "Nr"))
- return STF_INTERNAL_ERROR;
-
- if (cur_debugging & IMPAIR_BUST_MR2)
- {
- /* generate a pointless large VID payload to push message over MTU */
- pb_stream vid_pbs;
-
- if (!out_generic((send_cr)? ISAKMP_NEXT_CR : np,
- &isakmp_vendor_id_desc, &md->rbody, &vid_pbs))
- return STF_INTERNAL_ERROR;
- if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID"))
- return STF_INTERNAL_ERROR;
- close_output_pbs(&vid_pbs);
- }
+ /* Nr out */
+ if (!build_and_ship_nonce(&st->st_nr, &md->rbody
+ , (cur_debugging & IMPAIR_BUST_MR2)? ISAKMP_NEXT_VID
+ : (send_cr? ISAKMP_NEXT_CR : np), "Nr"))
+ return STF_INTERNAL_ERROR;
+
+ if (cur_debugging & IMPAIR_BUST_MR2)
+ {
+ /* generate a pointless large VID payload to push message over MTU */
+ pb_stream vid_pbs;
+
+ if (!out_generic((send_cr)? ISAKMP_NEXT_CR : np,
+ &isakmp_vendor_id_desc, &md->rbody, &vid_pbs))
+ return STF_INTERNAL_ERROR;
+ if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID"))
+ return STF_INTERNAL_ERROR;
+ close_output_pbs(&vid_pbs);
+ }
#else
- /* Nr out */
- if (!build_and_ship_nonce(&st->st_nr, &md->rbody,
- (send_cr)? ISAKMP_NEXT_CR : np, "Nr"))
- return STF_INTERNAL_ERROR;
+ /* Nr out */
+ if (!build_and_ship_nonce(&st->st_nr, &md->rbody,
+ (send_cr)? ISAKMP_NEXT_CR : np, "Nr"))
+ return STF_INTERNAL_ERROR;
#endif
- /* CR out */
- if (send_cr)
- {
- if (st->st_connection->kind == CK_PERMANENT)
+ /* CR out */
+ if (send_cr)
{
- if (!build_and_ship_CR(CERT_X509_SIGNATURE
- , st->st_connection->spd.that.ca
- , &md->rbody, np))
- return STF_INTERNAL_ERROR;
+ if (st->st_connection->kind == CK_PERMANENT)
+ {
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE
+ , st->st_connection->spd.that.ca
+ , &md->rbody, np))
+ return STF_INTERNAL_ERROR;
+ }
+ else
+ {
+ generalName_t *ca = NULL;
+
+ if (collect_rw_ca_candidates(md, &ca))
+ {
+ generalName_t *gn;
+
+ for (gn = ca; gn != NULL; gn = gn->next)
+ {
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE, gn->name
+ , &md->rbody
+ , gn->next == NULL ? np : ISAKMP_NEXT_CR))
+ return STF_INTERNAL_ERROR;
+ }
+ free_generalNames(ca, FALSE);
+ }
+ else
+ {
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE, chunk_empty
+ , &md->rbody, np))
+ return STF_INTERNAL_ERROR;
+ }
+ }
}
- else
+
+ if (st->nat_traversal & NAT_T_WITH_NATD)
{
- generalName_t *ca = NULL;
+ if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md))
+ return STF_INTERNAL_ERROR;
+ }
- if (collect_rw_ca_candidates(md, &ca))
- {
- generalName_t *gn;
+ /* finish message */
+ close_message(&md->rbody);
- for (gn = ca; gn != NULL; gn = gn->next)
- {
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, gn->name
- , &md->rbody
- , gn->next == NULL ? np : ISAKMP_NEXT_CR))
- return STF_INTERNAL_ERROR;
- }
- free_generalNames(ca, FALSE);
- }
- else
- {
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, empty_chunk
- , &md->rbody, np))
- return STF_INTERNAL_ERROR;
- }
- }
- }
-
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md))
- 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);
- if (!generate_skeyids_iv(st))
- return STF_FAIL + AUTHENTICATION_FAILED;
- update_iv(st);
-
- return STF_OK;
+ /* next message will be encrypted, but not this one.
+ * We could defer this calculation.
+ */
+ compute_dh_shared(st, st->st_gi);
+ if (!generate_skeyids_iv(st))
+ return STF_FAIL + AUTHENTICATION_FAILED;
+ update_iv(st);
+
+ return STF_OK;
}
/* STATE_MAIN_I2:
@@ -3478,172 +3340,174 @@ main_inI2_outR2(struct msg_digest *md)
*
* The following are not yet implemented.
* SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * --> HDR*, HASH_I
+ * --> HDR*, HASH_I
* SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- * --> HDR*, HASH_I
+ * --> HDR*, HASH_I
*/
-stf_status
-main_inR2_outI3(struct msg_digest *md)
+stf_status main_inR2_outI3(struct msg_digest *md)
{
- struct state *const st = md->st;
- pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
- pb_stream id_pbs; /* ID Payload; also used for hash calculation */
-
- certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
- cert_t mycert = st->st_connection->spd.this.cert;
- bool requested, send_cert, send_cr;
-
- bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
- || st->st_oakley.auth == XAUTHInitRSA
- || st->st_oakley.auth == XAUTHRespRSA;
-
- int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
-
- /* 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"));
-
- /* decode certificate requests */
- st->st_connection->got_certrequest = FALSE;
- decode_cr(md, st->st_connection);
-
- /* free collected certificate requests since as initiator
- * we don't heed them anyway
- */
- free_generalNames(st->st_connection->requested_ca, TRUE);
- st->st_connection->requested_ca = NULL;
-
- /* send certificate if auth is RSA, we have one and we want
- * or are requested to send it
- */
- requested = cert_policy == CERT_SEND_IF_ASKED
- && st->st_connection->got_certrequest;
- send_cert = RSA_auth && mycert.type != CERT_NONE
- && (cert_policy == CERT_ALWAYS_SEND || requested);
-
- /* send certificate request if we don't have a preloaded RSA public key */
- send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
-
- /* done parsing; initialize crypto */
- compute_dh_shared(st, st->st_gr, st->st_oakley.group);
- if (!generate_skeyids_iv(st))
- return STF_FAIL + AUTHENTICATION_FAILED;
-
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- nat_traversal_natd_lookup(md);
- }
- if (st->nat_traversal)
- {
- nat_traversal_show_result(st->nat_traversal, md->sender_port);
- }
- if (st->nat_traversal & NAT_T_WITH_KA)
- {
- nat_traversal_new_ka_event();
- }
-
- /*************** 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;
-
- build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this);
- id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : 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);
- }
+ struct state *const st = md->st;
+ pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+ pb_stream id_pbs; /* ID Payload; also used for hash calculation */
- /* CERT out */
- if (RSA_auth)
- {
- DBG(DBG_CONTROL,
- DBG_log("our certificate policy is %s"
- , enum_name(&cert_policy_names, cert_policy))
- )
- if (mycert.type != CERT_NONE)
- {
- const char *request_text = "";
+ certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
+ cert_t mycert = st->st_connection->spd.this.cert;
+ bool requested, send_cert, send_cr;
+ bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
+
+ int auth_payload = pubkey_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
+
+ /* 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"));
+
+ /* decode certificate requests */
+ st->st_connection->got_certrequest = FALSE;
+ decode_cr(md, st->st_connection);
+
+ /* free collected certificate requests since as initiator
+ * we don't heed them anyway
+ */
+ free_generalNames(st->st_connection->requested_ca, TRUE);
+ st->st_connection->requested_ca = NULL;
+
+ /* send certificate if auth is RSA, we have one and we want
+ * or are requested to send it
+ */
+ requested = cert_policy == CERT_SEND_IF_ASKED
+ && st->st_connection->got_certrequest;
+ send_cert = pubkey_auth && mycert.type != CERT_NONE
+ && (cert_policy == CERT_ALWAYS_SEND || requested);
+
+ /* send certificate request if we don't have a preloaded RSA public key */
+ send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
- if (cert_policy == CERT_SEND_IF_ASKED)
- request_text = (send_cert)? "upon request":"without request";
- plog("we have a cert %s sending it %s"
- , send_cert? "and are":"but are not", request_text);
+ /* done parsing; initialize crypto */
+ compute_dh_shared(st, st->st_gr);
+ if (!generate_skeyids_iv(st))
+ return STF_FAIL + AUTHENTICATION_FAILED;
+
+ if (st->nat_traversal & NAT_T_WITH_NATD)
+ {
+ nat_traversal_natd_lookup(md);
}
- else
+ if (st->nat_traversal)
+ {
+ nat_traversal_show_result(st->nat_traversal, md->sender_port);
+ }
+ if (st->nat_traversal & NAT_T_WITH_KA)
{
- plog("we don't have a cert");
+ nat_traversal_new_ka_event();
}
- }
- if (send_cert)
- {
- pb_stream cert_pbs;
- struct isakmp_cert cert_hd;
- cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG;
- cert_hd.isacert_type = mycert.type;
+ /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
+ /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
- if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
- return STF_INTERNAL_ERROR;
- if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT"))
- return STF_INTERNAL_ERROR;
- close_output_pbs(&cert_pbs);
- }
+ /* HDR* out done */
- /* CR out */
- if (send_cr)
- {
- if (!build_and_ship_CR(mycert.type, st->st_connection->spd.that.ca
- , &md->rbody, ISAKMP_NEXT_SIG))
- return STF_INTERNAL_ERROR;
- }
+ /* IDii out */
+ {
+ struct isakmp_ipsec_id id_hd;
+ chunk_t id_b;
- /* HASH_I or SIG_I out */
- {
- u_char hash_val[MAX_DIGEST_LEN];
- size_t hash_len = main_mode_hash(st, hash_val, TRUE, &id_pbs);
+ build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this);
+ id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : 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);
+ }
- if (auth_payload == ISAKMP_NEXT_HASH)
+ /* CERT out */
+ if (pubkey_auth)
{
- /* 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;
+ DBG(DBG_CONTROL,
+ DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
+ )
+ if (mycert.type != CERT_NONE)
+ {
+ const char *request_text = "";
+
+ if (cert_policy == CERT_SEND_IF_ASKED)
+ request_text = (send_cert)? "upon request":"without request";
+ plog("we have a cert %s sending it %s"
+ , send_cert? "and are":"but are not", request_text);
+ }
+ else
+ {
+ plog("we don't have a cert");
+ }
}
- else
+ if (send_cert)
{
- /* 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);
+ pb_stream cert_pbs;
- if (sig_len == 0)
- {
- loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
- return STF_FAIL + AUTHENTICATION_FAILED;
- }
+ struct isakmp_cert cert_hd;
+ cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG;
+ cert_hd.isacert_type = mycert.type;
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
- , &md->rbody, sig_val, sig_len, "SIG_I"))
- return STF_INTERNAL_ERROR;
+ if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
+ return STF_INTERNAL_ERROR;
+ if (!out_chunk(cert_get_encoding(mycert), &cert_pbs, "CERT"))
+ return STF_INTERNAL_ERROR;
+ close_output_pbs(&cert_pbs);
+ }
+
+ /* CR out */
+ if (send_cr)
+ {
+ if (!build_and_ship_CR(mycert.type, st->st_connection->spd.that.ca
+ , &md->rbody, ISAKMP_NEXT_SIG))
+ return STF_INTERNAL_ERROR;
+ }
+
+ /* HASH_I or SIG_I out */
+ {
+ u_char hash_buf[MAX_DIGEST_LEN];
+ chunk_t hash = chunk_from_buf(hash_buf);
+
+ main_mode_hash(st, &hash, TRUE, &id_pbs);
+
+ if (auth_payload == ISAKMP_NEXT_HASH)
+ {
+ /* HASH_I out */
+ if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody,
+ hash.ptr, hash.len, "HASH_I"))
+ {
+ return STF_INTERNAL_ERROR;
+ }
+ }
+ else
+ {
+ /* SIG_I out */
+ u_char sig_val[RSA_MAX_OCTETS];
+ signature_scheme_t scheme;
+ size_t sig_len;
+
+ scheme = oakley_to_signature_scheme(st->st_oakley.auth);
+
+ sig_len = sign_hash(scheme, st->st_connection, sig_val, hash);
+ if (sig_len == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "unable to locate my private key for 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;
+ }
}
- }
- /* encrypt message, except for fixed part of header */
+ /* 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 */
+ /* st_new_iv was computed by generate_skeyids_iv */
+ if (!encrypt_message(&md->rbody, st))
+ return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- return STF_OK;
+ return STF_OK;
}
/* Shared logic for asynchronous lookup of DNS KEY records.
@@ -3651,31 +3515,31 @@ main_inR2_outI3(struct msg_digest *md)
*/
enum key_oppo_step {
- kos_null,
- kos_his_txt
+ kos_null,
+ kos_his_txt
#ifdef USE_KEYRR
- , kos_his_key
+ , kos_his_key
#endif
};
struct key_continuation {
- struct adns_continuation ac; /* common prefix */
- struct msg_digest *md;
- enum key_oppo_step step;
- bool failure_ok;
- err_t last_ugh;
+ struct adns_continuation ac; /* common prefix */
+ struct msg_digest *md;
+ enum key_oppo_step step;
+ bool failure_ok;
+ err_t last_ugh;
};
typedef stf_status (key_tail_fn)(struct msg_digest *md
- , struct key_continuation *kc);
-static void
-report_key_dns_failure(struct id *id, err_t ugh)
+ , struct key_continuation *kc);
+
+static void report_key_dns_failure(struct id *id, err_t ugh)
{
- char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
+ char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
- (void) idtoa(id, id_buf, sizeof(id_buf));
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
- "; DNS search for KEY failed (%s)", id_buf, ugh);
+ (void) idtoa(id, id_buf, sizeof(id_buf));
+ loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
+ "; DNS search for KEY failed (%s)", id_buf, ugh);
}
@@ -3688,135 +3552,145 @@ report_key_dns_failure(struct id *id, err_t ugh)
*/
static stf_status
main_id_and_auth(struct msg_digest *md
- , bool initiator /* are we the Initiator? */
- , cont_fn_t cont_fn /* continuation function */
- , const struct key_continuation *kc /* current state, can be NULL */
+ , bool initiator /* are we the Initiator? */
+ , cont_fn_t cont_fn /* continuation function */
+ , const struct key_continuation *kc /* current state, can be NULL */
)
{
- struct state *st = md->st;
- u_char hash_val[MAX_DIGEST_LEN];
- size_t hash_len;
- struct id peer;
- stf_status r = STF_OK;
-
- /* ID Payload in */
- if (!decode_peer_id(md, &peer))
- return STF_FAIL + INVALID_ID_INFORMATION;
-
- /* Hash the ID Payload.
- * main_mode_hash requires idpl->cur to be at end of payload
- * so we temporarily set if so.
- */
- {
- pb_stream *idpl = &md->chain[ISAKMP_NEXT_ID]->pbs;
- u_int8_t *old_cur = idpl->cur;
-
- idpl->cur = idpl->roof;
- hash_len = main_mode_hash(st, hash_val, !initiator, idpl);
- idpl->cur = old_cur;
- }
-
- switch (st->st_oakley.auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- {
- pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
-
- if (pbs_left(hash_pbs) != hash_len
- || memcmp(hash_pbs->cur, hash_val, hash_len) != 0)
- {
- DBG_cond_dump(DBG_CRYPT, "received HASH:"
- , hash_pbs->cur, pbs_left(hash_pbs));
- loglog(RC_LOG_SERIOUS, "received Hash Payload does not match computed value");
- /* XXX Could send notification back */
- r = STF_FAIL + INVALID_HASH_INFORMATION;
- }
+ u_char hash_buf[MAX_DIGEST_LEN];
+ chunk_t hash = chunk_from_buf(hash_buf);
+ struct state *st = md->st;
+ struct id peer;
+ stf_status r = STF_OK;
+
+ /* ID Payload in */
+ if (!decode_peer_id(md, &peer))
+ return STF_FAIL + INVALID_ID_INFORMATION;
+
+ /* Hash the ID Payload.
+ * main_mode_hash requires idpl->cur to be at end of payload
+ * so we temporarily set if so.
+ */
+ {
+ pb_stream *idpl = &md->chain[ISAKMP_NEXT_ID]->pbs;
+ u_int8_t *old_cur = idpl->cur;
+
+ idpl->cur = idpl->roof;
+ main_mode_hash(st, &hash, !initiator, idpl);
+ idpl->cur = old_cur;
}
- break;
- case OAKLEY_RSA_SIG:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- r = RSA_check_signature(&peer, st, hash_val, hash_len
- , &md->chain[ISAKMP_NEXT_SIG]->pbs
+ switch (st->st_oakley.auth)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ {
+ pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
+
+ if (pbs_left(hash_pbs) != hash.len
+ || memcmp(hash_pbs->cur, hash.ptr, hash.len) != 0)
+ {
+ DBG_cond_dump(DBG_CRYPT, "received HASH:"
+ , hash_pbs->cur, pbs_left(hash_pbs));
+ loglog(RC_LOG_SERIOUS, "received Hash Payload does not match computed value");
+ /* XXX Could send notification back */
+ r = STF_FAIL + INVALID_HASH_INFORMATION;
+ }
+ }
+ break;
+
+ case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ r = check_signature(KEY_RSA, &peer, st, hash,
+ &md->chain[ISAKMP_NEXT_SIG]->pbs,
#ifdef USE_KEYRR
- , kc == NULL? NULL : kc->ac.keys_from_dns
+ kc == NULL? NULL : kc->ac.keys_from_dns,
#endif /* USE_KEYRR */
- , kc == NULL? NULL : kc->ac.gateways_from_dns
- );
-
- if (r == STF_SUSPEND)
- {
- /* initiate/resume asynchronous DNS lookup for key */
- struct key_continuation *nkc
- = alloc_thing(struct key_continuation, "key continuation");
- enum key_oppo_step step_done = kc == NULL? kos_null : kc->step;
- err_t ugh = NULL;
+ kc == NULL? NULL : kc->ac.gateways_from_dns
+ );
+
+ if (r == STF_SUSPEND)
+ {
+ /* initiate/resume asynchronous DNS lookup for key */
+ struct key_continuation *nkc = malloc_thing(struct key_continuation);
+ enum key_oppo_step step_done = kc == NULL? kos_null : kc->step;
+ err_t ugh = NULL;
- /* Record that state is used by a suspended md */
- passert(st->st_suspended_md == NULL);
- st->st_suspended_md = md;
+ /* Record that state is used by a suspended md */
+ passert(st->st_suspended_md == NULL);
+ st->st_suspended_md = md;
- nkc->failure_ok = FALSE;
- nkc->md = md;
+ nkc->failure_ok = FALSE;
+ nkc->md = md;
- switch (step_done)
- {
- case kos_null:
- /* first try: look for the TXT records */
- nkc->step = kos_his_txt;
+ switch (step_done)
+ {
+ case kos_null:
+ /* first try: look for the TXT records */
+ nkc->step = kos_his_txt;
#ifdef USE_KEYRR
- nkc->failure_ok = TRUE;
+ nkc->failure_ok = TRUE;
#endif
- ugh = start_adns_query(&peer
- , &peer /* SG itself */
- , T_TXT
- , cont_fn
- , &nkc->ac);
- break;
+ ugh = start_adns_query(&peer
+ , &peer /* SG itself */
+ , T_TXT
+ , cont_fn
+ , &nkc->ac);
+ break;
#ifdef USE_KEYRR
- case kos_his_txt:
- /* second try: look for the KEY records */
- nkc->step = kos_his_key;
- ugh = start_adns_query(&peer
- , NULL /* no sgw for KEY */
- , T_KEY
- , cont_fn
- , &nkc->ac);
- break;
+ case kos_his_txt:
+ /* second try: look for the KEY records */
+ nkc->step = kos_his_key;
+ ugh = start_adns_query(&peer
+ , NULL /* no sgw for KEY */
+ , T_KEY
+ , cont_fn
+ , &nkc->ac);
+ break;
#endif /* USE_KEYRR */
- default:
- bad_case(step_done);
- }
+ default:
+ bad_case(step_done);
+ }
- if (ugh != NULL)
- {
- report_key_dns_failure(&peer, ugh);
- st->st_suspended_md = NULL;
- r = STF_FAIL + INVALID_KEY_INFORMATION;
- }
- }
- break;
+ if (ugh != NULL)
+ {
+ report_key_dns_failure(&peer, ugh);
+ st->st_suspended_md = NULL;
+ r = STF_FAIL + INVALID_KEY_INFORMATION;
+ }
+ }
+ break;
- default:
- bad_case(st->st_oakley.auth);
- }
- if (r != STF_OK)
- return r;
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ r = check_signature(KEY_ECDSA, &peer, st, hash,
+ &md->chain[ISAKMP_NEXT_SIG]->pbs,
+#ifdef USE_KEYRR
+ NULL,
+#endif /* USE_KEYRR */
+ NULL);
+ break;
+
+ default:
+ bad_case(st->st_oakley.auth);
+ }
+ if (r != STF_OK)
+ return r;
- DBG(DBG_CRYPT, DBG_log("authentication succeeded"));
+ DBG(DBG_CRYPT, DBG_log("authentication succeeded"));
- /*
- * With the peer ID known, let's see if we need to switch connections.
- */
- if (!switch_connection(md, &peer, initiator))
- return STF_FAIL + INVALID_ID_INFORMATION;
+ /*
+ * With the peer ID known, let's see if we need to switch connections.
+ */
+ if (!switch_connection(md, &peer, initiator))
+ return STF_FAIL + INVALID_ID_INFORMATION;
- return r;
+ return r;
}
/* This continuation is called as part of either
@@ -3840,46 +3714,44 @@ main_id_and_auth(struct msg_digest *md
* to find authentication, or we run out of things
* to try.
*/
-static void
-key_continue(struct adns_continuation *cr
-, err_t ugh
-, key_tail_fn *tail)
+static void key_continue(struct adns_continuation *cr, err_t ugh,
+ key_tail_fn *tail)
{
- struct key_continuation *kc = (void *)cr;
- struct state *st = kc->md->st;
+ struct key_continuation *kc = (void *)cr;
+ struct state *st = kc->md->st;
- passert(cur_state == NULL);
+ passert(cur_state == NULL);
- /* if st == NULL, our state has been deleted -- just clean up */
- if (st != NULL)
- {
- stf_status r;
+ /* if st == NULL, our state has been deleted -- just clean up */
+ if (st != NULL)
+ {
+ stf_status r;
- passert(st->st_suspended_md == kc->md);
- st->st_suspended_md = NULL; /* no longer connected or suspended */
- cur_state = st;
+ passert(st->st_suspended_md == kc->md);
+ st->st_suspended_md = NULL; /* no longer connected or suspended */
+ cur_state = st;
- if (!kc->failure_ok && ugh != NULL)
- {
- report_key_dns_failure(&st->st_connection->spd.that.id, ugh);
- r = STF_FAIL + INVALID_KEY_INFORMATION;
- }
- else
- {
+ if (!kc->failure_ok && ugh != NULL)
+ {
+ report_key_dns_failure(&st->st_connection->spd.that.id, ugh);
+ r = STF_FAIL + INVALID_KEY_INFORMATION;
+ }
+ else
+ {
#ifdef USE_KEYRR
- passert(kc->step == kos_his_txt || kc->step == kos_his_key);
+ passert(kc->step == kos_his_txt || kc->step == kos_his_key);
#else
- passert(kc->step == kos_his_txt);
+ passert(kc->step == kos_his_txt);
#endif
- kc->last_ugh = ugh; /* record previous error in case we need it */
- r = (*tail)(kc->md, kc);
- }
- complete_state_transition(&kc->md, r);
- }
- if (kc->md != NULL)
- release_md(kc->md);
- cur_state = NULL;
+ kc->last_ugh = ugh; /* record previous error in case we need it */
+ r = (*tail)(kc->md, kc);
+ }
+ complete_state_transition(&kc->md, r);
+ }
+ if (kc->md != NULL)
+ release_md(kc->md);
+ cur_state = NULL;
}
/* STATE_MAIN_R2:
@@ -3893,174 +3765,173 @@ key_continue(struct adns_continuation *cr
* - main_inI3_outR3_tail to finish or suspend for DNS lookup
* - main_inI3_outR3_continue to start main_inI3_outR3_tail again
*/
-static key_tail_fn main_inI3_outR3_tail; /* forward */
+static key_tail_fn main_inI3_outR3_tail; /* forward */
-stf_status
-main_inI3_outR3(struct msg_digest *md)
+stf_status main_inI3_outR3(struct msg_digest *md)
{
- return main_inI3_outR3_tail(md, NULL);
+ return main_inI3_outR3_tail(md, NULL);
}
-static void
-main_inI3_outR3_continue(struct adns_continuation *cr, err_t ugh)
+static void main_inI3_outR3_continue(struct adns_continuation *cr, err_t ugh)
{
- key_continue(cr, ugh, main_inI3_outR3_tail);
+ key_continue(cr, ugh, main_inI3_outR3_tail);
}
static stf_status
main_inI3_outR3_tail(struct msg_digest *md
, struct key_continuation *kc)
{
- struct state *const st = md->st;
- u_int8_t auth_payload;
- pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
- certpolicy_t cert_policy;
- cert_t mycert;
- bool RSA_auth;
- bool send_cert;
- bool requested;
-
- /* ID and HASH_I or SIG_I in
- * Note: this may switch the connection being used!
- */
- {
- stf_status r = main_id_and_auth(md, FALSE
- , main_inI3_outR3_continue
- , kc);
-
- if (r != STF_OK)
- return r;
- }
-
- /* send certificate if auth is RSA, we have one and we want
- * or are requested to send it
- */
- cert_policy = st->st_connection->spd.this.sendcert;
- mycert = st->st_connection->spd.this.cert;
- requested = cert_policy == CERT_SEND_IF_ASKED
- && st->st_connection->got_certrequest;
- RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
- || st->st_oakley.auth == XAUTHInitRSA
- || st->st_oakley.auth == XAUTHRespRSA;
- send_cert = RSA_auth
- && mycert.type != CERT_NONE
- && (cert_policy == CERT_ALWAYS_SEND || requested);
-
- /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
- /* proccess_packet() would automatically generate the HDR*
- * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE.
- * We don't do this because we wish there to be no partially
- * built output packet if we need to suspend for asynch DNS.
- */
- /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
-
- /* HDR* out
- * If auth were PKE_AUTH or RPKE_AUTH, ISAKMP_NEXT_HASH would
- * be first payload.
- */
- echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
-
- auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
-
- /* IDir out */
- {
- /* id_hd should be struct isakmp_id, but struct isakmp_ipsec_id
- * allows build_id_payload() to work for both phases.
+ struct state *const st = md->st;
+ u_int8_t auth_payload;
+ pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
+ certpolicy_t cert_policy;
+ cert_t mycert;
+ bool pubkey_auth, send_cert, requested;
+
+ /* ID and HASH_I or SIG_I in
+ * Note: this may switch the connection being used!
*/
- struct isakmp_ipsec_id id_hd;
- chunk_t id_b;
-
- build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this);
- id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload;
- if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
- || !out_chunk(id_b, &r_id_pbs, "my identity"))
- return STF_INTERNAL_ERROR;
- close_output_pbs(&r_id_pbs);
- }
-
- /* CERT out */
- if (RSA_auth)
- {
- DBG(DBG_CONTROL,
- DBG_log("our certificate policy is %s"
- , enum_name(&cert_policy_names, cert_policy))
- )
- if (mycert.type != CERT_NONE)
{
- const char *request_text = "";
+ stf_status r = main_id_and_auth(md, FALSE
+ , main_inI3_outR3_continue
+ , kc);
- if (cert_policy == CERT_SEND_IF_ASKED)
- request_text = (send_cert)? "upon request":"without request";
- plog("we have a cert %s sending it %s"
- , send_cert? "and are":"but are not", request_text);
+ if (r != STF_OK)
+ return r;
}
- else
+
+ /* send certificate if pubkey authentication is used, we have one
+ * and we want or are requested to send it
+ */
+ cert_policy = st->st_connection->spd.this.sendcert;
+ mycert = st->st_connection->spd.this.cert;
+ requested = cert_policy == CERT_SEND_IF_ASKED
+ && st->st_connection->got_certrequest;
+ pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
+ send_cert = pubkey_auth && mycert.type != CERT_NONE &&
+ (cert_policy == CERT_ALWAYS_SEND || requested);
+
+ /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
+ /* proccess_packet() would automatically generate the HDR*
+ * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE.
+ * We don't do this because we wish there to be no partially
+ * built output packet if we need to suspend for asynch DNS.
+ */
+ /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
+
+ /* HDR* out
+ * If auth were PKE_AUTH or RPKE_AUTH, ISAKMP_NEXT_HASH would
+ * be first payload.
+ */
+ echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
+
+ auth_payload = pubkey_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
+
+ /* IDir out */
{
- plog("we don't have a cert");
+ /* id_hd should be struct isakmp_id, but struct isakmp_ipsec_id
+ * allows build_id_payload() to work for both phases.
+ */
+ struct isakmp_ipsec_id id_hd;
+ chunk_t id_b;
+
+ build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this);
+ id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload;
+ if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
+ || !out_chunk(id_b, &r_id_pbs, "my identity"))
+ return STF_INTERNAL_ERROR;
+ close_output_pbs(&r_id_pbs);
}
- }
- if (send_cert)
- {
- pb_stream cert_pbs;
- struct isakmp_cert cert_hd;
- cert_hd.isacert_np = ISAKMP_NEXT_SIG;
- cert_hd.isacert_type = mycert.type;
+ /* CERT out */
+ if (pubkey_auth)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
+ )
+ if (mycert.type != CERT_NONE)
+ {
+ const char *request_text = "";
- if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
- return STF_INTERNAL_ERROR;
- if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT"))
- return STF_INTERNAL_ERROR;
- close_output_pbs(&cert_pbs);
- }
+ if (cert_policy == CERT_SEND_IF_ASKED)
+ request_text = (send_cert)? "upon request":"without request";
+ plog("we have a cert %s sending it %s"
+ , send_cert? "and are":"but are not", request_text);
+ }
+ else
+ {
+ plog("we don't have a cert");
+ }
+ }
+ if (send_cert)
+ {
+ pb_stream cert_pbs;
- /* HASH_R or SIG_R out */
- {
- u_char hash_val[MAX_DIGEST_LEN];
- size_t hash_len = main_mode_hash(st, hash_val, FALSE, &r_id_pbs);
+ struct isakmp_cert cert_hd;
+ cert_hd.isacert_np = ISAKMP_NEXT_SIG;
+ cert_hd.isacert_type = mycert.type;
- if (auth_payload == ISAKMP_NEXT_HASH)
- {
- /* HASH_R out */
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
- , hash_val, hash_len, "HASH_R"))
+ if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
return STF_INTERNAL_ERROR;
+ if (!out_chunk(cert_get_encoding(mycert), &cert_pbs, "CERT"))
+ return STF_INTERNAL_ERROR;
+ close_output_pbs(&cert_pbs);
}
- else
+
+ /* HASH_R or SIG_R out */
{
- /* SIG_R 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_buf[MAX_DIGEST_LEN];
+ chunk_t hash = chunk_from_buf(hash_buf);
- if (sig_len == 0)
- {
- loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
- return STF_FAIL + AUTHENTICATION_FAILED;
- }
+ main_mode_hash(st, &hash, FALSE, &r_id_pbs);
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
- , &md->rbody, sig_val, sig_len, "SIG_R"))
- return STF_INTERNAL_ERROR;
+ if (auth_payload == ISAKMP_NEXT_HASH)
+ {
+ /* HASH_R out */
+ if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody,
+ hash.ptr, hash.len, "HASH_R"))
+ {
+ return STF_INTERNAL_ERROR;
+ }
+ }
+ else
+ {
+ /* SIG_R out */
+ u_char sig_val[RSA_MAX_OCTETS];
+ signature_scheme_t scheme;
+ size_t sig_len;
+
+ scheme = oakley_to_signature_scheme(st->st_oakley.auth);
+
+ sig_len = sign_hash(scheme, st->st_connection, sig_val, hash);
+ if (sig_len == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "unable to locate my private key for 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 */
+ /* encrypt message, sans fixed part of header */
- if (!encrypt_message(&md->rbody, st))
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
+ 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);
+ /* 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);
- ISAKMP_SA_established(st->st_connection, st->st_serialno);
+ ISAKMP_SA_established(st->st_connection, st->st_serialno);
- /* Save Phase 1 IV */
- st->st_ph1_iv_len = st->st_new_iv_len;
- set_ph1_iv(st, st->st_new_iv);
+ /* Save Phase 1 IV */
+ st->st_ph1_iv_len = st->st_new_iv_len;
+ set_ph1_iv(st, st->st_new_iv);
- return STF_OK;
+ return STF_OK;
}
/* STATE_MAIN_I3:
@@ -4073,48 +3944,45 @@ main_inI3_outR3_tail(struct msg_digest *md
* - main_inR3_continue to start main_inR3_tail again
*/
-static key_tail_fn main_inR3_tail; /* forward */
+static key_tail_fn main_inR3_tail; /* forward */
-stf_status
-main_inR3(struct msg_digest *md)
+stf_status main_inR3(struct msg_digest *md)
{
- return main_inR3_tail(md, NULL);
+ return main_inR3_tail(md, NULL);
}
-static void
-main_inR3_continue(struct adns_continuation *cr, err_t ugh)
+static void main_inR3_continue(struct adns_continuation *cr, err_t ugh)
{
- key_continue(cr, ugh, main_inR3_tail);
+ key_continue(cr, ugh, main_inR3_tail);
}
-static stf_status
-main_inR3_tail(struct msg_digest *md
-, struct key_continuation *kc)
+static stf_status main_inR3_tail(struct msg_digest *md,
+ struct key_continuation *kc)
{
- struct state *const st = md->st;
+ struct state *const st = md->st;
- /* ID and HASH_R or SIG_R in
- * Note: this may switch the connection being used!
- */
- {
- stf_status r = main_id_and_auth(md, TRUE, main_inR3_continue, kc);
+ /* ID and HASH_R or SIG_R in
+ * Note: this may switch the connection being used!
+ */
+ {
+ stf_status r = main_id_and_auth(md, TRUE, main_inR3_continue, kc);
- if (r != STF_OK)
- return r;
- }
+ if (r != STF_OK)
+ return r;
+ }
- /**************** done input ****************/
+ /**************** done input ****************/
- ISAKMP_SA_established(st->st_connection, st->st_serialno);
+ ISAKMP_SA_established(st->st_connection, st->st_serialno);
- /* Save Phase 1 IV */
- st->st_ph1_iv_len = st->st_new_iv_len;
- set_ph1_iv(st, st->st_new_iv);
+ /* Save Phase 1 IV */
+ st->st_ph1_iv_len = st->st_new_iv_len;
+ set_ph1_iv(st, st->st_new_iv);
- update_iv(st); /* finalize our Phase 1 IV */
+ update_iv(st); /* finalize our Phase 1 IV */
- return STF_OK;
+ return STF_OK;
}
/* Handle first message of Phase 2 -- Quick Mode.
@@ -4182,15 +4050,15 @@ main_inR3_tail(struct msg_digest *md
*/
enum verify_oppo_step {
- vos_fail,
- vos_start,
- vos_our_client,
- vos_our_txt,
+ vos_fail,
+ vos_start,
+ vos_our_client,
+ vos_our_txt,
#ifdef USE_KEYRR
- vos_our_key,
+ vos_our_key,
#endif /* USE_KEYRR */
- vos_his_client,
- vos_done
+ vos_his_client,
+ vos_done
};
static const char *const verify_step_name[] = {
@@ -4207,834 +4075,833 @@ static const char *const verify_step_name[] = {
/* hold anything we can handle of a Phase 2 ID */
struct p2id {
- ip_subnet net;
- u_int8_t proto;
- u_int16_t port;
+ ip_subnet net;
+ u_int8_t proto;
+ u_int16_t port;
};
struct verify_oppo_bundle {
- enum verify_oppo_step step;
- bool failure_ok; /* if true, quick_inI1_outR1_continue will try
- * other things on DNS failure */
- struct msg_digest *md;
- struct p2id my, his;
- unsigned int new_iv_len; /* p1st's might change */
- u_char new_iv[MAX_DIGEST_LEN];
- /* int whackfd; */ /* not needed because we are Responder */
+ enum verify_oppo_step step;
+ bool failure_ok; /* if true, quick_inI1_outR1_continue will try
+ * other things on DNS failure */
+ struct msg_digest *md;
+ struct p2id my, his;
+ unsigned int new_iv_len; /* p1st's might change */
+ u_char new_iv[MAX_DIGEST_LEN];
+ /* int whackfd; */ /* not needed because we are Responder */
};
struct verify_oppo_continuation {
- struct adns_continuation ac; /* common prefix */
- struct verify_oppo_bundle b;
+ struct adns_continuation ac; /* common prefix */
+ struct verify_oppo_bundle b;
};
static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b
- , struct adns_continuation *ac);
+ , struct adns_continuation *ac);
-stf_status
-quick_inI1_outR1(struct msg_digest *md)
+stf_status quick_inI1_outR1(struct msg_digest *md)
{
- const struct state *const p1st = md->st;
- struct connection *c = p1st->st_connection;
- struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
- struct verify_oppo_bundle b;
-
- /* HASH(1) in */
- CHECK_QUICK_HASH(md
- , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
- , p1st, &md->hdr.isa_msgid, FALSE)
- , "HASH(1)", "Quick I1");
-
- /* [ IDci, IDcr ] in
- * We do this now (probably out of physical order) because
- * we wish to select the correct connection before we consult
- * it for policy.
- */
-
- if (id_pd != NULL)
- {
- /* ??? we are assuming IPSEC_DOI */
-
- /* IDci (initiator is peer) */
-
- if (!decode_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
- , &b.his.net, "peer client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
-
- /* Hack for MS 818043 NAT-T Update */
-
- if (id_pd->payload.ipsec_id.isaiid_idtype == ID_FQDN)
- happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net));
-
- /* End Hack for MS 818043 NAT-T Update */
-
- b.his.proto = id_pd->payload.ipsec_id.isaiid_protoid;
- b.his.port = id_pd->payload.ipsec_id.isaiid_port;
- b.his.net.addr.u.v4.sin_port = htons(b.his.port);
-
- /* IDcr (we are responder) */
-
- if (!decode_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs
- , &b.my.net, "our client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
-
- b.my.proto = id_pd->next->payload.ipsec_id.isaiid_protoid;
- b.my.port = id_pd->next->payload.ipsec_id.isaiid_port;
- b.my.net.addr.u.v4.sin_port = htons(b.my.port);
- }
- else
- {
- /* implicit IDci and IDcr: peer and self */
- if (!sameaddrtype(&c->spd.this.host_addr, &c->spd.that.host_addr))
- return STF_FAIL;
-
- happy(addrtosubnet(&c->spd.this.host_addr, &b.my.net));
- happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net));
- b.his.proto = b.my.proto = 0;
- b.his.port = b.my.port = 0;
- }
- b.step = vos_start;
- b.md = md;
- b.new_iv_len = p1st->st_new_iv_len;
- memcpy(b.new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
- return quick_inI1_outR1_tail(&b, NULL);
+ const struct state *const p1st = md->st;
+ struct connection *c = p1st->st_connection;
+ struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
+ struct verify_oppo_bundle b;
+
+ /* HASH(1) in */
+ CHECK_QUICK_HASH(md
+ , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
+ , p1st, &md->hdr.isa_msgid, FALSE)
+ , "HASH(1)", "Quick I1");
+
+ /* [ IDci, IDcr ] in
+ * We do this now (probably out of physical order) because
+ * we wish to select the correct connection before we consult
+ * it for policy.
+ */
+
+ if (id_pd != NULL)
+ {
+ /* ??? we are assuming IPSEC_DOI */
+
+ /* IDci (initiator is peer) */
+
+ if (!decode_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
+ , &b.his.net, "peer client"))
+ return STF_FAIL + INVALID_ID_INFORMATION;
+
+ /* Hack for MS 818043 NAT-T Update */
+
+ if (id_pd->payload.ipsec_id.isaiid_idtype == ID_FQDN)
+ happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net));
+
+ /* End Hack for MS 818043 NAT-T Update */
+
+ b.his.proto = id_pd->payload.ipsec_id.isaiid_protoid;
+ b.his.port = id_pd->payload.ipsec_id.isaiid_port;
+ b.his.net.addr.u.v4.sin_port = htons(b.his.port);
+
+ /* IDcr (we are responder) */
+
+ if (!decode_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs
+ , &b.my.net, "our client"))
+ return STF_FAIL + INVALID_ID_INFORMATION;
+
+ b.my.proto = id_pd->next->payload.ipsec_id.isaiid_protoid;
+ b.my.port = id_pd->next->payload.ipsec_id.isaiid_port;
+ b.my.net.addr.u.v4.sin_port = htons(b.my.port);
+ }
+ else
+ {
+ /* implicit IDci and IDcr: peer and self */
+ if (!sameaddrtype(&c->spd.this.host_addr, &c->spd.that.host_addr))
+ return STF_FAIL;
+
+ happy(addrtosubnet(&c->spd.this.host_addr, &b.my.net));
+ happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net));
+ b.his.proto = b.my.proto = 0;
+ b.his.port = b.my.port = 0;
+ }
+ b.step = vos_start;
+ b.md = md;
+ b.new_iv_len = p1st->st_new_iv_len;
+ memcpy(b.new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
+ return quick_inI1_outR1_tail(&b, NULL);
}
static void
report_verify_failure(struct verify_oppo_bundle *b, err_t ugh)
{
- struct state *st = b->md->st;
- char fgwb[ADDRTOT_BUF]
- , cb[ADDRTOT_BUF];
- ip_address client;
- err_t which = NULL;
-
- switch (b->step)
- {
- case vos_our_client:
- case vos_our_txt:
+ struct state *st = b->md->st;
+ char fgwb[ADDRTOT_BUF]
+ , cb[ADDRTOT_BUF];
+ ip_address client;
+ err_t which = NULL;
+
+ switch (b->step)
+ {
+ case vos_our_client:
+ case vos_our_txt:
#ifdef USE_KEYRR
- case vos_our_key:
+ case vos_our_key:
#endif /* USE_KEYRR */
- which = "our";
- networkof(&b->my.net, &client);
- break;
-
- case vos_his_client:
- which = "his";
- networkof(&b->his.net, &client);
- break;
-
- case vos_start:
- case vos_done:
- case vos_fail:
- default:
- bad_case(b->step);
- }
-
- addrtot(&st->st_connection->spd.that.host_addr, 0, fgwb, sizeof(fgwb));
- addrtot(&client, 0, cb, sizeof(cb));
- loglog(RC_OPPOFAILURE
- , "gateway %s wants connection with %s as %s client, but DNS fails to confirm delegation: %s"
- , fgwb, cb, which, ugh);
+ which = "our";
+ networkof(&b->my.net, &client);
+ break;
+
+ case vos_his_client:
+ which = "his";
+ networkof(&b->his.net, &client);
+ break;
+
+ case vos_start:
+ case vos_done:
+ case vos_fail:
+ default:
+ bad_case(b->step);
+ }
+
+ addrtot(&st->st_connection->spd.that.host_addr, 0, fgwb, sizeof(fgwb));
+ addrtot(&client, 0, cb, sizeof(cb));
+ loglog(RC_OPPOFAILURE
+ , "gateway %s wants connection with %s as %s client, but DNS fails to confirm delegation: %s"
+ , fgwb, cb, which, ugh);
}
-static void
-quick_inI1_outR1_continue(struct adns_continuation *cr, err_t ugh)
+static void quick_inI1_outR1_continue(struct adns_continuation *cr, err_t ugh)
{
- stf_status r;
- struct verify_oppo_continuation *vc = (void *)cr;
- struct verify_oppo_bundle *b = &vc->b;
- struct state *st = b->md->st;
-
- passert(cur_state == NULL);
- /* if st == NULL, our state has been deleted -- just clean up */
- if (st != NULL)
- {
- passert(st->st_suspended_md == b->md);
- st->st_suspended_md = NULL; /* no longer connected or suspended */
- cur_state = st;
- if (!b->failure_ok && ugh != NULL)
- {
- report_verify_failure(b, ugh);
- r = STF_FAIL + INVALID_ID_INFORMATION;
- }
- else
+ stf_status r;
+ struct verify_oppo_continuation *vc = (void *)cr;
+ struct verify_oppo_bundle *b = &vc->b;
+ struct state *st = b->md->st;
+
+ passert(cur_state == NULL);
+ /* if st == NULL, our state has been deleted -- just clean up */
+ if (st != NULL)
{
- r = quick_inI1_outR1_tail(b, cr);
+ passert(st->st_suspended_md == b->md);
+ st->st_suspended_md = NULL; /* no longer connected or suspended */
+ cur_state = st;
+ if (!b->failure_ok && ugh != NULL)
+ {
+ report_verify_failure(b, ugh);
+ r = STF_FAIL + INVALID_ID_INFORMATION;
+ }
+ else
+ {
+ r = quick_inI1_outR1_tail(b, cr);
+ }
+ complete_state_transition(&b->md, r);
}
- complete_state_transition(&b->md, r);
- }
- if (b->md != NULL)
- release_md(b->md);
- cur_state = NULL;
+ if (b->md != NULL)
+ release_md(b->md);
+ cur_state = NULL;
}
-static stf_status
-quick_inI1_outR1_start_query(struct verify_oppo_bundle *b
-, enum verify_oppo_step next_step)
+static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
+ enum verify_oppo_step next_step)
{
- struct msg_digest *md = b->md;
- struct state *p1st = md->st;
- struct connection *c = p1st->st_connection;
- struct verify_oppo_continuation *vc
- = alloc_thing(struct verify_oppo_continuation, "verify continuation");
- struct id id /* subject of query */
- , *our_id /* needed for myid playing */
- , our_id_space; /* ephemeral: no need for unshare_id_content */
- ip_address client;
- err_t ugh = NULL;
-
- /* Record that state is used by a suspended md */
- b->step = next_step; /* not just vc->b.step */
- vc->b = *b;
- passert(p1st->st_suspended_md == NULL);
- p1st->st_suspended_md = b->md;
-
- DBG(DBG_CONTROL,
- {
- char ours[SUBNETTOT_BUF];
- char his[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
- subnettot(&c->spd.that.client, 0, his, sizeof(his));
-
- DBG_log("responding with DNS query - from %s to %s new state: %s"
- , ours, his, verify_step_name[b->step]);
- });
-
- /* Resolve %myid in a cheesy way.
- * We have to do the resolution because start_adns_query
- * et al have insufficient information to do so.
- * If %myid is already known, we'll use that value
- * (XXX this may be a mistake: it could be stale).
- * If %myid is unknown, we should check to see if
- * there are credentials for the IP address or the FQDN.
- * Instead, we'll just assume the IP address since we are
- * acting as the responder and only the IP address would
- * have gotten it to us.
- * We don't even try to do this for the other side:
- * %myid makes no sense for the other side (but it is syntactically
- * legal).
- */
- our_id = resolve_myid(&c->spd.this.id);
- if (our_id->kind == ID_NONE)
- {
- iptoid(&c->spd.this.host_addr, &our_id_space);
- our_id = &our_id_space;
- }
-
- switch (next_step)
- {
- case vos_our_client:
- networkof(&b->my.net, &client);
- iptoid(&client, &id);
- vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&id
- , our_id
- , T_TXT
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
-
- case vos_our_txt:
- vc->b.failure_ok = b->failure_ok = TRUE;
- ugh = start_adns_query(our_id
- , our_id /* self as SG */
- , T_TXT
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
+ struct msg_digest *md = b->md;
+ struct state *p1st = md->st;
+ struct connection *c = p1st->st_connection;
+ struct verify_oppo_continuation *vc = malloc_thing(struct verify_oppo_continuation);
+ struct id id /* subject of query */
+ , *our_id /* needed for myid playing */
+ , our_id_space; /* ephemeral: no need for unshare_id_content */
+ ip_address client;
+ err_t ugh = NULL;
+
+ /* Record that state is used by a suspended md */
+ b->step = next_step; /* not just vc->b.step */
+ vc->b = *b;
+ passert(p1st->st_suspended_md == NULL);
+ p1st->st_suspended_md = b->md;
+
+ DBG(DBG_CONTROL,
+ {
+ char ours[SUBNETTOT_BUF];
+ char his[SUBNETTOT_BUF];
+
+ subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
+ subnettot(&c->spd.that.client, 0, his, sizeof(his));
+
+ DBG_log("responding with DNS query - from %s to %s new state: %s"
+ , ours, his, verify_step_name[b->step]);
+ });
+
+ /* Resolve %myid in a cheesy way.
+ * We have to do the resolution because start_adns_query
+ * et al have insufficient information to do so.
+ * If %myid is already known, we'll use that value
+ * (XXX this may be a mistake: it could be stale).
+ * If %myid is unknown, we should check to see if
+ * there are credentials for the IP address or the FQDN.
+ * Instead, we'll just assume the IP address since we are
+ * acting as the responder and only the IP address would
+ * have gotten it to us.
+ * We don't even try to do this for the other side:
+ * %myid makes no sense for the other side (but it is syntactically
+ * legal).
+ */
+ our_id = resolve_myid(&c->spd.this.id);
+ if (our_id->kind == ID_ANY)
+ {
+ iptoid(&c->spd.this.host_addr, &our_id_space);
+ our_id = &our_id_space;
+ }
+
+ switch (next_step)
+ {
+ case vos_our_client:
+ networkof(&b->my.net, &client);
+ iptoid(&client, &id);
+ vc->b.failure_ok = b->failure_ok = FALSE;
+ ugh = start_adns_query(&id
+ , our_id
+ , T_TXT
+ , quick_inI1_outR1_continue
+ , &vc->ac);
+ break;
+
+ case vos_our_txt:
+ vc->b.failure_ok = b->failure_ok = TRUE;
+ ugh = start_adns_query(our_id
+ , our_id /* self as SG */
+ , T_TXT
+ , quick_inI1_outR1_continue
+ , &vc->ac);
+ break;
#ifdef USE_KEYRR
- case vos_our_key:
- vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(our_id
- , NULL
- , T_KEY
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
+ case vos_our_key:
+ vc->b.failure_ok = b->failure_ok = FALSE;
+ ugh = start_adns_query(our_id
+ , NULL
+ , T_KEY
+ , quick_inI1_outR1_continue
+ , &vc->ac);
+ break;
#endif
- case vos_his_client:
- networkof(&b->his.net, &client);
- iptoid(&client, &id);
- vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&id
- , &c->spd.that.id
- , T_TXT
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
-
- default:
- bad_case(next_step);
- }
-
- if (ugh != NULL)
- {
- /* note: we'd like to use vc->b but vc has been freed
- * so we have to use b. This is why we plunked next_state
- * into b, not just vc->b.
- */
- report_verify_failure(b, ugh);
- p1st->st_suspended_md = NULL;
- return STF_FAIL + INVALID_ID_INFORMATION;
- }
- else
- {
- return STF_SUSPEND;
- }
+ case vos_his_client:
+ networkof(&b->his.net, &client);
+ iptoid(&client, &id);
+ vc->b.failure_ok = b->failure_ok = FALSE;
+ ugh = start_adns_query(&id
+ , &c->spd.that.id
+ , T_TXT
+ , quick_inI1_outR1_continue
+ , &vc->ac);
+ break;
+
+ default:
+ bad_case(next_step);
+ }
+
+ if (ugh != NULL)
+ {
+ /* note: we'd like to use vc->b but vc has been freed
+ * so we have to use b. This is why we plunked next_state
+ * into b, not just vc->b.
+ */
+ report_verify_failure(b, ugh);
+ p1st->st_suspended_md = NULL;
+ return STF_FAIL + INVALID_ID_INFORMATION;
+ }
+ else
+ {
+ return STF_SUSPEND;
+ }
}
-static enum verify_oppo_step
-quick_inI1_outR1_process_answer(struct verify_oppo_bundle *b
-, struct adns_continuation *ac
-, struct state *p1st)
+static enum verify_oppo_step quick_inI1_outR1_process_answer(
+ struct verify_oppo_bundle *b,
+ struct adns_continuation *ac,
+ struct state *p1st)
{
- struct connection *c = p1st->st_connection;
- enum verify_oppo_step next_step = vos_our_client;
- err_t ugh = NULL;
-
- DBG(DBG_CONTROL,
- {
- char ours[SUBNETTOT_BUF];
- char his[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
- subnettot(&c->spd.that.client, 0, his, sizeof(his));
- DBG_log("responding on demand from %s to %s state: %s"
- , ours, his, verify_step_name[b->step]);
- });
-
- /* process just completed DNS query (if any) */
- switch (b->step)
- {
- case vos_start:
- /* no query to digest */
- next_step = vos_our_client;
- break;
-
- case vos_our_client:
- next_step = vos_his_client;
- {
- const struct RSA_private_key *pri = get_RSA_private_key(c);
- struct gw_info *gwp;
-
- if (pri == NULL)
- {
- ugh = "we don't know our own key";
- break;
- }
- ugh = "our client does not delegate us as its Security Gateway";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- ugh = "our client delegates us as its Security Gateway but with the wrong public key";
- /* If there is no key in the TXT record,
- * we count it as a win, but we will have
- * to separately fetch and check the KEY record.
- * If there is a key from the TXT record,
- * we count it as a win if we match the key.
- */
- if (!gwp->gw_key_present)
- {
- next_step = vos_our_txt;
- ugh = NULL; /* good! */
- break;
- }
- else if (same_RSA_public_key(&pri->pub, &gwp->key->u.rsa))
+ struct connection *c = p1st->st_connection;
+ enum verify_oppo_step next_step = vos_our_client;
+ err_t ugh = NULL;
+
+ DBG(DBG_CONTROL,
{
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- break;
+ char ours[SUBNETTOT_BUF];
+ char his[SUBNETTOT_BUF];
+
+ subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
+ subnettot(&c->spd.that.client, 0, his, sizeof(his));
+ DBG_log("responding on demand from %s to %s state: %s"
+ , ours, his, verify_step_name[b->step]);
+ });
- case vos_our_txt:
- next_step = vos_his_client;
+ /* process just completed DNS query (if any) */
+ switch (b->step)
{
- const struct RSA_private_key *pri = get_RSA_private_key(c);
+ case vos_start:
+ /* no query to digest */
+ next_step = vos_our_client;
+ break;
+
+ case vos_our_client:
+ next_step = vos_his_client;
+ {
+ private_key_t *private = get_private_key(c);
+ struct gw_info *gwp;
- if (pri == NULL)
- {
- ugh = "we don't know our own key";
+ if (private == NULL)
+ {
+ ugh = "we don't know our own key";
+ break;
+ }
+ ugh = "our client does not delegate us as its Security Gateway";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ ugh = "our client delegates us as its Security Gateway but with the wrong public key";
+ /* If there is no key in the TXT record,
+ * we count it as a win, but we will have
+ * to separately fetch and check the KEY record.
+ * If there is a key from the TXT record,
+ * we count it as a win if we match the key.
+ */
+ if (!gwp->gw_key_present)
+ {
+ next_step = vos_our_txt;
+ ugh = NULL; /* good! */
+ break;
+ }
+ else if (private->belongs_to(private, gwp->key->public_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
break;
- }
- {
- struct gw_info *gwp;
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ case vos_our_txt:
+ next_step = vos_his_client;
{
+ private_key_t *private = get_private_key(c);
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own key";
+ break;
+ }
+ {
+ struct gw_info *gwp;
+
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
#ifdef USE_KEYRR
- /* not an error yet, because we have to check KEY RR as well */
- ugh = NULL;
+ /* not an error yet, because we have to check KEY RR as well */
+ ugh = NULL;
#else
- ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
+ ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
#endif
- if (gwp->gw_key_present
- && same_RSA_public_key(&pri->pub, &gwp->key->u.rsa))
- {
- ugh = NULL; /* good! */
- break;
- }
+ if (gwp->gw_key_present
+ && private->belongs_to(private, gwp->key->public_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
#ifdef USE_KEYRR
- next_step = vos_our_key;
+ next_step = vos_our_key;
#endif
+ }
+ }
}
- }
- }
- break;
+ break;
#ifdef USE_KEYRR
- case vos_our_key:
- next_step = vos_his_client;
- {
- const struct RSA_private_key *pri = get_RSA_private_key(c);
+ case vos_our_key:
+ next_step = vos_his_client;
+ {
+ private_key_t *private = get_private_key(c);
- if (pri == NULL)
- {
- ugh = "we don't know our own key";
+ if (private == NULL)
+ {
+ ugh = "we don't know our own key";
+ break;
+ }
+ {
+ pubkey_list_t *kp;
+
+ ugh = "our client delegation depends on our missing " RRNAME " record";
+ for (kp = ac->keys_from_dns; kp != NULL; kp = kp->next)
+ {
+ ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
+ if (private->belongs_to(private, kp->key->public_key))
+ {
+ /* do this only once a day */
+ if (!logged_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS, "found KEY RR but not TXT RR. See http://www.freeswan.org/err/txt-change.html.");
+ logged_txt_warning = TRUE;
+ }
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ }
break;
- }
- {
- pubkey_list_t *kp;
+#endif /* USE_KEYRR */
- ugh = "our client delegation depends on our missing " RRNAME " record";
- for (kp = ac->keys_from_dns; kp != NULL; kp = kp->next)
+ case vos_his_client:
+ next_step = vos_done;
{
- ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
- if (same_RSA_public_key(&pri->pub, &kp->key->u.rsa))
- {
- /* do this only once a day */
- if (!logged_txt_warning)
+ public_key_t *pub_key;
+ identification_t *p1st_keyid;
+ struct gw_info *gwp;
+
+ /* check that the public key that authenticated
+ * the ISAKMP SA (p1st) will do for this gateway.
+ */
+ pub_key = p1st->st_peer_pubkey->public_key;
+ p1st_keyid = pub_key->get_id(pub_key, ID_PUBKEY_INFO_SHA1);
+
+ ugh = "peer's client does not delegate to peer";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
{
- loglog(RC_LOG_SERIOUS, "found KEY RR but not TXT RR. See http://www.freeswan.org/err/txt-change.html.");
- logged_txt_warning = TRUE;
+ ugh = "peer and its client disagree about public key";
+ /* If there is a key from the TXT record,
+ * we count it as a win if we match the key.
+ * If there was no key, we claim a match since
+ * it implies fetching a KEY from the same
+ * place we must have gotten it.
+ */
+ if (!gwp->gw_key_present || p1st_keyid->equals(p1st_keyid,
+ gwp->key->public_key->get_id(gwp->key->public_key,
+ ID_PUBKEY_INFO_SHA1))
+ )
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
}
- ugh = NULL; /* good! */
- break;
- }
}
- }
+ break;
+
+ default:
+ bad_case(b->step);
}
- break;
-#endif /* USE_KEYRR */
- case vos_his_client:
- next_step = vos_done;
+ if (ugh != NULL)
{
- struct gw_info *gwp;
-
- /* check that the public key that authenticated
- * the ISAKMP SA (p1st) will do for this gateway.
- */
-
- ugh = "peer's client does not delegate to peer";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- ugh = "peer and its client disagree about public key";
- /* If there is a key from the TXT record,
- * we count it as a win if we match the key.
- * If there was no key, we claim a match since
- * it implies fetching a KEY from the same
- * place we must have gotten it.
- */
- if (!gwp->gw_key_present
- || same_RSA_public_key(&p1st->st_peer_pubkey->u.rsa
- , &gwp->key->u.rsa))
- {
- ugh = NULL; /* good! */
- break;
- }
- }
+ report_verify_failure(b, ugh);
+ next_step = vos_fail;
}
- break;
-
- default:
- bad_case(b->step);
- }
-
- if (ugh != NULL)
- {
- report_verify_failure(b, ugh);
- next_step = vos_fail;
- }
- return next_step;
+ return next_step;
}
-static stf_status
-quick_inI1_outR1_tail(struct verify_oppo_bundle *b
-, struct adns_continuation *ac)
+static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
+ struct adns_continuation *ac)
{
- struct msg_digest *md = b->md;
- struct state *const p1st = md->st;
- struct connection *c = p1st->st_connection;
- struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
- ip_subnet *our_net = &b->my.net
- , *his_net = &b->his.net;
-
- u_char /* set by START_HASH_PAYLOAD: */
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* from where to start hashing */
-
- /* Now that we have identities of client subnets, we must look for
- * a suitable connection (our current one only matches for hosts).
- */
- {
- struct connection *p = find_client_connection(c
- , our_net, his_net, b->my.proto, b->my.port, b->his.proto, b->his.port);
-
- if (p == NULL)
- {
- /* This message occurs in very puzzling circumstances
- * so we must add as much information and beauty as we can.
- */
- struct end
- me = c->spd.this,
- he = c->spd.that;
- char buf[2*SUBNETTOT_BUF + 2*ADDRTOT_BUF + 2*BUF_LEN + 2*ADDRTOT_BUF + 12]; /* + 12 for separating */
- size_t l;
-
- me.client = *our_net;
- me.has_client = !subnetisaddr(our_net, &me.host_addr);
- me.protocol = b->my.proto;
- me.port = b->my.port;
-
- he.client = *his_net;
- he.has_client = !subnetisaddr(his_net, &he.host_addr);
- he.protocol = b->his.proto;
- he.port = b->his.port;
-
- l = format_end(buf, sizeof(buf), &me, NULL, TRUE, LEMPTY);
- l += snprintf(buf + l, sizeof(buf) - l, "...");
- (void)format_end(buf + l, sizeof(buf) - l, &he, NULL, FALSE, LEMPTY);
- plog("cannot respond to IPsec SA request"
- " because no connection is known for %s"
- , buf);
- return STF_FAIL + INVALID_ID_INFORMATION;
- }
- else if (p != c)
- {
- /* We've got a better connection: it can support the
- * specified clients. But it may need instantiation.
- */
- if (p->kind == CK_TEMPLATE)
- {
- /* Yup, it needs instantiation. How much?
- * Is it a Road Warrior connection (simple)
- * or is it an Opportunistic connection (needing gw validation)?
- */
- if (p->policy & POLICY_OPPO)
- {
- /* Opportunistic case: delegation must be verified.
- * Here be dragons.
- */
- enum verify_oppo_step next_step;
- ip_address our_client, his_client;
-
- passert(subnetishost(our_net) && subnetishost(his_net));
- networkof(our_net, &our_client);
- networkof(his_net, &his_client);
-
- next_step = quick_inI1_outR1_process_answer(b, ac, p1st);
- if (next_step == vos_fail)
- return STF_FAIL + INVALID_ID_INFORMATION;
+ struct msg_digest *md = b->md;
+ struct state *const p1st = md->st;
+ struct connection *c = p1st->st_connection;
+ struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
+ ip_subnet *our_net = &b->my.net
+ , *his_net = &b->his.net;
- /* short circuit: if peer's client is self,
- * accept that we've verified delegation in Phase 1
- */
- if (next_step == vos_his_client
- && sameaddr(&c->spd.that.host_addr, &his_client))
- next_step = vos_done;
+ u_char /* set by START_HASH_PAYLOAD: */
+ *r_hashval, /* where in reply to jam hash value */
+ *r_hash_start; /* from where to start hashing */
- /* the second chunk: initiate the next DNS query (if any) */
- DBG(DBG_CONTROL,
- {
- char ours[SUBNETTOT_BUF];
- char his[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
- subnettot(&c->spd.that.client, 0, his, sizeof(his));
-
- DBG_log("responding on demand from %s to %s new state: %s"
- , ours, his, verify_step_name[next_step]);
- });
-
- /* start next DNS query and suspend (if necessary) */
- if (next_step != vos_done)
- return quick_inI1_outR1_start_query(b, next_step);
-
- /* Instantiate inbound Opportunistic connection,
- * carrying over authenticated peer ID
- * and filling in a few more details.
- * We used to include gateways_from_dns, but that
- * seems pointless at this stage of negotiation.
- * We should record DNS sec use, if any -- belongs in
- * state during perhaps.
- */
- p = oppo_instantiate(p, &c->spd.that.host_addr, &c->spd.that.id
- , NULL, &our_client, &his_client);
- }
- else
+ /* Now that we have identities of client subnets, we must look for
+ * a suitable connection (our current one only matches for hosts).
+ */
+ {
+ struct connection *p = find_client_connection(c
+ , our_net, his_net, b->my.proto, b->my.port, b->his.proto, b->his.port);
+
+ if (p == NULL)
{
- /* Plain Road Warrior:
- * instantiate, carrying over authenticated peer ID
- */
- p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
- , his_net, &c->spd.that.id);
+ /* This message occurs in very puzzling circumstances
+ * so we must add as much information and beauty as we can.
+ */
+ struct end
+ me = c->spd.this,
+ he = c->spd.that;
+ char buf[2*SUBNETTOT_BUF + 2*ADDRTOT_BUF + 2*BUF_LEN + 2*ADDRTOT_BUF + 12]; /* + 12 for separating */
+ size_t l;
+
+ me.client = *our_net;
+ me.has_client = !subnetisaddr(our_net, &me.host_addr);
+ me.protocol = b->my.proto;
+ me.port = b->my.port;
+
+ he.client = *his_net;
+ he.has_client = !subnetisaddr(his_net, &he.host_addr);
+ he.protocol = b->his.proto;
+ he.port = b->his.port;
+
+ l = format_end(buf, sizeof(buf), &me, NULL, TRUE, LEMPTY);
+ l += snprintf(buf + l, sizeof(buf) - l, "...");
+ (void)format_end(buf + l, sizeof(buf) - l, &he, NULL, FALSE, LEMPTY);
+ plog("cannot respond to IPsec SA request"
+ " because no connection is known for %s"
+ , buf);
+ return STF_FAIL + INVALID_ID_INFORMATION;
}
- }
+ else if (p != c)
+ {
+ /* We've got a better connection: it can support the
+ * specified clients. But it may need instantiation.
+ */
+ if (p->kind == CK_TEMPLATE)
+ {
+ /* Yup, it needs instantiation. How much?
+ * Is it a Road Warrior connection (simple)
+ * or is it an Opportunistic connection (needing gw validation)?
+ */
+ if (p->policy & POLICY_OPPO)
+ {
+ /* Opportunistic case: delegation must be verified.
+ * Here be dragons.
+ */
+ enum verify_oppo_step next_step;
+ ip_address our_client, his_client;
+
+ passert(subnetishost(our_net) && subnetishost(his_net));
+ networkof(our_net, &our_client);
+ networkof(his_net, &his_client);
+
+ next_step = quick_inI1_outR1_process_answer(b, ac, p1st);
+ if (next_step == vos_fail)
+ return STF_FAIL + INVALID_ID_INFORMATION;
+
+ /* short circuit: if peer's client is self,
+ * accept that we've verified delegation in Phase 1
+ */
+ if (next_step == vos_his_client
+ && sameaddr(&c->spd.that.host_addr, &his_client))
+ next_step = vos_done;
+
+ /* the second chunk: initiate the next DNS query (if any) */
+ DBG(DBG_CONTROL,
+ {
+ char ours[SUBNETTOT_BUF];
+ char his[SUBNETTOT_BUF];
+
+ subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
+ subnettot(&c->spd.that.client, 0, his, sizeof(his));
+
+ DBG_log("responding on demand from %s to %s new state: %s"
+ , ours, his, verify_step_name[next_step]);
+ });
+
+ /* start next DNS query and suspend (if necessary) */
+ if (next_step != vos_done)
+ return quick_inI1_outR1_start_query(b, next_step);
+
+ /* Instantiate inbound Opportunistic connection,
+ * carrying over authenticated peer ID
+ * and filling in a few more details.
+ * We used to include gateways_from_dns, but that
+ * seems pointless at this stage of negotiation.
+ * We should record DNS sec use, if any -- belongs in
+ * state during perhaps.
+ */
+ p = oppo_instantiate(p, &c->spd.that.host_addr, &c->spd.that.id
+ , NULL, &our_client, &his_client);
+ }
+ else
+ {
+ /* Plain Road Warrior:
+ * instantiate, carrying over authenticated peer ID
+ */
+ p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
+ , his_net, &c->spd.that.id);
+ }
+ }
#ifdef DEBUG
- /* temporarily bump up cur_debugging to get "using..." message
- * printed if we'd want it with new connection.
- */
- {
- lset_t old_cur_debugging = cur_debugging;
-
- cur_debugging |= p->extra_debugging;
- DBG(DBG_CONTROL, DBG_log("using connection \"%s\"", p->name));
- cur_debugging = old_cur_debugging;
- }
+ /* temporarily bump up cur_debugging to get "using..." message
+ * printed if we'd want it with new connection.
+ */
+ {
+ lset_t old_cur_debugging = cur_debugging;
+
+ cur_debugging |= p->extra_debugging;
+ DBG(DBG_CONTROL, DBG_log("using connection \"%s\"", p->name));
+ cur_debugging = old_cur_debugging;
+ }
#endif
- c = p;
- }
- /* fill in the client's true ip address/subnet */
- if (p->spd.that.has_client_wildcard)
- {
- p->spd.that.client = *his_net;
- p->spd.that.has_client_wildcard = FALSE;
- }
- else if (is_virtual_connection(c))
- {
- c->spd.that.client = *his_net;
- c->spd.that.virt = NULL;
- if (subnetishost(his_net) && addrinsubnet(&c->spd.that.host_addr, his_net))
- c->spd.that.has_client = FALSE;
- }
+ c = p;
+ }
+ /* fill in the client's true ip address/subnet */
+ if (p->spd.that.has_client_wildcard)
+ {
+ p->spd.that.client = *his_net;
+ p->spd.that.has_client_wildcard = FALSE;
+ }
+ else if (is_virtual_connection(c))
+ {
+ c->spd.that.client = *his_net;
+ c->spd.that.virt = NULL;
+ if (subnetishost(his_net) && addrinsubnet(&c->spd.that.host_addr, his_net))
+ c->spd.that.has_client = FALSE;
+ }
- /* fill in the client's true port */
- if (p->spd.that.has_port_wildcard)
- {
- int port = htons(b->his.port);
+ /* fill in the client's true port */
+ if (p->spd.that.has_port_wildcard)
+ {
+ int port = htons(b->his.port);
- setportof(port, &p->spd.that.host_addr);
- setportof(port, &p->spd.that.client.addr);
+ setportof(port, &p->spd.that.host_addr);
+ setportof(port, &p->spd.that.client.addr);
- p->spd.that.port = b->his.port;
- p->spd.that.has_port_wildcard = FALSE;
+ p->spd.that.port = b->his.port;
+ p->spd.that.has_port_wildcard = FALSE;
+ }
}
- }
-
- /* now that we are sure of our connection, create our new state */
- {
- struct state *const st = duplicate_state(p1st);
-
- /* first: fill in missing bits of our new state object
- * note: we don't copy over st_peer_pubkey, the public key
- * that authenticated the ISAKMP SA. We only need it in this
- * routine, so we can "reach back" to p1st to get it.
- */
- if (st->st_connection != c)
+ /* now that we are sure of our connection, create our new state */
{
- struct connection *t = st->st_connection;
+ struct state *const st = duplicate_state(p1st);
- st->st_connection = c;
- set_cur_connection(c);
- connection_discard(t);
- }
+ /* first: fill in missing bits of our new state object
+ * note: we don't copy over st_peer_pubkey, the public key
+ * that authenticated the ISAKMP SA. We only need it in this
+ * routine, so we can "reach back" to p1st to get it.
+ */
- st->st_try = 0; /* not our job to try again from start */
+ if (st->st_connection != c)
+ {
+ struct connection *t = st->st_connection;
- st->st_msgid = md->hdr.isa_msgid;
+ st->st_connection = c;
+ set_cur_connection(c);
+ connection_discard(t);
+ }
- st->st_new_iv_len = b->new_iv_len;
- memcpy(st->st_new_iv, b->new_iv, b->new_iv_len);
+ st->st_try = 0; /* not our job to try again from start */
- set_cur_state(st); /* (caller will reset) */
- md->st = st; /* feed back new state */
+ st->st_msgid = md->hdr.isa_msgid;
- st->st_peeruserprotoid = b->his.proto;
- st->st_peeruserport = b->his.port;
- st->st_myuserprotoid = b->my.proto;
- st->st_myuserport = b->my.port;
+ st->st_new_iv_len = b->new_iv_len;
+ memcpy(st->st_new_iv, b->new_iv, b->new_iv_len);
- insert_state(st); /* needs cookies, connection, and msgid */
+ set_cur_state(st); /* (caller will reset) */
+ md->st = st; /* feed back new state */
- /* copy the connection's
- * IPSEC policy into our state. The ISAKMP policy is water under
- * the bridge, I think. It will reflect the ISAKMP SA that we
- * are using.
- */
- st->st_policy = (p1st->st_policy & POLICY_ISAKMP_MASK)
- | (c->policy & ~POLICY_ISAKMP_MASK);
+ st->st_peeruserprotoid = b->his.proto;
+ st->st_peeruserport = b->his.port;
+ st->st_myuserprotoid = b->my.proto;
+ st->st_myuserport = b->my.port;
- if (p1st->nat_traversal & NAT_T_DETECTED)
- {
- st->nat_traversal = p1st->nat_traversal;
- nat_traversal_change_port_lookup(md, md->st);
- }
- else
- {
- st->nat_traversal = 0;
- }
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_NATOA))
- {
- nat_traversal_natoa_lookup(md);
- }
+ insert_state(st); /* needs cookies, connection, and msgid */
- /* Start the output packet.
- *
- * proccess_packet() would automatically generate the HDR*
- * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE.
- * We don't do this because we wish there to be no partially
- * built output packet if we need to suspend for asynch DNS.
- *
- * We build the reply packet as we parse the message since
- * the parse_ipsec_sa_body emits the reply SA
- */
+ /* copy the connection's
+ * IPSEC policy into our state. The ISAKMP policy is water under
+ * the bridge, I think. It will reflect the ISAKMP SA that we
+ * are using.
+ */
+ st->st_policy = (p1st->st_policy & POLICY_ISAKMP_MASK)
+ | (c->policy & ~POLICY_ISAKMP_MASK);
- /* HDR* out */
- echo_hdr(md, TRUE, ISAKMP_NEXT_HASH);
+ if (p1st->nat_traversal & NAT_T_DETECTED)
+ {
+ st->nat_traversal = p1st->nat_traversal;
+ nat_traversal_change_port_lookup(md, md->st);
+ }
+ else
+ {
+ st->nat_traversal = 0;
+ }
+ if ((st->nat_traversal & NAT_T_DETECTED)
+ && (st->nat_traversal & NAT_T_WITH_NATOA))
+ {
+ nat_traversal_natoa_lookup(md);
+ }
- /* HASH(2) out -- first pass */
- START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_SA);
+ /* Start the output packet.
+ *
+ * proccess_packet() would automatically generate the HDR*
+ * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE.
+ * We don't do this because we wish there to be no partially
+ * built output packet if we need to suspend for asynch DNS.
+ *
+ * We build the reply packet as we parse the message since
+ * the parse_ipsec_sa_body emits the reply SA
+ */
- /* process SA (in and out) */
- {
- struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
- pb_stream r_sa_pbs;
- struct isakmp_sa sa = sapd->payload.sa;
+ /* HDR* out */
+ echo_hdr(md, TRUE, ISAKMP_NEXT_HASH);
- /* sa header is unchanged -- except for np */
- sa.isasa_np = ISAKMP_NEXT_NONCE;
- if (!out_struct(&sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
- return STF_INTERNAL_ERROR;
+ /* HASH(2) out -- first pass */
+ START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_SA);
- /* parse and accept body */
- st->st_pfs_group = &unset_group;
- RETURN_STF_FAILURE(parse_ipsec_sa_body(&sapd->pbs
- , &sapd->payload.sa, &r_sa_pbs, FALSE, st));
- }
+ /* process SA (in and out) */
+ {
+ struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
+ pb_stream r_sa_pbs;
+ struct isakmp_sa sa = sapd->payload.sa;
+
+ /* sa header is unchanged -- except for np */
+ sa.isasa_np = ISAKMP_NEXT_NONCE;
+ if (!out_struct(&sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
+ return STF_INTERNAL_ERROR;
+
+ /* parse and accept body */
+ st->st_pfs_group = &unset_group;
+ RETURN_STF_FAILURE(parse_ipsec_sa_body(&sapd->pbs
+ , &sapd->payload.sa, &r_sa_pbs, FALSE, st));
+ }
- passert(st->st_pfs_group != &unset_group);
+ passert(st->st_pfs_group != &unset_group);
- if ((st->st_policy & POLICY_PFS) && st->st_pfs_group == NULL)
- {
- loglog(RC_LOG_SERIOUS, "we require PFS but Quick I1 SA specifies no GROUP_DESCRIPTION");
- return STF_FAIL + NO_PROPOSAL_CHOSEN; /* ??? */
- }
+ if ((st->st_policy & POLICY_PFS) && st->st_pfs_group == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "we require PFS but Quick I1 SA specifies no GROUP_DESCRIPTION");
+ return STF_FAIL + NO_PROPOSAL_CHOSEN; /* ??? */
+ }
- /* Ni in */
- RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni"));
+ /* Ni in */
+ RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni"));
- /* [ KE ] in (for PFS) */
- RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gi, "Gi", "Quick Mode I1"));
+ /* [ KE ] in (for PFS) */
+ RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gi, "Gi", "Quick Mode I1"));
- plog("responding to Quick Mode");
+ plog("responding to Quick Mode");
- /**** finish reply packet: Nr [, KE ] [, IDci, IDcr ] ****/
+ /**** finish reply packet: Nr [, KE ] [, IDci, IDcr ] ****/
- /* Nr out */
- if (!build_and_ship_nonce(&st->st_nr, &md->rbody
- , st->st_pfs_group != NULL? ISAKMP_NEXT_KE : id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE
- , "Nr"))
- return STF_INTERNAL_ERROR;
+ /* Nr out */
+ if (!build_and_ship_nonce(&st->st_nr, &md->rbody
+ , st->st_pfs_group != NULL? ISAKMP_NEXT_KE : id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE
+ , "Nr"))
+ return STF_INTERNAL_ERROR;
- /* [ KE ] out (for PFS) */
+ /* [ KE ] out (for PFS) */
- if (st->st_pfs_group != NULL)
- {
- if (!build_and_ship_KE(st, &st->st_gr, st->st_pfs_group
- , &md->rbody, id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE))
- return STF_INTERNAL_ERROR;
+ if (st->st_pfs_group != NULL)
+ {
+ if (!build_and_ship_KE(st, &st->st_gr, st->st_pfs_group
+ , &md->rbody, id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE))
+ return STF_INTERNAL_ERROR;
- /* MPZ-Operations might be done after sending the packet... */
- compute_dh_shared(st, st->st_gi, st->st_pfs_group);
- }
+ /* MPZ-Operations might be done after sending the packet... */
+ compute_dh_shared(st, st->st_gi);
+ }
- /* [ IDci, IDcr ] out */
- if (id_pd != NULL)
- {
- struct isakmp_ipsec_id *p = (void *)md->rbody.cur; /* UGH! */
+ /* [ IDci, IDcr ] out */
+ if (id_pd != NULL)
+ {
+ struct isakmp_ipsec_id *p = (void *)md->rbody.cur; /* UGH! */
- if (!out_raw(id_pd->pbs.start, pbs_room(&id_pd->pbs), &md->rbody, "IDci"))
- return STF_INTERNAL_ERROR;
- p->isaiid_np = ISAKMP_NEXT_ID;
+ if (!out_raw(id_pd->pbs.start, pbs_room(&id_pd->pbs), &md->rbody, "IDci"))
+ return STF_INTERNAL_ERROR;
+ p->isaiid_np = ISAKMP_NEXT_ID;
- p = (void *)md->rbody.cur; /* UGH! */
+ p = (void *)md->rbody.cur; /* UGH! */
- if (!out_raw(id_pd->next->pbs.start, pbs_room(&id_pd->next->pbs), &md->rbody, "IDcr"))
- return STF_INTERNAL_ERROR;
- p->isaiid_np = ISAKMP_NEXT_NONE;
- }
+ if (!out_raw(id_pd->next->pbs.start, pbs_room(&id_pd->next->pbs), &md->rbody, "IDcr"))
+ return STF_INTERNAL_ERROR;
+ p->isaiid_np = ISAKMP_NEXT_NONE;
+ }
- if ((st->nat_traversal & NAT_T_WITH_NATOA)
- && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
- && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT))
- {
- /** Send NAT-OA if our address is NATed and if we use Transport Mode */
- if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &md->rbody, md->st))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT)
- && (c->spd.that.has_client))
- {
- /** Remove client **/
- addrtosubnet(&c->spd.that.host_addr, &c->spd.that.client);
- c->spd.that.has_client = FALSE;
- }
+ if ((st->nat_traversal & NAT_T_WITH_NATOA)
+ && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
+ && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT))
+ {
+ /** Send NAT-OA if our address is NATed and if we use Transport Mode */
+ if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &md->rbody, md->st))
+ {
+ return STF_INTERNAL_ERROR;
+ }
+ }
+ if ((st->nat_traversal & NAT_T_DETECTED)
+ && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT)
+ && (c->spd.that.has_client))
+ {
+ /** Remove client **/
+ addrtosubnet(&c->spd.that.host_addr, &c->spd.that.client);
+ c->spd.that.has_client = FALSE;
+ }
- /* Compute reply HASH(2) and insert in output */
- (void)quick_mode_hash12(r_hashval, r_hash_start, md->rbody.cur
- , st, &st->st_msgid, TRUE);
+ /* Compute reply HASH(2) and insert in output */
+ (void)quick_mode_hash12(r_hashval, r_hash_start, md->rbody.cur
+ , st, &st->st_msgid, TRUE);
- /* Derive new keying material */
- compute_keymats(st);
+ /* Derive new keying material */
+ compute_keymats(st);
- /* Tell the kernel to establish the new inbound SA
- * (unless the commit bit is set -- which we don't support).
- * We do this before any state updating so that
- * failure won't look like success.
- */
- if (!install_inbound_ipsec_sa(st))
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
+ /* Tell the kernel to establish the new inbound SA
+ * (unless the commit bit is set -- which we don't support).
+ * We do this before any state updating so that
+ * failure won't look like success.
+ */
+ if (!install_inbound_ipsec_sa(st))
+ return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- /* encrypt message, except for fixed part of header */
+ /* encrypt message, except for fixed part of header */
- if (!encrypt_message(&md->rbody, st))
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
+ if (!encrypt_message(&md->rbody, st))
+ return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- return STF_OK;
- }
+ return STF_OK;
+ }
}
/*
* Initialize RFC 3706 Dead Peer Detection
*/
-static void
-dpd_init(struct state *st)
+static void dpd_init(struct state *st)
{
- struct state *p1st = find_state(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr, 0);
-
- if (p1st == NULL)
- loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD");
- else if (p1st->st_dpd)
- {
- plog("Dead Peer Detection (RFC 3706) enabled");
- /* randomize the first DPD event */
-
- event_schedule(EVENT_DPD
- , (0.5 + rand()/(RAND_MAX + 1.E0)) * st->st_connection->dpd_delay
- , st);
- }
+ struct state *p1st = find_state(st->st_icookie, st->st_rcookie
+ , &st->st_connection->spd.that.host_addr, 0);
+
+ if (p1st == NULL)
+ loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD");
+ else if (p1st->st_dpd)
+ {
+ plog("Dead Peer Detection (RFC 3706) enabled");
+ /* randomize the first DPD event */
+
+ event_schedule(EVENT_DPD
+ , (0.5 + rand()/(RAND_MAX + 1.E0)) * st->st_connection->dpd_delay
+ , st);
+ }
}
/* Handle (the single) message from Responder in Quick Mode.
@@ -5043,152 +4910,151 @@ dpd_init(struct state *st)
* (see RFC 2409 "IKE" 5.5)
* Installs inbound and outbound IPsec SAs, routing, etc.
*/
-stf_status
-quick_inR1_outI2(struct msg_digest *md)
+stf_status quick_inR1_outI2(struct msg_digest *md)
{
- struct state *const st = md->st;
- const struct connection *c = st->st_connection;
+ struct state *const st = md->st;
+ const struct connection *c = st->st_connection;
- /* HASH(2) in */
- CHECK_QUICK_HASH(md
- , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
- , st, &st->st_msgid, TRUE)
- , "HASH(2)", "Quick R1");
-
- /* SA in */
- {
- struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
+ /* HASH(2) in */
+ CHECK_QUICK_HASH(md
+ , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
+ , st, &st->st_msgid, TRUE)
+ , "HASH(2)", "Quick R1");
- RETURN_STF_FAILURE(parse_ipsec_sa_body(&sa_pd->pbs
- , &sa_pd->payload.sa, NULL, TRUE, st));
- }
+ /* SA in */
+ {
+ struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
- /* Nr in */
- RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
+ RETURN_STF_FAILURE(parse_ipsec_sa_body(&sa_pd->pbs
+ , &sa_pd->payload.sa, NULL, TRUE, st));
+ }
- /* [ KE ] in (for PFS) */
- RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1"));
+ /* Nr in */
+ RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
- if (st->st_pfs_group != NULL)
- compute_dh_shared(st, st->st_gr, st->st_pfs_group);
+ /* [ KE ] in (for PFS) */
+ RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1"));
- /* [ IDci, IDcr ] in; these must match what we sent */
+ if (st->st_pfs_group != NULL)
+ compute_dh_shared(st, st->st_gr);
- {
- struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
+ /* [ IDci, IDcr ] in; these must match what we sent */
- if (id_pd != NULL)
{
- /* ??? we are assuming IPSEC_DOI */
+ struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
- /* IDci (we are initiator) */
+ if (id_pd != NULL)
+ {
+ /* ??? we are assuming IPSEC_DOI */
- if (!check_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
- , &st->st_myuserprotoid, &st->st_myuserport
- , &st->st_connection->spd.this.client
- , "our client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
+ /* IDci (we are initiator) */
- /* IDcr (responder is peer) */
+ if (!check_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
+ , &st->st_myuserprotoid, &st->st_myuserport
+ , &st->st_connection->spd.this.client
+ , "our client"))
+ return STF_FAIL + INVALID_ID_INFORMATION;
- if (!check_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs
- , &st->st_peeruserprotoid, &st->st_peeruserport
- , &st->st_connection->spd.that.client
- , "peer client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
- }
- else
- {
- /* no IDci, IDcr: we must check that the defaults match our proposal */
- if (!subnetisaddr(&c->spd.this.client, &c->spd.this.host_addr)
- || !subnetisaddr(&c->spd.that.client, &c->spd.that.host_addr))
- {
- loglog(RC_LOG_SERIOUS, "IDci, IDcr payloads missing in message"
- " but default does not match proposal");
- return STF_FAIL + INVALID_ID_INFORMATION;
- }
+ /* IDcr (responder is peer) */
+
+ if (!check_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs
+ , &st->st_peeruserprotoid, &st->st_peeruserport
+ , &st->st_connection->spd.that.client
+ , "peer client"))
+ return STF_FAIL + INVALID_ID_INFORMATION;
+ }
+ else
+ {
+ /* no IDci, IDcr: we must check that the defaults match our proposal */
+ if (!subnetisaddr(&c->spd.this.client, &c->spd.this.host_addr)
+ || !subnetisaddr(&c->spd.that.client, &c->spd.that.host_addr))
+ {
+ loglog(RC_LOG_SERIOUS, "IDci, IDcr payloads missing in message"
+ " but default does not match proposal");
+ return STF_FAIL + INVALID_ID_INFORMATION;
+ }
+ }
}
- }
- /* check the peer's group attributes */
-
- {
- const ietfAttrList_t *peer_list = NULL;
+ /* check the peer's group attributes */
- get_peer_ca_and_groups(st->st_connection, &peer_list);
-
- if (!group_membership(peer_list, st->st_connection->name
- , st->st_connection->spd.that.groups))
{
- char buf[BUF_LEN];
+ const ietfAttrList_t *peer_list = NULL;
+
+ get_peer_ca_and_groups(st->st_connection, &peer_list);
- format_groups(st->st_connection->spd.that.groups, buf, BUF_LEN);
- loglog(RC_LOG_SERIOUS, "peer is not member of one of the groups: %s"
- , buf);
- return STF_FAIL + INVALID_ID_INFORMATION;
- }
- }
+ if (!group_membership(peer_list, st->st_connection->name
+ , st->st_connection->spd.that.groups))
+ {
+ char buf[BUF_LEN];
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_NATOA))
- {
- nat_traversal_natoa_lookup(md);
+ format_groups(st->st_connection->spd.that.groups, buf, BUF_LEN);
+ loglog(RC_LOG_SERIOUS, "peer is not member of one of the groups: %s"
+ , buf);
+ return STF_FAIL + INVALID_ID_INFORMATION;
+ }
}
- /* ??? We used to copy the accepted proposal into the state, but it was
- * never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs).
- */
+ if ((st->nat_traversal & NAT_T_DETECTED)
+ && (st->nat_traversal & NAT_T_WITH_NATOA))
+ {
+ nat_traversal_natoa_lookup(md);
+ }
+
+ /* ??? We used to copy the accepted proposal into the state, but it was
+ * never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs).
+ */
- /**************** build reply packet HDR*, HASH(3) ****************/
+ /**************** build reply packet HDR*, HASH(3) ****************/
- /* HDR* out done */
+ /* HDR* out done */
- /* HASH(3) out -- since this is the only content, no passes needed */
- {
- u_char /* set by START_HASH_PAYLOAD: */
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
+ /* HASH(3) out -- since this is the only content, no passes needed */
+ {
+ u_char /* set by START_HASH_PAYLOAD: */
+ *r_hashval, /* where in reply to jam hash value */
+ *r_hash_start; /* start of what is to be hashed */
- START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_NONE);
- (void)quick_mode_hash3(r_hashval, st);
- }
+ START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_NONE);
+ (void)quick_mode_hash3(r_hashval, st);
+ }
- /* Derive new keying material */
- compute_keymats(st);
+ /* Derive new keying material */
+ compute_keymats(st);
- /* Tell the kernel to establish the inbound, outbound, and routing part
- * of the new SA (unless the commit bit is set -- which we don't support).
- * We do this before any state updating so that
- * failure won't look like success.
- */
- if (!install_ipsec_sa(st, TRUE))
- return STF_INTERNAL_ERROR;
+ /* Tell the kernel to establish the inbound, outbound, and routing part
+ * of the new SA (unless the commit bit is set -- which we don't support).
+ * We do this before any state updating so that
+ * failure won't look like success.
+ */
+ if (!install_ipsec_sa(st, TRUE))
+ return STF_INTERNAL_ERROR;
- /* encrypt message, except for fixed part of header */
+ /* encrypt message, except for fixed part of header */
- if (!encrypt_message(&md->rbody, st))
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
+ if (!encrypt_message(&md->rbody, st))
+ return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- {
- DBG(DBG_CONTROLMORE, DBG_log("inR1_outI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
- , st->st_connection->name
- , st->st_connection->instance_serial
- , st->st_serialno
- , st->st_connection->newest_ipsec_sa
- , st->st_connection->spd.eroute_owner));
- }
-
- st->st_connection->newest_ipsec_sa = st->st_serialno;
+ {
+ DBG(DBG_CONTROLMORE, DBG_log("inR1_outI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
+ , st->st_connection->name
+ , st->st_connection->instance_serial
+ , st->st_serialno
+ , st->st_connection->newest_ipsec_sa
+ , st->st_connection->spd.eroute_owner));
+ }
+
+ st->st_connection->newest_ipsec_sa = st->st_serialno;
- /* note (presumed) success */
- if (c->gw_info != NULL)
- c->gw_info->key->last_worked_time = now();
+ /* note (presumed) success */
+ if (c->gw_info != NULL)
+ c->gw_info->key->last_worked_time = now();
- /* If we want DPD on this connection then initialize it */
- if (st->st_connection->dpd_action != DPD_ACTION_NONE)
- dpd_init(st);
+ /* If we want DPD on this connection then initialize it */
+ if (st->st_connection->dpd_action != DPD_ACTION_NONE)
+ dpd_init(st);
- return STF_OK;
+ return STF_OK;
}
/* Handle last message of Quick Mode.
@@ -5196,245 +5062,253 @@ quick_inR1_outI2(struct msg_digest *md)
* (see RFC 2409 "IKE" 5.5)
* Installs outbound IPsec SAs, routing, etc.
*/
-stf_status
-quick_inI2(struct msg_digest *md)
+stf_status quick_inI2(struct msg_digest *md)
{
- struct state *const st = md->st;
-
- /* HASH(3) in */
- CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st)
- , "HASH(3)", "Quick I2");
-
- /* Tell the kernel to establish the outbound and routing part of the new SA
- * (the previous state established inbound)
- * (unless the commit bit is set -- which we don't support).
- * We do this before any state updating so that
- * failure won't look like success.
- */
- if (!install_ipsec_sa(st, FALSE))
- return STF_INTERNAL_ERROR;
-
- {
- DBG(DBG_CONTROLMORE, DBG_log("inI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
- , st->st_connection->name
- , st->st_connection->instance_serial
- , st->st_serialno
- , st->st_connection->newest_ipsec_sa
- , st->st_connection->spd.eroute_owner));
- }
-
- st->st_connection->newest_ipsec_sa = st->st_serialno;
-
- update_iv(st); /* not actually used, but tidy */
-
- /* note (presumed) success */
- {
- struct gw_info *gw = st->st_connection->gw_info;
-
- if (gw != NULL)
- gw->key->last_worked_time = now();
- }
-
- /* If we want DPD on this connection then initialize it */
- if (st->st_connection->dpd_action != DPD_ACTION_NONE)
- dpd_init(st);
-
- return STF_OK;
+ struct state *const st = md->st;
+
+ /* HASH(3) in */
+ CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st)
+ , "HASH(3)", "Quick I2");
+
+ /* Tell the kernel to establish the outbound and routing part of the new SA
+ * (the previous state established inbound)
+ * (unless the commit bit is set -- which we don't support).
+ * We do this before any state updating so that
+ * failure won't look like success.
+ */
+ if (!install_ipsec_sa(st, FALSE))
+ return STF_INTERNAL_ERROR;
+
+ {
+ DBG(DBG_CONTROLMORE, DBG_log("inI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
+ , st->st_connection->name
+ , st->st_connection->instance_serial
+ , st->st_serialno
+ , st->st_connection->newest_ipsec_sa
+ , st->st_connection->spd.eroute_owner));
+ }
+
+ st->st_connection->newest_ipsec_sa = st->st_serialno;
+
+ update_iv(st); /* not actually used, but tidy */
+
+ /* note (presumed) success */
+ {
+ struct gw_info *gw = st->st_connection->gw_info;
+
+ if (gw != NULL)
+ gw->key->last_worked_time = now();
+ }
+
+ /* If we want DPD on this connection then initialize it */
+ if (st->st_connection->dpd_action != DPD_ACTION_NONE)
+ dpd_init(st);
+
+ return STF_OK;
}
-static stf_status
-send_isakmp_notification(struct state *st, u_int16_t type
- , const void *data, size_t len)
+static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
+ const void *data, size_t len)
{
- msgid_t msgid;
- pb_stream reply;
- pb_stream rbody;
- u_char
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
-
- msgid = generate_msgid(st);
-
- init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "ISAKMP notify");
-
- /* 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, st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
- impossible();
- }
- /* HASH -- create and note space to be filled later */
- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_N);
-
- /* NOTIFY */
- {
- pb_stream notify_pbs;
- struct isakmp_notification isan;
-
- isan.isan_np = ISAKMP_NEXT_NONE;
- isan.isan_doi = ISAKMP_DOI_IPSEC;
- isan.isan_protoid = PROTO_ISAKMP;
- isan.isan_spisize = COOKIE_SIZE * 2;
- isan.isan_type = type;
- if (!out_struct(&isan, &isakmp_notification_desc, &rbody, &notify_pbs))
- return STF_INTERNAL_ERROR;
- if (!out_raw(st->st_icookie, COOKIE_SIZE, &notify_pbs, "notify icookie"))
- return STF_INTERNAL_ERROR;
- if (!out_raw(st->st_rcookie, COOKIE_SIZE, &notify_pbs, "notify rcookie"))
- return STF_INTERNAL_ERROR;
- if (data != NULL && len > 0)
- if (!out_raw(data, len, &notify_pbs, "notify data"))
- return STF_INTERNAL_ERROR;
- close_output_pbs(&notify_pbs);
- }
-
- {
- /* finish computing HASH */
- struct hmac_ctx ctx;
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
- hmac_update(&ctx, (const u_char *) &msgid, sizeof(msgid_t));
- hmac_update(&ctx, r_hash_start, rbody.cur-r_hash_start);
- hmac_final(r_hashval, &ctx);
-
- DBG(DBG_CRYPT,
- DBG_log("HASH computed:");
- DBG_dump("", r_hashval, ctx.hmac_digest_size));
- }
-
- /* Encrypt message (preserve st_iv and st_new_iv) */
- {
- u_char old_iv[MAX_DIGEST_LEN];
- u_char new_iv[MAX_DIGEST_LEN];
+ msgid_t msgid;
+ pb_stream reply;
+ pb_stream rbody;
+ u_char
+ *r_hashval, /* where in reply to jam hash value */
+ *r_hash_start; /* start of what is to be hashed */
+
+ msgid = generate_msgid(st);
+
+ init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "ISAKMP notify");
+
+ /* 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, st->st_icookie, COOKIE_SIZE);
+ memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
+ if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
+ impossible();
+ }
+ /* HASH -- create and note space to be filled later */
+ START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_N);
- u_int old_iv_len = st->st_iv_len;
- u_int new_iv_len = st->st_new_iv_len;
+ /* NOTIFY */
+ {
+ pb_stream notify_pbs;
+ struct isakmp_notification isan;
+
+ isan.isan_np = ISAKMP_NEXT_NONE;
+ isan.isan_doi = ISAKMP_DOI_IPSEC;
+ isan.isan_protoid = PROTO_ISAKMP;
+ isan.isan_spisize = COOKIE_SIZE * 2;
+ isan.isan_type = type;
+ if (!out_struct(&isan, &isakmp_notification_desc, &rbody, &notify_pbs))
+ return STF_INTERNAL_ERROR;
+ if (!out_raw(st->st_icookie, COOKIE_SIZE, &notify_pbs, "notify icookie"))
+ return STF_INTERNAL_ERROR;
+ if (!out_raw(st->st_rcookie, COOKIE_SIZE, &notify_pbs, "notify rcookie"))
+ return STF_INTERNAL_ERROR;
+ if (data != NULL && len > 0)
+ if (!out_raw(data, len, &notify_pbs, "notify data"))
+ return STF_INTERNAL_ERROR;
+ close_output_pbs(&notify_pbs);
+ }
+
+ {
+ /* finish computing HASH */
+ chunk_t msgid_chunk = chunk_from_thing(msgid);
+ chunk_t msg_chunk = { r_hash_start, rbody.cur-r_hash_start };
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid_a);
+ prf->get_bytes(prf, msgid_chunk, NULL);
+ prf->get_bytes(prf, msg_chunk, r_hashval);
+
+ DBG(DBG_CRYPT,
+ DBG_log("HASH computed:");
+ DBG_dump("", r_hashval, prf->get_block_size(prf));
+ )
+ prf->destroy(prf);
+ }
+
+ /* Encrypt message (preserve st_iv and st_new_iv) */
+ {
+ u_char old_iv[MAX_DIGEST_LEN];
+ u_char new_iv[MAX_DIGEST_LEN];
- if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN)
- return STF_INTERNAL_ERROR;
+ u_int old_iv_len = st->st_iv_len;
+ u_int new_iv_len = st->st_new_iv_len;
- memcpy(old_iv, st->st_iv, old_iv_len);
- memcpy(new_iv, st->st_new_iv, new_iv_len);
+ if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN)
+ return STF_INTERNAL_ERROR;
- init_phase2_iv(st, &msgid);
- if (!encrypt_message(&rbody, st))
- return STF_INTERNAL_ERROR;
-
- /* restore preserved st_iv and st_new_iv */
- memcpy(st->st_iv, old_iv, old_iv_len);
- memcpy(st->st_new_iv, new_iv, new_iv_len);
- st->st_iv_len = old_iv_len;
- st->st_new_iv_len = new_iv_len;
- }
-
- /* Send packet (preserve st_tpacket) */
- {
- chunk_t saved_tpacket = st->st_tpacket;
-
- setchunk(st->st_tpacket, reply.start, pbs_offset(&reply));
- send_packet(st, "ISAKMP notify");
- st->st_tpacket = saved_tpacket;
- }
-
- return STF_IGNORE;
+ memcpy(old_iv, st->st_iv, old_iv_len);
+ memcpy(new_iv, st->st_new_iv, new_iv_len);
+
+ init_phase2_iv(st, &msgid);
+ if (!encrypt_message(&rbody, st))
+ return STF_INTERNAL_ERROR;
+
+ /* restore preserved st_iv and st_new_iv */
+ memcpy(st->st_iv, old_iv, old_iv_len);
+ memcpy(st->st_new_iv, new_iv, new_iv_len);
+ st->st_iv_len = old_iv_len;
+ st->st_new_iv_len = new_iv_len;
+ }
+
+ /* Send packet (preserve st_tpacket) */
+ {
+ chunk_t saved_tpacket = st->st_tpacket;
+
+ st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply));
+ send_packet(st, "ISAKMP notify");
+ st->st_tpacket = saved_tpacket;
+ }
+
+ return STF_IGNORE;
}
/*
* DPD Out Initiator
*/
-void
-dpd_outI(struct state *p2st)
+void dpd_outI(struct state *p2st)
{
- struct state *st;
- u_int32_t seqno;
- time_t tm;
- time_t idle_time;
- time_t delay = p2st->st_connection->dpd_delay;
- time_t timeout = p2st->st_connection->dpd_timeout;
-
- /* find the newest related Phase 1 state */
- st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
-
- if (st == NULL)
- {
- loglog(RC_LOG_SERIOUS, "DPD: Could not find newest phase 1 state");
- return;
- }
-
- /* If no DPD, then get out of here */
- if (!st->st_dpd)
- return;
-
- /* schedule the next periodic DPD event */
- event_schedule(EVENT_DPD, delay, p2st);
-
- /* Current time */
- tm = now();
-
- /* Make sure we really need to invoke DPD */
- if (!was_eroute_idle(p2st, delay, &idle_time))
- {
+ struct state *st;
+ u_int32_t seqno;
+ time_t tm;
+ time_t idle_time;
+ time_t delay = p2st->st_connection->dpd_delay;
+ time_t timeout = p2st->st_connection->dpd_timeout;
+
+ /* find the newest related Phase 1 state */
+ st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
+
+ if (st == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "DPD: Could not find newest phase 1 state");
+ return;
+ }
+
+ /* If no DPD, then get out of here */
+ if (!st->st_dpd)
+ return;
+
+ /* schedule the next periodic DPD event */
+ event_schedule(EVENT_DPD, delay, p2st);
+
+ /* Current time */
+ tm = now();
+
+ /* Make sure we really need to invoke DPD */
+ if (!was_eroute_idle(p2st, delay, &idle_time))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("recent eroute activity %u seconds ago, "
+ "no need to send DPD notification"
+ , (int)idle_time)
+ )
+ st->st_last_dpd = tm;
+ delete_dpd_event(st);
+ return;
+ }
+
+ /* If an R_U_THERE has been sent or received recently, or if a
+ * companion Phase 2 SA has shown eroute activity,
+ * then we don't need to invoke DPD.
+ */
+ if (tm < st->st_last_dpd + delay)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("recent DPD activity %u seconds ago, "
+ "no need to send DPD notification"
+ , (int)(tm - st->st_last_dpd))
+ )
+ return;
+ }
+
+ if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ return;
+
+ if (!st->st_dpd_seqno)
+ {
+ rng_t *rng;
+
+ /* Get a non-zero random value that has room to grow */
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ rng->get_bytes(rng, sizeof(st->st_dpd_seqno), (u_char *)&st->st_dpd_seqno);
+ rng->destroy(rng);
+ st->st_dpd_seqno &= 0x7fff;
+ st->st_dpd_seqno++;
+ }
+ seqno = htonl(st->st_dpd_seqno);
+
+ if (send_isakmp_notification(st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE)
+ {
+ loglog(RC_LOG_SERIOUS, "DPD: Could not send R_U_THERE");
+ return;
+ }
DBG(DBG_CONTROL,
- DBG_log("recent eroute activity %u seconds ago, "
- "no need to send DPD notification"
- , (int)idle_time)
+ DBG_log("sent DPD notification R_U_THERE with seqno = %u", st->st_dpd_seqno)
)
+ st->st_dpd_expectseqno = st->st_dpd_seqno++;
st->st_last_dpd = tm;
- delete_dpd_event(st);
- return;
- }
-
- /* If an R_U_THERE has been sent or received recently, or if a
- * companion Phase 2 SA has shown eroute activity,
- * then we don't need to invoke DPD.
- */
- if (tm < st->st_last_dpd + delay)
- {
- DBG(DBG_CONTROL,
- DBG_log("recent DPD activity %u seconds ago, "
- "no need to send DPD notification"
- , (int)(tm - st->st_last_dpd))
- )
- return;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- return;
-
- if (!st->st_dpd_seqno)
- {
- /* Get a non-zero random value that has room to grow */
- get_rnd_bytes((u_char *)&st->st_dpd_seqno, sizeof(st->st_dpd_seqno));
- st->st_dpd_seqno &= 0x7fff;
- st->st_dpd_seqno++;
- }
- seqno = htonl(st->st_dpd_seqno);
-
- if (send_isakmp_notification(st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE)
- {
- loglog(RC_LOG_SERIOUS, "DPD: Could not send R_U_THERE");
- return;
- }
- DBG(DBG_CONTROL,
- DBG_log("sent DPD notification R_U_THERE with seqno = %u", st->st_dpd_seqno)
- )
- st->st_dpd_expectseqno = st->st_dpd_seqno++;
- st->st_last_dpd = tm;
- /* Only schedule a new timeout if there isn't one currently,
- * or if it would be sooner than the current timeout. */
- if (st->st_dpd_event == NULL
- || st->st_dpd_event->ev_time > tm + timeout)
- {
- delete_dpd_event(st);
- event_schedule(EVENT_DPD_TIMEOUT, timeout, st);
- }
+ /* Only schedule a new timeout if there isn't one currently,
+ * or if it would be sooner than the current timeout. */
+ if (st->st_dpd_event == NULL
+ || st->st_dpd_event->ev_time > tm + timeout)
+ {
+ delete_dpd_event(st);
+ event_schedule(EVENT_DPD_TIMEOUT, timeout, st);
+ }
}
/*
@@ -5444,139 +5318,139 @@ stf_status
dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs)
{
time_t tm = now();
- u_int32_t seqno;
-
- if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "DPD: Received R_U_THERE for unestablished ISAKMP SA");
- return STF_IGNORE;
- }
- if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
- {
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid SPI length (%d)", n->isan_spisize);
- return STF_FAIL + PAYLOAD_MALFORMED;
- }
-
- if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
- {
+ u_int32_t seqno;
+
+ if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ loglog(RC_LOG_SERIOUS, "DPD: Received R_U_THERE for unestablished ISAKMP SA");
+ return STF_IGNORE;
+ }
+ if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
+ {
+ loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid SPI length (%d)", n->isan_spisize);
+ return STF_FAIL + PAYLOAD_MALFORMED;
+ }
+
+ if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
+ {
#ifdef APPLY_CRISCO
- /* Ignore it, cisco sends odd icookies */
+ /* Ignore it, cisco sends odd icookies */
#else
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid icookie (broken Cisco?)");
- return STF_FAIL + INVALID_COOKIE;
+ loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid icookie (broken Cisco?)");
+ return STF_FAIL + INVALID_COOKIE;
#endif
- }
- pbs->cur += COOKIE_SIZE;
-
- if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0)
- {
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid rcookie (broken Cisco?)");
- return STF_FAIL + INVALID_COOKIE;
- }
- pbs->cur += COOKIE_SIZE;
-
- if (pbs_left(pbs) != sizeof(seqno))
- {
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid data length (%d)"
- , (int) pbs_left(pbs));
- return STF_FAIL + PAYLOAD_MALFORMED;
- }
-
- seqno = ntohl(*(u_int32_t *)pbs->cur);
- DBG(DBG_CONTROL,
- DBG_log("received DPD notification R_U_THERE with seqno = %u", seqno)
- )
-
- if (st->st_dpd_peerseqno && seqno <= st->st_dpd_peerseqno) {
- loglog(RC_LOG_SERIOUS, "DPD: Received old or duplicate R_U_THERE");
- return STF_IGNORE;
- }
-
- st->st_dpd_peerseqno = seqno;
- delete_dpd_event(st);
-
- if (send_isakmp_notification(st, R_U_THERE_ACK, pbs->cur, pbs_left(pbs)) != STF_IGNORE)
- {
- loglog(RC_LOG_SERIOUS, "DPD Info: could not send R_U_THERE_ACK");
- return STF_IGNORE;
- }
- DBG(DBG_CONTROL,
- DBG_log("sent DPD notification R_U_THERE_ACK with seqno = %u", seqno)
- )
-
- st->st_last_dpd = tm;
- return STF_IGNORE;
+ }
+ pbs->cur += COOKIE_SIZE;
+
+ if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0)
+ {
+ loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid rcookie (broken Cisco?)");
+ return STF_FAIL + INVALID_COOKIE;
+ }
+ pbs->cur += COOKIE_SIZE;
+
+ if (pbs_left(pbs) != sizeof(seqno))
+ {
+ loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid data length (%d)"
+ , (int) pbs_left(pbs));
+ return STF_FAIL + PAYLOAD_MALFORMED;
+ }
+
+ seqno = ntohl(*(u_int32_t *)pbs->cur);
+ DBG(DBG_CONTROL,
+ DBG_log("received DPD notification R_U_THERE with seqno = %u", seqno)
+ )
+
+ if (st->st_dpd_peerseqno && seqno <= st->st_dpd_peerseqno) {
+ loglog(RC_LOG_SERIOUS, "DPD: Received old or duplicate R_U_THERE");
+ return STF_IGNORE;
+ }
+
+ st->st_dpd_peerseqno = seqno;
+ delete_dpd_event(st);
+
+ if (send_isakmp_notification(st, R_U_THERE_ACK, pbs->cur, pbs_left(pbs)) != STF_IGNORE)
+ {
+ loglog(RC_LOG_SERIOUS, "DPD Info: could not send R_U_THERE_ACK");
+ return STF_IGNORE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("sent DPD notification R_U_THERE_ACK with seqno = %u", seqno)
+ )
+
+ st->st_last_dpd = tm;
+ return STF_IGNORE;
}
/*
* DPD out Responder
*/
-stf_status
-dpd_inR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs)
+stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
+ pb_stream *pbs)
{
- u_int32_t seqno;
+ u_int32_t seqno;
- if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS
- , "DPD: Received R_U_THERE_ACK for unestablished ISAKMP SA");
- return STF_FAIL;
- }
+ if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ {
+ loglog(RC_LOG_SERIOUS
+ , "DPD: Received R_U_THERE_ACK for unestablished ISAKMP SA");
+ return STF_FAIL;
+ }
if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
- {
- loglog(RC_LOG_SERIOUS
- , "DPD: R_U_THERE_ACK has invalid SPI length (%d)"
- , n->isan_spisize);
- return STF_FAIL + PAYLOAD_MALFORMED;
- }
-
- if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
- {
+ {
+ loglog(RC_LOG_SERIOUS
+ , "DPD: R_U_THERE_ACK has invalid SPI length (%d)"
+ , n->isan_spisize);
+ return STF_FAIL + PAYLOAD_MALFORMED;
+ }
+
+ if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
+ {
#ifdef APPLY_CRISCO
- /* Ignore it, cisco sends odd icookies */
+ /* Ignore it, cisco sends odd icookies */
#else
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid icookie");
- return STF_FAIL + INVALID_COOKIE;
+ loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid icookie");
+ return STF_FAIL + INVALID_COOKIE;
#endif
- }
- pbs->cur += COOKIE_SIZE;
+ }
+ pbs->cur += COOKIE_SIZE;
- if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0)
- {
+ if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0)
+ {
#ifdef APPLY_CRISCO
- /* Ignore it, cisco sends odd icookies */
+ /* Ignore it, cisco sends odd icookies */
#else
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid rcookie");
- return STF_FAIL + INVALID_COOKIE;
+ loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid rcookie");
+ return STF_FAIL + INVALID_COOKIE;
#endif
- }
- pbs->cur += COOKIE_SIZE;
-
- if (pbs_left(pbs) != sizeof(seqno))
- {
- loglog(RC_LOG_SERIOUS
- , " DPD: R_U_THERE_ACK has invalid data length (%d)"
- , (int) pbs_left(pbs));
- return STF_FAIL + PAYLOAD_MALFORMED;
- }
-
- seqno = ntohl(*(u_int32_t *)pbs->cur);
- DBG(DBG_CONTROL,
- DBG_log("received DPD notification R_U_THERE_ACK with seqno = %u"
- , seqno)
- )
-
- if (!st->st_dpd_expectseqno && seqno != st->st_dpd_expectseqno)
- {
- loglog(RC_LOG_SERIOUS
- , "DPD: R_U_THERE_ACK has unexpected sequence number");
- return STF_FAIL + PAYLOAD_MALFORMED;
- }
-
- st->st_dpd_expectseqno = 0;
- delete_dpd_event(st);
- return STF_IGNORE;
+ }
+ pbs->cur += COOKIE_SIZE;
+
+ if (pbs_left(pbs) != sizeof(seqno))
+ {
+ loglog(RC_LOG_SERIOUS
+ , " DPD: R_U_THERE_ACK has invalid data length (%d)"
+ , (int) pbs_left(pbs));
+ return STF_FAIL + PAYLOAD_MALFORMED;
+ }
+
+ seqno = ntohl(*(u_int32_t *)pbs->cur);
+ DBG(DBG_CONTROL,
+ DBG_log("received DPD notification R_U_THERE_ACK with seqno = %u"
+ , seqno)
+ )
+
+ if (!st->st_dpd_expectseqno && seqno != st->st_dpd_expectseqno)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "DPD: R_U_THERE_ACK has unexpected sequence number");
+ return STF_FAIL + PAYLOAD_MALFORMED;
+ }
+
+ st->st_dpd_expectseqno = 0;
+ delete_dpd_event(st);
+ return STF_IGNORE;
}
/*
@@ -5589,67 +5463,67 @@ dpd_inR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs)
void
dpd_timeout(struct state *st)
{
- struct state *newest_phase1_st;
- struct connection *c = st->st_connection;
- int action = st->st_connection->dpd_action;
- char cname[BUF_LEN];
-
- passert(action == DPD_ACTION_HOLD
- || action == DPD_ACTION_CLEAR
- || DPD_ACTION_RESTART);
-
- /* is there a newer phase1_state? */
- newest_phase1_st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
- if (newest_phase1_st != NULL && newest_phase1_st != st)
- {
- plog("DPD: Phase1 state #%ld has been superseded by #%ld"
- " - timeout ignored"
- , st->st_serialno, newest_phase1_st->st_serialno);
- return;
- }
-
- loglog(RC_LOG_SERIOUS, "DPD: No response from peer - declaring peer dead");
-
- /* delete the state, which is probably in phase 2 */
- set_cur_connection(c);
- plog("DPD: Terminating all SAs using this connection");
- delete_states_by_connection(c, TRUE);
- reset_cur_connection();
-
- switch (action)
- {
- case DPD_ACTION_HOLD:
- /* dpdaction=hold - Wipe the SA's but %trap the eroute so we don't
- * leak traffic. Also, being in %trap means new packets will
- * force an initiation of the conn again.
- */
- loglog(RC_LOG_SERIOUS, "DPD: Putting connection \"%s\" into %%trap", c->name);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, TRUE);
- break;
- case DPD_ACTION_CLEAR:
- /* dpdaction=clear - Wipe the SA & eroute - everything */
- loglog(RC_LOG_SERIOUS, "DPD: Clearing connection \"%s\"", c->name);
- unroute_connection(c);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, TRUE);
- break;
- case DPD_ACTION_RESTART:
- /* dpdaction=restart - Restart connection,
- * except if roadwarrior connection
- */
- loglog(RC_LOG_SERIOUS, "DPD: Restarting connection \"%s\"", c->name);
- unroute_connection(c);
-
- /* caching the connection name before deletion */
- strncpy(cname, c->name, BUF_LEN);
-
- if (c->kind == CK_INSTANCE)
- delete_connection(c, TRUE);
- initiate_connection(cname, NULL_FD);
- break;
- default:
- loglog(RC_LOG_SERIOUS, "DPD: unknown action");
- }
+ struct state *newest_phase1_st;
+ struct connection *c = st->st_connection;
+ int action = st->st_connection->dpd_action;
+ char cname[BUF_LEN];
+
+ passert(action == DPD_ACTION_HOLD
+ || action == DPD_ACTION_CLEAR
+ || DPD_ACTION_RESTART);
+
+ /* is there a newer phase1_state? */
+ newest_phase1_st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
+ if (newest_phase1_st != NULL && newest_phase1_st != st)
+ {
+ plog("DPD: Phase1 state #%ld has been superseded by #%ld"
+ " - timeout ignored"
+ , st->st_serialno, newest_phase1_st->st_serialno);
+ return;
+ }
+
+ loglog(RC_LOG_SERIOUS, "DPD: No response from peer - declaring peer dead");
+
+ /* delete the state, which is probably in phase 2 */
+ set_cur_connection(c);
+ plog("DPD: Terminating all SAs using this connection");
+ delete_states_by_connection(c, TRUE);
+ reset_cur_connection();
+
+ switch (action)
+ {
+ case DPD_ACTION_HOLD:
+ /* dpdaction=hold - Wipe the SA's but %trap the eroute so we don't
+ * leak traffic. Also, being in %trap means new packets will
+ * force an initiation of the conn again.
+ */
+ loglog(RC_LOG_SERIOUS, "DPD: Putting connection \"%s\" into %%trap", c->name);
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, TRUE);
+ break;
+ case DPD_ACTION_CLEAR:
+ /* dpdaction=clear - Wipe the SA & eroute - everything */
+ loglog(RC_LOG_SERIOUS, "DPD: Clearing connection \"%s\"", c->name);
+ unroute_connection(c);
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, TRUE);
+ break;
+ case DPD_ACTION_RESTART:
+ /* dpdaction=restart - Restart connection,
+ * except if roadwarrior connection
+ */
+ loglog(RC_LOG_SERIOUS, "DPD: Restarting connection \"%s\"", c->name);
+ unroute_connection(c);
+
+ /* caching the connection name before deletion */
+ strncpy(cname, c->name, BUF_LEN);
+
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, TRUE);
+ initiate_connection(cname, NULL_FD);
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "DPD: unknown action");
+ }
}
diff --git a/src/pluto/ipsec_doi.h b/src/pluto/ipsec_doi.h
index 60b5e4e31..2e242e903 100644
--- a/src/pluto/ipsec_doi.h
+++ b/src/pluto/ipsec_doi.h
@@ -10,55 +10,53 @@
* 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: ipsec_doi.h 3252 2007-10-06 21:24:50Z andreas $
*/
extern void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np);
extern void ipsecdoi_initiate(int whack_sock, struct connection *c
- , lset_t policy, unsigned long try, so_serial_t replacing);
+ , lset_t policy, unsigned long try, so_serial_t replacing);
extern void ipsecdoi_replace(struct state *st, unsigned long try);
extern void init_phase2_iv(struct state *st, const msgid_t *msgid);
extern stf_status quick_outI1(int whack_sock
- , struct state *isakmp_sa
- , struct connection *c
- , lset_t policy
- , unsigned long try
- , so_serial_t replacing);
+ , struct state *isakmp_sa
+ , struct connection *c
+ , lset_t policy
+ , unsigned long try
+ , so_serial_t replacing);
extern state_transition_fn
- main_inI1_outR1,
- main_inR1_outI2,
- main_inI2_outR2,
- main_inR2_outI3,
- main_inI3_outR3,
- main_inR3,
- quick_inI1_outR1,
- quick_inR1_outI2,
- quick_inI2;
+ main_inI1_outR1,
+ main_inR1_outI2,
+ main_inI2_outR2,
+ main_inR2_outI3,
+ main_inI3_outR3,
+ main_inR3,
+ quick_inI1_outR1,
+ quick_inR1_outI2,
+ quick_inI2;
extern void send_delete(struct state *st);
extern void accept_delete(struct state *st, struct msg_digest *md
- , struct payload_digest *p);
+ , struct payload_digest *p);
extern void close_message(pb_stream *pbs);
extern bool encrypt_message(pb_stream *pbs, struct state *st);
extern void send_notification_from_state(struct state *st,
- enum state_kind state, u_int16_t type);
+ enum state_kind state, u_int16_t type);
extern void send_notification_from_md(struct msg_digest *md, u_int16_t type);
extern const char *init_pluto_vendorid(void);
extern void dpd_outI(struct state *st);
extern stf_status dpd_inI_outR(struct state *st
- , struct isakmp_notification *const n, pb_stream *n_pbs);
+ , struct isakmp_notification *const n, pb_stream *n_pbs);
extern stf_status dpd_inR(struct state *st
- , struct isakmp_notification *const n, pb_stream *n_pbs);
+ , struct isakmp_notification *const n, pb_stream *n_pbs);
extern void dpd_timeout(struct state *st);
/* START_HASH_PAYLOAD
@@ -70,14 +68,14 @@ extern void dpd_timeout(struct state *st);
* - it references variables local to the caller (r_hashval, r_hash_start, st)
*/
#define START_HASH_PAYLOAD(rbody, np) { \
- pb_stream hash_pbs; \
- if (!out_generic(np, &isakmp_hash_desc, &(rbody), &hash_pbs)) \
- return STF_INTERNAL_ERROR; \
- r_hashval = hash_pbs.cur; /* remember where to plant value */ \
- if (!out_zero(st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) \
- return STF_INTERNAL_ERROR; \
- close_output_pbs(&hash_pbs); \
- r_hash_start = (rbody).cur; /* hash from after HASH payload */ \
+ pb_stream hash_pbs; \
+ if (!out_generic(np, &isakmp_hash_desc, &(rbody), &hash_pbs)) \
+ return STF_INTERNAL_ERROR; \
+ r_hashval = hash_pbs.cur; /* remember where to plant value */ \
+ if (!out_zero(st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) \
+ return STF_INTERNAL_ERROR; \
+ close_output_pbs(&hash_pbs); \
+ r_hash_start = (rbody).cur; /* hash from after HASH payload */ \
}
/* CHECK_QUICK_HASH
@@ -88,17 +86,17 @@ extern void dpd_timeout(struct state *st);
* expression to reference them (hash_val, hash_pbs)
*/
#define CHECK_QUICK_HASH(md, do_hash, hash_name, msg_name) { \
- pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; \
- u_char hash_val[MAX_DIGEST_LEN]; \
- size_t hash_len = do_hash; \
- if (pbs_left(hash_pbs) != hash_len \
- || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) \
- { \
- DBG_cond_dump(DBG_CRYPT, "received " hash_name ":", hash_pbs->cur, pbs_left(hash_pbs)); \
- loglog(RC_LOG_SERIOUS, "received " hash_name " does not match computed value in " msg_name); \
- /* XXX Could send notification back */ \
- return STF_FAIL + INVALID_HASH_INFORMATION; \
- } \
- }
+ pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; \
+ u_char hash_val[MAX_DIGEST_LEN]; \
+ size_t hash_len = do_hash; \
+ if (pbs_left(hash_pbs) != hash_len \
+ || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) \
+ { \
+ DBG_cond_dump(DBG_CRYPT, "received " hash_name ":", hash_pbs->cur, pbs_left(hash_pbs)); \
+ loglog(RC_LOG_SERIOUS, "received " hash_name " does not match computed value in " msg_name); \
+ /* XXX Could send notification back */ \
+ return STF_FAIL + INVALID_HASH_INFORMATION; \
+ } \
+ }
diff --git a/src/pluto/kameipsec.h b/src/pluto/kameipsec.h
index 5f08c7d38..5e9d8ce99 100644
--- a/src/pluto/kameipsec.h
+++ b/src/pluto/kameipsec.h
@@ -3,45 +3,45 @@
/* The definitions, required to talk to KAME racoon IKE. */
-#define IPSEC_PORT_ANY 0
-#define IPSEC_ULPROTO_ANY 255
-#define IPSEC_PROTO_ANY 255
+#define IPSEC_PORT_ANY 0
+#define IPSEC_ULPROTO_ANY 255
+#define IPSEC_PROTO_ANY 255
enum {
- IPSEC_MODE_ANY = 0, /* We do not support this for SA */
- IPSEC_MODE_TRANSPORT = 1,
- IPSEC_MODE_TUNNEL = 2
+ IPSEC_MODE_ANY = 0, /* We do not support this for SA */
+ IPSEC_MODE_TRANSPORT = 1,
+ IPSEC_MODE_TUNNEL = 2
};
enum {
- IPSEC_DIR_ANY = 0,
- IPSEC_DIR_INBOUND = 1,
- IPSEC_DIR_OUTBOUND = 2,
- IPSEC_DIR_FWD = 3, /* It is our own */
- IPSEC_DIR_MAX = 4,
- IPSEC_DIR_INVALID = 5
+ IPSEC_DIR_ANY = 0,
+ IPSEC_DIR_INBOUND = 1,
+ IPSEC_DIR_OUTBOUND = 2,
+ IPSEC_DIR_FWD = 3, /* It is our own */
+ IPSEC_DIR_MAX = 4,
+ IPSEC_DIR_INVALID = 5
};
enum {
- IPSEC_POLICY_DISCARD = 0,
- IPSEC_POLICY_NONE = 1,
- IPSEC_POLICY_IPSEC = 2,
- IPSEC_POLICY_ENTRUST = 3,
- IPSEC_POLICY_BYPASS = 4
+ IPSEC_POLICY_DISCARD = 0,
+ IPSEC_POLICY_NONE = 1,
+ IPSEC_POLICY_IPSEC = 2,
+ IPSEC_POLICY_ENTRUST = 3,
+ IPSEC_POLICY_BYPASS = 4
};
enum {
- IPSEC_LEVEL_DEFAULT = 0,
- IPSEC_LEVEL_USE = 1,
- IPSEC_LEVEL_REQUIRE = 2,
- IPSEC_LEVEL_UNIQUE = 3
+ IPSEC_LEVEL_DEFAULT = 0,
+ IPSEC_LEVEL_USE = 1,
+ IPSEC_LEVEL_REQUIRE = 2,
+ IPSEC_LEVEL_UNIQUE = 3
};
-#define IPSEC_MANUAL_REQID_MAX 0x3fff
+#define IPSEC_MANUAL_REQID_MAX 0x3fff
#define IPSEC_REPLAYWSIZE 32
#define IP_IPSEC_POLICY 16
#define IPV6_IPSEC_POLICY 34
-#endif /* __IPSEC_H */
+#endif /* __IPSEC_H */
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index d42ac3372..f698de2c8 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -11,8 +11,6 @@
* 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: kernel.c 3846 2008-04-18 17:01:45Z andreas $
*/
#include <stddef.h>
@@ -31,12 +29,14 @@
#include <arpa/inet.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <library.h>
+#include <crypto/rngs/rng.h>
#ifdef KLIPS
#include <signal.h>
-#include <sys/time.h> /* for select(2) */
-#include <sys/types.h> /* for select(2) */
+#include <sys/time.h> /* for select(2) */
+#include <sys/types.h> /* for select(2) */
#include <pfkeyv2.h>
#include <pfkey.h>
#include "kameipsec.h"
@@ -44,7 +44,6 @@
#include "constants.h"
#include "defs.h"
-#include "rnd.h"
#include "id.h"
#include "connections.h"
#include "state.h"
@@ -56,7 +55,7 @@
#include "log.h"
#include "ca.h"
#include "server.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include "keys.h"
#include "nat_traversal.h"
#include "alg_info.h"
@@ -69,7 +68,7 @@ bool can_do_IPcomp = TRUE; /* can system actually perform IPCOMP? */
* logic loses track and swats them? 64 is the best KLIPS can do.
* And 32 is the best XFRM can do...
*/
-#define REPLAY_WINDOW 64
+#define REPLAY_WINDOW 64
#define REPLAY_WINDOW_XFRM 32
/* test if the routes required for two different connections agree
@@ -77,11 +76,11 @@ bool can_do_IPcomp = TRUE; /* can system actually perform IPCOMP? */
* testing that the interfaces and nexthops match.
*/
#define routes_agree(c, d) ((c)->interface == (d)->interface \
- && sameaddr(&(c)->spd.this.host_nexthop, &(d)->spd.this.host_nexthop))
+ && sameaddr(&(c)->spd.this.host_nexthop, &(d)->spd.this.host_nexthop))
#ifndef KLIPS
-bool no_klips = TRUE; /* don't actually use KLIPS */
+bool no_klips = TRUE; /* don't actually use KLIPS */
#else /* !KLIPS */
@@ -96,50 +95,49 @@ bool no_klips = TRUE; /* don't actually use KLIPS */
* which %holds are news and which others should expire.
*/
-#define SHUNT_SCAN_INTERVAL (60 * 2) /* time between scans of eroutes */
+#define SHUNT_SCAN_INTERVAL (60 * 2) /* time between scans of eroutes */
/* SHUNT_PATIENCE only has resolution down to a multiple of the sample rate,
* SHUNT_SCAN_INTERVAL.
* By making SHUNT_PATIENCE an odd multiple of half of SHUNT_SCAN_INTERVAL,
* we minimize the effects of jitter.
*/
-#define SHUNT_PATIENCE (SHUNT_SCAN_INTERVAL * 15 / 2) /* inactivity timeout */
+#define SHUNT_PATIENCE (SHUNT_SCAN_INTERVAL * 15 / 2) /* inactivity timeout */
struct bare_shunt {
- policy_prio_t policy_prio;
- ip_subnet ours;
- ip_subnet his;
- ip_said said;
- int transport_proto;
- unsigned long count;
- time_t last_activity;
- char *why;
- struct bare_shunt *next;
+ policy_prio_t policy_prio;
+ ip_subnet ours;
+ ip_subnet his;
+ ip_said said;
+ int transport_proto;
+ unsigned long count;
+ time_t last_activity;
+ char *why;
+ struct bare_shunt *next;
};
static struct bare_shunt *bare_shunts = NULL;
#ifdef DEBUG
-static void
-DBG_bare_shunt(const char *op, const struct bare_shunt *bs)
+static void DBG_bare_shunt(const char *op, const struct bare_shunt *bs)
{
- DBG(DBG_KLIPS,
- {
- int ourport = ntohs(portof(&(bs)->ours.addr));
- int hisport = ntohs(portof(&(bs)->his.addr));
- char ourst[SUBNETTOT_BUF];
- char hist[SUBNETTOT_BUF];
- char sat[SATOT_BUF];
- char prio[POLICY_PRIO_BUF];
-
- subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
- subnettot(&(bs)->his, 0, hist, sizeof(hist));
- satot(&(bs)->said, 0, sat, sizeof(sat));
- fmt_policy_prio(bs->policy_prio, prio);
- DBG_log("%s bare shunt %p %s:%d -> %s:%d => %s:%d %s %s"
- , op, (const void *)(bs), ourst, ourport, hist, hisport
- , sat, (bs)->transport_proto, prio, (bs)->why);
- });
+ DBG(DBG_KLIPS,
+ {
+ int ourport = ntohs(portof(&(bs)->ours.addr));
+ int hisport = ntohs(portof(&(bs)->his.addr));
+ char ourst[SUBNETTOT_BUF];
+ char hist[SUBNETTOT_BUF];
+ char sat[SATOT_BUF];
+ char prio[POLICY_PRIO_BUF];
+
+ subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
+ subnettot(&(bs)->his, 0, hist, sizeof(hist));
+ satot(&(bs)->said, 0, sat, sizeof(sat));
+ fmt_policy_prio(bs->policy_prio, prio);
+ DBG_log("%s bare shunt %p %s:%d -> %s:%d => %s:%d %s %s"
+ , op, (const void *)(bs), ourst, ourport, hist, hisport
+ , sat, (bs)->transport_proto, prio, (bs)->why);
+ });
}
#else /* !DEBUG */
#define DBG_bare_shunt(op, bs) {}
@@ -152,112 +150,108 @@ DBG_bare_shunt(const char *op, const struct bare_shunt *bs)
struct eroute_info *orphaned_holds = NULL;
/* forward declaration */
-static bool shunt_eroute(struct connection *c
- , struct spd_route *sr
- , enum routing_t rt_kind
- , unsigned int op, const char *opname);
-static void set_text_said(char *text_said
- , const ip_address *dst
- , ipsec_spi_t spi
- , int proto);
+static bool shunt_eroute(struct connection *c, struct spd_route *sr,
+ enum routing_t rt_kind, unsigned int op,
+ const char *opname);
+
+static void set_text_said(char *text_said, const ip_address *dst,
+ ipsec_spi_t spi, int proto);
-bool no_klips = FALSE; /* don't actually use KLIPS */
+bool no_klips = FALSE; /* don't actually use KLIPS */
static const struct pfkey_proto_info null_proto_info[2] = {
+ {
+ proto: IPPROTO_ESP,
+ encapsulation: ENCAPSULATION_MODE_TRANSPORT,
+ reqid: 0
+ },
+ {
+ proto: 0,
+ encapsulation: 0,
+ reqid: 0
+ }
+};
+
+void record_and_initiate_opportunistic(const ip_subnet *ours,
+ const ip_subnet *his,
+ int transport_proto, const char *why)
+{
+ passert(samesubnettype(ours, his));
+
+ /* Add to bare shunt list.
+ * We need to do this because the shunt was installed by KLIPS
+ * which can't do this itself.
+ */
{
- proto: IPPROTO_ESP,
- encapsulation: ENCAPSULATION_MODE_TRANSPORT,
- reqid: 0
- },
+ struct bare_shunt *bs = malloc_thing(struct bare_shunt);
+
+ bs->why = clone_str(why);
+ bs->ours = *ours;
+ bs->his = *his;
+ bs->transport_proto = transport_proto;
+ bs->policy_prio = BOTTOM_PRIO;
+
+ bs->said.proto = SA_INT;
+ bs->said.spi = htonl(SPI_HOLD);
+ bs->said.dst = *aftoinfo(subnettypeof(ours))->any;
+
+ bs->count = 0;
+ bs->last_activity = now();
+
+ bs->next = bare_shunts;
+ bare_shunts = bs;
+ DBG_bare_shunt("add", bs);
+ }
+
+ /* actually initiate opportunism */
{
- proto: 0,
- encapsulation: 0,
- reqid: 0
+ ip_address src, dst;
+
+ networkof(ours, &src);
+ networkof(his, &dst);
+ initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD);
}
-};
-void
-record_and_initiate_opportunistic(const ip_subnet *ours
- , const ip_subnet *his
- , int transport_proto
- , const char *why)
-{
- passert(samesubnettype(ours, his));
-
- /* Add to bare shunt list.
- * We need to do this because the shunt was installed by KLIPS
- * which can't do this itself.
- */
- {
- struct bare_shunt *bs = alloc_thing(struct bare_shunt, "bare shunt");
-
- bs->why = clone_str(why, "story for bare shunt");
- bs->ours = *ours;
- bs->his = *his;
- bs->transport_proto = transport_proto;
- bs->policy_prio = BOTTOM_PRIO;
-
- bs->said.proto = SA_INT;
- bs->said.spi = htonl(SPI_HOLD);
- bs->said.dst = *aftoinfo(subnettypeof(ours))->any;
-
- bs->count = 0;
- bs->last_activity = now();
-
- bs->next = bare_shunts;
- bare_shunts = bs;
- DBG_bare_shunt("add", bs);
- }
-
- /* actually initiate opportunism */
- {
- ip_address src, dst;
-
- networkof(ours, &src);
- networkof(his, &dst);
- initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD);
- }
-
- /* if present, remove from orphaned_holds list.
- * NOTE: we do this last in case ours or his is a pointer into a member.
- */
- {
- struct eroute_info **pp, *p;
-
- for (pp = &orphaned_holds; (p = *pp) != NULL; pp = &p->next)
- {
- if (samesubnet(ours, &p->ours)
- && samesubnet(his, &p->his)
- && transport_proto == p->transport_proto
- && portof(&ours->addr) == portof(&p->ours.addr)
- && portof(&his->addr) == portof(&p->his.addr))
- {
- *pp = p->next;
- pfree(p);
- break;
- }
+ /* if present, remove from orphaned_holds list.
+ * NOTE: we do this last in case ours or his is a pointer into a member.
+ */
+ {
+ struct eroute_info **pp, *p;
+
+ for (pp = &orphaned_holds; (p = *pp) != NULL; pp = &p->next)
+ {
+ if (samesubnet(ours, &p->ours)
+ && samesubnet(his, &p->his)
+ && transport_proto == p->transport_proto
+ && portof(&ours->addr) == portof(&p->ours.addr)
+ && portof(&his->addr) == portof(&p->his.addr))
+ {
+ *pp = p->next;
+ free(p);
+ break;
+ }
+ }
}
- }
}
#endif /* KLIPS */
static unsigned get_proto_reqid(unsigned base, int proto)
{
- switch (proto)
- {
- default:
- case IPPROTO_COMP:
- base++;
- /* fall through */
- case IPPROTO_ESP:
- base++;
- /* fall through */
- case IPPROTO_AH:
- break;
- }
-
- return base;
+ switch (proto)
+ {
+ default:
+ case IPPROTO_COMP:
+ base++;
+ /* fall through */
+ case IPPROTO_ESP:
+ base++;
+ /* fall through */
+ case IPPROTO_AH:
+ break;
+ }
+
+ return base;
}
/* Generate Unique SPI numbers.
@@ -281,33 +275,39 @@ static unsigned get_proto_reqid(unsigned base, int proto)
* check if the number was previously used (assuming that no
* SPI lives longer than 4G of its successors).
*/
-ipsec_spi_t
-get_ipsec_spi(ipsec_spi_t avoid, int proto, struct spd_route *sr, bool tunnel)
+ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid, int proto, struct spd_route *sr,
+ bool tunnel)
{
- static ipsec_spi_t spi = 0; /* host order, so not returned directly! */
- char text_said[SATOT_BUF];
+ static ipsec_spi_t spi = 0; /* host order, so not returned directly! */
+ char text_said[SATOT_BUF];
+ rng_t *rng;
- set_text_said(text_said, &sr->this.host_addr, 0, proto);
+ set_text_said(text_said, &sr->this.host_addr, 0, proto);
- if (kernel_ops->get_spi)
- return kernel_ops->get_spi(&sr->that.host_addr
- , &sr->this.host_addr, proto, tunnel
- , get_proto_reqid(sr->reqid, proto)
- , IPSEC_DOI_SPI_OUR_MIN, 0xffffffff
- , text_said);
-
- spi++;
- while (spi < IPSEC_DOI_SPI_OUR_MIN || spi == ntohl(avoid))
- get_rnd_bytes((u_char *)&spi, sizeof(spi));
+ if (kernel_ops->get_spi)
+ {
+ return kernel_ops->get_spi(&sr->that.host_addr
+ , &sr->this.host_addr, proto, tunnel
+ , get_proto_reqid(sr->reqid, proto)
+ , IPSEC_DOI_SPI_OUR_MIN, 0xffffffff
+ , text_said);
+ }
- DBG(DBG_CONTROL,
+ spi++;
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ while (spi < IPSEC_DOI_SPI_OUR_MIN || spi == ntohl(avoid))
{
- ipsec_spi_t spi_net = htonl(spi);
+ rng->get_bytes(rng, sizeof(spi), (u_char *)&spi);
+ }
+ rng->destroy(rng);
+ DBG(DBG_CONTROL,
+ {
+ ipsec_spi_t spi_net = htonl(spi);
- DBG_dump("generate SPI:", (u_char *)&spi_net, sizeof(spi_net));
- });
+ DBG_dump("generate SPI:", (u_char *)&spi_net, sizeof(spi_net));
+ });
- return htonl(spi);
+ return htonl(spi);
}
/* Generate Unique CPI numbers.
@@ -318,38 +318,40 @@ get_ipsec_spi(ipsec_spi_t avoid, int proto, struct spd_route *sr, bool tunnel)
* If we can't find one easily, return 0 (a bad SPI,
* no matter what order) indicating failure.
*/
-ipsec_spi_t
-get_my_cpi(struct spd_route *sr, bool tunnel)
+ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel)
{
- static cpi_t
- first_busy_cpi = 0,
- latest_cpi;
- char text_said[SATOT_BUF];
+ static cpi_t first_busy_cpi = 0, latest_cpi;
+ char text_said[SATOT_BUF];
+ rng_t *rng;
- set_text_said(text_said, &sr->this.host_addr, 0, IPPROTO_COMP);
+ set_text_said(text_said, &sr->this.host_addr, 0, IPPROTO_COMP);
- if (kernel_ops->get_spi)
- return kernel_ops->get_spi(&sr->that.host_addr
- , &sr->this.host_addr, IPPROTO_COMP, tunnel
- , get_proto_reqid(sr->reqid, IPPROTO_COMP)
- , IPCOMP_FIRST_NEGOTIATED, IPCOMP_LAST_NEGOTIATED
- , text_said);
+ if (kernel_ops->get_spi)
+ {
+ return kernel_ops->get_spi(&sr->that.host_addr
+ , &sr->this.host_addr, IPPROTO_COMP, tunnel
+ , get_proto_reqid(sr->reqid, IPPROTO_COMP)
+ , IPCOMP_FIRST_NEGOTIATED, IPCOMP_LAST_NEGOTIATED
+ , text_said);
+ }
- while (!(IPCOMP_FIRST_NEGOTIATED <= first_busy_cpi && first_busy_cpi < IPCOMP_LAST_NEGOTIATED))
- {
- get_rnd_bytes((u_char *)&first_busy_cpi, sizeof(first_busy_cpi));
- latest_cpi = first_busy_cpi;
- }
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ while (!(IPCOMP_FIRST_NEGOTIATED <= first_busy_cpi && first_busy_cpi < IPCOMP_LAST_NEGOTIATED))
+ {
+ rng->get_bytes(rng, sizeof(first_busy_cpi), (u_char *)&first_busy_cpi);
+ latest_cpi = first_busy_cpi;
+ }
+ rng->destroy(rng);
- latest_cpi++;
+ latest_cpi++;
- if (latest_cpi == first_busy_cpi)
- find_my_cpi_gap(&latest_cpi, &first_busy_cpi);
+ if (latest_cpi == first_busy_cpi)
+ find_my_cpi_gap(&latest_cpi, &first_busy_cpi);
- if (latest_cpi > IPCOMP_LAST_NEGOTIATED)
- latest_cpi = IPCOMP_FIRST_NEGOTIATED;
+ if (latest_cpi > IPCOMP_LAST_NEGOTIATED)
+ latest_cpi = IPCOMP_FIRST_NEGOTIATED;
- return htonl((ipsec_spi_t)latest_cpi);
+ return htonl((ipsec_spi_t)latest_cpi);
}
/* invoke the updown script to do the routing and firewall commands required
@@ -386,872 +388,864 @@ get_my_cpi(struct spd_route *sr, bool tunnel)
*/
#ifndef DEFAULT_UPDOWN
-# define DEFAULT_UPDOWN "ipsec _updown"
+# define DEFAULT_UPDOWN "ipsec _updown"
#endif
-static bool
-do_command(struct connection *c, struct spd_route *sr, const char *verb)
+static bool do_command(struct connection *c, struct spd_route *sr,
+ const char *verb)
{
- char cmd[1536]; /* arbitrary limit on shell command length */
- const char *verb_suffix;
+ char cmd[1536]; /* arbitrary limit on shell command length */
+ const char *verb_suffix;
- /* figure out which verb suffix applies */
- {
- const char *hs, *cs;
-
- switch (addrtypeof(&sr->this.host_addr))
+ /* figure out which verb suffix applies */
{
- case AF_INET:
- hs = "-host";
- cs = "-client";
- break;
- case AF_INET6:
- hs = "-host-v6";
- cs = "-client-v6";
- break;
- default:
- loglog(RC_LOG_SERIOUS, "unknown address family");
- return FALSE;
- }
- verb_suffix = subnetisaddr(&sr->this.client, &sr->this.host_addr)
- ? hs : cs;
- }
-
- /* form the command string */
- {
- char
- nexthop_str[sizeof("PLUTO_NEXT_HOP='' ") +ADDRTOT_BUF] = "",
- srcip_str[sizeof("PLUTO_MY_SOURCEIP='' ")+ADDRTOT_BUF] = "",
- me_str[ADDRTOT_BUF],
- myid_str[BUF_LEN],
- myclient_str[SUBNETTOT_BUF],
- myclientnet_str[ADDRTOT_BUF],
- myclientmask_str[ADDRTOT_BUF],
- peer_str[ADDRTOT_BUF],
- peerid_str[BUF_LEN],
- peerclient_str[SUBNETTOT_BUF],
- peerclientnet_str[ADDRTOT_BUF],
- peerclientmask_str[ADDRTOT_BUF],
- peerca_str[BUF_LEN],
- secure_myid_str[BUF_LEN] = "",
- secure_peerid_str[BUF_LEN] = "",
- secure_peerca_str[BUF_LEN] = "";
- ip_address ta;
- pubkey_list_t *p;
-
- if (addrbytesptr(&sr->this.host_nexthop, NULL)
- && !isanyaddr(&sr->this.host_nexthop))
- {
- char *n;
-
- strcpy(nexthop_str, "PLUTO_NEXT_HOP='");
- n = nexthop_str + strlen(nexthop_str);
-
- addrtot(&sr->this.host_nexthop, 0
- ,n , sizeof(nexthop_str)-strlen(nexthop_str));
- strncat(nexthop_str, "' ", sizeof(nexthop_str));
- }
-
- if (addrbytesptr(&sr->this.host_srcip, NULL)
- && !isanyaddr(&sr->this.host_srcip))
- {
- char *n;
-
- strcpy(srcip_str, "PLUTO_MY_SOURCEIP='");
- n = srcip_str + strlen(srcip_str);
-
- addrtot(&sr->this.host_srcip, 0
- ,n , sizeof(srcip_str)-strlen(srcip_str));
- strncat(srcip_str, "' ", sizeof(srcip_str));
- }
-
- addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
- idtoa(&sr->this.id, myid_str, sizeof(myid_str));
- escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));
- subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str));
- networkof(&sr->this.client, &ta);
- addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str));
- maskof(&sr->this.client, &ta);
- addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
-
- addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str));
- idtoa(&sr->that.id, peerid_str, sizeof(peerid_str));
- escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str));
- subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str));
- networkof(&sr->that.client, &ta);
- addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str));
- maskof(&sr->that.client, &ta);
- addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str));
-
- for (p = pubkeys; p != NULL; p = p->next)
- {
- pubkey_t *key = p->key;
- int pathlen;
-
- if (key->alg == PUBKEY_ALG_RSA && same_id(&sr->that.id, &key->id)
- && trusted_ca(key->issuer, sr->that.ca, &pathlen))
- {
- dntoa_or_null(peerca_str, BUF_LEN, key->issuer, "");
- escape_metachar(peerca_str, secure_peerca_str, sizeof(secure_peerca_str));
- break;
- }
- }
-
- if (-1 == snprintf(cmd, sizeof(cmd)
- , "2>&1 " /* capture stderr along with stdout */
- "PLUTO_VERSION='1.1' " /* change VERSION when interface spec changes */
- "PLUTO_VERB='%s%s' "
- "PLUTO_CONNECTION='%s' "
- "%s" /* optional PLUTO_NEXT_HOP */
- "PLUTO_INTERFACE='%s' "
- "%s" /* optional PLUTO_HOST_ACCESS */
- "PLUTO_REQID='%u' "
- "PLUTO_ME='%s' "
- "PLUTO_MY_ID='%s' "
- "PLUTO_MY_CLIENT='%s' "
- "PLUTO_MY_CLIENT_NET='%s' "
- "PLUTO_MY_CLIENT_MASK='%s' "
- "PLUTO_MY_PORT='%u' "
- "PLUTO_MY_PROTOCOL='%u' "
- "PLUTO_PEER='%s' "
- "PLUTO_PEER_ID='%s' "
- "PLUTO_PEER_CLIENT='%s' "
- "PLUTO_PEER_CLIENT_NET='%s' "
- "PLUTO_PEER_CLIENT_MASK='%s' "
- "PLUTO_PEER_PORT='%u' "
- "PLUTO_PEER_PROTOCOL='%u' "
- "PLUTO_PEER_CA='%s' "
- "%s" /* optional PLUTO_MY_SRCIP */
- "%s" /* actual script */
- , verb, verb_suffix
- , c->name
- , nexthop_str
- , c->interface->vname
- , sr->this.hostaccess? "PLUTO_HOST_ACCESS='1' " : ""
- , sr->reqid + 1 /* ESP requid */
- , me_str
- , secure_myid_str
- , myclient_str
- , myclientnet_str
- , myclientmask_str
- , sr->this.port
- , sr->this.protocol
- , peer_str
- , secure_peerid_str
- , peerclient_str
- , peerclientnet_str
- , peerclientmask_str
- , sr->that.port
- , sr->that.protocol
- , secure_peerca_str
- , srcip_str
- , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown))
- {
- loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix);
- return FALSE;
- }
- }
-
- DBG(DBG_CONTROL, DBG_log("executing %s%s: %s"
- , verb, verb_suffix, cmd));
+ const char *hs, *cs;
-#ifdef KLIPS
- if (!no_klips)
- {
- /* invoke the script, catching stderr and stdout
- * It may be of concern that some file descriptors will
- * be inherited. For the ones under our control, we
- * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.
- * Any used by library routines (perhaps the resolver or syslog)
- * will remain.
- */
- FILE *f = popen(cmd, "r");
-
- if (f == NULL)
- {
- loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);
- return FALSE;
+ switch (addrtypeof(&sr->this.host_addr))
+ {
+ case AF_INET:
+ hs = "-host";
+ cs = "-client";
+ break;
+ case AF_INET6:
+ hs = "-host-v6";
+ cs = "-client-v6";
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "unknown address family");
+ return FALSE;
+ }
+ verb_suffix = subnetisaddr(&sr->this.client, &sr->this.host_addr)
+ ? hs : cs;
}
- /* log any output */
- for (;;)
+ /* form the command string */
{
- /* if response doesn't fit in this buffer, it will be folded */
- char resp[256];
+ char
+ nexthop_str[sizeof("PLUTO_NEXT_HOP='' ") +ADDRTOT_BUF] = "",
+ srcip_str[sizeof("PLUTO_MY_SOURCEIP='' ")+ADDRTOT_BUF] = "",
+ me_str[ADDRTOT_BUF],
+ myid_str[BUF_LEN],
+ myclient_str[SUBNETTOT_BUF],
+ myclientnet_str[ADDRTOT_BUF],
+ myclientmask_str[ADDRTOT_BUF],
+ peer_str[ADDRTOT_BUF],
+ peerid_str[BUF_LEN],
+ peerclient_str[SUBNETTOT_BUF],
+ peerclientnet_str[ADDRTOT_BUF],
+ peerclientmask_str[ADDRTOT_BUF],
+ peerca_str[BUF_LEN],
+ secure_myid_str[BUF_LEN] = "",
+ secure_peerid_str[BUF_LEN] = "",
+ secure_peerca_str[BUF_LEN] = "";
+ ip_address ta;
+ pubkey_list_t *p;
+
+ if (addrbytesptr(&sr->this.host_nexthop, NULL)
+ && !isanyaddr(&sr->this.host_nexthop))
+ {
+ char *n;
+
+ strcpy(nexthop_str, "PLUTO_NEXT_HOP='");
+ n = nexthop_str + strlen(nexthop_str);
+
+ addrtot(&sr->this.host_nexthop, 0
+ ,n , sizeof(nexthop_str)-strlen(nexthop_str));
+ strncat(nexthop_str, "' ", sizeof(nexthop_str));
+ }
- if (fgets(resp, sizeof(resp), f) == NULL)
- {
- if (ferror(f))
+ if (addrbytesptr(&sr->this.host_srcip, NULL)
+ && !isanyaddr(&sr->this.host_srcip))
{
- log_errno((e, "fgets failed on output of %s%s command"
- , verb, verb_suffix));
- return FALSE;
+ char *n;
+
+ strcpy(srcip_str, "PLUTO_MY_SOURCEIP='");
+ n = srcip_str + strlen(srcip_str);
+
+ addrtot(&sr->this.host_srcip, 0
+ ,n , sizeof(srcip_str)-strlen(srcip_str));
+ strncat(srcip_str, "' ", sizeof(srcip_str));
}
- else
+
+ addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
+ idtoa(&sr->this.id, myid_str, sizeof(myid_str));
+ escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));
+ subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str));
+ networkof(&sr->this.client, &ta);
+ addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str));
+ maskof(&sr->this.client, &ta);
+ addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
+
+ addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str));
+ idtoa(&sr->that.id, peerid_str, sizeof(peerid_str));
+ escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str));
+ subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str));
+ networkof(&sr->that.client, &ta);
+ addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str));
+ maskof(&sr->that.client, &ta);
+ addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str));
+
+ for (p = pubkeys; p != NULL; p = p->next)
{
- passert(feof(f));
- break;
+ pubkey_t *key = p->key;
+ key_type_t type = key->public_key->get_type(key->public_key);
+ int pathlen;
+
+ if (type == KEY_RSA && same_id(&sr->that.id, &key->id) &&
+ trusted_ca(key->issuer, sr->that.ca, &pathlen))
+ {
+ dntoa_or_null(peerca_str, BUF_LEN, key->issuer, "");
+ escape_metachar(peerca_str, secure_peerca_str, sizeof(secure_peerca_str));
+ break;
+ }
}
- }
- else
- {
- char *e = resp + strlen(resp);
- if (e > resp && e[-1] == '\n')
- e[-1] = '\0'; /* trim trailing '\n' */
- plog("%s%s output: %s", verb, verb_suffix, resp);
- }
+ if (-1 == snprintf(cmd, sizeof(cmd)
+ , "2>&1 " /* capture stderr along with stdout */
+ "PLUTO_VERSION='1.1' " /* change VERSION when interface spec changes */
+ "PLUTO_VERB='%s%s' "
+ "PLUTO_CONNECTION='%s' "
+ "%s" /* optional PLUTO_NEXT_HOP */
+ "PLUTO_INTERFACE='%s' "
+ "%s" /* optional PLUTO_HOST_ACCESS */
+ "PLUTO_REQID='%u' "
+ "PLUTO_ME='%s' "
+ "PLUTO_MY_ID='%s' "
+ "PLUTO_MY_CLIENT='%s' "
+ "PLUTO_MY_CLIENT_NET='%s' "
+ "PLUTO_MY_CLIENT_MASK='%s' "
+ "PLUTO_MY_PORT='%u' "
+ "PLUTO_MY_PROTOCOL='%u' "
+ "PLUTO_PEER='%s' "
+ "PLUTO_PEER_ID='%s' "
+ "PLUTO_PEER_CLIENT='%s' "
+ "PLUTO_PEER_CLIENT_NET='%s' "
+ "PLUTO_PEER_CLIENT_MASK='%s' "
+ "PLUTO_PEER_PORT='%u' "
+ "PLUTO_PEER_PROTOCOL='%u' "
+ "PLUTO_PEER_CA='%s' "
+ "%s" /* optional PLUTO_MY_SRCIP */
+ "%s" /* actual script */
+ , verb, verb_suffix
+ , c->name
+ , nexthop_str
+ , c->interface->vname
+ , sr->this.hostaccess? "PLUTO_HOST_ACCESS='1' " : ""
+ , sr->reqid + 1 /* ESP requid */
+ , me_str
+ , secure_myid_str
+ , myclient_str
+ , myclientnet_str
+ , myclientmask_str
+ , sr->this.port
+ , sr->this.protocol
+ , peer_str
+ , secure_peerid_str
+ , peerclient_str
+ , peerclientnet_str
+ , peerclientmask_str
+ , sr->that.port
+ , sr->that.protocol
+ , secure_peerca_str
+ , srcip_str
+ , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown))
+ {
+ loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix);
+ return FALSE;
+ }
}
- /* report on and react to return code */
+ DBG(DBG_CONTROL, DBG_log("executing %s%s: %s"
+ , verb, verb_suffix, cmd));
+
+#ifdef KLIPS
+ if (!no_klips)
{
- int r = pclose(f);
+ /* invoke the script, catching stderr and stdout
+ * It may be of concern that some file descriptors will
+ * be inherited. For the ones under our control, we
+ * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.
+ * Any used by library routines (perhaps the resolver or syslog)
+ * will remain.
+ */
+ FILE *f = popen(cmd, "r");
- if (r == -1)
- {
- log_errno((e, "pclose failed for %s%s command"
- , verb, verb_suffix));
- return FALSE;
- }
- else if (WIFEXITED(r))
- {
- if (WEXITSTATUS(r) != 0)
+ if (f == NULL)
{
- loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"
- , verb, verb_suffix, WEXITSTATUS(r));
- return FALSE;
+ loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);
+ return FALSE;
+ }
+
+ /* log any output */
+ for (;;)
+ {
+ /* if response doesn't fit in this buffer, it will be folded */
+ char resp[256];
+
+ if (fgets(resp, sizeof(resp), f) == NULL)
+ {
+ if (ferror(f))
+ {
+ log_errno((e, "fgets failed on output of %s%s command"
+ , verb, verb_suffix));
+ return FALSE;
+ }
+ else
+ {
+ passert(feof(f));
+ break;
+ }
+ }
+ else
+ {
+ char *e = resp + strlen(resp);
+
+ if (e > resp && e[-1] == '\n')
+ e[-1] = '\0'; /* trim trailing '\n' */
+ plog("%s%s output: %s", verb, verb_suffix, resp);
+ }
+ }
+
+ /* report on and react to return code */
+ {
+ int r = pclose(f);
+
+ if (r == -1)
+ {
+ log_errno((e, "pclose failed for %s%s command"
+ , verb, verb_suffix));
+ return FALSE;
+ }
+ else if (WIFEXITED(r))
+ {
+ if (WEXITSTATUS(r) != 0)
+ {
+ loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"
+ , verb, verb_suffix, WEXITSTATUS(r));
+ return FALSE;
+ }
+ }
+ else if (WIFSIGNALED(r))
+ {
+ loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"
+ , verb, verb_suffix, WTERMSIG(r));
+ return FALSE;
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"
+ , verb, verb_suffix, r);
+ return FALSE;
+ }
}
- }
- else if (WIFSIGNALED(r))
- {
- loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"
- , verb, verb_suffix, WTERMSIG(r));
- return FALSE;
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"
- , verb, verb_suffix, r);
- return FALSE;
- }
}
- }
#endif /* KLIPS */
- return TRUE;
+ return TRUE;
}
/* Check that we can route (and eroute). Diagnose if we cannot. */
enum routability {
- route_impossible = 0,
- route_easy = 1,
- route_nearconflict = 2,
- route_farconflict = 3
+ route_impossible = 0,
+ route_easy = 1,
+ route_nearconflict = 2,
+ route_farconflict = 3
};
-static enum routability
-could_route(struct connection *c)
+static enum routability could_route(struct connection *c)
{
- struct spd_route *esr, *rosr;
- struct connection *ero /* who, if anyone, owns our eroute? */
- , *ro = route_owner(c, &rosr, &ero, &esr); /* who owns our route? */
-
- /* it makes no sense to route a connection that is ISAKMP-only */
- if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
- {
- loglog(RC_ROUTE, "cannot route an ISAKMP-only connection");
- return route_impossible;
- }
-
- /* if this is a Road Warrior template, we cannot route.
- * Opportunistic template is OK.
- */
- if (c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO))
- {
- loglog(RC_ROUTE, "cannot route Road Warrior template");
- return route_impossible;
- }
-
- /* if we don't know nexthop, we cannot route */
- if (isanyaddr(&c->spd.this.host_nexthop))
- {
- loglog(RC_ROUTE, "cannot route connection without knowing our nexthop");
- return route_impossible;
- }
-
- /* if routing would affect IKE messages, reject */
- if (!no_klips
- && c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT
- && c->spd.this.host_port != IKE_UDP_PORT
- && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client))
- {
- loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client");
- return route_impossible;
- }
-
- /* If there is already a route for peer's client subnet
- * and it disagrees about interface or nexthop, we cannot steal it.
- * Note: if this connection is already routed (perhaps for another
- * state object), the route will agree.
- * This is as it should be -- it will arise during rekeying.
- */
- if (ro != NULL && !routes_agree(ro, c))
- {
- loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\""
- , ro->name);
- return route_impossible; /* another connection already
- using the eroute */
- }
+ struct spd_route *esr, *rosr;
+ struct connection *ero /* who, if anyone, owns our eroute? */
+ , *ro = route_owner(c, &rosr, &ero, &esr); /* who owns our route? */
-#ifdef KLIPS
- /* if there is an eroute for another connection, there is a problem */
- if (ero != NULL && ero != c)
- {
- struct connection *ero2, *ero_top;
- struct connection *inside, *outside;
-
- /*
- * note, wavesec (PERMANENT) goes *outside* and
- * OE goes *inside* (TEMPLATE)
+ /* it makes no sense to route a connection that is ISAKMP-only */
+ if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
+ {
+ loglog(RC_ROUTE, "cannot route an ISAKMP-only connection");
+ return route_impossible;
+ }
+
+ /* if this is a Road Warrior template, we cannot route.
+ * Opportunistic template is OK.
*/
- inside = NULL;
- outside= NULL;
- if (ero->kind == CK_PERMANENT
- && c->kind == CK_TEMPLATE)
+ if (c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO))
{
- outside = ero;
- inside = c;
+ loglog(RC_ROUTE, "cannot route Road Warrior template");
+ return route_impossible;
}
- else if (c->kind == CK_PERMANENT
- && ero->kind == CK_TEMPLATE)
+
+ /* if we don't know nexthop, we cannot route */
+ if (isanyaddr(&c->spd.this.host_nexthop))
{
- outside = c;
- inside = ero;
+ loglog(RC_ROUTE, "cannot route connection without knowing our nexthop");
+ return route_impossible;
}
- /* okay, check again, with correct order */
- if (outside && outside->kind == CK_PERMANENT
- && inside && inside->kind == CK_TEMPLATE)
+ /* if routing would affect IKE messages, reject */
+ if (!no_klips
+ && c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT
+ && c->spd.this.host_port != IKE_UDP_PORT
+ && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client))
{
- char inst[CONN_INST_BUF];
+ loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client");
+ return route_impossible;
+ }
- /* this is a co-terminal attempt of the "near" kind. */
- /* when chaining, we chain from inside to outside */
+ /* If there is already a route for peer's client subnet
+ * and it disagrees about interface or nexthop, we cannot steal it.
+ * Note: if this connection is already routed (perhaps for another
+ * state object), the route will agree.
+ * This is as it should be -- it will arise during rekeying.
+ */
+ if (ro != NULL && !routes_agree(ro, c))
+ {
+ loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\""
+ , ro->name);
+ return route_impossible; /* another connection already
+ using the eroute */
+ }
- /* XXX permit multiple deep connections? */
- passert(inside->policy_next == NULL);
+#ifdef KLIPS
+ /* if there is an eroute for another connection, there is a problem */
+ if (ero != NULL && ero != c)
+ {
+ struct connection *ero2, *ero_top;
+ struct connection *inside, *outside;
- inside->policy_next = outside;
+ /*
+ * note, wavesec (PERMANENT) goes *outside* and
+ * OE goes *inside* (TEMPLATE)
+ */
+ inside = NULL;
+ outside= NULL;
+ if (ero->kind == CK_PERMANENT
+ && c->kind == CK_TEMPLATE)
+ {
+ outside = ero;
+ inside = c;
+ }
+ else if (c->kind == CK_PERMANENT
+ && ero->kind == CK_TEMPLATE)
+ {
+ outside = c;
+ inside = ero;
+ }
- /* since we are going to steal the eroute from the secondary
- * policy, we need to make sure that it no longer thinks that
- * it owns the eroute.
- */
- outside->spd.eroute_owner = SOS_NOBODY;
- outside->spd.routing = RT_UNROUTED_KEYED;
+ /* okay, check again, with correct order */
+ if (outside && outside->kind == CK_PERMANENT
+ && inside && inside->kind == CK_TEMPLATE)
+ {
+ char inst[CONN_INST_BUF];
- /* set the priority of the new eroute owner to be higher
- * than that of the current eroute owner
- */
- inside->prio = outside->prio + 1;
+ /* this is a co-terminal attempt of the "near" kind. */
+ /* when chaining, we chain from inside to outside */
- fmt_conn_instance(inside, inst);
+ /* XXX permit multiple deep connections? */
+ passert(inside->policy_next == NULL);
- loglog(RC_LOG_SERIOUS
- , "conflict on eroute (%s), switching eroute to %s and linking %s"
- , inst, inside->name, outside->name);
+ inside->policy_next = outside;
- return route_nearconflict;
- }
+ /* since we are going to steal the eroute from the secondary
+ * policy, we need to make sure that it no longer thinks that
+ * it owns the eroute.
+ */
+ outside->spd.eroute_owner = SOS_NOBODY;
+ outside->spd.routing = RT_UNROUTED_KEYED;
- /* look along the chain of policies for one with the same name */
- ero_top = ero;
+ /* set the priority of the new eroute owner to be higher
+ * than that of the current eroute owner
+ */
+ inside->prio = outside->prio + 1;
- for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next)
- {
- if (ero2->kind == CK_TEMPLATE
- && streq(ero2->name, c->name))
- break;
- }
+ fmt_conn_instance(inside, inst);
- /* If we fell of the end of the list, then we found no TEMPLATE
- * so there must be a conflict that we can't resolve.
- * As the names are not equal, then we aren't replacing/rekeying.
- */
- if (ero2 == NULL)
- {
- char inst[CONN_INST_BUF];
+ loglog(RC_LOG_SERIOUS
+ , "conflict on eroute (%s), switching eroute to %s and linking %s"
+ , inst, inside->name, outside->name);
+
+ return route_nearconflict;
+ }
+
+ /* look along the chain of policies for one with the same name */
+ ero_top = ero;
+
+ for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next)
+ {
+ if (ero2->kind == CK_TEMPLATE
+ && streq(ero2->name, c->name))
+ break;
+ }
+
+ /* If we fell of the end of the list, then we found no TEMPLATE
+ * so there must be a conflict that we can't resolve.
+ * As the names are not equal, then we aren't replacing/rekeying.
+ */
+ if (ero2 == NULL)
+ {
+ char inst[CONN_INST_BUF];
- fmt_conn_instance(ero, inst);
+ fmt_conn_instance(ero, inst);
- loglog(RC_LOG_SERIOUS
- , "cannot install eroute -- it is in use for \"%s\"%s #%lu"
- , ero->name, inst, esr->eroute_owner);
- return FALSE; /* another connection already using the eroute */
+ loglog(RC_LOG_SERIOUS
+ , "cannot install eroute -- it is in use for \"%s\"%s #%lu"
+ , ero->name, inst, esr->eroute_owner);
+ return FALSE; /* another connection already using the eroute */
+ }
}
- }
#endif /* KLIPS */
- return route_easy;
+ return route_easy;
}
-bool
-trap_connection(struct connection *c)
+bool trap_connection(struct connection *c)
{
- switch (could_route(c))
- {
- case route_impossible:
- return FALSE;
-
- case route_nearconflict:
- case route_easy:
- /* RT_ROUTED_TUNNEL is treated specially: we don't override
- * because we don't want to lose track of the IPSEC_SAs etc.
- */
- if (c->spd.routing < RT_ROUTED_TUNNEL)
+ switch (could_route(c))
{
- return route_and_eroute(c, &c->spd, NULL);
+ case route_impossible:
+ return FALSE;
+
+ case route_nearconflict:
+ case route_easy:
+ /* RT_ROUTED_TUNNEL is treated specially: we don't override
+ * because we don't want to lose track of the IPSEC_SAs etc.
+ */
+ if (c->spd.routing < RT_ROUTED_TUNNEL)
+ {
+ return route_and_eroute(c, &c->spd, NULL);
+ }
+ return TRUE;
+
+ case route_farconflict:
+ return FALSE;
}
- return TRUE;
- case route_farconflict:
return FALSE;
- }
-
- return FALSE;
}
-/* delete any eroute for a connection and unroute it if route isn't shared */
-void
-unroute_connection(struct connection *c)
+/**
+ * Delete any eroute for a connection and unroute it if route isn't shared
+ */
+void unroute_connection(struct connection *c)
{
- struct spd_route *sr;
- enum routing_t cr;
-
- for (sr = &c->spd; sr; sr = sr->next)
- {
- cr = sr->routing;
+ struct spd_route *sr;
+ enum routing_t cr;
- if (erouted(cr))
+ for (sr = &c->spd; sr; sr = sr->next)
{
- /* cannot handle a live one */
- passert(sr->routing != RT_ROUTED_TUNNEL);
+ cr = sr->routing;
+
+ if (erouted(cr))
+ {
+ /* cannot handle a live one */
+ passert(sr->routing != RT_ROUTED_TUNNEL);
#ifdef KLIPS
- shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete");
+ shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete");
#endif
- }
+ }
- sr->routing = RT_UNROUTED; /* do now so route_owner won't find us */
+ sr->routing = RT_UNROUTED; /* do now so route_owner won't find us */
- /* only unroute if no other connection shares it */
- if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL)
- (void) do_command(c, sr, "unroute");
- }
+ /* only unroute if no other connection shares it */
+ if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL)
+ (void) do_command(c, sr, "unroute");
+ }
}
#ifdef KLIPS
-static void
-set_text_said(char *text_said, const ip_address *dst, ipsec_spi_t spi, int proto)
+static void set_text_said(char *text_said, const ip_address *dst,
+ ipsec_spi_t spi, int proto)
{
- ip_said said;
+ ip_said said;
- initsaid(dst, spi, proto, &said);
- satot(&said, 0, text_said, SATOT_BUF);
+ initsaid(dst, spi, proto, &said);
+ satot(&said, 0, text_said, SATOT_BUF);
}
/* find an entry in the bare_shunt table.
* Trick: return a pointer to the pointer to the entry;
* this allows the entry to be deleted.
*/
-static struct bare_shunt **
-bare_shunt_ptr(const ip_subnet *ours, const ip_subnet *his, int transport_proto)
+static struct bare_shunt** bare_shunt_ptr(const ip_subnet *ours,
+ const ip_subnet *his,
+ int transport_proto)
{
- struct bare_shunt *p, **pp;
-
- for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next)
- {
- if (samesubnet(ours, &p->ours)
- && samesubnet(his, &p->his)
- && transport_proto == p->transport_proto
- && portof(&ours->addr) == portof(&p->ours.addr)
- && portof(&his->addr) == portof(&p->his.addr))
- return pp;
- }
- return NULL;
+ struct bare_shunt *p, **pp;
+
+ for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next)
+ {
+ if (samesubnet(ours, &p->ours)
+ && samesubnet(his, &p->his)
+ && transport_proto == p->transport_proto
+ && portof(&ours->addr) == portof(&p->ours.addr)
+ && portof(&his->addr) == portof(&p->his.addr))
+ return pp;
+ }
+ return NULL;
}
/* free a bare_shunt entry, given a pointer to the pointer */
-static void
-free_bare_shunt(struct bare_shunt **pp)
+static void free_bare_shunt(struct bare_shunt **pp)
{
- if (pp == NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("delete bare shunt: null pointer")
- )
- }
- else
- {
- struct bare_shunt *p = *pp;
-
- *pp = p->next;
- DBG_bare_shunt("delete", p);
- pfree(p->why);
- pfree(p);
- }
+ if (pp == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("delete bare shunt: null pointer")
+ )
+ }
+ else
+ {
+ struct bare_shunt *p = *pp;
+
+ *pp = p->next;
+ DBG_bare_shunt("delete", p);
+ free(p->why);
+ free(p);
+ }
}
void
show_shunt_status(void)
{
- struct bare_shunt *bs;
-
- for (bs = bare_shunts; bs != NULL; bs = bs->next)
- {
- /* Print interesting fields. Ignore count and last_active. */
-
- int ourport = ntohs(portof(&bs->ours.addr));
- int hisport = ntohs(portof(&bs->his.addr));
- char ourst[SUBNETTOT_BUF];
- char hist[SUBNETTOT_BUF];
- char sat[SATOT_BUF];
- char prio[POLICY_PRIO_BUF];
-
- subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
- subnettot(&(bs)->his, 0, hist, sizeof(hist));
- satot(&(bs)->said, 0, sat, sizeof(sat));
- fmt_policy_prio(bs->policy_prio, prio);
-
- whack_log(RC_COMMENT, "%s:%d -> %s:%d => %s:%d %s %s"
- , ourst, ourport, hist, hisport, sat, bs->transport_proto
- , prio, bs->why);
- }
- if (bare_shunts != NULL)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
+ struct bare_shunt *bs;
+
+ for (bs = bare_shunts; bs != NULL; bs = bs->next)
+ {
+ /* Print interesting fields. Ignore count and last_active. */
+
+ int ourport = ntohs(portof(&bs->ours.addr));
+ int hisport = ntohs(portof(&bs->his.addr));
+ char ourst[SUBNETTOT_BUF];
+ char hist[SUBNETTOT_BUF];
+ char sat[SATOT_BUF];
+ char prio[POLICY_PRIO_BUF];
+
+ subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
+ subnettot(&(bs)->his, 0, hist, sizeof(hist));
+ satot(&(bs)->said, 0, sat, sizeof(sat));
+ fmt_policy_prio(bs->policy_prio, prio);
+
+ whack_log(RC_COMMENT, "%s:%d -> %s:%d => %s:%d %s %s"
+ , ourst, ourport, hist, hisport, sat, bs->transport_proto
+ , prio, bs->why);
+ }
+ if (bare_shunts != NULL)
+ whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
}
/* Setup an IPsec route entry.
* op is one of the ERO_* operators.
*/
-static bool
-raw_eroute(const ip_address *this_host
- , const ip_subnet *this_client
- , const ip_address *that_host
- , const ip_subnet *that_client
- , ipsec_spi_t spi
- , unsigned int proto
- , unsigned int satype
- , unsigned int transport_proto
- , const struct pfkey_proto_info *proto_info
- , time_t use_lifetime
- , unsigned int op
- , const char *opname USED_BY_DEBUG)
+static bool raw_eroute(const ip_address *this_host,
+ const ip_subnet *this_client,
+ const ip_address *that_host,
+ const ip_subnet *that_client,
+ ipsec_spi_t spi,
+ unsigned int proto,
+ unsigned int satype,
+ unsigned int transport_proto,
+ const struct pfkey_proto_info *proto_info,
+ time_t use_lifetime,
+ unsigned int op,
+ const char *opname USED_BY_DEBUG)
{
- char text_said[SATOT_BUF];
+ char text_said[SATOT_BUF];
- set_text_said(text_said, that_host, spi, proto);
+ set_text_said(text_said, that_host, spi, proto);
- DBG(DBG_CONTROL | DBG_KLIPS,
- {
- int sport = ntohs(portof(&this_client->addr));
- int dport = ntohs(portof(&that_client->addr));
- char mybuf[SUBNETTOT_BUF];
- char peerbuf[SUBNETTOT_BUF];
-
- subnettot(this_client, 0, mybuf, sizeof(mybuf));
- subnettot(that_client, 0, peerbuf, sizeof(peerbuf));
- DBG_log("%s eroute %s:%d -> %s:%d => %s:%d"
- , opname, mybuf, sport, peerbuf, dport
- , text_said, transport_proto);
- });
-
- return kernel_ops->raw_eroute(this_host, this_client
- , that_host, that_client, spi, satype, transport_proto, proto_info
- , use_lifetime, op, text_said);
+ DBG(DBG_CONTROL | DBG_KLIPS,
+ {
+ int sport = ntohs(portof(&this_client->addr));
+ int dport = ntohs(portof(&that_client->addr));
+ char mybuf[SUBNETTOT_BUF];
+ char peerbuf[SUBNETTOT_BUF];
+
+ subnettot(this_client, 0, mybuf, sizeof(mybuf));
+ subnettot(that_client, 0, peerbuf, sizeof(peerbuf));
+ DBG_log("%s eroute %s:%d -> %s:%d => %s:%d"
+ , opname, mybuf, sport, peerbuf, dport
+ , text_said, transport_proto);
+ });
+
+ return kernel_ops->raw_eroute(this_host, this_client
+ , that_host, that_client, spi, satype, transport_proto, proto_info
+ , use_lifetime, op, text_said);
}
/* test to see if %hold remains */
-bool
-has_bare_hold(const ip_address *src, const ip_address *dst, int transport_proto)
+bool has_bare_hold(const ip_address *src, const ip_address *dst,
+ int transport_proto)
{
- ip_subnet this_client, that_client;
- struct bare_shunt **bspp;
-
- passert(addrtypeof(src) == addrtypeof(dst));
- happy(addrtosubnet(src, &this_client));
- happy(addrtosubnet(dst, &that_client));
- bspp = bare_shunt_ptr(&this_client, &that_client, transport_proto);
- return bspp != NULL
- && (*bspp)->said.proto == SA_INT && (*bspp)->said.spi == htonl(SPI_HOLD);
+ ip_subnet this_client, that_client;
+ struct bare_shunt **bspp;
+
+ passert(addrtypeof(src) == addrtypeof(dst));
+ happy(addrtosubnet(src, &this_client));
+ happy(addrtosubnet(dst, &that_client));
+ bspp = bare_shunt_ptr(&this_client, &that_client, transport_proto);
+ return bspp != NULL
+ && (*bspp)->said.proto == SA_INT && (*bspp)->said.spi == htonl(SPI_HOLD);
}
/* Replace (or delete) a shunt that is in the bare_shunts table.
* Issues the PF_KEY commands and updates the bare_shunts table.
*/
-bool
-replace_bare_shunt(const ip_address *src, const ip_address *dst
- , policy_prio_t policy_prio
- , ipsec_spi_t shunt_spi /* in host order! */
- , bool repl /* if TRUE, replace; if FALSE, delete */
- , unsigned int transport_proto
- , const char *why)
+bool replace_bare_shunt(const ip_address *src, const ip_address *dst,
+ policy_prio_t policy_prio, ipsec_spi_t shunt_spi,
+ bool repl, unsigned int transport_proto, const char *why)
{
- ip_subnet this_client, that_client;
- ip_subnet this_broad_client, that_broad_client;
- const ip_address *null_host = aftoinfo(addrtypeof(src))->any;
-
- passert(addrtypeof(src) == addrtypeof(dst));
- happy(addrtosubnet(src, &this_client));
- happy(addrtosubnet(dst, &that_client));
- this_broad_client = this_client;
- that_broad_client = that_client;
- setportof(0, &this_broad_client.addr);
- setportof(0, &that_broad_client.addr);
-
- if (repl)
- {
- struct bare_shunt **bs_pp = bare_shunt_ptr(&this_broad_client
- , &that_broad_client, 0);
-
- /* is there already a broad host-to-host bare shunt? */
- if (bs_pp == NULL)
- {
- if (raw_eroute(null_host, &this_broad_client, null_host, &that_broad_client
- , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT
- , 0, null_proto_info
- , SHUNT_PATIENCE, ERO_ADD, why))
- {
- struct bare_shunt *bs = alloc_thing(struct bare_shunt, "bare shunt");
-
- bs->ours = this_broad_client;
- bs->his = that_broad_client;
- bs->transport_proto = 0;
- bs->said.proto = SA_INT;
- bs->why = clone_str(why, "bare shunt story");
- bs->policy_prio = policy_prio;
- bs->said.spi = htonl(shunt_spi);
- bs->said.dst = *null_host;
- bs->count = 0;
- bs->last_activity = now();
- bs->next = bare_shunts;
- bare_shunts = bs;
- DBG_bare_shunt("add", bs);
- }
+ ip_subnet this_client, that_client;
+ ip_subnet this_broad_client, that_broad_client;
+ const ip_address *null_host = aftoinfo(addrtypeof(src))->any;
+
+ passert(addrtypeof(src) == addrtypeof(dst));
+ happy(addrtosubnet(src, &this_client));
+ happy(addrtosubnet(dst, &that_client));
+ this_broad_client = this_client;
+ that_broad_client = that_client;
+ setportof(0, &this_broad_client.addr);
+ setportof(0, &that_broad_client.addr);
+
+ if (repl)
+ {
+ struct bare_shunt **bs_pp = bare_shunt_ptr(&this_broad_client
+ , &that_broad_client, 0);
+
+ /* is there already a broad host-to-host bare shunt? */
+ if (bs_pp == NULL)
+ {
+ if (raw_eroute(null_host, &this_broad_client, null_host, &that_broad_client
+ , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT
+ , 0, null_proto_info
+ , SHUNT_PATIENCE, ERO_ADD, why))
+ {
+ struct bare_shunt *bs = malloc_thing(struct bare_shunt);
+
+ bs->ours = this_broad_client;
+ bs->his = that_broad_client;
+ bs->transport_proto = 0;
+ bs->said.proto = SA_INT;
+ bs->why = clone_str(why);
+ bs->policy_prio = policy_prio;
+ bs->said.spi = htonl(shunt_spi);
+ bs->said.dst = *null_host;
+ bs->count = 0;
+ bs->last_activity = now();
+ bs->next = bare_shunts;
+ bare_shunts = bs;
+ DBG_bare_shunt("add", bs);
+ }
+ }
+ shunt_spi = SPI_HOLD;
}
- shunt_spi = SPI_HOLD;
- }
- if (raw_eroute(null_host, &this_client, null_host, &that_client
- , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT
- , transport_proto, null_proto_info
- , SHUNT_PATIENCE, ERO_DELETE, why))
- {
- struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client
- , transport_proto);
+ if (raw_eroute(null_host, &this_client, null_host, &that_client
+ , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT
+ , transport_proto, null_proto_info
+ , SHUNT_PATIENCE, ERO_DELETE, why))
+ {
+ struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client
+ , transport_proto);
- /* delete bare eroute */
- free_bare_shunt(bs_pp);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ /* delete bare eroute */
+ free_bare_shunt(bs_pp);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
-static bool
-eroute_connection(struct spd_route *sr
-, ipsec_spi_t spi, unsigned int proto, unsigned int satype
-, const struct pfkey_proto_info *proto_info
-, unsigned int op, const char *opname)
+static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
+ unsigned int proto, unsigned int satype,
+ const struct pfkey_proto_info *proto_info,
+ unsigned int op, const char *opname)
{
- const ip_address *peer = &sr->that.host_addr;
- char buf2[256];
+ const ip_address *peer = &sr->that.host_addr;
+ char buf2[256];
- snprintf(buf2, sizeof(buf2)
- , "eroute_connection %s", opname);
+ snprintf(buf2, sizeof(buf2)
+ , "eroute_connection %s", opname);
- if (proto == SA_INT)
- peer = aftoinfo(addrtypeof(peer))->any;
+ if (proto == SA_INT)
+ peer = aftoinfo(addrtypeof(peer))->any;
- return raw_eroute(&sr->this.host_addr, &sr->this.client
- , peer
- , &sr->that.client
- , spi, proto, satype
- , sr->this.protocol, proto_info, 0, op, buf2);
+ return raw_eroute(&sr->this.host_addr, &sr->this.client
+ , peer
+ , &sr->that.client
+ , spi, proto, satype
+ , sr->this.protocol, proto_info, 0, op, buf2);
}
/* assign a bare hold to a connection */
-bool
-assign_hold(struct connection *c USED_BY_DEBUG
- , struct spd_route *sr
- , int transport_proto
- , const ip_address *src, const ip_address *dst)
+bool assign_hold(struct connection *c USED_BY_DEBUG, struct spd_route *sr,
+ int transport_proto,
+ const ip_address *src,
+ const ip_address *dst)
{
- /* either the automatically installed %hold eroute is broad enough
- * or we try to add a broader one and delete the automatic one.
- * Beware: this %hold might be already handled, but still squeak
- * through because of a race.
- */
- enum routing_t ro = sr->routing /* routing, old */
- , rn = ro; /* routing, new */
-
- passert(LHAS(LELEM(CK_PERMANENT) | LELEM(CK_INSTANCE), c->kind));
- /* figure out what routing should become */
- switch (ro)
- {
- case RT_UNROUTED:
- rn = RT_UNROUTED_HOLD;
- break;
- case RT_ROUTED_PROSPECTIVE:
- rn = RT_ROUTED_HOLD;
- break;
- default:
- /* no change: this %hold is old news and should just be deleted */
- break;
- }
-
- /* we need a broad %hold, not the narrow one.
- * First we ensure that there is a broad %hold.
- * There may already be one (race condition): no need to create one.
- * There may already be a %trap: replace it.
- * There may not be any broad eroute: add %hold.
- * Once the broad %hold is in place, delete the narrow one.
- */
- if (rn != ro)
- {
- if (erouted(ro)
- ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
- , null_proto_info
- , ERO_REPLACE, "replace %trap with broad %hold")
- : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
- , null_proto_info
- , ERO_ADD, "add broad %hold"))
- {
- return FALSE;
- }
- }
- if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE
- , transport_proto, "delete narrow %hold"))
- {
- return FALSE;
- }
- sr->routing = rn;
- return TRUE;
+ /* either the automatically installed %hold eroute is broad enough
+ * or we try to add a broader one and delete the automatic one.
+ * Beware: this %hold might be already handled, but still squeak
+ * through because of a race.
+ */
+ enum routing_t ro = sr->routing /* routing, old */
+ , rn = ro; /* routing, new */
+
+ passert(LHAS(LELEM(CK_PERMANENT) | LELEM(CK_INSTANCE), c->kind));
+ /* figure out what routing should become */
+ switch (ro)
+ {
+ case RT_UNROUTED:
+ rn = RT_UNROUTED_HOLD;
+ break;
+ case RT_ROUTED_PROSPECTIVE:
+ rn = RT_ROUTED_HOLD;
+ break;
+ default:
+ /* no change: this %hold is old news and should just be deleted */
+ break;
+ }
+
+ /* we need a broad %hold, not the narrow one.
+ * First we ensure that there is a broad %hold.
+ * There may already be one (race condition): no need to create one.
+ * There may already be a %trap: replace it.
+ * There may not be any broad eroute: add %hold.
+ * Once the broad %hold is in place, delete the narrow one.
+ */
+ if (rn != ro)
+ {
+ if (erouted(ro)
+ ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
+ , null_proto_info
+ , ERO_REPLACE, "replace %trap with broad %hold")
+ : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
+ , null_proto_info
+ , ERO_ADD, "add broad %hold"))
+ {
+ return FALSE;
+ }
+ }
+ if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE
+ , transport_proto, "delete narrow %hold"))
+ {
+ return FALSE;
+ }
+ sr->routing = rn;
+ return TRUE;
}
/* install or remove eroute for SA Group */
-static bool
-sag_eroute(struct state *st, struct spd_route *sr
- , unsigned op, const char *opname)
+static bool sag_eroute(struct state *st, struct spd_route *sr,
+ unsigned op, const char *opname)
{
- u_int inner_proto = 0;
- u_int inner_satype = 0;
- ipsec_spi_t inner_spi = 0;
- struct pfkey_proto_info proto_info[4];
- int i;
- bool tunnel;
-
- /* figure out the SPI and protocol (in two forms)
- * for the innermost transformation.
- */
-
- i = sizeof(proto_info) / sizeof(proto_info[0]) - 1;
- proto_info[i].proto = 0;
- tunnel = FALSE;
-
- if (st->st_ah.present)
- {
- inner_spi = st->st_ah.attrs.spi;
- inner_proto = SA_AH;
- inner_satype = SADB_SATYPE_AH;
-
- i--;
- proto_info[i].proto = IPPROTO_AH;
- proto_info[i].encapsulation = st->st_ah.attrs.encapsulation;
- tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
- proto_info[i].reqid = sr->reqid;
- }
-
- if (st->st_esp.present)
- {
- inner_spi = st->st_esp.attrs.spi;
- inner_proto = SA_ESP;
- inner_satype = SADB_SATYPE_ESP;
-
- i--;
- proto_info[i].proto = IPPROTO_ESP;
- proto_info[i].encapsulation = st->st_esp.attrs.encapsulation;
- tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
- proto_info[i].reqid = sr->reqid + 1;
- }
-
- if (st->st_ipcomp.present)
- {
- inner_spi = st->st_ipcomp.attrs.spi;
- inner_proto = SA_COMP;
- inner_satype = SADB_X_SATYPE_COMP;
-
- i--;
- proto_info[i].proto = IPPROTO_COMP;
- proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation;
- tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
- proto_info[i].reqid = sr->reqid + 2;
- }
-
- if (i == sizeof(proto_info) / sizeof(proto_info[0]) - 1)
- {
- impossible(); /* no transform at all! */
- }
-
- if (tunnel)
- {
- int j;
-
- inner_spi = st->st_tunnel_out_spi;
- inner_proto = SA_IPIP;
- inner_satype = SADB_X_SATYPE_IPIP;
-
- proto_info[i].encapsulation = ENCAPSULATION_MODE_TUNNEL;
- for (j = i + 1; proto_info[j].proto; j++)
- {
- proto_info[j].encapsulation = ENCAPSULATION_MODE_TRANSPORT;
- }
- }
-
- return eroute_connection(sr
- , inner_spi, inner_proto, inner_satype, proto_info + i
- , op, opname);
+ u_int inner_proto = 0;
+ u_int inner_satype = 0;
+ ipsec_spi_t inner_spi = 0;
+ struct pfkey_proto_info proto_info[4];
+ int i;
+ bool tunnel;
+
+ /* figure out the SPI and protocol (in two forms)
+ * for the innermost transformation.
+ */
+
+ i = sizeof(proto_info) / sizeof(proto_info[0]) - 1;
+ proto_info[i].proto = 0;
+ tunnel = FALSE;
+
+ if (st->st_ah.present)
+ {
+ inner_spi = st->st_ah.attrs.spi;
+ inner_proto = SA_AH;
+ inner_satype = SADB_SATYPE_AH;
+
+ i--;
+ proto_info[i].proto = IPPROTO_AH;
+ proto_info[i].encapsulation = st->st_ah.attrs.encapsulation;
+ tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
+ proto_info[i].reqid = sr->reqid;
+ }
+
+ if (st->st_esp.present)
+ {
+ inner_spi = st->st_esp.attrs.spi;
+ inner_proto = SA_ESP;
+ inner_satype = SADB_SATYPE_ESP;
+
+ i--;
+ proto_info[i].proto = IPPROTO_ESP;
+ proto_info[i].encapsulation = st->st_esp.attrs.encapsulation;
+ tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
+ proto_info[i].reqid = sr->reqid + 1;
+ }
+
+ if (st->st_ipcomp.present)
+ {
+ inner_spi = st->st_ipcomp.attrs.spi;
+ inner_proto = SA_COMP;
+ inner_satype = SADB_X_SATYPE_COMP;
+
+ i--;
+ proto_info[i].proto = IPPROTO_COMP;
+ proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation;
+ tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
+ proto_info[i].reqid = sr->reqid + 2;
+ }
+
+ if (i == sizeof(proto_info) / sizeof(proto_info[0]) - 1)
+ {
+ impossible(); /* no transform at all! */
+ }
+
+ if (tunnel)
+ {
+ int j;
+
+ inner_spi = st->st_tunnel_out_spi;
+ inner_proto = SA_IPIP;
+ inner_satype = SADB_X_SATYPE_IPIP;
+
+ proto_info[i].encapsulation = ENCAPSULATION_MODE_TUNNEL;
+ for (j = i + 1; proto_info[j].proto; j++)
+ {
+ proto_info[j].encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ }
+ }
+
+ return eroute_connection(sr
+ , inner_spi, inner_proto, inner_satype, proto_info + i
+ , op, opname);
}
/* compute a (host-order!) SPI to implement the policy in connection c */
ipsec_spi_t
shunt_policy_spi(struct connection *c, bool prospective)
{
- /* note: these are in host order :-( */
- static const ipsec_spi_t shunt_spi[] =
- {
- SPI_TRAP, /* --initiateontraffic */
- SPI_PASS, /* --pass */
- SPI_DROP, /* --drop */
- SPI_REJECT, /* --reject */
- };
-
- static const ipsec_spi_t fail_spi[] =
- {
- 0, /* --none*/
- SPI_PASS, /* --failpass */
- SPI_DROP, /* --faildrop */
- SPI_REJECT, /* --failreject */
- };
-
- return prospective
- ? shunt_spi[(c->policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT]
- : fail_spi[(c->policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT];
+ /* note: these are in host order :-( */
+ static const ipsec_spi_t shunt_spi[] =
+ {
+ SPI_TRAP, /* --initiateontraffic */
+ SPI_PASS, /* --pass */
+ SPI_DROP, /* --drop */
+ SPI_REJECT, /* --reject */
+ };
+
+ static const ipsec_spi_t fail_spi[] =
+ {
+ 0, /* --none*/
+ SPI_PASS, /* --failpass */
+ SPI_DROP, /* --faildrop */
+ SPI_REJECT, /* --failreject */
+ };
+
+ return prospective
+ ? shunt_spi[(c->policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT]
+ : fail_spi[(c->policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT];
}
/* Add/replace/delete a shunt eroute.
@@ -1261,89 +1255,87 @@ shunt_policy_spi(struct connection *c, bool prospective)
* If negotiation has failed, the choice between %trap/%pass/%drop/%reject
* is specified in the policy of connection c.
*/
-static bool
-shunt_eroute(struct connection *c
-, struct spd_route *sr
-, enum routing_t rt_kind
-, unsigned int op, const char *opname)
+static bool shunt_eroute(struct connection *c, struct spd_route *sr,
+ enum routing_t rt_kind,
+ unsigned int op, const char *opname)
{
- /* We are constructing a special SAID for the eroute.
- * The destination doesn't seem to matter, but the family does.
- * The protocol is SA_INT -- mark this as shunt.
- * The satype has no meaning, but is required for PF_KEY header!
- * The SPI signifies the kind of shunt.
- */
- ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE);
- bool ok;
-
- if (spi == 0)
- {
- /* we're supposed to end up with no eroute: rejig op and opname */
- switch (op)
- {
- case ERO_REPLACE:
- /* replace with nothing == delete */
- op = ERO_DELETE;
- opname = "delete";
- break;
- case ERO_ADD:
- /* add nothing == do nothing */
- return TRUE;
- case ERO_DELETE:
- /* delete remains delete */
- break;
- default:
- bad_case(op);
- }
- }
- if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE)
- {
- /* We think that we have an eroute, but we don't.
- * Adjust the request and account for eclipses.
+ /* We are constructing a special SAID for the eroute.
+ * The destination doesn't seem to matter, but the family does.
+ * The protocol is SA_INT -- mark this as shunt.
+ * The satype has no meaning, but is required for PF_KEY header!
+ * The SPI signifies the kind of shunt.
*/
- passert(eclipsable(sr));
- switch (op)
- {
- case ERO_REPLACE:
- /* really an add */
- op = ERO_ADD;
- opname = "replace eclipsed";
- eclipse_count--;
- break;
- case ERO_DELETE:
- /* delete unnecessary: we don't actually have an eroute */
- eclipse_count--;
- return TRUE;
- case ERO_ADD:
- default:
- bad_case(op);
+ ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE);
+ bool ok;
+
+ if (spi == 0)
+ {
+ /* we're supposed to end up with no eroute: rejig op and opname */
+ switch (op)
+ {
+ case ERO_REPLACE:
+ /* replace with nothing == delete */
+ op = ERO_DELETE;
+ opname = "delete";
+ break;
+ case ERO_ADD:
+ /* add nothing == do nothing */
+ return TRUE;
+ case ERO_DELETE:
+ /* delete remains delete */
+ break;
+ default:
+ bad_case(op);
+ }
}
- }
- else if (eclipse_count > 0 && op == ERO_DELETE && eclipsable(sr))
- {
- /* maybe we are uneclipsing something */
- struct spd_route *esr;
- struct connection *ue = eclipsed(c, &esr);
-
- if (ue != NULL)
- {
- esr->routing = RT_ROUTED_PROSPECTIVE;
- return shunt_eroute(ue, esr
- , RT_ROUTED_PROSPECTIVE, ERO_REPLACE, "restoring eclipsed");
- }
- }
-
- ok = TRUE;
- if (kernel_ops->inbound_eroute)
- {
- ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
- , &c->spd.this.host_addr, &c->spd.this.client
- , htonl(spi), SA_INT, SADB_X_SATYPE_INT
- , 0, null_proto_info, 0
- , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname);
- }
- return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT
- , null_proto_info, op, opname) && ok;
+ if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE)
+ {
+ /* We think that we have an eroute, but we don't.
+ * Adjust the request and account for eclipses.
+ */
+ passert(eclipsable(sr));
+ switch (op)
+ {
+ case ERO_REPLACE:
+ /* really an add */
+ op = ERO_ADD;
+ opname = "replace eclipsed";
+ eclipse_count--;
+ break;
+ case ERO_DELETE:
+ /* delete unnecessary: we don't actually have an eroute */
+ eclipse_count--;
+ return TRUE;
+ case ERO_ADD:
+ default:
+ bad_case(op);
+ }
+ }
+ else if (eclipse_count > 0 && op == ERO_DELETE && eclipsable(sr))
+ {
+ /* maybe we are uneclipsing something */
+ struct spd_route *esr;
+ struct connection *ue = eclipsed(c, &esr);
+
+ if (ue != NULL)
+ {
+ esr->routing = RT_ROUTED_PROSPECTIVE;
+ return shunt_eroute(ue, esr
+ , RT_ROUTED_PROSPECTIVE, ERO_REPLACE, "restoring eclipsed");
+ }
+ }
+
+ ok = TRUE;
+ if (kernel_ops->inbound_eroute)
+ {
+ ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
+ , &c->spd.this.host_addr, &c->spd.this.client
+ , htonl(spi), SA_INT, SADB_X_SATYPE_INT
+ , 0, null_proto_info, 0
+ , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname);
+ }
+ return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT
+ , null_proto_info, op, opname) && ok;
}
@@ -1357,28 +1349,27 @@ shunt_eroute(struct connection *c
* The task here is to remove the ":p" part so that the rest can be read
* by another routine.
*/
-static const char *
-read_proto(const char * s, size_t * len, int * transport_proto)
+static const char *read_proto(const char * s, size_t * len, int * transport_proto)
{
- const char * p;
- const char * ugh;
- unsigned long proto;
- size_t l;
-
- l = *len;
- p = memchr(s, ':', l);
- if (p == 0) {
- *transport_proto = 0;
- return 0;
- }
- ugh = ttoul(p+1, l-((p-s)+1), 10, &proto);
- if (ugh != 0)
- return ugh;
- if (proto > 65535)
- return "protocol number is too large, legal range is 0-65535";
- *len = p-s;
- *transport_proto = proto;
- return 0;
+ const char * p;
+ const char * ugh;
+ unsigned long proto;
+ size_t l;
+
+ l = *len;
+ p = memchr(s, ':', l);
+ if (p == 0) {
+ *transport_proto = 0;
+ return 0;
+ }
+ ugh = ttoul(p+1, l-((p-s)+1), 10, &proto);
+ if (ugh != 0)
+ return ugh;
+ if (proto > 65535)
+ return "protocol number is too large, legal range is 0-65535";
+ *len = p-s;
+ *transport_proto = proto;
+ return 0;
}
@@ -1407,937 +1398,931 @@ read_proto(const char * s, size_t * len, int * transport_proto)
* searching for each is sequential. If this becomes a problem, faster
* searches could be implemented (hash or radix tree, for example).
*/
-void
-scan_proc_shunts(void)
+void scan_proc_shunts(void)
{
- static const char procname[] = "/proc/net/ipsec_eroute";
- FILE *f;
- time_t nw = now();
- int lino;
- struct eroute_info *expired = NULL;
-
- event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
-
- DBG(DBG_CONTROL,
- DBG_log("scanning for shunt eroutes")
- )
-
- /* free any leftover entries: they will be refreshed if still current */
- while (orphaned_holds != NULL)
- {
- struct eroute_info *p = orphaned_holds;
-
- orphaned_holds = p->next;
- pfree(orphaned_holds);
- }
-
- /* decode the /proc file. Don't do anything strenuous to it
- * (certainly no PF_KEY stuff) to minimize the chance that it
- * might change underfoot.
- */
-
- f = fopen(procname, "r");
- if (f == NULL)
- return;
-
- /* for each line... */
- for (lino = 1; ; lino++)
- {
- unsigned char buf[1024]; /* should be big enough */
- chunk_t field[10]; /* 10 is loose upper bound */
- chunk_t *ff = NULL; /* fixed fields (excluding optional count) */
- int fi;
- struct eroute_info eri;
- char *cp;
- err_t context = ""
- , ugh = NULL;
-
- cp = fgets(buf, sizeof(buf), f);
- if (cp == NULL)
- break;
-
- /* break out each field
- * Note: if there are too many fields, just stop;
- * it will be diagnosed a little later.
- */
- for (fi = 0; fi < (int)elemsof(field); fi++)
+ static const char procname[] = "/proc/net/ipsec_eroute";
+ FILE *f;
+ time_t nw = now();
+ int lino;
+ struct eroute_info *expired = NULL;
+
+ event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
+
+ DBG(DBG_CONTROL,
+ DBG_log("scanning for shunt eroutes")
+ )
+
+ /* free any leftover entries: they will be refreshed if still current */
+ while (orphaned_holds != NULL)
{
- static const char sep[] = " \t\n"; /* field-separating whitespace */
- size_t w;
+ struct eroute_info *p = orphaned_holds;
- cp += strspn(cp, sep); /* find start of field */
- w = strcspn(cp, sep); /* find width of field */
- setchunk(field[fi], cp, w);
- cp += w;
- if (w == 0)
- break;
+ orphaned_holds = p->next;
+ free(orphaned_holds);
}
- /* This odd do-hickey is to share error reporting code.
- * A break will get to that common code. The setting
- * of "ugh" and "context" parameterize it.
+ /* decode the /proc file. Don't do anything strenuous to it
+ * (certainly no PF_KEY stuff) to minimize the chance that it
+ * might change underfoot.
*/
- do {
- /* Old entries have no packet count; new ones do.
- * check if things are as they should be.
- */
- if (fi == 5)
- ff = &field[0]; /* old form, with no count */
- else if (fi == 6)
- ff = &field[1]; /* new form, with count */
- else
- {
- ugh = "has wrong number of fields";
- break;
- }
-
- if (ff[1].len != 2
- || strncmp(ff[1].ptr, "->", 2) != 0
- || ff[3].len != 2
- || strncmp(ff[3].ptr, "=>", 2) != 0)
- {
- ugh = "is missing -> or =>";
- break;
- }
- /* actually digest fields of interest */
+ f = fopen(procname, "r");
+ if (f == NULL)
+ return;
- /* packet count */
+ /* for each line... */
+ for (lino = 1; ; lino++)
+ {
+ unsigned char buf[1024]; /* should be big enough */
+ chunk_t field[10]; /* 10 is loose upper bound */
+ chunk_t *ff = NULL; /* fixed fields (excluding optional count) */
+ int fi;
+ struct eroute_info eri;
+ char *cp;
+ err_t context = ""
+ , ugh = NULL;
+
+ cp = fgets(buf, sizeof(buf), f);
+ if (cp == NULL)
+ break;
- eri.count = 0;
- if (ff != field)
- {
- context = "count field is malformed: ";
- ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count);
- if (ugh != NULL)
- break;
- }
+ /* break out each field
+ * Note: if there are too many fields, just stop;
+ * it will be diagnosed a little later.
+ */
+ for (fi = 0; fi < (int)countof(field); fi++)
+ {
+ static const char sep[] = " \t\n"; /* field-separating whitespace */
+ size_t w;
+
+ cp += strspn(cp, sep); /* find start of field */
+ w = strcspn(cp, sep); /* find width of field */
+ field[fi] = chunk_create(cp, w);
+ cp += w;
+ if (w == 0)
+ break;
+ }
- /* our client */
+ /* This odd do-hickey is to share error reporting code.
+ * A break will get to that common code. The setting
+ * of "ugh" and "context" parameterize it.
+ */
+ do {
+ /* Old entries have no packet count; new ones do.
+ * check if things are as they should be.
+ */
+ if (fi == 5)
+ ff = &field[0]; /* old form, with no count */
+ else if (fi == 6)
+ ff = &field[1]; /* new form, with count */
+ else
+ {
+ ugh = "has wrong number of fields";
+ break;
+ }
- context = "source subnet field malformed: ";
- ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours);
- if (ugh != NULL)
- break;
+ if (ff[1].len != 2
+ || strncmp(ff[1].ptr, "->", 2) != 0
+ || ff[3].len != 2
+ || strncmp(ff[3].ptr, "=>", 2) != 0)
+ {
+ ugh = "is missing -> or =>";
+ break;
+ }
- /* his client */
+ /* actually digest fields of interest */
- context = "destination subnet field malformed: ";
- ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his);
- if (ugh != NULL)
- break;
+ /* packet count */
- /* SAID */
+ eri.count = 0;
+ if (ff != field)
+ {
+ context = "count field is malformed: ";
+ ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count);
+ if (ugh != NULL)
+ break;
+ }
- context = "SA ID field malformed: ";
- ugh = read_proto(ff[4].ptr, &ff[4].len, &eri.transport_proto);
- if (ugh != NULL)
- break;
- ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said);
- } while (FALSE);
-
- if (ugh != NULL)
- {
- plog("INTERNAL ERROR: %s line %d %s%s"
- , procname, lino, context, ugh);
- continue; /* ignore rest of line */
- }
-
- /* Now we have decoded eroute, let's consider it.
- * For shunt eroutes:
- *
- * %hold: if not known, add to orphaned_holds list for initiation
- * because ACQUIRE might have been lost.
- *
- * %pass, %drop, %reject: determine if idle; if so, blast it away.
- * Can occur bare (if DNS provided insufficient information)
- * or with a connection (failure context).
- * Could even be installed by ipsec manual.
- *
- * %trap: always welcome.
- *
- * For other eroutes: find state and record count change
- */
- if (eri.said.proto == SA_INT)
- {
- /* shunt eroute */
- switch (ntohl(eri.said.spi))
- {
- case SPI_HOLD:
- if (bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto) == NULL
- && shunt_owner(&eri.ours, &eri.his) == NULL)
+ /* our client */
+
+ context = "source subnet field malformed: ";
+ ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours);
+ if (ugh != NULL)
+ break;
+
+ /* his client */
+
+ context = "destination subnet field malformed: ";
+ ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his);
+ if (ugh != NULL)
+ break;
+
+ /* SAID */
+
+ context = "SA ID field malformed: ";
+ ugh = read_proto(ff[4].ptr, &ff[4].len, &eri.transport_proto);
+ if (ugh != NULL)
+ break;
+ ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said);
+ } while (FALSE);
+
+ if (ugh != NULL)
{
- int ourport = ntohs(portof(&eri.ours.addr));
- int hisport = ntohs(portof(&eri.his.addr));
- char ourst[SUBNETTOT_BUF];
- char hist[SUBNETTOT_BUF];
- char sat[SATOT_BUF];
-
- subnettot(&eri.ours, 0, ourst, sizeof(ourst));
- subnettot(&eri.his, 0, hist, sizeof(hist));
- satot(&eri.said, 0, sat, sizeof(sat));
-
- DBG(DBG_CONTROL,
- DBG_log("add orphaned shunt %s:%d -> %s:%d => %s:%d"
- , ourst, ourport, hist, hisport, sat, eri.transport_proto)
- )
- eri.next = orphaned_holds;
- orphaned_holds = clone_thing(eri, "orphaned %hold");
+ plog("INTERNAL ERROR: %s line %d %s%s"
+ , procname, lino, context, ugh);
+ continue; /* ignore rest of line */
}
- break;
- case SPI_PASS:
- case SPI_DROP:
- case SPI_REJECT:
- /* nothing sensible to do if we don't have counts */
- if (ff != field)
+ /* Now we have decoded eroute, let's consider it.
+ * For shunt eroutes:
+ *
+ * %hold: if not known, add to orphaned_holds list for initiation
+ * because ACQUIRE might have been lost.
+ *
+ * %pass, %drop, %reject: determine if idle; if so, blast it away.
+ * Can occur bare (if DNS provided insufficient information)
+ * or with a connection (failure context).
+ * Could even be installed by ipsec manual.
+ *
+ * %trap: always welcome.
+ *
+ * For other eroutes: find state and record count change
+ */
+ if (eri.said.proto == SA_INT)
{
- struct bare_shunt **bs_pp
- = bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto);
-
- if (bs_pp != NULL)
- {
- struct bare_shunt *bs = *bs_pp;
-
- if (eri.count != bs->count)
+ /* shunt eroute */
+ switch (ntohl(eri.said.spi))
{
- bs->count = eri.count;
- bs->last_activity = nw;
+ case SPI_HOLD:
+ if (bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto) == NULL
+ && shunt_owner(&eri.ours, &eri.his) == NULL)
+ {
+ int ourport = ntohs(portof(&eri.ours.addr));
+ int hisport = ntohs(portof(&eri.his.addr));
+ char ourst[SUBNETTOT_BUF];
+ char hist[SUBNETTOT_BUF];
+ char sat[SATOT_BUF];
+
+ subnettot(&eri.ours, 0, ourst, sizeof(ourst));
+ subnettot(&eri.his, 0, hist, sizeof(hist));
+ satot(&eri.said, 0, sat, sizeof(sat));
+
+ DBG(DBG_CONTROL,
+ DBG_log("add orphaned shunt %s:%d -> %s:%d => %s:%d"
+ , ourst, ourport, hist, hisport, sat, eri.transport_proto)
+ )
+ eri.next = orphaned_holds;
+ orphaned_holds = clone_thing(eri);
+ }
+ break;
+
+ case SPI_PASS:
+ case SPI_DROP:
+ case SPI_REJECT:
+ /* nothing sensible to do if we don't have counts */
+ if (ff != field)
+ {
+ struct bare_shunt **bs_pp
+ = bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto);
+
+ if (bs_pp != NULL)
+ {
+ struct bare_shunt *bs = *bs_pp;
+
+ if (eri.count != bs->count)
+ {
+ bs->count = eri.count;
+ bs->last_activity = nw;
+ }
+ else if (nw - bs->last_activity > SHUNT_PATIENCE)
+ {
+ eri.next = expired;
+ expired = clone_thing(eri);
+ }
+ }
+ }
+ break;
+
+ case SPI_TRAP:
+ break;
+
+ default:
+ bad_case(ntohl(eri.said.spi));
}
- else if (nw - bs->last_activity > SHUNT_PATIENCE)
- {
- eri.next = expired;
- expired = clone_thing(eri, "expired %pass");
- }
- }
}
- break;
-
- case SPI_TRAP:
- break;
+ else
+ {
+ /* regular (non-shunt) eroute */
+ state_eroute_usage(&eri.ours, &eri.his, eri.count, nw);
+ }
+ } /* for each line */
+ fclose(f);
- default:
- bad_case(ntohl(eri.said.spi));
- }
- }
- else
+ /* Now that we've finished processing the /proc file,
+ * it is safe to delete the expired %pass shunts.
+ */
+ while (expired != NULL)
{
- /* regular (non-shunt) eroute */
- state_eroute_usage(&eri.ours, &eri.his, eri.count, nw);
- }
- } /* for each line */
- fclose(f);
-
- /* Now that we've finished processing the /proc file,
- * it is safe to delete the expired %pass shunts.
- */
- while (expired != NULL)
- {
- struct eroute_info *p = expired;
- ip_address src, dst;
-
- networkof(&p->ours, &src);
- networkof(&p->his, &dst);
- (void) replace_bare_shunt(&src, &dst
- , BOTTOM_PRIO /* not used because we are deleting. This value is a filler */
- , SPI_PASS /* not used because we are deleting. This value is a filler */
- , FALSE, p->transport_proto, "delete expired bare shunts");
- expired = p->next;
- pfree(p);
- }
+ struct eroute_info *p = expired;
+ ip_address src, dst;
+
+ networkof(&p->ours, &src);
+ networkof(&p->his, &dst);
+ (void) replace_bare_shunt(&src, &dst
+ , BOTTOM_PRIO /* not used because we are deleting. This value is a filler */
+ , SPI_PASS /* not used because we are deleting. This value is a filler */
+ , FALSE, p->transport_proto, "delete expired bare shunts");
+ expired = p->next;
+ free(p);
+ }
}
-static bool
-del_spi(ipsec_spi_t spi, int proto
-, const ip_address *src, const ip_address *dest)
+static bool del_spi(ipsec_spi_t spi, int proto,
+ const ip_address *src, const ip_address *dest)
{
- char text_said[SATOT_BUF];
- struct kernel_sa sa;
+ char text_said[SATOT_BUF];
+ struct kernel_sa sa;
- set_text_said(text_said, dest, spi, proto);
+ set_text_said(text_said, dest, spi, proto);
- DBG(DBG_KLIPS, DBG_log("delete %s", text_said));
+ DBG(DBG_KLIPS, DBG_log("delete %s", text_said));
- memset(&sa, 0, sizeof(sa));
- sa.spi = spi;
- sa.proto = proto;
- sa.src = src;
- sa.dst = dest;
- sa.text_said = text_said;
+ memset(&sa, 0, sizeof(sa));
+ sa.spi = spi;
+ sa.proto = proto;
+ sa.src = src;
+ sa.dst = dest;
+ sa.text_said = text_said;
- return kernel_ops->del_sa(&sa);
+ return kernel_ops->del_sa(&sa);
}
/* Setup a pair of SAs. Code taken from setsa.c and spigrp.c, in
* ipsec-0.5.
*/
-static bool
-setup_half_ipsec_sa(struct state *st, bool inbound)
+static bool setup_half_ipsec_sa(struct state *st, bool inbound)
{
- /* Build an inbound or outbound SA */
-
- struct connection *c = st->st_connection;
- ip_subnet src, dst;
- ip_subnet src_client, dst_client;
- ipsec_spi_t inner_spi = 0;
- u_int proto = 0;
- u_int satype = SADB_SATYPE_UNSPEC;
- bool replace;
-
- /* SPIs, saved for spigrouping or undoing, if necessary */
- struct kernel_sa
- said[EM_MAXRELSPIS],
- *said_next = said;
-
- char text_said[SATOT_BUF];
- int encapsulation;
-
- replace = inbound && (kernel_ops->get_spi != NULL);
-
- src.maskbits = 0;
- dst.maskbits = 0;
-
- if (inbound)
- {
- src.addr = c->spd.that.host_addr;
- dst.addr = c->spd.this.host_addr;
- src_client = c->spd.that.client;
- dst_client = c->spd.this.client;
- }
- else
- {
- src.addr = c->spd.this.host_addr,
- dst.addr = c->spd.that.host_addr;
- src_client = c->spd.this.client;
- dst_client = c->spd.that.client;
- }
-
- encapsulation = ENCAPSULATION_MODE_TRANSPORT;
- if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- encapsulation = ENCAPSULATION_MODE_TUNNEL;
- }
-
- memset(said, 0, sizeof(said));
-
- /* If we are tunnelling, set up IP in IP pseudo SA */
-
- if (kernel_ops->inbound_eroute)
- {
- inner_spi = 256;
- proto = SA_IPIP;
- satype = SADB_SATYPE_UNSPEC;
- }
- else if (encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- /* XXX hack alert -- we SHOULD NOT HAVE TO HAVE A DIFFERENT SPI
- * XXX FOR IP-in-IP ENCAPSULATION!
- */
+ /* Build an inbound or outbound SA */
- ipsec_spi_t ipip_spi;
+ struct connection *c = st->st_connection;
+ ip_subnet src, dst;
+ ip_subnet src_client, dst_client;
+ ipsec_spi_t inner_spi = 0;
+ u_int proto = 0;
+ u_int satype = SADB_SATYPE_UNSPEC;
+ bool replace;
- /* Allocate an SPI for the tunnel.
- * Since our peer will never see this,
- * and it comes from its own number space,
- * it is purely a local implementation wart.
- */
+ /* SPIs, saved for spigrouping or undoing, if necessary */
+ struct kernel_sa
+ said[EM_MAXRELSPIS],
+ *said_next = said;
+
+ char text_said[SATOT_BUF];
+ int encapsulation;
+
+ replace = inbound && (kernel_ops->get_spi != NULL);
+
+ src.maskbits = 0;
+ dst.maskbits = 0;
+
+ if (inbound)
+ {
+ src.addr = c->spd.that.host_addr;
+ dst.addr = c->spd.this.host_addr;
+ src_client = c->spd.that.client;
+ dst_client = c->spd.this.client;
+ }
+ else
{
- static ipsec_spi_t last_tunnel_spi = IPSEC_DOI_SPI_OUR_MIN;
+ src.addr = c->spd.this.host_addr,
+ dst.addr = c->spd.that.host_addr;
+ src_client = c->spd.this.client;
+ dst_client = c->spd.that.client;
+ }
- ipip_spi = htonl(++last_tunnel_spi);
- if (inbound)
- st->st_tunnel_in_spi = ipip_spi;
- else
- st->st_tunnel_out_spi = ipip_spi;
+ encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ {
+ encapsulation = ENCAPSULATION_MODE_TUNNEL;
}
- set_text_said(text_said
- , &c->spd.that.host_addr, ipip_spi, SA_IPIP);
+ memset(said, 0, sizeof(said));
- said_next->src = &src.addr;
- said_next->dst = &dst.addr;
- said_next->src_client = &src_client;
- said_next->dst_client = &dst_client;
- said_next->spi = ipip_spi;
- said_next->satype = SADB_X_SATYPE_IPIP;
- said_next->text_said = text_said;
+ /* If we are tunnelling, set up IP in IP pseudo SA */
- if (!kernel_ops->add_sa(said_next, replace))
- goto fail;
+ if (kernel_ops->inbound_eroute)
+ {
+ inner_spi = 256;
+ proto = SA_IPIP;
+ satype = SADB_SATYPE_UNSPEC;
+ }
+ else if (encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ {
+ /* XXX hack alert -- we SHOULD NOT HAVE TO HAVE A DIFFERENT SPI
+ * XXX FOR IP-in-IP ENCAPSULATION!
+ */
- said_next++;
+ ipsec_spi_t ipip_spi;
- inner_spi = ipip_spi;
- proto = SA_IPIP;
- satype = SADB_X_SATYPE_IPIP;
- }
+ /* Allocate an SPI for the tunnel.
+ * Since our peer will never see this,
+ * and it comes from its own number space,
+ * it is purely a local implementation wart.
+ */
+ {
+ static ipsec_spi_t last_tunnel_spi = IPSEC_DOI_SPI_OUR_MIN;
- /* set up IPCOMP SA, if any */
+ ipip_spi = htonl(++last_tunnel_spi);
+ if (inbound)
+ st->st_tunnel_in_spi = ipip_spi;
+ else
+ st->st_tunnel_out_spi = ipip_spi;
+ }
- if (st->st_ipcomp.present)
- {
- ipsec_spi_t ipcomp_spi = inbound? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi;
- unsigned compalg;
+ set_text_said(text_said
+ , &c->spd.that.host_addr, ipip_spi, SA_IPIP);
- switch (st->st_ipcomp.attrs.transid)
- {
- case IPCOMP_DEFLATE:
- compalg = SADB_X_CALG_DEFLATE;
- break;
+ said_next->src = &src.addr;
+ said_next->dst = &dst.addr;
+ said_next->src_client = &src_client;
+ said_next->dst_client = &dst_client;
+ said_next->spi = ipip_spi;
+ said_next->satype = SADB_X_SATYPE_IPIP;
+ said_next->text_said = text_said;
- default:
- loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented"
- , enum_name(&ipcomp_transformid_names, st->st_ipcomp.attrs.transid));
- goto fail;
- }
+ if (!kernel_ops->add_sa(said_next, replace))
+ goto fail;
- set_text_said(text_said, &dst.addr, ipcomp_spi, SA_COMP);
+ said_next++;
- said_next->src = &src.addr;
- said_next->dst = &dst.addr;
- said_next->src_client = &src_client;
- said_next->dst_client = &dst_client;
- said_next->spi = ipcomp_spi;
- said_next->satype = SADB_X_SATYPE_COMP;
- said_next->compalg = compalg;
- said_next->encapsulation = encapsulation;
- said_next->reqid = c->spd.reqid + 2;
- said_next->text_said = text_said;
+ inner_spi = ipip_spi;
+ proto = SA_IPIP;
+ satype = SADB_X_SATYPE_IPIP;
+ }
- if (!kernel_ops->add_sa(said_next, replace))
- goto fail;
+ /* set up IPCOMP SA, if any */
- said_next++;
+ if (st->st_ipcomp.present)
+ {
+ ipsec_spi_t ipcomp_spi = inbound? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi;
+ unsigned compalg;
- encapsulation = ENCAPSULATION_MODE_TRANSPORT;
- }
+ switch (st->st_ipcomp.attrs.transid)
+ {
+ case IPCOMP_DEFLATE:
+ compalg = SADB_X_CALG_DEFLATE;
+ break;
+
+ default:
+ loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented"
+ , enum_name(&ipcomp_transformid_names, st->st_ipcomp.attrs.transid));
+ goto fail;
+ }
- /* set up ESP SA, if any */
+ set_text_said(text_said, &dst.addr, ipcomp_spi, SA_COMP);
- if (st->st_esp.present)
- {
- ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi;
- u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat;
- const struct esp_info *ei;
- u_int16_t key_len;
-
- static const struct esp_info esp_info[] = {
- { ESP_NULL, AUTH_ALGORITHM_HMAC_MD5,
- 0, HMAC_MD5_KEY_LEN,
- SADB_EALG_NULL, SADB_AALG_MD5HMAC },
- { ESP_NULL, AUTH_ALGORITHM_HMAC_SHA1,
- 0, HMAC_SHA1_KEY_LEN,
- SADB_EALG_NULL, SADB_AALG_SHA1HMAC },
-
- { ESP_DES, AUTH_ALGORITHM_NONE,
- DES_CBC_BLOCK_SIZE, 0,
- SADB_EALG_DESCBC, SADB_AALG_NONE },
- { ESP_DES, AUTH_ALGORITHM_HMAC_MD5,
- DES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN,
- SADB_EALG_DESCBC, SADB_AALG_MD5HMAC },
- { ESP_DES, AUTH_ALGORITHM_HMAC_SHA1,
- DES_CBC_BLOCK_SIZE,
- HMAC_SHA1_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_SHA1HMAC },
-
- { ESP_3DES, AUTH_ALGORITHM_NONE,
- DES_CBC_BLOCK_SIZE * 3, 0,
- SADB_EALG_3DESCBC, SADB_AALG_NONE },
- { ESP_3DES, AUTH_ALGORITHM_HMAC_MD5,
- DES_CBC_BLOCK_SIZE * 3, HMAC_MD5_KEY_LEN,
- SADB_EALG_3DESCBC, SADB_AALG_MD5HMAC },
- { ESP_3DES, AUTH_ALGORITHM_HMAC_SHA1,
- DES_CBC_BLOCK_SIZE * 3, HMAC_SHA1_KEY_LEN,
- SADB_EALG_3DESCBC, SADB_AALG_SHA1HMAC },
- };
+ said_next->src = &src.addr;
+ said_next->dst = &dst.addr;
+ said_next->src_client = &src_client;
+ said_next->dst_client = &dst_client;
+ said_next->spi = ipcomp_spi;
+ said_next->satype = SADB_X_SATYPE_COMP;
+ said_next->compalg = compalg;
+ said_next->encapsulation = encapsulation;
+ said_next->reqid = c->spd.reqid + 2;
+ said_next->text_said = text_said;
- u_int8_t natt_type = 0;
- u_int16_t natt_sport = 0;
- u_int16_t natt_dport = 0;
- ip_address natt_oa;
+ if (!kernel_ops->add_sa(said_next, replace))
+ goto fail;
- if (st->nat_traversal & NAT_T_DETECTED)
- {
- natt_type = (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) ?
- ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE;
- natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port;
- natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port;
- natt_oa = st->nat_oa;
+ said_next++;
+
+ encapsulation = ENCAPSULATION_MODE_TRANSPORT;
}
- for (ei = esp_info; ; ei++)
+ /* set up ESP SA, if any */
+
+ if (st->st_esp.present)
{
- if (ei == &esp_info[elemsof(esp_info)])
- {
- /* Check for additional kernel alg */
-#ifndef NO_KERNEL_ALG
- if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid,
- st->st_esp.attrs.auth))!=NULL) {
- break;
+ ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi;
+ u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat;
+ const struct esp_info *ei;
+ u_int16_t key_len;
+
+ static const struct esp_info esp_info[] = {
+ { ESP_NULL, AUTH_ALGORITHM_HMAC_MD5,
+ 0, HMAC_MD5_KEY_LEN,
+ SADB_EALG_NULL, SADB_AALG_MD5HMAC },
+ { ESP_NULL, AUTH_ALGORITHM_HMAC_SHA1,
+ 0, HMAC_SHA1_KEY_LEN,
+ SADB_EALG_NULL, SADB_AALG_SHA1HMAC },
+
+ { ESP_DES, AUTH_ALGORITHM_NONE,
+ DES_CBC_BLOCK_SIZE, 0,
+ SADB_EALG_DESCBC, SADB_AALG_NONE },
+ { ESP_DES, AUTH_ALGORITHM_HMAC_MD5,
+ DES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN,
+ SADB_EALG_DESCBC, SADB_AALG_MD5HMAC },
+ { ESP_DES, AUTH_ALGORITHM_HMAC_SHA1,
+ DES_CBC_BLOCK_SIZE,
+ HMAC_SHA1_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_SHA1HMAC },
+
+ { ESP_3DES, AUTH_ALGORITHM_NONE,
+ DES_CBC_BLOCK_SIZE * 3, 0,
+ SADB_EALG_3DESCBC, SADB_AALG_NONE },
+ { ESP_3DES, AUTH_ALGORITHM_HMAC_MD5,
+ DES_CBC_BLOCK_SIZE * 3, HMAC_MD5_KEY_LEN,
+ SADB_EALG_3DESCBC, SADB_AALG_MD5HMAC },
+ { ESP_3DES, AUTH_ALGORITHM_HMAC_SHA1,
+ DES_CBC_BLOCK_SIZE * 3, HMAC_SHA1_KEY_LEN,
+ SADB_EALG_3DESCBC, SADB_AALG_SHA1HMAC },
+ };
+
+ u_int8_t natt_type = 0;
+ u_int16_t natt_sport = 0;
+ u_int16_t natt_dport = 0;
+ ip_address natt_oa;
+
+ if (st->nat_traversal & NAT_T_DETECTED)
+ {
+ natt_type = (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) ?
+ ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE;
+ natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port;
+ natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port;
+ natt_oa = st->nat_oa;
}
-#endif
- /* note: enum_show may use a static buffer, so two
- * calls in one printf would be a mistake.
- * enum_name does the same job, without a static buffer,
- * assuming the name will be found.
- */
- loglog(RC_LOG_SERIOUS, "ESP transform %s / auth %s not implemented yet"
- , enum_name(&esp_transformid_names, st->st_esp.attrs.transid)
- , enum_name(&auth_alg_names, st->st_esp.attrs.auth));
- goto fail;
- }
-
- if (st->st_esp.attrs.transid == ei->transid
- && st->st_esp.attrs.auth == ei->auth)
- break;
- }
+ for (ei = esp_info; ; ei++)
+ {
+ if (ei == &esp_info[countof(esp_info)])
+ {
+ /* Check for additional kernel alg */
+#ifndef NO_KERNEL_ALG
+ if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid,
+ st->st_esp.attrs.auth))!=NULL) {
+ break;
+ }
+#endif
- key_len = st->st_esp.attrs.key_len/8;
- if (key_len)
- {
- /* XXX: must change to check valid _range_ key_len */
- if (key_len > ei->enckeylen)
- {
- loglog(RC_LOG_SERIOUS, "ESP transform %s passed key_len=%d > %d",
- enum_name(&esp_transformid_names, st->st_esp.attrs.transid),
- (int)key_len, (int)ei->enckeylen);
- goto fail;
- }
- }
- else
- {
- key_len = ei->enckeylen;
- }
- /* Grrrrr.... f*cking 7 bits jurassic algos */
+ /* note: enum_show may use a static buffer, so two
+ * calls in one printf would be a mistake.
+ * enum_name does the same job, without a static buffer,
+ * assuming the name will be found.
+ */
+ loglog(RC_LOG_SERIOUS, "ESP transform %s / auth %s not implemented yet"
+ , enum_name(&esp_transformid_names, st->st_esp.attrs.transid)
+ , enum_name(&auth_alg_names, st->st_esp.attrs.auth));
+ goto fail;
+ }
- /* 168 bits in kernel, need 192 bits for keymat_len */
- if (ei->transid == ESP_3DES && key_len == 21)
- key_len = 24;
+ if (st->st_esp.attrs.transid == ei->transid
+ && st->st_esp.attrs.auth == ei->auth)
+ break;
+ }
- /* 56 bits in kernel, need 64 bits for keymat_len */
- if (ei->transid == ESP_DES && key_len == 7)
- key_len = 8;
+ key_len = st->st_esp.attrs.key_len/8;
+ if (key_len)
+ {
+ /* XXX: must change to check valid _range_ key_len */
+ if (key_len > ei->enckeylen)
+ {
+ loglog(RC_LOG_SERIOUS, "ESP transform %s passed key_len=%d > %d",
+ enum_name(&esp_transformid_names, st->st_esp.attrs.transid),
+ (int)key_len, (int)ei->enckeylen);
+ goto fail;
+ }
+ }
+ else
+ {
+ key_len = ei->enckeylen;
+ }
+ /* Grrrrr.... f*cking 7 bits jurassic algos */
+
+ /* 168 bits in kernel, need 192 bits for keymat_len */
+ if (ei->transid == ESP_3DES && key_len == 21)
+ key_len = 24;
+
+ /* 56 bits in kernel, need 64 bits for keymat_len */
+ if (ei->transid == ESP_DES && key_len == 7)
+ key_len = 8;
+
+ /* divide up keying material */
+ /* passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen); */
+ DBG(DBG_KLIPS|DBG_CONTROL|DBG_PARSING,
+ if(st->st_esp.keymat_len != key_len + ei->authkeylen)
+ DBG_log("keymat_len=%d key_len=%d authkeylen=%d",
+ st->st_esp.keymat_len, (int)key_len, (int)ei->authkeylen);
+ )
+ passert(st->st_esp.keymat_len == key_len + ei->authkeylen);
+
+ set_text_said(text_said, &dst.addr, esp_spi, SA_ESP);
+
+ said_next->src = &src.addr;
+ said_next->dst = &dst.addr;
+ said_next->src_client = &src_client;
+ said_next->dst_client = &dst_client;
+ said_next->spi = esp_spi;
+ said_next->satype = SADB_SATYPE_ESP;
+ said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM;
+ said_next->authalg = ei->authalg;
+ said_next->authkeylen = ei->authkeylen;
+ /* said_next->authkey = esp_dst_keymat + ei->enckeylen; */
+ said_next->authkey = esp_dst_keymat + key_len;
+ said_next->encalg = ei->encryptalg;
+ /* said_next->enckeylen = ei->enckeylen; */
+ said_next->enckeylen = key_len;
+ said_next->enckey = esp_dst_keymat;
+ said_next->encapsulation = encapsulation;
+ said_next->reqid = c->spd.reqid + 1;
+ said_next->natt_sport = natt_sport;
+ said_next->natt_dport = natt_dport;
+ said_next->transid = st->st_esp.attrs.transid;
+ said_next->natt_type = natt_type;
+ said_next->natt_oa = &natt_oa;
+ said_next->text_said = text_said;
+
+ if (!kernel_ops->add_sa(said_next, replace))
+ goto fail;
+
+ said_next++;
+
+ encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ }
- /* divide up keying material */
- /* passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen); */
- DBG(DBG_KLIPS|DBG_CONTROL|DBG_PARSING,
- if(st->st_esp.keymat_len != key_len + ei->authkeylen)
- DBG_log("keymat_len=%d key_len=%d authkeylen=%d",
- st->st_esp.keymat_len, (int)key_len, (int)ei->authkeylen);
- )
- passert(st->st_esp.keymat_len == key_len + ei->authkeylen);
-
- set_text_said(text_said, &dst.addr, esp_spi, SA_ESP);
-
- said_next->src = &src.addr;
- said_next->dst = &dst.addr;
- said_next->src_client = &src_client;
- said_next->dst_client = &dst_client;
- said_next->spi = esp_spi;
- said_next->satype = SADB_SATYPE_ESP;
- said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM;
- said_next->authalg = ei->authalg;
- said_next->authkeylen = ei->authkeylen;
- /* said_next->authkey = esp_dst_keymat + ei->enckeylen; */
- said_next->authkey = esp_dst_keymat + key_len;
- said_next->encalg = ei->encryptalg;
- /* said_next->enckeylen = ei->enckeylen; */
- said_next->enckeylen = key_len;
- said_next->enckey = esp_dst_keymat;
- said_next->encapsulation = encapsulation;
- said_next->reqid = c->spd.reqid + 1;
- said_next->natt_sport = natt_sport;
- said_next->natt_dport = natt_dport;
- said_next->transid = st->st_esp.attrs.transid;
- said_next->natt_type = natt_type;
- said_next->natt_oa = &natt_oa;
- said_next->text_said = text_said;
-
- if (!kernel_ops->add_sa(said_next, replace))
- goto fail;
-
- said_next++;
+ /* set up AH SA, if any */
- encapsulation = ENCAPSULATION_MODE_TRANSPORT;
- }
+ if (st->st_ah.present)
+ {
+ ipsec_spi_t ah_spi = inbound? st->st_ah.our_spi : st->st_ah.attrs.spi;
+ u_char *ah_dst_keymat = inbound? st->st_ah.our_keymat : st->st_ah.peer_keymat;
- /* set up AH SA, if any */
+ unsigned char authalg;
- if (st->st_ah.present)
- {
- ipsec_spi_t ah_spi = inbound? st->st_ah.our_spi : st->st_ah.attrs.spi;
- u_char *ah_dst_keymat = inbound? st->st_ah.our_keymat : st->st_ah.peer_keymat;
+ switch (st->st_ah.attrs.auth)
+ {
+ case AUTH_ALGORITHM_HMAC_MD5:
+ authalg = SADB_AALG_MD5HMAC;
+ break;
- unsigned char authalg;
+ case AUTH_ALGORITHM_HMAC_SHA1:
+ authalg = SADB_AALG_SHA1HMAC;
+ break;
- switch (st->st_ah.attrs.auth)
- {
- case AUTH_ALGORITHM_HMAC_MD5:
- authalg = SADB_AALG_MD5HMAC;
- break;
+ default:
+ loglog(RC_LOG_SERIOUS, "%s not implemented yet"
+ , enum_show(&auth_alg_names, st->st_ah.attrs.auth));
+ goto fail;
+ }
- case AUTH_ALGORITHM_HMAC_SHA1:
- authalg = SADB_AALG_SHA1HMAC;
- break;
+ set_text_said(text_said, &dst.addr, ah_spi, SA_AH);
- default:
- loglog(RC_LOG_SERIOUS, "%s not implemented yet"
- , enum_show(&auth_alg_names, st->st_ah.attrs.auth));
- goto fail;
- }
+ said_next->src = &src.addr;
+ said_next->dst = &dst.addr;
+ said_next->src_client = &src_client;
+ said_next->dst_client = &dst_client;
+ said_next->spi = ah_spi;
+ said_next->satype = SADB_SATYPE_AH;
+ said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM;
+ said_next->authalg = authalg;
+ said_next->authkeylen = st->st_ah.keymat_len;
+ said_next->authkey = ah_dst_keymat;
+ said_next->encapsulation = encapsulation;
+ said_next->reqid = c->spd.reqid;
+ said_next->text_said = text_said;
- set_text_said(text_said, &dst.addr, ah_spi, SA_AH);
+ if (!kernel_ops->add_sa(said_next, replace))
+ goto fail;
- said_next->src = &src.addr;
- said_next->dst = &dst.addr;
- said_next->src_client = &src_client;
- said_next->dst_client = &dst_client;
- said_next->spi = ah_spi;
- said_next->satype = SADB_SATYPE_AH;
- said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM;
- said_next->authalg = authalg;
- said_next->authkeylen = st->st_ah.keymat_len;
- said_next->authkey = ah_dst_keymat;
- said_next->encapsulation = encapsulation;
- said_next->reqid = c->spd.reqid;
- said_next->text_said = text_said;
+ said_next++;
- if (!kernel_ops->add_sa(said_next, replace))
- goto fail;
+ encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ }
- said_next++;
+ if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ {
+ encapsulation = ENCAPSULATION_MODE_TUNNEL;
+ }
- encapsulation = ENCAPSULATION_MODE_TRANSPORT;
- }
-
- if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- encapsulation = ENCAPSULATION_MODE_TUNNEL;
- }
-
- if (kernel_ops->inbound_eroute ? c->spd.eroute_owner == SOS_NOBODY
- : encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- /* If inbound, and policy does not specifie DISABLEARRIVALCHECK,
- * tell KLIPS to enforce the IP addresses appropriate for this tunnel.
- * Note reversed ends.
- * Not much to be done on failure.
- */
- if (inbound && (c->policy & POLICY_DISABLEARRIVALCHECK) == 0)
+ if (kernel_ops->inbound_eroute ? c->spd.eroute_owner == SOS_NOBODY
+ : encapsulation == ENCAPSULATION_MODE_TUNNEL)
{
- struct pfkey_proto_info proto_info[4];
- int i = 0;
-
- if (st->st_ipcomp.present)
- {
- proto_info[i].proto = IPPROTO_COMP;
- proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation;
- proto_info[i].reqid = c->spd.reqid + 2;
- i++;
- }
-
- if (st->st_esp.present)
- {
- proto_info[i].proto = IPPROTO_ESP;
- proto_info[i].encapsulation = st->st_esp.attrs.encapsulation;
- proto_info[i].reqid = c->spd.reqid + 1;
- i++;
- }
-
- if (st->st_ah.present)
- {
- proto_info[i].proto = IPPROTO_AH;
- proto_info[i].encapsulation = st->st_ah.attrs.encapsulation;
- proto_info[i].reqid = c->spd.reqid;
- i++;
- }
-
- proto_info[i].proto = 0;
-
- if (kernel_ops->inbound_eroute
- && encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- proto_info[0].encapsulation = ENCAPSULATION_MODE_TUNNEL;
- for (i = 1; proto_info[i].proto; i++)
+ /* If inbound, and policy does not specifie DISABLEARRIVALCHECK,
+ * tell KLIPS to enforce the IP addresses appropriate for this tunnel.
+ * Note reversed ends.
+ * Not much to be done on failure.
+ */
+ if (inbound && (c->policy & POLICY_DISABLEARRIVALCHECK) == 0)
{
- proto_info[i].encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ struct pfkey_proto_info proto_info[4];
+ int i = 0;
+
+ if (st->st_ipcomp.present)
+ {
+ proto_info[i].proto = IPPROTO_COMP;
+ proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation;
+ proto_info[i].reqid = c->spd.reqid + 2;
+ i++;
+ }
+
+ if (st->st_esp.present)
+ {
+ proto_info[i].proto = IPPROTO_ESP;
+ proto_info[i].encapsulation = st->st_esp.attrs.encapsulation;
+ proto_info[i].reqid = c->spd.reqid + 1;
+ i++;
+ }
+
+ if (st->st_ah.present)
+ {
+ proto_info[i].proto = IPPROTO_AH;
+ proto_info[i].encapsulation = st->st_ah.attrs.encapsulation;
+ proto_info[i].reqid = c->spd.reqid;
+ i++;
+ }
+
+ proto_info[i].proto = 0;
+
+ if (kernel_ops->inbound_eroute
+ && encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ {
+ proto_info[0].encapsulation = ENCAPSULATION_MODE_TUNNEL;
+ for (i = 1; proto_info[i].proto; i++)
+ {
+ proto_info[i].encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ }
+ }
+
+ /* MCR - should be passed a spd_eroute structure here */
+ (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
+ , &c->spd.this.host_addr, &c->spd.this.client
+ , inner_spi, proto, satype, c->spd.this.protocol
+ , proto_info, 0
+ , ERO_ADD_INBOUND, "add inbound");
}
- }
-
- /* MCR - should be passed a spd_eroute structure here */
- (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
- , &c->spd.this.host_addr, &c->spd.this.client
- , inner_spi, proto, satype, c->spd.this.protocol
- , proto_info, 0
- , ERO_ADD_INBOUND, "add inbound");
- }
- }
-
- /* If there are multiple SPIs, group them. */
-
- if (kernel_ops->grp_sa && said_next > &said[1])
- {
- struct kernel_sa *s;
+ }
+
+ /* If there are multiple SPIs, group them. */
- /* group SAs, two at a time, inner to outer (backwards in said[])
- * The grouping is by pairs. So if said[] contains ah esp ipip,
- * the grouping would be ipip:esp, esp:ah.
- */
- for (s = said; s < said_next-1; s++)
- {
- char
- text_said0[SATOT_BUF],
- text_said1[SATOT_BUF];
-
- /* group s[1] and s[0], in that order */
-
- set_text_said(text_said0, s[0].dst, s[0].spi, s[0].proto);
- set_text_said(text_said1, s[1].dst, s[1].spi, s[1].proto);
-
- DBG(DBG_KLIPS, DBG_log("grouping %s and %s", text_said1, text_said0));
-
- s[0].text_said = text_said0;
- s[1].text_said = text_said1;
-
- if (!kernel_ops->grp_sa(s + 1, s))
- goto fail;
- }
- /* could update said, but it will not be used */
- }
-
- return TRUE;
+ if (kernel_ops->grp_sa && said_next > &said[1])
+ {
+ struct kernel_sa *s;
+
+ /* group SAs, two at a time, inner to outer (backwards in said[])
+ * The grouping is by pairs. So if said[] contains ah esp ipip,
+ * the grouping would be ipip:esp, esp:ah.
+ */
+ for (s = said; s < said_next-1; s++)
+ {
+ char
+ text_said0[SATOT_BUF],
+ text_said1[SATOT_BUF];
+
+ /* group s[1] and s[0], in that order */
+
+ set_text_said(text_said0, s[0].dst, s[0].spi, s[0].proto);
+ set_text_said(text_said1, s[1].dst, s[1].spi, s[1].proto);
+
+ DBG(DBG_KLIPS, DBG_log("grouping %s and %s", text_said1, text_said0));
+
+ s[0].text_said = text_said0;
+ s[1].text_said = text_said1;
+
+ if (!kernel_ops->grp_sa(s + 1, s))
+ goto fail;
+ }
+ /* could update said, but it will not be used */
+ }
+
+ return TRUE;
fail:
- {
- /* undo the done SPIs */
- while (said_next-- != said)
- (void) del_spi(said_next->spi, said_next->proto
- , &src.addr, said_next->dst);
- return FALSE;
- }
+ {
+ /* undo the done SPIs */
+ while (said_next-- != said)
+ (void) del_spi(said_next->spi, said_next->proto
+ , &src.addr, said_next->dst);
+ return FALSE;
+ }
}
/* teardown_ipsec_sa is a canibalized version of setup_ipsec_sa */
-static bool
-teardown_half_ipsec_sa(struct state *st, bool inbound)
+static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
{
- /* We need to delete AH, ESP, and IP in IP SPIs.
- * But if there is more than one, they have been grouped
- * so deleting any one will do. So we just delete the
- * first one found. It may or may not be the only one.
- */
- struct connection *c = st->st_connection;
- struct {
- unsigned proto;
- struct ipsec_proto_info *info;
- } protos[4];
- int i;
- bool result;
-
- i = 0;
- if (kernel_ops->inbound_eroute && inbound
- && c->spd.eroute_owner == SOS_NOBODY)
- {
- (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
- , &c->spd.this.host_addr, &c->spd.this.client
- , 256, IPSEC_PROTO_ANY, SADB_SATYPE_UNSPEC, c->spd.this.protocol
- , null_proto_info, 0
- , ERO_DEL_INBOUND, "delete inbound");
- }
-
- if (!kernel_ops->grp_sa)
- {
- if (st->st_ah.present)
+ /* We need to delete AH, ESP, and IP in IP SPIs.
+ * But if there is more than one, they have been grouped
+ * so deleting any one will do. So we just delete the
+ * first one found. It may or may not be the only one.
+ */
+ struct connection *c = st->st_connection;
+ struct {
+ unsigned proto;
+ struct ipsec_proto_info *info;
+ } protos[4];
+ int i;
+ bool result;
+
+ i = 0;
+ if (kernel_ops->inbound_eroute && inbound
+ && c->spd.eroute_owner == SOS_NOBODY)
{
- protos[i].info = &st->st_ah;
- protos[i].proto = SA_AH;
- i++;
+ (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
+ , &c->spd.this.host_addr, &c->spd.this.client
+ , 256, IPSEC_PROTO_ANY, SADB_SATYPE_UNSPEC, c->spd.this.protocol
+ , null_proto_info, 0
+ , ERO_DEL_INBOUND, "delete inbound");
}
- if (st->st_esp.present)
+ if (!kernel_ops->grp_sa)
{
- protos[i].info = &st->st_esp;
- protos[i].proto = SA_ESP;
- i++;
- }
+ if (st->st_ah.present)
+ {
+ protos[i].info = &st->st_ah;
+ protos[i].proto = SA_AH;
+ i++;
+ }
- if (st->st_ipcomp.present)
- {
- protos[i].info = &st->st_ipcomp;
- protos[i].proto = SA_COMP;
- i++;
- }
- }
- else if (st->st_ah.present)
- {
- protos[i].info = &st->st_ah;
- protos[i].proto = SA_AH;
- i++;
- }
- else if (st->st_esp.present)
- {
- protos[i].info = &st->st_esp;
- protos[i].proto = SA_ESP;
- i++;
- }
- else
- {
- impossible(); /* neither AH nor ESP in outbound SA bundle! */
- }
- protos[i].proto = 0;
-
- result = TRUE;
- for (i = 0; protos[i].proto; i++)
- {
- unsigned proto = protos[i].proto;
- ipsec_spi_t spi;
- const ip_address *src, *dst;
+ if (st->st_esp.present)
+ {
+ protos[i].info = &st->st_esp;
+ protos[i].proto = SA_ESP;
+ i++;
+ }
- if (inbound)
+ if (st->st_ipcomp.present)
+ {
+ protos[i].info = &st->st_ipcomp;
+ protos[i].proto = SA_COMP;
+ i++;
+ }
+ }
+ else if (st->st_ah.present)
+ {
+ protos[i].info = &st->st_ah;
+ protos[i].proto = SA_AH;
+ i++;
+ }
+ else if (st->st_esp.present)
{
- spi = protos[i].info->our_spi;
- src = &c->spd.that.host_addr;
- dst = &c->spd.this.host_addr;
+ protos[i].info = &st->st_esp;
+ protos[i].proto = SA_ESP;
+ i++;
}
else
{
- spi = protos[i].info->attrs.spi;
- src = &c->spd.this.host_addr;
- dst = &c->spd.that.host_addr;
+ impossible(); /* neither AH nor ESP in outbound SA bundle! */
}
+ protos[i].proto = 0;
+
+ result = TRUE;
+ for (i = 0; protos[i].proto; i++)
+ {
+ unsigned proto = protos[i].proto;
+ ipsec_spi_t spi;
+ const ip_address *src, *dst;
+
+ if (inbound)
+ {
+ spi = protos[i].info->our_spi;
+ src = &c->spd.that.host_addr;
+ dst = &c->spd.this.host_addr;
+ }
+ else
+ {
+ spi = protos[i].info->attrs.spi;
+ src = &c->spd.this.host_addr;
+ dst = &c->spd.that.host_addr;
+ }
- result &= del_spi(spi, proto, src, dst);
- }
- return result;
+ result &= del_spi(spi, proto, src, dst);
+ }
+ return result;
}
/*
* get information about a given sa
*/
-bool
-get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
+bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
{
- char text_said[SATOT_BUF];
- struct kernel_sa sa;
- struct connection *c = st->st_connection;
+ char text_said[SATOT_BUF];
+ struct kernel_sa sa;
+ struct connection *c = st->st_connection;
- *use_time = UNDEFINED_TIME;
+ *use_time = UNDEFINED_TIME;
- if (kernel_ops->get_sa == NULL || !st->st_esp.present)
- return FALSE;
+ if (kernel_ops->get_sa == NULL || !st->st_esp.present)
+ return FALSE;
- memset(&sa, 0, sizeof(sa));
- sa.proto = SA_ESP;
-
- if (inbound)
- {
- sa.src = &c->spd.that.host_addr;
- sa.dst = &c->spd.this.host_addr;
- sa.spi = st->st_esp.our_spi;
- }
- else
- {
- sa.src = &c->spd.this.host_addr;
- sa.dst = &c->spd.that.host_addr;
- sa.spi = st->st_esp.attrs.spi;
- }
- set_text_said(text_said, sa.dst, sa.spi, sa.proto);
-
- sa.text_said = text_said;
-
- DBG(DBG_KLIPS,
- DBG_log("get %s", text_said)
- )
- if (!kernel_ops->get_sa(&sa, bytes))
- return FALSE;
- DBG(DBG_KLIPS,
- DBG_log(" current: %d bytes", *bytes)
- )
-
- if (st->st_serialno == c->spd.eroute_owner)
- {
- DBG(DBG_KLIPS,
- DBG_log("get %sbound policy with reqid %u"
- , inbound? "in":"out", (u_int)c->spd.reqid + 1)
- )
- sa.transport_proto = c->spd.this.protocol;
- sa.encapsulation = st->st_esp.attrs.encapsulation;
+ memset(&sa, 0, sizeof(sa));
+ sa.proto = SA_ESP;
if (inbound)
{
- sa.src_client = &c->spd.that.client;
- sa.dst_client = &c->spd.this.client;
+ sa.src = &c->spd.that.host_addr;
+ sa.dst = &c->spd.this.host_addr;
+ sa.spi = st->st_esp.our_spi;
}
else
{
- sa.src_client = &c->spd.this.client;
- sa.dst_client = &c->spd.that.client;
+ sa.src = &c->spd.this.host_addr;
+ sa.dst = &c->spd.that.host_addr;
+ sa.spi = st->st_esp.attrs.spi;
}
- if (!kernel_ops->get_policy(&sa, inbound, use_time))
- return FALSE;
+ set_text_said(text_said, sa.dst, sa.spi, sa.proto);
+
+ sa.text_said = text_said;
+
+ DBG(DBG_KLIPS,
+ DBG_log("get %s", text_said)
+ )
+ if (!kernel_ops->get_sa(&sa, bytes))
+ return FALSE;
DBG(DBG_KLIPS,
- DBG_log(" use_time: %s", timetoa(use_time, FALSE))
+ DBG_log(" current: %d bytes", *bytes)
)
- }
- return TRUE;
+
+ if (st->st_serialno == c->spd.eroute_owner)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("get %sbound policy with reqid %u"
+ , inbound? "in":"out", (u_int)c->spd.reqid + 1)
+ )
+ sa.transport_proto = c->spd.this.protocol;
+ sa.encapsulation = st->st_esp.attrs.encapsulation;
+
+ if (inbound)
+ {
+ sa.src_client = &c->spd.that.client;
+ sa.dst_client = &c->spd.this.client;
+ }
+ else
+ {
+ sa.src_client = &c->spd.this.client;
+ sa.dst_client = &c->spd.that.client;
+ }
+ if (!kernel_ops->get_policy(&sa, inbound, use_time))
+ return FALSE;
+ DBG(DBG_KLIPS,
+ DBG_log(" use_time: %T", use_time, FALSE)
+ )
+ }
+ return TRUE;
}
const struct kernel_ops *kernel_ops;
#endif /* KLIPS */
-void
-init_kernel(void)
+void init_kernel(void)
{
#ifdef KLIPS
- if (no_klips)
- {
- kernel_ops = &noklips_kernel_ops;
- return;
- }
+ if (no_klips)
+ {
+ kernel_ops = &noklips_kernel_ops;
+ return;
+ }
- init_pfkey();
+ init_pfkey();
- kernel_ops = &klips_kernel_ops;
+ kernel_ops = &klips_kernel_ops;
#if defined(linux) && defined(KERNEL26_SUPPORT)
- {
- bool linux_ipsec = 0;
- struct stat buf;
-
- linux_ipsec = (stat("/proc/net/pfkey", &buf) == 0);
- if (linux_ipsec)
- {
- plog("Using Linux 2.6 IPsec interface code");
- kernel_ops = &linux_kernel_ops;
- }
- else
- {
- plog("Using KLIPS IPsec interface code");
- }
- }
+ {
+ bool linux_ipsec = 0;
+ struct stat buf;
+
+ linux_ipsec = (stat("/proc/net/pfkey", &buf) == 0);
+ if (linux_ipsec)
+ {
+ plog("Using Linux 2.6 IPsec interface code");
+ kernel_ops = &linux_kernel_ops;
+ }
+ else
+ {
+ plog("Using KLIPS IPsec interface code");
+ }
+ }
#endif
- if (kernel_ops->init)
- {
- kernel_ops->init();
- }
+ if (kernel_ops->init)
+ {
+ kernel_ops->init();
+ }
- /* register SA types that we can negotiate */
- can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
- kernel_ops->pfkey_register();
+ /* register SA types that we can negotiate */
+ can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
+ kernel_ops->pfkey_register();
- if (!kernel_ops->policy_lifetime)
- {
- event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
- }
+ if (!kernel_ops->policy_lifetime)
+ {
+ event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
+ }
#endif
}
@@ -2345,60 +2330,59 @@ init_kernel(void)
* The Responder will subsequently use install_ipsec_sa for the outbound.
* The Initiator uses install_ipsec_sa to install both at once.
*/
-bool
-install_inbound_ipsec_sa(struct state *st)
+bool install_inbound_ipsec_sa(struct state *st)
{
- struct connection *const c = st->st_connection;
-
- /* If our peer has a fixed-address client, check if we already
- * have a route for that client that conflicts. We will take this
- * as proof that that route and the connections using it are
- * obsolete and should be eliminated. Interestingly, this is
- * the only case in which we can tell that a connection is obsolete.
- */
- passert(c->kind == CK_PERMANENT || c->kind == CK_INSTANCE);
- if (c->spd.that.has_client)
- {
- for (;;)
- {
- struct spd_route *esr;
- struct connection *o = route_owner(c, &esr, NULL, NULL);
-
- if (o == NULL)
- break; /* nobody has a route */
-
- /* note: we ignore the client addresses at this end */
- if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr)
- && o->interface == c->interface)
- break; /* existing route is compatible */
-
- if (o->kind == CK_TEMPLATE && streq(o->name, c->name))
- break; /* ??? is this good enough?? */
-
- loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route"
- , o->name, ip_str(&o->spd.that.host_addr));
- release_connection(o, FALSE);
- }
- }
-
- DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa() checking if we can route"));
- /* check that we will be able to route and eroute */
- switch (could_route(c))
- {
- case route_easy:
- case route_nearconflict:
- break;
-
- default:
- return FALSE;
- }
+ struct connection *const c = st->st_connection;
+
+ /* If our peer has a fixed-address client, check if we already
+ * have a route for that client that conflicts. We will take this
+ * as proof that that route and the connections using it are
+ * obsolete and should be eliminated. Interestingly, this is
+ * the only case in which we can tell that a connection is obsolete.
+ */
+ passert(c->kind == CK_PERMANENT || c->kind == CK_INSTANCE);
+ if (c->spd.that.has_client)
+ {
+ for (;;)
+ {
+ struct spd_route *esr;
+ struct connection *o = route_owner(c, &esr, NULL, NULL);
+
+ if (o == NULL)
+ break; /* nobody has a route */
+
+ /* note: we ignore the client addresses at this end */
+ if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr)
+ && o->interface == c->interface)
+ break; /* existing route is compatible */
+
+ if (o->kind == CK_TEMPLATE && streq(o->name, c->name))
+ break; /* ??? is this good enough?? */
+
+ loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route"
+ , o->name, ip_str(&o->spd.that.host_addr));
+ release_connection(o, FALSE);
+ }
+ }
+
+ DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa() checking if we can route"));
+ /* check that we will be able to route and eroute */
+ switch (could_route(c))
+ {
+ case route_easy:
+ case route_nearconflict:
+ break;
+
+ default:
+ return FALSE;
+ }
#ifdef KLIPS
- /* (attempt to) actually set up the SAs */
- return setup_half_ipsec_sa(st, TRUE);
+ /* (attempt to) actually set up the SAs */
+ return setup_half_ipsec_sa(st, TRUE);
#else /* !KLIPS */
- DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa()"));
- return TRUE;
+ DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa()"));
+ return TRUE;
#endif /* !KLIPS */
}
@@ -2407,481 +2391,479 @@ install_inbound_ipsec_sa(struct state *st)
* Any SA Group must have already been created.
* On failure, steps will be unwound.
*/
-bool
-route_and_eroute(struct connection *c USED_BY_KLIPS
- , struct spd_route *sr USED_BY_KLIPS
- , struct state *st USED_BY_KLIPS)
+bool route_and_eroute(struct connection *c USED_BY_KLIPS,
+ struct spd_route *sr USED_BY_KLIPS,
+ struct state *st USED_BY_KLIPS)
{
#ifdef KLIPS
- struct spd_route *esr;
- struct spd_route *rosr;
- struct connection *ero /* who, if anyone, owns our eroute? */
- , *ro = route_owner(c, &rosr, &ero, &esr);
- bool eroute_installed = FALSE
- , firewall_notified = FALSE
- , route_installed = FALSE;
-
- struct connection *ero_top;
- struct bare_shunt **bspp;
-
- DBG(DBG_CONTROLMORE,
- DBG_log("route_and_eroute with c: %s (next: %s) ero:%s esr:{%p} ro:%s rosr:{%p} and state: %lu"
- , c->name
- , (c->policy_next ? c->policy_next->name : "none")
- , ero ? ero->name : "null"
- , esr
- , ro ? ro->name : "null"
- , rosr
- , st ? st->st_serialno : 0));
-
- /* look along the chain of policies for one with the same name */
- ero_top = ero;
+ struct spd_route *esr;
+ struct spd_route *rosr;
+ struct connection *ero /* who, if anyone, owns our eroute? */
+ , *ro = route_owner(c, &rosr, &ero, &esr);
+ bool eroute_installed = FALSE
+ , firewall_notified = FALSE
+ , route_installed = FALSE;
+
+ struct connection *ero_top;
+ struct bare_shunt **bspp;
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log("route_and_eroute with c: %s (next: %s) ero:%s esr:{%p} ro:%s rosr:{%p} and state: %lu"
+ , c->name
+ , (c->policy_next ? c->policy_next->name : "none")
+ , ero ? ero->name : "null"
+ , esr
+ , ro ? ro->name : "null"
+ , rosr
+ , st ? st->st_serialno : 0));
+
+ /* look along the chain of policies for one with the same name */
+ ero_top = ero;
#if 0
- /* XXX - mcr this made sense before, and likely will make sense
- * again, so I'l leaving this to remind me what is up */
- if (ero!= NULL && ero->routing == RT_UNROUTED_KEYED)
- ero = NULL;
-
- for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next)
- if ((ero2->kind == CK_TEMPLATE || ero2->kind==CK_SECONDARY)
- && streq(ero2->name, c->name))
- break;
+ /* XXX - mcr this made sense before, and likely will make sense
+ * again, so I'l leaving this to remind me what is up */
+ if (ero!= NULL && ero->routing == RT_UNROUTED_KEYED)
+ ero = NULL;
+
+ for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next)
+ if ((ero2->kind == CK_TEMPLATE || ero2->kind==CK_SECONDARY)
+ && streq(ero2->name, c->name))
+ break;
#endif
- bspp = (ero == NULL)
- ? bare_shunt_ptr(&sr->this.client, &sr->that.client, sr->this.protocol)
- : NULL;
+ bspp = (ero == NULL)
+ ? bare_shunt_ptr(&sr->this.client, &sr->that.client, sr->this.protocol)
+ : NULL;
- /* install the eroute */
+ /* install the eroute */
- passert(bspp == NULL || ero == NULL); /* only one non-NULL */
+ passert(bspp == NULL || ero == NULL); /* only one non-NULL */
- if (bspp != NULL || ero != NULL)
- {
- /* We're replacing an eroute */
+ if (bspp != NULL || ero != NULL)
+ {
+ /* We're replacing an eroute */
- /* if no state provided, then install a shunt for later */
- if (st == NULL)
- eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE
- , ERO_REPLACE, "replace");
- else
- eroute_installed = sag_eroute(st, sr, ERO_REPLACE, "replace");
+ /* if no state provided, then install a shunt for later */
+ if (st == NULL)
+ eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE
+ , ERO_REPLACE, "replace");
+ else
+ eroute_installed = sag_eroute(st, sr, ERO_REPLACE, "replace");
#if 0
- /* XXX - MCR. I previously felt that this was a bogus check */
- if (ero != NULL && ero != c && esr != sr)
- {
- /* By elimination, we must be eclipsing ero. Check. */
- passert(ero->kind == CK_TEMPLATE && streq(ero->name, c->name));
- passert(LHAS(LELEM(RT_ROUTED_PROSPECTIVE) | LELEM(RT_ROUTED_ECLIPSED)
- , esr->routing));
- passert(samesubnet(&esr->this.client, &sr->this.client)
- && samesubnet(&esr->that.client, &sr->that.client));
- }
+ /* XXX - MCR. I previously felt that this was a bogus check */
+ if (ero != NULL && ero != c && esr != sr)
+ {
+ /* By elimination, we must be eclipsing ero. Check. */
+ passert(ero->kind == CK_TEMPLATE && streq(ero->name, c->name));
+ passert(LHAS(LELEM(RT_ROUTED_PROSPECTIVE) | LELEM(RT_ROUTED_ECLIPSED)
+ , esr->routing));
+ passert(samesubnet(&esr->this.client, &sr->this.client)
+ && samesubnet(&esr->that.client, &sr->that.client));
+ }
#endif
- /* remember to free bspp iff we make it out of here alive */
- }
- else
- {
- /* we're adding an eroute */
-
- /* if no state provided, then install a shunt for later */
- if (st == NULL)
- eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE
- , ERO_ADD, "add");
- else
- eroute_installed = sag_eroute(st, sr, ERO_ADD, "add");
- }
-
- /* notify the firewall of a new tunnel */
-
- if (eroute_installed)
- {
- /* do we have to notify the firewall? Yes, if we are installing
- * a tunnel eroute and the firewall wasn't notified
- * for a previous tunnel with the same clients. Any Previous
- * tunnel would have to be for our connection, so the actual
- * test is simple.
- */
- firewall_notified = st == NULL /* not a tunnel eroute */
- || sr->eroute_owner != SOS_NOBODY /* already notified */
- || do_command(c, sr, "up"); /* go ahead and notify */
- }
-
- /* install the route */
-
- DBG(DBG_CONTROL,
- DBG_log("route_and_eroute: firewall_notified: %s"
- , firewall_notified ? "true" : "false"));
- if (!firewall_notified)
- {
- /* we're in trouble -- don't do routing */
- }
- else if (ro == NULL)
- {
- /* a new route: no deletion required, but preparation is */
- (void) do_command(c, sr, "prepare"); /* just in case; ignore failure */
- route_installed = do_command(c, sr, "route");
- }
- else if (routed(sr->routing)
- || routes_agree(ro, c))
- {
- route_installed = TRUE; /* nothing to be done */
- }
- else
- {
- /* Some other connection must own the route
- * and the route must disagree. But since could_route
- * must have allowed our stealing it, we'll do so.
- *
- * A feature of LINUX allows us to install the new route
- * before deleting the old if the nexthops differ.
- * This reduces the "window of vulnerability" when packets
- * might flow in the clear.
- */
- if (sameaddr(&sr->this.host_nexthop, &esr->this.host_nexthop))
- {
- (void) do_command(ro, sr, "unroute");
- route_installed = do_command(c, sr, "route");
+ /* remember to free bspp iff we make it out of here alive */
}
else
{
- route_installed = do_command(c, sr, "route");
- (void) do_command(ro, sr, "unroute");
+ /* we're adding an eroute */
+
+ /* if no state provided, then install a shunt for later */
+ if (st == NULL)
+ eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE
+ , ERO_ADD, "add");
+ else
+ eroute_installed = sag_eroute(st, sr, ERO_ADD, "add");
}
- /* record unrouting */
- if (route_installed)
- {
- do {
- passert(!erouted(rosr->routing));
- rosr->routing = RT_UNROUTED;
+ /* notify the firewall of a new tunnel */
- /* no need to keep old value */
- ro = route_owner(c, &rosr, NULL, NULL);
- } while (ro != NULL);
+ if (eroute_installed)
+ {
+ /* do we have to notify the firewall? Yes, if we are installing
+ * a tunnel eroute and the firewall wasn't notified
+ * for a previous tunnel with the same clients. Any Previous
+ * tunnel would have to be for our connection, so the actual
+ * test is simple.
+ */
+ firewall_notified = st == NULL /* not a tunnel eroute */
+ || sr->eroute_owner != SOS_NOBODY /* already notified */
+ || do_command(c, sr, "up"); /* go ahead and notify */
}
- }
- /* all done -- clean up */
- if (route_installed)
- {
- /* Success! */
+ /* install the route */
- if (bspp != NULL)
+ DBG(DBG_CONTROL,
+ DBG_log("route_and_eroute: firewall_notified: %s"
+ , firewall_notified ? "true" : "false"));
+ if (!firewall_notified)
{
- free_bare_shunt(bspp);
+ /* we're in trouble -- don't do routing */
}
- else if (ero != NULL && ero != c)
+ else if (ro == NULL)
{
- /* check if ero is an ancestor of c. */
- struct connection *ero2;
-
- for (ero2 = c; ero2 != NULL && ero2 != c; ero2 = ero2->policy_next)
- ;
-
- if (ero2 == NULL)
- {
- /* By elimination, we must be eclipsing ero. Checked above. */
- if (ero->spd.routing != RT_ROUTED_ECLIPSED)
- {
- ero->spd.routing = RT_ROUTED_ECLIPSED;
- eclipse_count++;
- }
- }
+ /* a new route: no deletion required, but preparation is */
+ (void) do_command(c, sr, "prepare"); /* just in case; ignore failure */
+ route_installed = do_command(c, sr, "route");
}
-
- if (st == NULL)
+ else if (routed(sr->routing)
+ || routes_agree(ro, c))
{
- passert(sr->eroute_owner == SOS_NOBODY);
- sr->routing = RT_ROUTED_PROSPECTIVE;
+ route_installed = TRUE; /* nothing to be done */
}
else
{
- char cib[CONN_INST_BUF];
- sr->routing = RT_ROUTED_TUNNEL;
+ /* Some other connection must own the route
+ * and the route must disagree. But since could_route
+ * must have allowed our stealing it, we'll do so.
+ *
+ * A feature of LINUX allows us to install the new route
+ * before deleting the old if the nexthops differ.
+ * This reduces the "window of vulnerability" when packets
+ * might flow in the clear.
+ */
+ if (sameaddr(&sr->this.host_nexthop, &esr->this.host_nexthop))
+ {
+ (void) do_command(ro, sr, "unroute");
+ route_installed = do_command(c, sr, "route");
+ }
+ else
+ {
+ route_installed = do_command(c, sr, "route");
+ (void) do_command(ro, sr, "unroute");
+ }
- DBG(DBG_CONTROL,
- DBG_log("route_and_eroute: instance \"%s\"%s, setting eroute_owner {spd=%p,sr=%p} to #%ld (was #%ld) (newest_ipsec_sa=#%ld)"
- , st->st_connection->name
- , (fmt_conn_instance(st->st_connection, cib), cib)
- , &st->st_connection->spd, sr
- , st->st_serialno
- , sr->eroute_owner
- , st->st_connection->newest_ipsec_sa));
- sr->eroute_owner = st->st_serialno;
- }
+ /* record unrouting */
+ if (route_installed)
+ {
+ do {
+ passert(!erouted(rosr->routing));
+ rosr->routing = RT_UNROUTED;
- return TRUE;
- }
- else
- {
- /* Failure! Unwind our work. */
- if (firewall_notified && sr->eroute_owner == SOS_NOBODY)
- (void) do_command(c, sr, "down");
+ /* no need to keep old value */
+ ro = route_owner(c, &rosr, NULL, NULL);
+ } while (ro != NULL);
+ }
+ }
- if (eroute_installed)
+ /* all done -- clean up */
+ if (route_installed)
{
- /* Restore original eroute, if we can.
- * Since there is nothing much to be done if the restoration
- * fails, ignore success or failure.
- */
- if (bspp != NULL)
- {
- /* Restore old bare_shunt.
- * I don't think that this case is very likely.
- * Normally a bare shunt would have been assigned
- * to a connection before we've gotten this far.
- */
- struct bare_shunt *bs = *bspp;
-
- (void) raw_eroute(&bs->said.dst /* should be useless */
- , &bs->ours
- , &bs->said.dst /* should be useless */
- , &bs->his
- , bs->said.spi /* network order */
- , SA_INT
- , SADB_X_SATYPE_INT
- , 0
- , null_proto_info
- , SHUNT_PATIENCE
- , ERO_REPLACE, "restore");
- }
- else if (ero != NULL)
- {
- /* restore ero's former glory */
- if (esr->eroute_owner == SOS_NOBODY)
+ /* Success! */
+
+ if (bspp != NULL)
{
- /* note: normal or eclipse case */
- (void) shunt_eroute(ero, esr
- , esr->routing, ERO_REPLACE, "restore");
+ free_bare_shunt(bspp);
}
- else
+ else if (ero != NULL && ero != c)
{
- /* Try to find state that owned eroute.
- * Don't do anything if it cannot be found.
- * This case isn't likely since we don't run
- * the updown script when replacing a SA group
- * with its successor (for the same conn).
- */
- struct state *ost = state_with_serialno(esr->eroute_owner);
-
- if (ost != NULL)
- (void) sag_eroute(ost, esr, ERO_REPLACE, "restore");
+ /* check if ero is an ancestor of c. */
+ struct connection *ero2;
+
+ for (ero2 = c; ero2 != NULL && ero2 != c; ero2 = ero2->policy_next)
+ ;
+
+ if (ero2 == NULL)
+ {
+ /* By elimination, we must be eclipsing ero. Checked above. */
+ if (ero->spd.routing != RT_ROUTED_ECLIPSED)
+ {
+ ero->spd.routing = RT_ROUTED_ECLIPSED;
+ eclipse_count++;
+ }
+ }
}
- }
- else
- {
- /* there was no previous eroute: delete whatever we installed */
+
if (st == NULL)
- (void) shunt_eroute(c, sr
- , sr->routing, ERO_DELETE, "delete");
+ {
+ passert(sr->eroute_owner == SOS_NOBODY);
+ sr->routing = RT_ROUTED_PROSPECTIVE;
+ }
else
- (void) sag_eroute(st, sr
- , ERO_DELETE, "delete");
- }
+ {
+ char cib[CONN_INST_BUF];
+ sr->routing = RT_ROUTED_TUNNEL;
+
+ DBG(DBG_CONTROL,
+ DBG_log("route_and_eroute: instance \"%s\"%s, setting eroute_owner {spd=%p,sr=%p} to #%ld (was #%ld) (newest_ipsec_sa=#%ld)"
+ , st->st_connection->name
+ , (fmt_conn_instance(st->st_connection, cib), cib)
+ , &st->st_connection->spd, sr
+ , st->st_serialno
+ , sr->eroute_owner
+ , st->st_connection->newest_ipsec_sa));
+ sr->eroute_owner = st->st_serialno;
+ }
+
+ return TRUE;
}
+ else
+ {
+ /* Failure! Unwind our work. */
+ if (firewall_notified && sr->eroute_owner == SOS_NOBODY)
+ (void) do_command(c, sr, "down");
- return FALSE;
- }
+ if (eroute_installed)
+ {
+ /* Restore original eroute, if we can.
+ * Since there is nothing much to be done if the restoration
+ * fails, ignore success or failure.
+ */
+ if (bspp != NULL)
+ {
+ /* Restore old bare_shunt.
+ * I don't think that this case is very likely.
+ * Normally a bare shunt would have been assigned
+ * to a connection before we've gotten this far.
+ */
+ struct bare_shunt *bs = *bspp;
+
+ (void) raw_eroute(&bs->said.dst /* should be useless */
+ , &bs->ours
+ , &bs->said.dst /* should be useless */
+ , &bs->his
+ , bs->said.spi /* network order */
+ , SA_INT
+ , SADB_X_SATYPE_INT
+ , 0
+ , null_proto_info
+ , SHUNT_PATIENCE
+ , ERO_REPLACE, "restore");
+ }
+ else if (ero != NULL)
+ {
+ /* restore ero's former glory */
+ if (esr->eroute_owner == SOS_NOBODY)
+ {
+ /* note: normal or eclipse case */
+ (void) shunt_eroute(ero, esr
+ , esr->routing, ERO_REPLACE, "restore");
+ }
+ else
+ {
+ /* Try to find state that owned eroute.
+ * Don't do anything if it cannot be found.
+ * This case isn't likely since we don't run
+ * the updown script when replacing a SA group
+ * with its successor (for the same conn).
+ */
+ struct state *ost = state_with_serialno(esr->eroute_owner);
+
+ if (ost != NULL)
+ (void) sag_eroute(ost, esr, ERO_REPLACE, "restore");
+ }
+ }
+ else
+ {
+ /* there was no previous eroute: delete whatever we installed */
+ if (st == NULL)
+ (void) shunt_eroute(c, sr
+ , sr->routing, ERO_DELETE, "delete");
+ else
+ (void) sag_eroute(st, sr
+ , ERO_DELETE, "delete");
+ }
+ }
+
+ return FALSE;
+ }
#else /* !KLIPS */
- return TRUE;
+ return TRUE;
#endif /* !KLIPS */
}
-bool
-install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS)
+bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS)
{
#ifdef KLIPS
- struct spd_route *sr;
-
- DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() for #%ld: %s"
- , st->st_serialno
- , inbound_also?
- "inbound and outbound" : "outbound only"));
-
- switch (could_route(st->st_connection))
- {
- case route_easy:
- case route_nearconflict:
- break;
+ struct spd_route *sr;
- default:
- return FALSE;
- }
+ DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() for #%ld: %s"
+ , st->st_serialno
+ , inbound_also?
+ "inbound and outbound" : "outbound only"));
- /* (attempt to) actually set up the SA group */
- if ((inbound_also && !setup_half_ipsec_sa(st, TRUE))
- || !setup_half_ipsec_sa(st, FALSE))
- return FALSE;
+ switch (could_route(st->st_connection))
+ {
+ case route_easy:
+ case route_nearconflict:
+ break;
- for (sr = &st->st_connection->spd; sr != NULL; sr = sr->next)
- {
- DBG(DBG_CONTROL, DBG_log("sr for #%ld: %s"
- , st->st_serialno
- , enum_name(&routing_story, sr->routing)));
+ default:
+ return FALSE;
+ }
- /*
- * if the eroute owner is not us, then make it us.
- * See test co-terminal-02, pluto-rekey-01, pluto-unit-02/oppo-twice
- */
- pexpect(sr->eroute_owner == SOS_NOBODY
- || sr->routing >= RT_ROUTED_TUNNEL);
+ /* (attempt to) actually set up the SA group */
+ if ((inbound_also && !setup_half_ipsec_sa(st, TRUE))
+ || !setup_half_ipsec_sa(st, FALSE))
+ return FALSE;
- if (sr->eroute_owner != st->st_serialno
- && sr->routing != RT_UNROUTED_KEYED)
+ for (sr = &st->st_connection->spd; sr != NULL; sr = sr->next)
{
- if (!route_and_eroute(st->st_connection, sr, st))
- {
- delete_ipsec_sa(st, FALSE);
- /* XXX go and unroute any SRs that were successfully
- * routed already.
+ DBG(DBG_CONTROL, DBG_log("sr for #%ld: %s"
+ , st->st_serialno
+ , enum_name(&routing_story, sr->routing)));
+
+ /*
+ * if the eroute owner is not us, then make it us.
+ * See test co-terminal-02, pluto-rekey-01, pluto-unit-02/oppo-twice
*/
- return FALSE;
- }
+ pexpect(sr->eroute_owner == SOS_NOBODY
+ || sr->routing >= RT_ROUTED_TUNNEL);
+
+ if (sr->eroute_owner != st->st_serialno
+ && sr->routing != RT_UNROUTED_KEYED)
+ {
+ if (!route_and_eroute(st->st_connection, sr, st))
+ {
+ delete_ipsec_sa(st, FALSE);
+ /* XXX go and unroute any SRs that were successfully
+ * routed already.
+ */
+ return FALSE;
+ }
+ }
}
- }
#else /* !KLIPS */
- DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() %s"
- , inbound_also? "inbound and oubound" : "outbound only"));
+ DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() %s"
+ , inbound_also? "inbound and oubound" : "outbound only"));
- switch (could_route(st->st_connection))
- {
- case route_easy:
- case route_nearconflict:
- break;
+ switch (could_route(st->st_connection))
+ {
+ case route_easy:
+ case route_nearconflict:
+ break;
- default:
- return FALSE;
- }
+ default:
+ return FALSE;
+ }
#endif /* !KLIPS */
- return TRUE;
+ return TRUE;
}
/* delete an IPSEC SA.
* we may not succeed, but we bull ahead anyway because
* we cannot do anything better by recognizing failure
*/
-void
-delete_ipsec_sa(struct state *st USED_BY_KLIPS, bool inbound_only USED_BY_KLIPS)
+void delete_ipsec_sa(struct state *st USED_BY_KLIPS,
+ bool inbound_only USED_BY_KLIPS)
{
#ifdef KLIPS
- if (!inbound_only)
- {
- /* If the state is the eroute owner, we must adjust
- * the routing for the connection.
- */
- struct connection *c = st->st_connection;
- struct spd_route *sr;
-
- passert(st->st_connection);
-
- for (sr = &c->spd; sr; sr = sr->next)
+ if (!inbound_only)
{
- if (sr->eroute_owner == st->st_serialno
- && sr->routing == RT_ROUTED_TUNNEL)
- {
- sr->eroute_owner = SOS_NOBODY;
-
- /* Routing should become RT_ROUTED_FAILURE,
- * but if POLICY_FAIL_NONE, then we just go
- * right back to RT_ROUTED_PROSPECTIVE as if no
- * failure happened.
+ /* If the state is the eroute owner, we must adjust
+ * the routing for the connection.
*/
- sr->routing = (c->policy & POLICY_FAIL_MASK) == POLICY_FAIL_NONE
- ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE;
+ struct connection *c = st->st_connection;
+ struct spd_route *sr;
- (void) do_command(c, sr, "down");
- if ((c->policy & POLICY_DONT_REKEY)
- && c->kind == CK_INSTANCE)
- {
- /* in this special case, even if the connection
- * is still alive (due to an ISAKMP SA),
- * we get rid of routing.
- * Even though there is still an eroute, the c->routing
- * setting will convince unroute_connection to delete it.
- * unroute_connection would be upset if c->routing == RT_ROUTED_TUNNEL
- */
- unroute_connection(c);
- }
- else
+ passert(st->st_connection);
+
+ for (sr = &c->spd; sr; sr = sr->next)
{
- (void) shunt_eroute(c, sr, sr->routing, ERO_REPLACE, "replace with shunt");
+ if (sr->eroute_owner == st->st_serialno
+ && sr->routing == RT_ROUTED_TUNNEL)
+ {
+ sr->eroute_owner = SOS_NOBODY;
+
+ /* Routing should become RT_ROUTED_FAILURE,
+ * but if POLICY_FAIL_NONE, then we just go
+ * right back to RT_ROUTED_PROSPECTIVE as if no
+ * failure happened.
+ */
+ sr->routing = (c->policy & POLICY_FAIL_MASK) == POLICY_FAIL_NONE
+ ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE;
+
+ (void) do_command(c, sr, "down");
+ if ((c->policy & POLICY_DONT_REKEY)
+ && c->kind == CK_INSTANCE)
+ {
+ /* in this special case, even if the connection
+ * is still alive (due to an ISAKMP SA),
+ * we get rid of routing.
+ * Even though there is still an eroute, the c->routing
+ * setting will convince unroute_connection to delete it.
+ * unroute_connection would be upset if c->routing == RT_ROUTED_TUNNEL
+ */
+ unroute_connection(c);
+ }
+ else
+ {
+ (void) shunt_eroute(c, sr, sr->routing, ERO_REPLACE, "replace with shunt");
+ }
+ }
}
- }
+ (void) teardown_half_ipsec_sa(st, FALSE);
}
- (void) teardown_half_ipsec_sa(st, FALSE);
- }
- (void) teardown_half_ipsec_sa(st, TRUE);
+ (void) teardown_half_ipsec_sa(st, TRUE);
#else /* !KLIPS */
- DBG(DBG_CONTROL, DBG_log("if I knew how, I'd eroute() and teardown_ipsec_sa()"));
+ DBG(DBG_CONTROL, DBG_log("if I knew how, I'd eroute() and teardown_ipsec_sa()"));
#endif /* !KLIPS */
}
#ifdef KLIPS
static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
{
- struct connection *c = st->st_connection;
- char text_said[SATOT_BUF];
- struct kernel_sa sa;
- ip_address
- src = inbound? c->spd.that.host_addr : c->spd.this.host_addr,
- dst = inbound? c->spd.this.host_addr : c->spd.that.host_addr;
-
- ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi;
-
- u_int16_t
- natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port,
- natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port;
-
- set_text_said(text_said, &dst, esp_spi, SA_ESP);
-
- memset(&sa, 0, sizeof(sa));
- sa.spi = esp_spi;
- sa.src = &src;
- sa.dst = &dst;
- sa.text_said = text_said;
- sa.authalg = alg_info_esp_aa2sadb(st->st_esp.attrs.auth);
- sa.natt_sport = natt_sport;
- sa.natt_dport = natt_dport;
- sa.transid = st->st_esp.attrs.transid;
-
- return kernel_ops->add_sa(&sa, TRUE);
+ struct connection *c = st->st_connection;
+ char text_said[SATOT_BUF];
+ struct kernel_sa sa;
+ ip_address
+ src = inbound? c->spd.that.host_addr : c->spd.this.host_addr,
+ dst = inbound? c->spd.this.host_addr : c->spd.that.host_addr;
+
+ ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi;
+
+ u_int16_t
+ natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port,
+ natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port;
+
+ set_text_said(text_said, &dst, esp_spi, SA_ESP);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.spi = esp_spi;
+ sa.src = &src;
+ sa.dst = &dst;
+ sa.text_said = text_said;
+ sa.authalg = alg_info_esp_aa2sadb(st->st_esp.attrs.auth);
+ sa.natt_sport = natt_sport;
+ sa.natt_dport = natt_dport;
+ sa.transid = st->st_esp.attrs.transid;
+
+ return kernel_ops->add_sa(&sa, TRUE);
}
#endif
bool update_ipsec_sa (struct state *st USED_BY_KLIPS)
{
#ifdef KLIPS
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- if (st->st_esp.present && (
- (!update_nat_t_ipsec_esp_sa (st, TRUE)) ||
- (!update_nat_t_ipsec_esp_sa (st, FALSE))))
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
{
- return FALSE;
+ if (st->st_esp.present && (
+ (!update_nat_t_ipsec_esp_sa (st, TRUE)) ||
+ (!update_nat_t_ipsec_esp_sa (st, FALSE))))
+ {
+ return FALSE;
+ }
}
- }
- else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- if (st->st_esp.present && !update_nat_t_ipsec_esp_sa (st, FALSE))
+ else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
{
- return FALSE;
+ if (st->st_esp.present && !update_nat_t_ipsec_esp_sa (st, FALSE))
+ {
+ return FALSE;
+ }
}
- }
- else
- {
- DBG_log("assert failed at %s:%d st_state=%d", __FILE__, __LINE__, st->st_state);
- return FALSE;
- }
- return TRUE;
+ else
+ {
+ DBG_log("assert failed at %s:%d st_state=%d", __FILE__, __LINE__, st->st_state);
+ return FALSE;
+ }
+ return TRUE;
#else /* !KLIPS */
- DBG(DBG_CONTROL, DBG_log("if I knew how, I'd update_ipsec_sa()"));
- return TRUE;
+ DBG(DBG_CONTROL, DBG_log("if I knew how, I'd update_ipsec_sa()"));
+ return TRUE;
#endif /* !KLIPS */
}
@@ -2890,106 +2872,105 @@ bool update_ipsec_sa (struct state *st USED_BY_KLIPS)
* If FALSE, DPD is not necessary. We also return TRUE for errors, as they
* could mean that the SA is broken and needs to be replace anyway.
*/
-bool
-was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time)
+bool was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time)
{
- static const char procname[] = "/proc/net/ipsec_spi";
- FILE *f;
- char buf[1024];
- u_int bytes;
- int ret = TRUE;
-
- passert(st != NULL);
-
- f = fopen(procname, "r");
- if (f == NULL)
- {
- /* Can't open the file, perhaps were are on 26sec? */
- time_t use_time;
-
- if (get_sa_info(st, TRUE, &bytes, &use_time)
- && use_time != UNDEFINED_TIME)
- {
- *idle_time = time(NULL) - use_time;
- ret = *idle_time >= idle_max;
- }
- }
- else
- {
- while (f != NULL)
- {
- char *line;
- char text_said[SATOT_BUF];
- u_int8_t proto = 0;
- ip_address dst;
- ip_said said;
- ipsec_spi_t spi = 0;
- static const char idle[] = "idle=";
-
- dst = st->st_connection->spd.this.host_addr; /* inbound SA */
- if (st->st_ah.present)
- {
- proto = SA_AH;
- spi = st->st_ah.our_spi;
- }
- if (st->st_esp.present)
- {
- proto = SA_ESP;
- spi = st->st_esp.our_spi;
- }
-
- if (proto == 0 && spi == 0)
- {
- ret = TRUE;
- break;
- }
-
- initsaid(&dst, spi, proto, &said);
- satot(&said, 'x', text_said, SATOT_BUF);
+ static const char procname[] = "/proc/net/ipsec_spi";
+ FILE *f;
+ char buf[1024];
+ u_int bytes;
+ int ret = TRUE;
- line = fgets(buf, sizeof(buf), f);
- if (line == NULL)
- {
- /* Reached end of list */
- ret = TRUE;
- break;
- }
+ passert(st != NULL);
- if (strncmp(line, text_said, strlen(text_said)) == 0)
- {
- /* we found a match, now try to find idle= */
- char *p = strstr(line, idle);
+ f = fopen(procname, "r");
+ if (f == NULL)
+ {
+ /* Can't open the file, perhaps were are on 26sec? */
+ time_t use_time;
- if (p == NULL)
+ if (get_sa_info(st, TRUE, &bytes, &use_time)
+ && use_time != UNDEFINED_TIME)
{
- /* SAs which haven't been used yet don't have it */
- ret = TRUE; /* it didn't have traffic */
- break;
+ *idle_time = time(NULL) - use_time;
+ ret = *idle_time >= idle_max;
}
- p += sizeof(idle)-1;
- if (*p == '\0')
- {
- ret = TRUE; /* be paranoid */
- break;
- }
- if (sscanf(p, "%d", (int *) idle_time) <= 0)
- {
- ret = TRUE;
- break;
- }
- if (*idle_time >= idle_max)
- {
- ret = TRUE;
- break;
- }
- else
+ }
+ else
+ {
+ while (f != NULL)
{
- ret = FALSE;
- break;
+ char *line;
+ char text_said[SATOT_BUF];
+ u_int8_t proto = 0;
+ ip_address dst;
+ ip_said said;
+ ipsec_spi_t spi = 0;
+ static const char idle[] = "idle=";
+
+ dst = st->st_connection->spd.this.host_addr; /* inbound SA */
+ if (st->st_ah.present)
+ {
+ proto = SA_AH;
+ spi = st->st_ah.our_spi;
+ }
+ if (st->st_esp.present)
+ {
+ proto = SA_ESP;
+ spi = st->st_esp.our_spi;
+ }
+
+ if (proto == 0 && spi == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+
+ initsaid(&dst, spi, proto, &said);
+ satot(&said, 'x', text_said, SATOT_BUF);
+
+ line = fgets(buf, sizeof(buf), f);
+ if (line == NULL)
+ {
+ /* Reached end of list */
+ ret = TRUE;
+ break;
+ }
+
+ if (strneq(line, text_said, strlen(text_said)))
+ {
+ /* we found a match, now try to find idle= */
+ char *p = strstr(line, idle);
+
+ if (p == NULL)
+ {
+ /* SAs which haven't been used yet don't have it */
+ ret = TRUE; /* it didn't have traffic */
+ break;
+ }
+ p += sizeof(idle)-1;
+ if (*p == '\0')
+ {
+ ret = TRUE; /* be paranoid */
+ break;
+ }
+ if (sscanf(p, "%d", (int *) idle_time) <= 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ if (*idle_time >= idle_max)
+ {
+ ret = TRUE;
+ break;
+ }
+ else
+ {
+ ret = FALSE;
+ break;
+ }
+ }
}
- }
+ fclose(f);
}
- fclose(f);
- }
- return ret;
+ return ret;
}
diff --git a/src/pluto/kernel.h b/src/pluto/kernel.h
index fdc2bf0a8..06850abfd 100644
--- a/src/pluto/kernel.h
+++ b/src/pluto/kernel.h
@@ -10,13 +10,11 @@
* 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: kernel.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include "connections.h"
-extern bool no_klips; /* don't actually use KLIPS */
+extern bool no_klips; /* don't actually use KLIPS */
extern bool can_do_IPcomp; /* can system actually perform IPCOMP? */
#ifdef KLIPS
@@ -28,96 +26,96 @@ extern bool can_do_IPcomp; /* can system actually perform IPCOMP? */
* limited to appropriate source and destination addresses.
*/
-#define ERO_MASK 0xFF
-#define ERO_FLAG_SHIFT 8
+#define ERO_MASK 0xFF
+#define ERO_FLAG_SHIFT 8
-#define ERO_DELETE SADB_X_DELFLOW
-#define ERO_ADD SADB_X_ADDFLOW
-#define ERO_REPLACE (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
-#define ERO_ADD_INBOUND (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
-#define ERO_DEL_INBOUND (SADB_X_DELFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
+#define ERO_DELETE SADB_X_DELFLOW
+#define ERO_ADD SADB_X_ADDFLOW
+#define ERO_REPLACE (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
+#define ERO_ADD_INBOUND (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
+#define ERO_DEL_INBOUND (SADB_X_DELFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
struct pfkey_proto_info {
- int proto;
- int encapsulation;
- unsigned reqid;
+ int proto;
+ int encapsulation;
+ unsigned reqid;
};
struct sadb_msg;
struct kernel_sa {
- const ip_address *src;
- const ip_address *dst;
+ const ip_address *src;
+ const ip_address *dst;
- const ip_subnet *src_client;
- const ip_subnet *dst_client;
+ const ip_subnet *src_client;
+ const ip_subnet *dst_client;
- ipsec_spi_t spi;
- unsigned proto;
- unsigned satype;
- unsigned transport_proto;
- unsigned replay_window;
- unsigned reqid;
+ ipsec_spi_t spi;
+ unsigned proto;
+ unsigned satype;
+ unsigned transport_proto;
+ unsigned replay_window;
+ unsigned reqid;
- unsigned authalg;
- unsigned authkeylen;
- char *authkey;
+ unsigned authalg;
+ unsigned authkeylen;
+ char *authkey;
- unsigned encalg;
- unsigned enckeylen;
- char *enckey;
+ unsigned encalg;
+ unsigned enckeylen;
+ char *enckey;
- unsigned compalg;
+ unsigned compalg;
- int encapsulation;
+ int encapsulation;
- u_int16_t natt_sport, natt_dport;
- u_int8_t transid, natt_type;
- ip_address *natt_oa;
+ u_int16_t natt_sport, natt_dport;
+ u_int8_t transid, natt_type;
+ ip_address *natt_oa;
- const char *text_said;
+ const char *text_said;
};
struct kernel_ops {
- enum {
- KERNEL_TYPE_NONE,
- KERNEL_TYPE_KLIPS,
- KERNEL_TYPE_LINUX,
- } type;
- bool inbound_eroute;
- bool policy_lifetime;
- int *async_fdp;
-
- void (*init)(void);
- void (*pfkey_register)(void);
- void (*pfkey_register_response)(const struct sadb_msg *msg);
- void (*process_queue)(void);
- void (*process_msg)(void);
- bool (*raw_eroute)(const ip_address *this_host,
- const ip_subnet *this_client,
- const ip_address *that_host,
- const ip_subnet *that_client,
- ipsec_spi_t spi,
- unsigned int satype,
- unsigned int transport_proto,
- const struct pfkey_proto_info *proto_info,
- time_t use_lifetime,
- unsigned int op,
- const char *text_said);
- bool (*get_policy)(const struct kernel_sa *sa, bool inbound,
- time_t *use_time);
- bool (*add_sa)(const struct kernel_sa *sa, bool replace);
- bool (*grp_sa)(const struct kernel_sa *sa_outer,
- const struct kernel_sa *sa_inner);
- bool (*del_sa)(const struct kernel_sa *sa);
- bool (*get_sa)(const struct kernel_sa *sa, u_int *bytes);
- ipsec_spi_t (*get_spi)(const ip_address *src,
- const ip_address *dst,
- int proto,
- bool tunnel_mode,
- unsigned reqid,
- ipsec_spi_t min,
- ipsec_spi_t max,
- const char *text_said);
+ enum {
+ KERNEL_TYPE_NONE,
+ KERNEL_TYPE_KLIPS,
+ KERNEL_TYPE_LINUX,
+ } type;
+ bool inbound_eroute;
+ bool policy_lifetime;
+ int *async_fdp;
+
+ void (*init)(void);
+ void (*pfkey_register)(void);
+ void (*pfkey_register_response)(const struct sadb_msg *msg);
+ void (*process_queue)(void);
+ void (*process_msg)(void);
+ bool (*raw_eroute)(const ip_address *this_host,
+ const ip_subnet *this_client,
+ const ip_address *that_host,
+ const ip_subnet *that_client,
+ ipsec_spi_t spi,
+ unsigned int satype,
+ unsigned int transport_proto,
+ const struct pfkey_proto_info *proto_info,
+ time_t use_lifetime,
+ unsigned int op,
+ const char *text_said);
+ bool (*get_policy)(const struct kernel_sa *sa, bool inbound,
+ time_t *use_time);
+ bool (*add_sa)(const struct kernel_sa *sa, bool replace);
+ bool (*grp_sa)(const struct kernel_sa *sa_outer,
+ const struct kernel_sa *sa_inner);
+ bool (*del_sa)(const struct kernel_sa *sa);
+ bool (*get_sa)(const struct kernel_sa *sa, u_int *bytes);
+ ipsec_spi_t (*get_spi)(const ip_address *src,
+ const ip_address *dst,
+ int proto,
+ bool tunnel_mode,
+ unsigned reqid,
+ ipsec_spi_t min,
+ ipsec_spi_t max,
+ const char *text_said);
};
@@ -126,13 +124,13 @@ extern const struct kernel_ops *kernel_ops;
/* information from /proc/net/ipsec_eroute */
struct eroute_info {
- unsigned long count;
- ip_subnet ours;
- ip_subnet his;
- ip_address dst;
- ip_said said;
- int transport_proto;
- struct eroute_info *next;
+ unsigned long count;
+ ip_subnet ours;
+ ip_subnet his;
+ ip_address dst;
+ ip_said said;
+ int transport_proto;
+ struct eroute_info *next;
};
extern struct eroute_info *orphaned_holds;
@@ -144,13 +142,13 @@ extern void show_shunt_status(void);
* Is there a PF_KEY equivalent?
*/
#ifndef EM_MAXRELSPIS
-# define EM_MAXRELSPIS 4 /* AH ESP IPCOMP IPIP */
+# define EM_MAXRELSPIS 4 /* AH ESP IPCOMP IPIP */
#endif
extern void record_and_initiate_opportunistic(const ip_subnet *
- , const ip_subnet *
- , int transport_proto
- , const char *why);
+ , const ip_subnet *
+ , int transport_proto
+ , const char *why);
extern void init_kernel(void);
@@ -160,39 +158,39 @@ extern bool trap_connection(struct connection *c);
extern void unroute_connection(struct connection *c);
extern bool has_bare_hold(const ip_address *src, const ip_address *dst
- , int transport_proto);
+ , int transport_proto);
extern bool replace_bare_shunt(const ip_address *src, const ip_address *dst
- , policy_prio_t policy_prio
- , ipsec_spi_t shunt_spi /* in host order! */
- , bool repl
- , unsigned int transport_proto
- , const char *why);
+ , policy_prio_t policy_prio
+ , ipsec_spi_t shunt_spi /* in host order! */
+ , bool repl
+ , unsigned int transport_proto
+ , const char *why);
extern bool assign_hold(struct connection *c
- , struct spd_route *sr
- , int transport_proto
- , const ip_address *src, const ip_address *dst);
+ , struct spd_route *sr
+ , int transport_proto
+ , const ip_address *src, const ip_address *dst);
extern ipsec_spi_t shunt_policy_spi(struct connection *c, bool prospective);
-struct state; /* forward declaration of tag */
+struct state; /* forward declaration of tag */
extern ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid
- , int proto
- , struct spd_route *sr
- , bool tunnel_mode);
+ , int proto
+ , struct spd_route *sr
+ , bool tunnel_mode);
extern ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel_mode);
extern bool install_inbound_ipsec_sa(struct state *st);
extern bool install_ipsec_sa(struct state *st, bool inbound_also);
extern void delete_ipsec_sa(struct state *st, bool inbound_only);
extern bool route_and_eroute(struct connection *c
- , struct spd_route *sr
- , struct state *st);
+ , struct spd_route *sr
+ , struct state *st);
extern bool was_eroute_idle(struct state *st, time_t idle_max
- , time_t *idle_time);
+ , time_t *idle_time);
extern bool get_sa_info(struct state *st, bool inbound, u_int *bytes
- , time_t *use_time);
+ , time_t *use_time);
extern bool update_ipsec_sa(struct state *st);
diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c
index 571d9cc9b..1590bdf02 100644
--- a/src/pluto/kernel_alg.c
+++ b/src/pluto/kernel_alg.c
@@ -1,5 +1,6 @@
/* Kernel runtime algorithm handling interface
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +11,6 @@
* 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: kernel_alg.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -27,7 +26,6 @@
#include <pfkey.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "constants.h"
#include "defs.h"
@@ -38,22 +36,10 @@
#include "kernel.h"
#include "kernel_alg.h"
#include "alg_info.h"
-
-#ifndef NO_PLUTO
#include "log.h"
#include "whack.h"
#include "db_ops.h"
-#else
-/*
- * macros/functions for compilation without pluto (eg: spi for manual conns)
- */
-extern int debug;
-#include <assert.h>
-#define passert(x) assert(x)
-#define DBG(cond, action) { if (debug) { action ; } }
-#define DBG_log(x, args...) fprintf(stderr, x "\n" , ##args);
-#define plog(x, args...) fprintf(stderr, x "\n" , ##args);
-#endif /* NO_PLUTO */
+
/* ALG storage */
static struct sadb_alg esp_aalg[SADB_AALG_MAX+1];
static struct sadb_alg esp_ealg[SADB_EALG_MAX+1];
@@ -62,714 +48,669 @@ static int esp_aalg_num = 0;
#define ESP_EALG_PRESENT(algo) (((algo)<=SADB_EALG_MAX)&&(esp_ealg[(algo)].sadb_alg_id==(algo)))
#define ESP_EALG_FOR_EACH_UPDOWN(algo) \
- for (algo=SADB_EALG_MAX; algo >0 ; algo--) \
- if (ESP_EALG_PRESENT(algo))
+ for (algo=SADB_EALG_MAX; algo >0 ; algo--) \
+ if (ESP_EALG_PRESENT(algo))
#define ESP_AALG_PRESENT(algo) ((algo<=SADB_AALG_MAX)&&(esp_aalg[(algo)].sadb_alg_id==(algo)))
#define ESP_AALG_FOR_EACH_UPDOWN(algo) \
- for (algo=SADB_AALG_MAX; algo >0 ; algo--) \
- if (ESP_AALG_PRESENT(algo))
+ for (algo=SADB_AALG_MAX; algo >0 ; algo--) \
+ if (ESP_AALG_PRESENT(algo))
-static struct sadb_alg*
-sadb_alg_ptr (int satype, int exttype, int alg_id, int rw)
+static struct sadb_alg* sadb_alg_ptr (int satype, int exttype, int alg_id,
+ int rw)
{
- struct sadb_alg *alg_p = NULL;
-
- switch (exttype)
- {
- case SADB_EXT_SUPPORTED_AUTH:
- if (alg_id > SADB_AALG_MAX)
- return NULL;
- break;
- case SADB_EXT_SUPPORTED_ENCRYPT:
- if (alg_id > SADB_EALG_MAX)
- return NULL;
- break;
- default:
- return NULL;
- }
-
- switch (satype)
- {
- case SADB_SATYPE_ESP:
- alg_p = (exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
- &esp_ealg[alg_id] : &esp_aalg[alg_id];
- /* get for write: increment elem count */
- if (rw)
+ struct sadb_alg *alg_p = NULL;
+
+ switch (exttype)
{
- (exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
- esp_ealg_num++ : esp_aalg_num++;
+ case SADB_EXT_SUPPORTED_AUTH:
+ if (alg_id > SADB_AALG_MAX)
+ return NULL;
+ break;
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ if (alg_id > SADB_EALG_MAX)
+ return NULL;
+ break;
+ default:
+ return NULL;
}
- break;
- case SADB_SATYPE_AH:
- default:
- return NULL;
- }
-
- return alg_p;
+
+ switch (satype)
+ {
+ case SADB_SATYPE_ESP:
+ alg_p = (exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
+ &esp_ealg[alg_id] : &esp_aalg[alg_id];
+ /* get for write: increment elem count */
+ if (rw)
+ {
+ (exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
+ esp_ealg_num++ : esp_aalg_num++;
+ }
+ break;
+ case SADB_SATYPE_AH:
+ default:
+ return NULL;
+ }
+
+ return alg_p;
}
-const struct sadb_alg *
-kernel_alg_sadb_alg_get(int satype, int exttype, int alg_id)
+const struct sadb_alg* kernel_alg_sadb_alg_get(int satype, int exttype,
+ int alg_id)
{
- return sadb_alg_ptr(satype, exttype, alg_id, 0);
+ return sadb_alg_ptr(satype, exttype, alg_id, 0);
}
/*
- * Forget previous registration
+ * Forget previous registration
*/
-static void
-kernel_alg_init(void)
+static void kernel_alg_init(void)
{
- DBG(DBG_KLIPS,
- DBG_log("alg_init(): memset(%p, 0, %d) memset(%p, 0, %d)",
- &esp_aalg, (int)sizeof (esp_aalg),
- &esp_ealg, (int)sizeof (esp_ealg))
- )
- memset (&esp_aalg, 0, sizeof (esp_aalg));
- memset (&esp_ealg, 0, sizeof (esp_ealg));
- esp_ealg_num=esp_aalg_num = 0;
+ DBG(DBG_KLIPS,
+ DBG_log("alg_init(): memset(%p, 0, %d) memset(%p, 0, %d)",
+ &esp_aalg, (int)sizeof (esp_aalg),
+ &esp_ealg, (int)sizeof (esp_ealg))
+ )
+ memset (&esp_aalg, 0, sizeof (esp_aalg));
+ memset (&esp_ealg, 0, sizeof (esp_ealg));
+ esp_ealg_num=esp_aalg_num = 0;
}
-static int
-kernel_alg_add(int satype, int exttype, const struct sadb_alg *sadb_alg)
+static int kernel_alg_add(int satype, int exttype,
+ const struct sadb_alg *sadb_alg)
{
- struct sadb_alg *alg_p = NULL;
- int alg_id = sadb_alg->sadb_alg_id;
-
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_add(): satype=%d, exttype=%d, alg_id=%d",
- satype, exttype, sadb_alg->sadb_alg_id)
- )
- if (!(alg_p = sadb_alg_ptr(satype, exttype, alg_id, 1)))
- return -1;
-
- /* This logic "mimics" KLIPS: first algo implementation will be used */
- if (alg_p->sadb_alg_id)
- {
+ struct sadb_alg *alg_p = NULL;
+ int alg_id = sadb_alg->sadb_alg_id;
+
DBG(DBG_KLIPS,
- DBG_log("kernel_alg_add(): discarding already setup "
- "satype=%d, exttype=%d, alg_id=%d",
- satype, exttype, sadb_alg->sadb_alg_id)
+ DBG_log("kernel_alg_add(): satype=%d, exttype=%d, alg_id=%d",
+ satype, exttype, sadb_alg->sadb_alg_id)
)
- return 0;
- }
- *alg_p = *sadb_alg;
- return 1;
+ if (!(alg_p = sadb_alg_ptr(satype, exttype, alg_id, 1)))
+ return -1;
+
+ /* This logic "mimics" KLIPS: first algo implementation will be used */
+ if (alg_p->sadb_alg_id)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_add(): discarding already setup "
+ "satype=%d, exttype=%d, alg_id=%d",
+ satype, exttype, sadb_alg->sadb_alg_id)
+ )
+ return 0;
+ }
+ *alg_p = *sadb_alg;
+ return 1;
}
-bool
-kernel_alg_esp_enc_ok(u_int alg_id, u_int key_len,
- struct alg_info_esp *alg_info __attribute__((unused)))
+bool kernel_alg_esp_enc_ok(u_int alg_id, u_int key_len,
+ struct alg_info_esp *alg_info __attribute__((unused)))
{
- struct sadb_alg *alg_p = NULL;
-
- /*
- * test #1: encrypt algo must be present
- */
- int ret = ESP_EALG_PRESENT(alg_id);
- if (!ret) goto out;
-
- alg_p = &esp_ealg[alg_id];
-
- /*
- * test #2: if key_len specified, it must be in range
- */
- if (key_len
- && (key_len < alg_p->sadb_alg_minbits || key_len > alg_p->sadb_alg_maxbits))
- {
- plog("kernel_alg_db_add() key_len not in range: alg_id=%d, "
- "key_len=%d, alg_minbits=%d, alg_maxbits=%d"
- , alg_id, key_len
- , alg_p->sadb_alg_minbits
- , alg_p->sadb_alg_maxbits);
- ret = FALSE;
- }
+ struct sadb_alg *alg_p = NULL;
+
+ /*
+ * test #1: encrypt algo must be present
+ */
+ int ret = ESP_EALG_PRESENT(alg_id);
+ if (!ret) goto out;
+
+ alg_p = &esp_ealg[alg_id];
+
+ /*
+ * test #2: if key_len specified, it must be in range
+ */
+ if (key_len
+ && (key_len < alg_p->sadb_alg_minbits || key_len > alg_p->sadb_alg_maxbits))
+ {
+ plog("kernel_alg_db_add() key_len not in range: alg_id=%d, "
+ "key_len=%d, alg_minbits=%d, alg_maxbits=%d"
+ , alg_id, key_len
+ , alg_p->sadb_alg_minbits
+ , alg_p->sadb_alg_maxbits);
+ ret = FALSE;
+ }
out:
- if (ret)
- {
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_esp_enc_ok(%d,%d): "
- "alg_id=%d, "
- "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
- "res=%d, ret=%d"
- , alg_id, key_len
- , alg_p->sadb_alg_id
- , alg_p->sadb_alg_ivlen
- , alg_p->sadb_alg_minbits
- , alg_p->sadb_alg_maxbits
- , alg_p->sadb_alg_reserved
- , ret);
- )
- }
- else
- {
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_esp_enc_ok(%d,%d): NO", alg_id, key_len);
- )
- }
- return ret;
+ if (ret)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_esp_enc_ok(%d,%d): "
+ "alg_id=%d, "
+ "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
+ "res=%d, ret=%d"
+ , alg_id, key_len
+ , alg_p->sadb_alg_id
+ , alg_p->sadb_alg_ivlen
+ , alg_p->sadb_alg_minbits
+ , alg_p->sadb_alg_maxbits
+ , alg_p->sadb_alg_reserved
+ , ret);
+ )
+ }
+ else
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_esp_enc_ok(%d,%d): NO", alg_id, key_len);
+ )
+ }
+ return ret;
}
/*
* ML: make F_STRICT logic consider enc,auth algorithms
*/
-#ifndef NO_PLUTO
-bool
-kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg, struct alg_info_esp *alg_info)
+bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg,
+ struct alg_info_esp *alg_info)
{
- int ealg_insecure;
-
- /*
- * key_len passed comes from esp_attrs read from peer
- * For many older algoritms (eg 3DES) this key_len is fixed
- * and get passed as 0.
- * ... then get default key_len
- */
- if (key_len == 0)
- key_len = kernel_alg_esp_enc_keylen(ealg) * BITS_PER_BYTE;
-
- /*
- * simple test to toss low key_len, will accept it only
- * if specified in "esp" string
- */
- ealg_insecure = (key_len < 128) ;
-
- if (ealg_insecure
- || (alg_info && alg_info->alg_info_flags & ALG_INFO_F_STRICT))
- {
- int i;
- struct esp_info *esp_info;
+ int ealg_insecure;
- if (alg_info)
+ /*
+ * key_len passed comes from esp_attrs read from peer
+ * For many older algoritms (eg 3DES) this key_len is fixed
+ * and get passed as 0.
+ * ... then get default key_len
+ */
+ if (key_len == 0)
+ key_len = kernel_alg_esp_enc_keylen(ealg) * BITS_PER_BYTE;
+
+ /*
+ * simple test to toss low key_len, will accept it only
+ * if specified in "esp" string
+ */
+ ealg_insecure = (key_len < 128) ;
+
+ if (ealg_insecure
+ || (alg_info && alg_info->alg_info_flags & ALG_INFO_F_STRICT))
{
- ALG_INFO_ESP_FOREACH(alg_info, esp_info, i)
- {
- if (esp_info->esp_ealg_id == ealg
- && (esp_info->esp_ealg_keylen == 0 || key_len == 0
- || esp_info->esp_ealg_keylen == key_len)
- && esp_info->esp_aalg_id == aalg)
+ int i;
+ struct esp_info *esp_info;
+
+ if (alg_info)
{
- if (ealg_insecure)
- {
- loglog(RC_LOG_SERIOUS
- , "You should NOT use insecure ESP algorithms [%s (%d)]!"
- , enum_name(&esp_transformid_names, ealg), key_len);
- }
- return TRUE;
+ ALG_INFO_ESP_FOREACH(alg_info, esp_info, i)
+ {
+ if (esp_info->esp_ealg_id == ealg
+ && (esp_info->esp_ealg_keylen == 0 || key_len == 0
+ || esp_info->esp_ealg_keylen == key_len)
+ && esp_info->esp_aalg_id == aalg)
+ {
+ if (ealg_insecure)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "You should NOT use insecure ESP algorithms [%s (%d)]!"
+ , enum_name(&esp_transformid_names, ealg), key_len);
+ }
+ return TRUE;
+ }
+ }
}
- }
+ plog("IPSec Transform [%s (%d), %s] refused due to %s",
+ enum_name(&esp_transformid_names, ealg), key_len,
+ enum_name(&auth_alg_names, aalg),
+ ealg_insecure ? "insecure key_len and enc. alg. not listed in \"esp\" string" : "strict flag");
+ return FALSE;
}
- plog("IPSec Transform [%s (%d), %s] refused due to %s",
- enum_name(&esp_transformid_names, ealg), key_len,
- enum_name(&auth_alg_names, aalg),
- ealg_insecure ? "insecure key_len and enc. alg. not listed in \"esp\" string" : "strict flag");
- return FALSE;
- }
- return TRUE;
+ return TRUE;
}
-#endif /* NO_PLUTO */
-/*
- * Load kernel_alg arrays from /proc
- * used in manual mode from klips/utils/spi.c
+/**
+ * Load kernel_alg arrays from /proc used in manual mode from klips/utils/spi.c
*/
-int
-kernel_alg_proc_read(void)
+int kernel_alg_proc_read(void)
{
- int satype;
- int supp_exttype;
- int alg_id, ivlen, minbits, maxbits;
- struct sadb_alg sadb_alg;
- int ret;
- char buf[128];
+ int satype;
+ int supp_exttype;
+ int alg_id, ivlen, minbits, maxbits;
+ struct sadb_alg sadb_alg;
+ int ret;
+ char buf[128];
- FILE *fp=fopen("/proc/net/pf_key_supported", "r");
+ FILE *fp=fopen("/proc/net/pf_key_supported", "r");
- if (!fp)
- return -1;
+ if (!fp)
+ return -1;
- kernel_alg_init();
+ kernel_alg_init();
- while (fgets(buf, sizeof(buf), fp))
- {
- if (buf[0] != ' ') /* skip titles */
- continue;
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (buf[0] != ' ') /* skip titles */
+ continue;
- sscanf(buf, "%d %d %d %d %d %d"
- ,&satype, &supp_exttype
- , &alg_id, &ivlen
- , &minbits, &maxbits);
+ sscanf(buf, "%d %d %d %d %d %d"
+ ,&satype, &supp_exttype
+ , &alg_id, &ivlen
+ , &minbits, &maxbits);
- switch (satype)
- {
- case SADB_SATYPE_ESP:
- switch(supp_exttype)
- {
- case SADB_EXT_SUPPORTED_AUTH:
- case SADB_EXT_SUPPORTED_ENCRYPT:
- sadb_alg.sadb_alg_id = alg_id;
- sadb_alg.sadb_alg_ivlen = ivlen;
- sadb_alg.sadb_alg_minbits = minbits;
- sadb_alg.sadb_alg_maxbits = maxbits;
- ret = kernel_alg_add(satype, supp_exttype, &sadb_alg);
- DBG(DBG_CRYPT,
- DBG_log("kernel_alg_proc_read() alg_id=%d, "
- "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
- "ret=%d"
- , sadb_alg.sadb_alg_id
- , sadb_alg.sadb_alg_ivlen
- , sadb_alg.sadb_alg_minbits
- , sadb_alg.sadb_alg_maxbits
- , ret)
- )
- }
- default:
- continue;
+ switch (satype)
+ {
+ case SADB_SATYPE_ESP:
+ switch(supp_exttype)
+ {
+ case SADB_EXT_SUPPORTED_AUTH:
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ sadb_alg.sadb_alg_id = alg_id;
+ sadb_alg.sadb_alg_ivlen = ivlen;
+ sadb_alg.sadb_alg_minbits = minbits;
+ sadb_alg.sadb_alg_maxbits = maxbits;
+ ret = kernel_alg_add(satype, supp_exttype, &sadb_alg);
+ DBG(DBG_CRYPT,
+ DBG_log("kernel_alg_proc_read() alg_id=%d, "
+ "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
+ "ret=%d"
+ , sadb_alg.sadb_alg_id
+ , sadb_alg.sadb_alg_ivlen
+ , sadb_alg.sadb_alg_minbits
+ , sadb_alg.sadb_alg_maxbits
+ , ret)
+ )
+ }
+ default:
+ continue;
+ }
}
- }
- fclose(fp);
- return 0;
+ fclose(fp);
+ return 0;
}
-/*
- * Load kernel_alg arrays pluto's SADB_REGISTER
- * user by pluto/kernel.c
+/**
+ * Load kernel_alg arrays pluto's SADB_REGISTER user by pluto/kernel.c
*/
-
-void
-kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen)
+void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen)
{
- /* Trick: one 'type-mangle-able' pointer to ease offset/assign */
- union {
- const struct sadb_msg *msg;
- const struct sadb_supported *supported;
- const struct sadb_ext *ext;
- const struct sadb_alg *alg;
- const char *ch;
- } sadb;
-
- int satype;
- int msglen;
- int i = 0;
-
- /* Initialize alg arrays */
- kernel_alg_init();
- satype = msg_buf->sadb_msg_satype;
- sadb.msg = msg_buf;
- msglen = sadb.msg->sadb_msg_len*IPSEC_PFKEYv2_ALIGN;
- msglen -= sizeof(struct sadb_msg);
- buflen -= sizeof(struct sadb_msg);
- passert(buflen > 0);
-
- sadb.msg++;
-
- while(msglen)
- {
- int supp_exttype = sadb.supported->sadb_supported_exttype;
- int supp_len = sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN;
-
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
- "sadb_msg_len=%d sadb_supported_len=%d"
- , satype==SADB_SATYPE_ESP? "ESP" : "AH"
- , msg_buf->sadb_msg_len, supp_len)
- )
- sadb.supported++;
- msglen -= supp_len;
- buflen -= supp_len;
- passert(buflen >= 0);
-
- for (supp_len -= sizeof(struct sadb_supported);
- supp_len;
- supp_len -= sizeof(struct sadb_alg), sadb.alg++,i++)
+ /* Trick: one 'type-mangle-able' pointer to ease offset/assign */
+ union {
+ const struct sadb_msg *msg;
+ const struct sadb_supported *supported;
+ const struct sadb_ext *ext;
+ const struct sadb_alg *alg;
+ const char *ch;
+ } sadb;
+
+ int satype;
+ int msglen;
+ int i = 0;
+
+ /* Initialize alg arrays */
+ kernel_alg_init();
+ satype = msg_buf->sadb_msg_satype;
+ sadb.msg = msg_buf;
+ msglen = sadb.msg->sadb_msg_len*IPSEC_PFKEYv2_ALIGN;
+ msglen -= sizeof(struct sadb_msg);
+ buflen -= sizeof(struct sadb_msg);
+ passert(buflen > 0);
+
+ sadb.msg++;
+
+ while(msglen)
{
- int ret = kernel_alg_add(satype, supp_exttype, sadb.alg);
-
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
- "alg[%d], exttype=%d, satype=%d, alg_id=%d, "
- "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
- "res=%d, ret=%d"
- , satype==SADB_SATYPE_ESP? "ESP" : "AH"
- , i
- , supp_exttype
- , satype
- , sadb.alg->sadb_alg_id
- , sadb.alg->sadb_alg_ivlen
- , sadb.alg->sadb_alg_minbits
- , sadb.alg->sadb_alg_maxbits
- , sadb.alg->sadb_alg_reserved
- , ret)
- )
+ int supp_exttype = sadb.supported->sadb_supported_exttype;
+ int supp_len = sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN;
+
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
+ "sadb_msg_len=%d sadb_supported_len=%d"
+ , satype==SADB_SATYPE_ESP? "ESP" : "AH"
+ , msg_buf->sadb_msg_len, supp_len)
+ )
+ sadb.supported++;
+ msglen -= supp_len;
+ buflen -= supp_len;
+ passert(buflen >= 0);
+
+ for (supp_len -= sizeof(struct sadb_supported);
+ supp_len;
+ supp_len -= sizeof(struct sadb_alg), sadb.alg++,i++)
+ {
+ int ret = kernel_alg_add(satype, supp_exttype, sadb.alg);
+
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
+ "alg[%d], exttype=%d, satype=%d, alg_id=%d, "
+ "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
+ "res=%d, ret=%d"
+ , satype==SADB_SATYPE_ESP? "ESP" : "AH"
+ , i
+ , supp_exttype
+ , satype
+ , sadb.alg->sadb_alg_id
+ , sadb.alg->sadb_alg_ivlen
+ , sadb.alg->sadb_alg_minbits
+ , sadb.alg->sadb_alg_maxbits
+ , sadb.alg->sadb_alg_reserved
+ , ret)
+ )
+ }
}
- }
}
-u_int
-kernel_alg_esp_enc_keylen(u_int alg_id)
+u_int kernel_alg_esp_enc_keylen(u_int alg_id)
{
- u_int keylen = 0;
+ u_int keylen = 0;
- if (!ESP_EALG_PRESENT(alg_id))
- goto none;
+ if (!ESP_EALG_PRESENT(alg_id))
+ goto none;
- keylen = esp_ealg[alg_id].sadb_alg_maxbits/BITS_PER_BYTE;
+ keylen = esp_ealg[alg_id].sadb_alg_maxbits/BITS_PER_BYTE;
- switch (alg_id)
- {
- /*
- * this is veryUgly[TM]
- * Peer should have sent KEY_LENGTH attribute for ESP_AES
- * but if not do force it to 128 instead of using sadb_alg_maxbits
- * from kernel.
- */
- case ESP_AES:
- keylen = 128/BITS_PER_BYTE;
- break;
- }
-
-none:
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_esp_enc_keylen():"
- "alg_id=%d, keylen=%d",
- alg_id, keylen)
- )
- return keylen;
+ switch (alg_id)
+ {
+ /*
+ * this is veryUgly[TM]
+ * Peer should have sent KEY_LENGTH attribute for ESP_AES
+ * but if not do force it to 128 instead of using sadb_alg_maxbits
+ * from kernel.
+ */
+ case ESP_AES:
+ keylen = 128/BITS_PER_BYTE;
+ break;
+ }
+
+none:
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_esp_enc_keylen():"
+ "alg_id=%d, keylen=%d",
+ alg_id, keylen)
+ )
+ return keylen;
}
-struct sadb_alg *
-kernel_alg_esp_sadb_alg(u_int alg_id)
+struct sadb_alg* kernel_alg_esp_sadb_alg(u_int alg_id)
{
- struct sadb_alg *sadb_alg = (ESP_EALG_PRESENT(alg_id))
- ? &esp_ealg[alg_id] : NULL;
-
- DBG(DBG_KLIPS,
- DBG_log("kernel_alg_esp_sadb_alg(): alg_id=%d, sadb_alg=%p"
- , alg_id, sadb_alg)
- )
- return sadb_alg;
+ struct sadb_alg *sadb_alg = (ESP_EALG_PRESENT(alg_id))
+ ? &esp_ealg[alg_id] : NULL;
+
+ DBG(DBG_KLIPS,
+ DBG_log("kernel_alg_esp_sadb_alg(): alg_id=%d, sadb_alg=%p"
+ , alg_id, sadb_alg)
+ )
+ return sadb_alg;
}
-#ifndef NO_PLUTO
void kernel_alg_list(void)
{
- u_int sadb_id;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered ESP Encryption Algorithms:");
- whack_log(RC_COMMENT, " ");
-
- for (sadb_id = 1; sadb_id <= SADB_EALG_MAX; sadb_id++)
- {
- if (ESP_EALG_PRESENT(sadb_id))
+ char buf[BUF_LEN];
+ char *pos;
+ int n, len;
+ u_int sadb_id;
+
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of registered ESP Algorithms:");
+ whack_log(RC_COMMENT, " ");
+
+ pos = buf;
+ *pos = '\0';
+ len = BUF_LEN;
+ for (sadb_id = 1; sadb_id <= SADB_EALG_MAX; sadb_id++)
{
- struct sadb_alg *alg_p = &esp_ealg[sadb_id];
-
- whack_log(RC_COMMENT, "#%-5d %s, blocksize: %d, keylen: %d-%d"
- , sadb_id
- , enum_name(&esp_transformid_names, sadb_id)
- , alg_p->sadb_alg_ivlen
- , alg_p->sadb_alg_minbits
- , alg_p->sadb_alg_maxbits
- );
+ if (ESP_EALG_PRESENT(sadb_id))
+ {
+ n = snprintf(pos, len, " %s",
+ enum_name(&esp_transformid_names, sadb_id));
+ pos += n;
+ len -= n;
+ if (len <= 0)
+ {
+ break;
+ }
+ }
}
- }
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered ESP Authentication Algorithms:");
- whack_log(RC_COMMENT, " ");
-
- for (sadb_id = 1; sadb_id <= SADB_AALG_MAX; sadb_id++)
- {
- if (ESP_AALG_PRESENT(sadb_id))
+ whack_log(RC_COMMENT, " encryption:%s", buf);
+
+ pos = buf;
+ *pos = '\0';
+ len = BUF_LEN;
+ for (sadb_id = 1; sadb_id <= SADB_AALG_MAX; sadb_id++)
{
- u_int aaid = alg_info_esp_sadb2aa(sadb_id);
- struct sadb_alg *alg_p = &esp_aalg[sadb_id];
-
- whack_log(RC_COMMENT, "#%-5d %s, keylen: %d-%d"
- , aaid
- , enum_name(&auth_alg_names, aaid)
- , alg_p->sadb_alg_minbits
- , alg_p->sadb_alg_maxbits
- );
+ if (ESP_AALG_PRESENT(sadb_id))
+ {
+ u_int aaid = alg_info_esp_sadb2aa(sadb_id);
+
+ n = snprintf(pos, len, " %s", enum_name(&auth_alg_names, aaid));
+ pos += n;
+ len -= n;
+ if (len <= 0)
+ {
+ break;
+ }
+ }
}
- }
+ whack_log(RC_COMMENT, " integrity: %s", buf);
}
-void
-kernel_alg_show_connection(struct connection *c, const char *instance)
+void kernel_alg_show_connection(struct connection *c, const char *instance)
{
- char buf[256];
- struct state *st;
-
- if (c->alg_info_esp)
- {
- alg_info_snprint(buf, sizeof(buf), (struct alg_info *)c->alg_info_esp);
- whack_log(RC_COMMENT
- , "\"%s\"%s: ESP algorithms wanted: %s"
- , c->name
- , instance
- , buf);
- }
- if (c->alg_info_esp)
- {
- alg_info_snprint_esp(buf, sizeof(buf), c->alg_info_esp);
- whack_log(RC_COMMENT
- , "\"%s\"%s: ESP algorithms loaded: %s"
- , c->name
- , instance
- , buf);
- }
- st = state_with_serialno(c->newest_ipsec_sa);
- if (st && st->st_esp.present)
- whack_log(RC_COMMENT
- , "\"%s\"%s: ESP algorithm newest: %s_%d-%s; pfsgroup=%s"
- , c->name
- , instance
- , enum_show(&esp_transformid_names, st->st_esp.attrs.transid)
- +4 /* strlen("ESP_") */
- , st->st_esp.attrs.key_len
- , enum_show(&auth_alg_names, st->st_esp.attrs.auth)+
- +15 /* strlen("AUTH_ALGORITHM_") */
- , c->policy & POLICY_PFS ?
- c->alg_info_esp->esp_pfsgroup ?
- enum_show(&oakley_group_names,
- c->alg_info_esp->esp_pfsgroup)
- +13 /*strlen("OAKLEY_GROUP_")*/
- : "<Phase1>"
- : "<N/A>"
- );
+ struct state *st = state_with_serialno(c->newest_ipsec_sa);
+
+ if (st && st->st_esp.present)
+ {
+ const char *aalg_name, *pfsgroup_name;
+
+ aalg_name = (c->policy & POLICY_AUTHENTICATE) ?
+ enum_show(&ah_transformid_names, st->st_ah.attrs.transid):
+ enum_show(&auth_alg_names, st->st_esp.attrs.auth);
+
+ pfsgroup_name = (c->policy & POLICY_PFS) ?
+ (c->alg_info_esp->esp_pfsgroup) ?
+ enum_show(&oakley_group_names,
+ c->alg_info_esp->esp_pfsgroup) :
+ "<Phase1>" : "<N/A>";
+
+ if (st->st_esp.attrs.key_len)
+ {
+ whack_log(RC_COMMENT, "\"%s\"%s: ESP%s proposal: %s_%u/%s/%s",
+ c->name, instance,
+ (st->st_ah.present) ? "/AH" : "",
+ enum_show(&esp_transformid_names, st->st_esp.attrs.transid),
+ st->st_esp.attrs.key_len, aalg_name, pfsgroup_name);
+ }
+ else
+ {
+ whack_log(RC_COMMENT, "\"%s\"%s: ESP%s proposal: %s/%s/%s",
+ c->name, instance,
+ (st->st_ah.present) ? "/AH" : "",
+ enum_show(&esp_transformid_names, st->st_esp.attrs.transid),
+ aalg_name, pfsgroup_name);
+ }
+ }
}
-#endif /* NO_PLUTO */
-bool
-kernel_alg_esp_auth_ok(u_int auth,
- struct alg_info_esp *alg_info __attribute__((unused)))
+bool kernel_alg_esp_auth_ok(u_int auth,
+ struct alg_info_esp *alg_info __attribute__((unused)))
{
- return ESP_AALG_PRESENT(alg_info_esp_aa2sadb(auth));
+ return ESP_AALG_PRESENT(alg_info_esp_aa2sadb(auth));
}
-u_int
-kernel_alg_esp_auth_keylen(u_int auth)
+u_int kernel_alg_esp_auth_keylen(u_int auth)
{
- u_int sadb_aalg = alg_info_esp_aa2sadb(auth);
+ u_int sadb_aalg = alg_info_esp_aa2sadb(auth);
- u_int a_keylen = (sadb_aalg)
- ? esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE
- : 0;
+ u_int a_keylen = (sadb_aalg)
+ ? esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE
+ : 0;
- DBG(DBG_CONTROL | DBG_CRYPT | DBG_PARSING,
- DBG_log("kernel_alg_esp_auth_keylen(auth=%d, sadb_aalg=%d): "
- "a_keylen=%d", auth, sadb_aalg, a_keylen)
- )
- return a_keylen;
+ DBG(DBG_CONTROL | DBG_CRYPT | DBG_PARSING,
+ DBG_log("kernel_alg_esp_auth_keylen(auth=%d, sadb_aalg=%d): "
+ "a_keylen=%d", auth, sadb_aalg, a_keylen)
+ )
+ return a_keylen;
}
-struct esp_info *
-kernel_alg_esp_info(int transid, int auth)
+struct esp_info* kernel_alg_esp_info(int transid, int auth)
{
- int sadb_aalg, sadb_ealg;
- static struct esp_info ei_buf;
-
- sadb_ealg = transid;
- sadb_aalg = alg_info_esp_aa2sadb(auth);
-
- if (!ESP_EALG_PRESENT(sadb_ealg))
- goto none;
- if (!ESP_AALG_PRESENT(sadb_aalg))
- goto none;
-
- memset(&ei_buf, 0, sizeof (ei_buf));
- ei_buf.transid = transid;
- ei_buf.auth = auth;
-
- /* don't return "default" keylen because this value is used from
- * setup_half_ipsec_sa() to "validate" keylen
- * In effect, enckeylen will be used as "max" value
- */
- ei_buf.enckeylen = esp_ealg[sadb_ealg].sadb_alg_maxbits/BITS_PER_BYTE;
- ei_buf.authkeylen = esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE;
- ei_buf.encryptalg = sadb_ealg;
- ei_buf.authalg = sadb_aalg;
-
- DBG(DBG_PARSING,
- DBG_log("kernel_alg_esp_info():"
- "transid=%d, auth=%d, ei=%p, "
- "enckeylen=%d, authkeylen=%d, encryptalg=%d, authalg=%d",
- transid, auth, &ei_buf,
- (int)ei_buf.enckeylen, (int)ei_buf.authkeylen,
- ei_buf.encryptalg, ei_buf.authalg)
- )
- return &ei_buf;
+ int sadb_aalg, sadb_ealg;
+ static struct esp_info ei_buf;
+
+ sadb_ealg = transid;
+ sadb_aalg = alg_info_esp_aa2sadb(auth);
+
+ if (!ESP_EALG_PRESENT(sadb_ealg))
+ goto none;
+ if (!ESP_AALG_PRESENT(sadb_aalg))
+ goto none;
+
+ memset(&ei_buf, 0, sizeof (ei_buf));
+ ei_buf.transid = transid;
+ ei_buf.auth = auth;
+
+ /* don't return "default" keylen because this value is used from
+ * setup_half_ipsec_sa() to "validate" keylen
+ * In effect, enckeylen will be used as "max" value
+ */
+ ei_buf.enckeylen = esp_ealg[sadb_ealg].sadb_alg_maxbits/BITS_PER_BYTE;
+ ei_buf.authkeylen = esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE;
+ ei_buf.encryptalg = sadb_ealg;
+ ei_buf.authalg = sadb_aalg;
+
+ DBG(DBG_PARSING,
+ DBG_log("kernel_alg_esp_info():"
+ "transid=%d, auth=%d, ei=%p, "
+ "enckeylen=%d, authkeylen=%d, encryptalg=%d, authalg=%d",
+ transid, auth, &ei_buf,
+ (int)ei_buf.enckeylen, (int)ei_buf.authkeylen,
+ ei_buf.encryptalg, ei_buf.authalg)
+ )
+ return &ei_buf;
none:
- DBG(DBG_PARSING,
- DBG_log("kernel_alg_esp_info():"
- "transid=%d, auth=%d, ei=NULL",
- transid, auth)
- )
- return NULL;
+ DBG(DBG_PARSING,
+ DBG_log("kernel_alg_esp_info():"
+ "transid=%d, auth=%d, ei=NULL",
+ transid, auth)
+ )
+ return NULL;
}
-#ifndef NO_PLUTO
-static void
-kernel_alg_policy_algorithms(struct esp_info *esp_info)
+static void kernel_alg_policy_algorithms(struct esp_info *esp_info)
{
- u_int ealg_id = esp_info->esp_ealg_id;
-
- switch(ealg_id)
- {
- case 0:
- case ESP_DES:
- case ESP_3DES:
- case ESP_NULL:
- case ESP_CAST:
- break;
- default:
- if (!esp_info->esp_ealg_keylen)
+ u_int ealg_id = esp_info->esp_ealg_id;
+
+ switch(ealg_id)
{
- /* algos that need KEY_LENGTH
- *
- * Note: this is a very dirty hack ;-)
- * Idea: Add a key_length_needed attribute to
- * esp_ealg ??
- */
- esp_info->esp_ealg_keylen = esp_ealg[ealg_id].sadb_alg_maxbits;
+ case 0:
+ case ESP_DES:
+ case ESP_3DES:
+ case ESP_NULL:
+ case ESP_CAST:
+ break;
+ default:
+ if (!esp_info->esp_ealg_keylen)
+ {
+ /* algos that need KEY_LENGTH
+ *
+ * Note: this is a very dirty hack ;-)
+ * Idea: Add a key_length_needed attribute to
+ * esp_ealg ??
+ */
+ esp_info->esp_ealg_keylen = esp_ealg[ealg_id].sadb_alg_maxbits;
+ }
}
- }
}
-static bool
-kernel_alg_db_add(struct db_context *db_ctx, struct esp_info *esp_info, lset_t policy)
+static bool kernel_alg_db_add(struct db_context *db_ctx,
+ struct esp_info *esp_info, lset_t policy)
{
- u_int ealg_id, aalg_id;
-
- ealg_id = esp_info->esp_ealg_id;
+ u_int ealg_id, aalg_id;
- if (!ESP_EALG_PRESENT(ealg_id))
- {
- DBG_log("kernel_alg_db_add() kernel enc ealg_id=%d not present", ealg_id);
- return FALSE;
- }
-
- if (!(policy & POLICY_AUTHENTICATE)) /* skip ESP auth attrs for AH */
- {
- aalg_id = alg_info_esp_aa2sadb(esp_info->esp_aalg_id);
+ ealg_id = esp_info->esp_ealg_id;
- if (!ESP_AALG_PRESENT(aalg_id))
+ if (!ESP_EALG_PRESENT(ealg_id))
{
- DBG_log("kernel_alg_db_add() kernel auth "
- "aalg_id=%d not present", aalg_id);
- return FALSE;
+ DBG_log("kernel_alg_db_add() kernel enc ealg_id=%d not present", ealg_id);
+ return FALSE;
}
- }
+
+ if (!(policy & POLICY_AUTHENTICATE)) /* skip ESP auth attrs for AH */
+ {
+ aalg_id = alg_info_esp_aa2sadb(esp_info->esp_aalg_id);
- /* do algo policy */
- kernel_alg_policy_algorithms(esp_info);
+ if (!ESP_AALG_PRESENT(aalg_id))
+ {
+ DBG_log("kernel_alg_db_add() kernel auth "
+ "aalg_id=%d not present", aalg_id);
+ return FALSE;
+ }
+ }
- /* open new transformation */
- db_trans_add(db_ctx, ealg_id);
+ /* do algo policy */
+ kernel_alg_policy_algorithms(esp_info);
- /* add ESP auth attr */
- if (!(policy & POLICY_AUTHENTICATE))
- db_attr_add_values(db_ctx, AUTH_ALGORITHM, esp_info->esp_aalg_id);
+ /* open new transformation */
+ db_trans_add(db_ctx, ealg_id);
- /* add keylegth if specified in esp= string */
- if (esp_info->esp_ealg_keylen)
- db_attr_add_values(db_ctx, KEY_LENGTH, esp_info->esp_ealg_keylen);
-
- return TRUE;
+ /* add ESP auth attr */
+ if (!(policy & POLICY_AUTHENTICATE))
+ db_attr_add_values(db_ctx, AUTH_ALGORITHM, esp_info->esp_aalg_id);
+
+ /* add keylegth if specified in esp= string */
+ if (esp_info->esp_ealg_keylen)
+ db_attr_add_values(db_ctx, KEY_LENGTH, esp_info->esp_ealg_keylen);
+
+ return TRUE;
}
-/*
- * Create proposal with runtime kernel algos, merging
- * with passed proposal if not NULL
+/*
+ * Create proposal with runtime kernel algos, merging
+ * with passed proposal if not NULL
*
- * for now this function does free() previous returned
- * malloced pointer (this quirk allows easier spdb.c change)
+ * for now this function does free() previous returned
+ * malloced pointer (this quirk allows easier spdb.c change)
*/
-struct db_context *
-kernel_alg_db_new(struct alg_info_esp *alg_info, lset_t policy )
+struct db_context* kernel_alg_db_new(struct alg_info_esp *alg_info,
+ lset_t policy )
{
- const struct esp_info *esp_info;
- struct esp_info tmp_esp_info;
- struct db_context *ctx_new=NULL;
- struct db_trans *t;
- struct db_prop *prop;
- u_int trans_cnt;
- int tn = 0;
-
- if (!(policy & POLICY_ENCRYPT)) /* not possible, I think */
- return NULL;
+ const struct esp_info *esp_info;
+ struct esp_info tmp_esp_info;
+ struct db_context *ctx_new = NULL;
+ struct db_prop *prop;
+ u_int trans_cnt = esp_ealg_num * esp_aalg_num;
- trans_cnt = esp_ealg_num * esp_aalg_num;
- DBG(DBG_EMITTING,
- DBG_log("kernel_alg_db_prop_new() initial trans_cnt=%d"
- , trans_cnt)
- )
-
- /* pass aprox. number of transforms and attributes */
- ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2);
+ if (!(policy & POLICY_ENCRYPT)) /* not possible, I think */
+ {
+ return NULL;
+ }
- /*
- * Loop: for each element (struct esp_info) of alg_info,
- * if kernel support is present then build the transform (and attrs)
- * if NULL alg_info, propose everything ...
- */
+ /* pass aprox. number of transforms and attributes */
+ ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2);
- if (alg_info)
- {
- int i;
+ /*
+ * Loop: for each element (struct esp_info) of alg_info,
+ * if kernel support is present then build the transform (and attrs)
+ * if NULL alg_info, propose everything ...
+ */
- ALG_INFO_ESP_FOREACH(alg_info, esp_info, i)
+ if (alg_info)
{
- tmp_esp_info = *esp_info;
- kernel_alg_db_add(ctx_new, &tmp_esp_info, policy);
+ int i;
+
+ ALG_INFO_ESP_FOREACH(alg_info, esp_info, i)
+ {
+ tmp_esp_info = *esp_info;
+ kernel_alg_db_add(ctx_new, &tmp_esp_info, policy);
+ }
}
- }
- else
- {
- u_int ealg_id;
-
- ESP_EALG_FOR_EACH_UPDOWN(ealg_id)
+ else
{
- u_int aalg_id;
-
- tmp_esp_info.esp_ealg_id = ealg_id;
- tmp_esp_info.esp_ealg_keylen = 0;
-
- for (aalg_id = 1; aalg_id <= SADB_AALG_MAX; aalg_id++)
- {
- if (ESP_AALG_PRESENT(aalg_id))
+ u_int ealg_id;
+
+ ESP_EALG_FOR_EACH_UPDOWN(ealg_id)
{
- tmp_esp_info.esp_aalg_id = alg_info_esp_sadb2aa(aalg_id);
- tmp_esp_info.esp_aalg_keylen = 0;
- kernel_alg_db_add(ctx_new, &tmp_esp_info, policy);
+ u_int aalg_id;
+
+ tmp_esp_info.esp_ealg_id = ealg_id;
+ tmp_esp_info.esp_ealg_keylen = 0;
+
+ for (aalg_id = 1; aalg_id <= SADB_AALG_MAX; aalg_id++)
+ {
+ if (ESP_AALG_PRESENT(aalg_id))
+ {
+ tmp_esp_info.esp_aalg_id = alg_info_esp_sadb2aa(aalg_id);
+ tmp_esp_info.esp_aalg_keylen = 0;
+ kernel_alg_db_add(ctx_new, &tmp_esp_info, policy);
+ }
+ }
}
- }
}
- }
-
- prop = db_prop_get(ctx_new);
-
- DBG(DBG_CONTROL|DBG_EMITTING,
- DBG_log("kernel_alg_db_prop_new() "
- "will return p_new->protoid=%d, p_new->trans_cnt=%d"
- , prop->protoid, prop->trans_cnt)
- )
-
- for (t = prop->trans, tn = 0; tn < prop->trans_cnt; tn++)
- {
- DBG(DBG_CONTROL|DBG_EMITTING,
- DBG_log("kernel_alg_db_prop_new() "
- " trans[%d]: transid=%d, attr_cnt=%d, "
- "attrs[0].type=%d, attrs[0].val=%d"
- , tn
- , t[tn].transid, t[tn].attr_cnt
- , t[tn].attrs[0].type, t[tn].attrs[0].val)
- )
- }
- return ctx_new;
+ prop = db_prop_get(ctx_new);
+ return ctx_new;
}
-#endif /* NO_PLUTO */
+
diff --git a/src/pluto/kernel_alg.h b/src/pluto/kernel_alg.h
index 14c2664aa..5ce8c3003 100644
--- a/src/pluto/kernel_alg.h
+++ b/src/pluto/kernel_alg.h
@@ -10,8 +10,6 @@
* 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: kernel_alg.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _KERNEL_ALG_H
diff --git a/src/pluto/kernel_netlink.c b/src/pluto/kernel_netlink.c
index 4269de66e..b4b4774c7 100644
--- a/src/pluto/kernel_netlink.c
+++ b/src/pluto/kernel_netlink.c
@@ -10,8 +10,6 @@
* 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: kernel_netlink.c 3850 2008-04-18 20:01:49Z andreas $
*/
#if defined(linux) && defined(KERNEL26_SUPPORT)
@@ -39,7 +37,7 @@
#include "kernel_netlink.h"
#include "kernel_pfkey.h"
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include "kernel_alg.h"
/* Minimum priority number in SPD used by pluto. */
@@ -48,72 +46,72 @@
static int netlinkfd = NULL_FD;
static int netlink_bcast_fd = NULL_FD;
-#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
+#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
static sparse_names xfrm_type_names = {
- NE(NLMSG_NOOP),
- NE(NLMSG_ERROR),
- NE(NLMSG_DONE),
- NE(NLMSG_OVERRUN),
+ NE(NLMSG_NOOP),
+ NE(NLMSG_ERROR),
+ NE(NLMSG_DONE),
+ NE(NLMSG_OVERRUN),
- NE(XFRM_MSG_NEWSA),
- NE(XFRM_MSG_DELSA),
- NE(XFRM_MSG_GETSA),
+ NE(XFRM_MSG_NEWSA),
+ NE(XFRM_MSG_DELSA),
+ NE(XFRM_MSG_GETSA),
- NE(XFRM_MSG_NEWPOLICY),
- NE(XFRM_MSG_DELPOLICY),
- NE(XFRM_MSG_GETPOLICY),
+ NE(XFRM_MSG_NEWPOLICY),
+ NE(XFRM_MSG_DELPOLICY),
+ NE(XFRM_MSG_GETPOLICY),
- NE(XFRM_MSG_ALLOCSPI),
- NE(XFRM_MSG_ACQUIRE),
- NE(XFRM_MSG_EXPIRE),
+ NE(XFRM_MSG_ALLOCSPI),
+ NE(XFRM_MSG_ACQUIRE),
+ NE(XFRM_MSG_EXPIRE),
- NE(XFRM_MSG_UPDPOLICY),
- NE(XFRM_MSG_UPDSA),
+ NE(XFRM_MSG_UPDPOLICY),
+ NE(XFRM_MSG_UPDSA),
- NE(XFRM_MSG_POLEXPIRE),
+ NE(XFRM_MSG_POLEXPIRE),
- NE(XFRM_MSG_MAX),
+ NE(XFRM_MSG_MAX),
- { 0, sparse_end }
+ { 0, sparse_end }
};
#undef NE
/* Authentication algorithms */
static sparse_names aalg_list = {
- { SADB_X_AALG_NULL, "digest_null" },
- { SADB_AALG_MD5HMAC, "md5" },
- { SADB_AALG_SHA1HMAC, "sha1" },
- { SADB_X_AALG_SHA2_256HMAC, "sha256" },
- { SADB_X_AALG_SHA2_384HMAC, "sha384" },
- { SADB_X_AALG_SHA2_512HMAC, "sha512" },
- { SADB_X_AALG_RIPEMD160HMAC, "ripemd160" },
- { SADB_X_AALG_AES_XCBC_MAC, "xcbc(aes)"},
- { SADB_X_AALG_NULL, "null" },
- { 0, sparse_end }
+ { SADB_X_AALG_NULL, "digest_null" },
+ { SADB_AALG_MD5HMAC, "md5" },
+ { SADB_AALG_SHA1HMAC, "sha1" },
+ { SADB_X_AALG_SHA2_256HMAC, "sha256" },
+ { SADB_X_AALG_SHA2_384HMAC, "sha384" },
+ { SADB_X_AALG_SHA2_512HMAC, "sha512" },
+ { SADB_X_AALG_RIPEMD160HMAC, "ripemd160" },
+ { SADB_X_AALG_AES_XCBC_MAC, "xcbc(aes)"},
+ { SADB_X_AALG_NULL, "null" },
+ { 0, sparse_end }
};
/* Encryption algorithms */
static sparse_names ealg_list = {
- { SADB_EALG_NULL, "cipher_null" },
- { SADB_EALG_DESCBC, "des" },
- { SADB_EALG_3DESCBC, "des3_ede" },
- { SADB_X_EALG_CASTCBC, "cast128" },
- { SADB_X_EALG_BLOWFISHCBC, "blowfish" },
- { SADB_X_EALG_AESCBC, "aes" },
- { SADB_X_EALG_CAMELLIACBC, "cbc(camellia)" },
- { SADB_X_EALG_SERPENTCBC, "serpent" },
- { SADB_X_EALG_TWOFISHCBC, "twofish" },
- { 0, sparse_end }
+ { SADB_EALG_NULL, "cipher_null" },
+ { SADB_EALG_DESCBC, "des" },
+ { SADB_EALG_3DESCBC, "des3_ede" },
+ { SADB_X_EALG_CASTCBC, "cast128" },
+ { SADB_X_EALG_BLOWFISHCBC, "blowfish" },
+ { SADB_X_EALG_AESCBC, "aes" },
+ { SADB_X_EALG_CAMELLIACBC, "cbc(camellia)" },
+ { SADB_X_EALG_SERPENTCBC, "serpent" },
+ { SADB_X_EALG_TWOFISHCBC, "twofish" },
+ { 0, sparse_end }
};
/* Compression algorithms */
static sparse_names calg_list = {
- { SADB_X_CALG_DEFLATE, "deflate" },
- { SADB_X_CALG_LZS, "lzs" },
- { SADB_X_CALG_LZJH, "lzjh" },
- { 0, sparse_end }
+ { SADB_X_CALG_DEFLATE, "deflate" },
+ { SADB_X_CALG_LZS, "lzs" },
+ { SADB_X_CALG_LZJH, "lzjh" },
+ { 0, sparse_end }
};
/** ip2xfrm - Take an IP address and convert to an xfrm.
@@ -124,14 +122,14 @@ static sparse_names calg_list = {
static void
ip2xfrm(const ip_address *addr, xfrm_address_t *xaddr)
{
- if (addr->u.v4.sin_family == AF_INET)
- {
- xaddr->a4 = addr->u.v4.sin_addr.s_addr;
- }
- else
- {
- memcpy(xaddr->a6, &addr->u.v6.sin6_addr, sizeof(xaddr->a6));
- }
+ if (addr->u.v4.sin_family == AF_INET)
+ {
+ xaddr->a4 = addr->u.v4.sin_addr.s_addr;
+ }
+ else
+ {
+ memcpy(xaddr->a6, &addr->u.v6.sin6_addr, sizeof(xaddr->a6));
+ }
}
/** init_netlink - Initialize the netlink inferface. Opens the sockets and
@@ -140,32 +138,32 @@ ip2xfrm(const ip_address *addr, xfrm_address_t *xaddr)
static void
init_netlink(void)
{
- struct sockaddr_nl addr;
+ struct sockaddr_nl addr;
- netlinkfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
+ netlinkfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
- if (netlinkfd < 0)
- exit_log_errno((e, "socket() in init_netlink()"));
+ if (netlinkfd < 0)
+ exit_log_errno((e, "socket() in init_netlink()"));
- if (fcntl(netlinkfd, F_SETFD, FD_CLOEXEC) != 0)
- exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_netlink()"));
+ if (fcntl(netlinkfd, F_SETFD, FD_CLOEXEC) != 0)
+ exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_netlink()"));
- netlink_bcast_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
+ netlink_bcast_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
- if (netlink_bcast_fd < 0)
- exit_log_errno((e, "socket() for bcast in init_netlink()"));
+ if (netlink_bcast_fd < 0)
+ exit_log_errno((e, "socket() for bcast in init_netlink()"));
- if (fcntl(netlink_bcast_fd, F_SETFD, FD_CLOEXEC) != 0)
- exit_log_errno((e, "fcntl(FD_CLOEXEC) for bcast in init_netlink()"));
+ if (fcntl(netlink_bcast_fd, F_SETFD, FD_CLOEXEC) != 0)
+ exit_log_errno((e, "fcntl(FD_CLOEXEC) for bcast in init_netlink()"));
- if (fcntl(netlink_bcast_fd, F_SETFL, O_NONBLOCK) != 0)
- exit_log_errno((e, "fcntl(O_NONBLOCK) for bcast in init_netlink()"));
+ if (fcntl(netlink_bcast_fd, F_SETFL, O_NONBLOCK) != 0)
+ exit_log_errno((e, "fcntl(O_NONBLOCK) for bcast in init_netlink()"));
- addr.nl_family = AF_NETLINK;
- addr.nl_pid = getpid();
- addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
- if (bind(netlink_bcast_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
- exit_log_errno((e, "Failed to bind bcast socket in init_netlink()"));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = getpid();
+ addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
+ if (bind(netlink_bcast_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ exit_log_errno((e, "Failed to bind bcast socket in init_netlink()"));
}
/** send_netlink_msg
@@ -182,139 +180,139 @@ static bool
send_netlink_msg(struct nlmsghdr *hdr, struct nlmsghdr *rbuf, size_t rbuf_len
, const char *description, const char *text_said)
{
- struct {
- struct nlmsghdr n;
- struct nlmsgerr e;
- char data[1024];
- } rsp;
-
- size_t len;
- ssize_t r;
- struct sockaddr_nl addr;
- static uint32_t seq;
-
- if (no_klips)
- {
- return TRUE;
- }
-
- hdr->nlmsg_seq = ++seq;
- len = hdr->nlmsg_len;
- do {
- r = write(netlinkfd, hdr, len);
- } while (r < 0 && errno == EINTR);
- if (r < 0)
- {
- log_errno((e
- , "netlink write() of %s message"
- " for %s %s failed"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , description, text_said));
- return FALSE;
- }
- else if ((size_t)r != len)
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR: netlink write() of %s message"
- " for %s %s truncated: %ld instead of %lu"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , description, text_said
- , (long)r, (unsigned long)len);
- return FALSE;
- }
-
- for (;;) {
- socklen_t alen;
+ struct {
+ struct nlmsghdr n;
+ struct nlmsgerr e;
+ char data[1024];
+ } rsp;
+
+ size_t len;
+ ssize_t r;
+ struct sockaddr_nl addr;
+ static uint32_t seq;
+
+ if (no_klips)
+ {
+ return TRUE;
+ }
- alen = sizeof(addr);
- r = recvfrom(netlinkfd, &rsp, sizeof(rsp), 0
- , (struct sockaddr *)&addr, &alen);
+ hdr->nlmsg_seq = ++seq;
+ len = hdr->nlmsg_len;
+ do {
+ r = write(netlinkfd, hdr, len);
+ } while (r < 0 && errno == EINTR);
if (r < 0)
{
- if (errno == EINTR)
- {
- continue;
- }
- log_errno((e
- , "netlink recvfrom() of response to our %s message"
- " for %s %s failed"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , description, text_said));
- return FALSE;
+ log_errno((e
+ , "netlink write() of %s message"
+ " for %s %s failed"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , description, text_said));
+ return FALSE;
}
- else if ((size_t) r < sizeof(rsp.n))
+ else if ((size_t)r != len)
{
- plog("netlink read truncated message: %ld bytes; ignore message"
- , (long) r);
- continue;
+ loglog(RC_LOG_SERIOUS
+ , "ERROR: netlink write() of %s message"
+ " for %s %s truncated: %ld instead of %lu"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , description, text_said
+ , (long)r, (unsigned long)len);
+ return FALSE;
}
- else if (addr.nl_pid != 0)
+
+ for (;;) {
+ socklen_t alen;
+
+ alen = sizeof(addr);
+ r = recvfrom(netlinkfd, &rsp, sizeof(rsp), 0
+ , (struct sockaddr *)&addr, &alen);
+ if (r < 0)
+ {
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ log_errno((e
+ , "netlink recvfrom() of response to our %s message"
+ " for %s %s failed"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , description, text_said));
+ return FALSE;
+ }
+ else if ((size_t) r < sizeof(rsp.n))
+ {
+ plog("netlink read truncated message: %ld bytes; ignore message"
+ , (long) r);
+ continue;
+ }
+ else if (addr.nl_pid != 0)
+ {
+ /* not for us: ignore */
+ DBG(DBG_KLIPS,
+ DBG_log("netlink: ignoring %s message from process %u"
+ , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)
+ , addr.nl_pid));
+ continue;
+ }
+ else if (rsp.n.nlmsg_seq != seq)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("netlink: ignoring out of sequence (%u/%u) message %s"
+ , rsp.n.nlmsg_seq, seq
+ , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)));
+ continue;
+ }
+ break;
+ }
+
+ if (rsp.n.nlmsg_len > (size_t) r)
{
- /* not for us: ignore */
- DBG(DBG_KLIPS,
- DBG_log("netlink: ignoring %s message from process %u"
- , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)
- , addr.nl_pid));
- continue;
+ loglog(RC_LOG_SERIOUS
+ , "netlink recvfrom() of response to our %s message"
+ " for %s %s was truncated: %ld instead of %lu"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , description, text_said
+ , (long) len, (unsigned long) rsp.n.nlmsg_len);
+ return FALSE;
}
- else if (rsp.n.nlmsg_seq != seq)
+ else if (rsp.n.nlmsg_type != NLMSG_ERROR
+ && (rbuf && rsp.n.nlmsg_type != rbuf->nlmsg_type))
{
- DBG(DBG_KLIPS,
- DBG_log("netlink: ignoring out of sequence (%u/%u) message %s"
- , rsp.n.nlmsg_seq, seq
- , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)));
- continue;
+ loglog(RC_LOG_SERIOUS
+ , "netlink recvfrom() of response to our %s message"
+ " for %s %s was of wrong type (%s)"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , description, text_said
+ , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type));
+ return FALSE;
}
- break;
- }
-
- if (rsp.n.nlmsg_len > (size_t) r)
- {
- loglog(RC_LOG_SERIOUS
- , "netlink recvfrom() of response to our %s message"
- " for %s %s was truncated: %ld instead of %lu"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , description, text_said
- , (long) len, (unsigned long) rsp.n.nlmsg_len);
- return FALSE;
- }
- else if (rsp.n.nlmsg_type != NLMSG_ERROR
- && (rbuf && rsp.n.nlmsg_type != rbuf->nlmsg_type))
- {
- loglog(RC_LOG_SERIOUS
- , "netlink recvfrom() of response to our %s message"
- " for %s %s was of wrong type (%s)"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , description, text_said
- , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type));
- return FALSE;
- }
- else if (rbuf)
- {
- if ((size_t) r > rbuf_len)
+ else if (rbuf)
{
- loglog(RC_LOG_SERIOUS
- , "netlink recvfrom() of response to our %s message"
- " for %s %s was too long: %ld > %lu"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , description, text_said
- , (long)r, (unsigned long)rbuf_len);
- return FALSE;
+ if ((size_t) r > rbuf_len)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "netlink recvfrom() of response to our %s message"
+ " for %s %s was too long: %ld > %lu"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , description, text_said
+ , (long)r, (unsigned long)rbuf_len);
+ return FALSE;
+ }
+ memcpy(rbuf, &rsp, r);
+ return TRUE;
+ }
+ else if (rsp.n.nlmsg_type == NLMSG_ERROR && rsp.e.error)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ERROR: netlink response for %s %s included errno %d: %s"
+ , description, text_said
+ , -rsp.e.error
+ , strerror(-rsp.e.error));
+ return FALSE;
}
- memcpy(rbuf, &rsp, r);
- return TRUE;
- }
- else if (rsp.n.nlmsg_type == NLMSG_ERROR && rsp.e.error)
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR: netlink response for %s %s included errno %d: %s"
- , description, text_said
- , -rsp.e.error
- , strerror(-rsp.e.error));
- return FALSE;
- }
- return TRUE;
+ return TRUE;
}
/** netlink_policy -
@@ -327,36 +325,36 @@ send_netlink_msg(struct nlmsghdr *hdr, struct nlmsghdr *rbuf, size_t rbuf_len
static bool
netlink_policy(struct nlmsghdr *hdr, bool enoent_ok, const char *text_said)
{
- struct {
- struct nlmsghdr n;
- struct nlmsgerr e;
- } rsp;
- int error;
-
- rsp.n.nlmsg_type = NLMSG_ERROR;
- if (!send_netlink_msg(hdr, &rsp.n, sizeof(rsp), "policy", text_said))
- {
- return FALSE;
- }
+ struct {
+ struct nlmsghdr n;
+ struct nlmsgerr e;
+ } rsp;
+ int error;
+
+ rsp.n.nlmsg_type = NLMSG_ERROR;
+ if (!send_netlink_msg(hdr, &rsp.n, sizeof(rsp), "policy", text_said))
+ {
+ return FALSE;
+ }
- error = -rsp.e.error;
- if (!error)
- {
- return TRUE;
- }
+ error = -rsp.e.error;
+ if (!error)
+ {
+ return TRUE;
+ }
- if (error == ENOENT && enoent_ok)
- {
- return TRUE;
- }
-
- loglog(RC_LOG_SERIOUS
- , "ERROR: netlink %s response for flow %s included errno %d: %s"
- , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
- , text_said
- , error
- , strerror(error));
- return FALSE;
+ if (error == ENOENT && enoent_ok)
+ {
+ return TRUE;
+ }
+
+ loglog(RC_LOG_SERIOUS
+ , "ERROR: netlink %s response for flow %s included errno %d: %s"
+ , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
+ , text_said
+ , error
+ , strerror(error));
+ return FALSE;
}
/** netlink_raw_eroute
@@ -376,192 +374,192 @@ netlink_policy(struct nlmsghdr *hdr, bool enoent_ok, const char *text_said)
*/
static bool
netlink_raw_eroute(const ip_address *this_host
- , const ip_subnet *this_client
- , const ip_address *that_host
- , const ip_subnet *that_client
- , ipsec_spi_t spi
- , unsigned int satype
- , unsigned int transport_proto
- , const struct pfkey_proto_info *proto_info
- , time_t use_lifetime UNUSED
- , unsigned int op
- , const char *text_said)
+ , const ip_subnet *this_client
+ , const ip_address *that_host
+ , const ip_subnet *that_client
+ , ipsec_spi_t spi
+ , unsigned int satype
+ , unsigned int transport_proto
+ , const struct pfkey_proto_info *proto_info
+ , time_t use_lifetime UNUSED
+ , unsigned int op
+ , const char *text_said)
{
- struct {
- struct nlmsghdr n;
- union {
- struct xfrm_userpolicy_info p;
- struct xfrm_userpolicy_id id;
- } u;
- char data[1024];
- } req;
- int shift;
- int dir;
- int family;
- int policy;
- bool ok;
- bool enoent_ok;
-
- policy = IPSEC_POLICY_IPSEC;
-
- if (satype == SADB_X_SATYPE_INT)
- {
- /* shunt route */
- switch (ntohl(spi))
+ struct {
+ struct nlmsghdr n;
+ union {
+ struct xfrm_userpolicy_info p;
+ struct xfrm_userpolicy_id id;
+ } u;
+ char data[1024];
+ } req;
+ int shift;
+ int dir;
+ int family;
+ int policy;
+ bool ok;
+ bool enoent_ok;
+
+ policy = IPSEC_POLICY_IPSEC;
+
+ if (satype == SADB_X_SATYPE_INT)
{
- case SPI_PASS:
- policy = IPSEC_POLICY_NONE;
- break;
- case SPI_DROP:
- case SPI_REJECT:
- default:
- policy = IPSEC_POLICY_DISCARD;
- break;
- case SPI_TRAP:
- case SPI_TRAPSUBNET:
- case SPI_HOLD:
- if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
- {
- return TRUE;
- }
- break;
- }
- }
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-
- family = that_client->addr.u.v4.sin_family;
- shift = (family == AF_INET) ? 5 : 7;
-
- req.u.p.sel.sport = portof(&this_client->addr);
- req.u.p.sel.dport = portof(&that_client->addr);
- req.u.p.sel.sport_mask = (req.u.p.sel.sport) ? ~0:0;
- req.u.p.sel.dport_mask = (req.u.p.sel.dport) ? ~0:0;
- ip2xfrm(&this_client->addr, &req.u.p.sel.saddr);
- ip2xfrm(&that_client->addr, &req.u.p.sel.daddr);
- req.u.p.sel.prefixlen_s = this_client->maskbits;
- req.u.p.sel.prefixlen_d = that_client->maskbits;
- req.u.p.sel.proto = transport_proto;
- req.u.p.sel.family = family;
-
- dir = XFRM_POLICY_OUT;
- if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
- {
- dir = XFRM_POLICY_IN;
- }
-
- if ((op & ERO_MASK) == ERO_DELETE)
- {
- req.u.id.dir = dir;
- req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.id)));
- }
- else
- {
- int src, dst;
-
- req.u.p.dir = dir;
-
- src = req.u.p.sel.prefixlen_s;
- dst = req.u.p.sel.prefixlen_d;
- if (dir != XFRM_POLICY_OUT) {
- src = req.u.p.sel.prefixlen_d;
- dst = req.u.p.sel.prefixlen_s;
+ /* shunt route */
+ switch (ntohl(spi))
+ {
+ case SPI_PASS:
+ policy = IPSEC_POLICY_NONE;
+ break;
+ case SPI_DROP:
+ case SPI_REJECT:
+ default:
+ policy = IPSEC_POLICY_DISCARD;
+ break;
+ case SPI_TRAP:
+ case SPI_TRAPSUBNET:
+ case SPI_HOLD:
+ if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
+ {
+ return TRUE;
+ }
+ break;
+ }
}
- req.u.p.priority = MIN_SPD_PRIORITY
- + (((2 << shift) - src) << shift)
- + (2 << shift) - dst;
- req.u.p.action = XFRM_POLICY_ALLOW;
- if (policy == IPSEC_POLICY_DISCARD)
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+
+ family = that_client->addr.u.v4.sin_family;
+ shift = (family == AF_INET) ? 5 : 7;
+
+ req.u.p.sel.sport = portof(&this_client->addr);
+ req.u.p.sel.dport = portof(&that_client->addr);
+ req.u.p.sel.sport_mask = (req.u.p.sel.sport) ? ~0:0;
+ req.u.p.sel.dport_mask = (req.u.p.sel.dport) ? ~0:0;
+ ip2xfrm(&this_client->addr, &req.u.p.sel.saddr);
+ ip2xfrm(&that_client->addr, &req.u.p.sel.daddr);
+ req.u.p.sel.prefixlen_s = this_client->maskbits;
+ req.u.p.sel.prefixlen_d = that_client->maskbits;
+ req.u.p.sel.proto = transport_proto;
+ req.u.p.sel.family = family;
+
+ dir = XFRM_POLICY_OUT;
+ if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
{
- req.u.p.action = XFRM_POLICY_BLOCK;
+ dir = XFRM_POLICY_IN;
}
- req.u.p.lft.soft_use_expires_seconds = use_lifetime;
- req.u.p.lft.soft_byte_limit = XFRM_INF;
- req.u.p.lft.soft_packet_limit = XFRM_INF;
- req.u.p.lft.hard_byte_limit = XFRM_INF;
- req.u.p.lft.hard_packet_limit = XFRM_INF;
-
- req.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
- if (op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
+
+ if ((op & ERO_MASK) == ERO_DELETE)
{
- req.n.nlmsg_type = XFRM_MSG_UPDPOLICY;
+ req.u.id.dir = dir;
+ req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.id)));
}
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p)));
- }
-
- if (policy == IPSEC_POLICY_IPSEC && (op & ERO_MASK) != ERO_DELETE)
- {
- struct rtattr *attr;
- struct xfrm_user_tmpl tmpl[4];
- int i;
-
- memset(tmpl, 0, sizeof(tmpl));
- for (i = 0; proto_info[i].proto; i++)
+ else
{
- tmpl[i].reqid = proto_info[i].reqid;
- tmpl[i].id.proto = proto_info[i].proto;
- tmpl[i].optional =
- proto_info[i].proto == IPPROTO_COMP && dir != XFRM_POLICY_OUT;
- tmpl[i].aalgos = tmpl[i].ealgos = tmpl[i].calgos = ~0;
- tmpl[i].mode =
- proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
-
- if (!tmpl[i].mode)
- {
- continue;
- }
-
- ip2xfrm(this_host, &tmpl[i].saddr);
- ip2xfrm(that_host, &tmpl[i].id.daddr);
+ int src, dst;
+
+ req.u.p.dir = dir;
+
+ src = req.u.p.sel.prefixlen_s;
+ dst = req.u.p.sel.prefixlen_d;
+ if (dir != XFRM_POLICY_OUT) {
+ src = req.u.p.sel.prefixlen_d;
+ dst = req.u.p.sel.prefixlen_s;
+ }
+ req.u.p.priority = MIN_SPD_PRIORITY
+ + (((2 << shift) - src) << shift)
+ + (2 << shift) - dst;
+
+ req.u.p.action = XFRM_POLICY_ALLOW;
+ if (policy == IPSEC_POLICY_DISCARD)
+ {
+ req.u.p.action = XFRM_POLICY_BLOCK;
+ }
+ req.u.p.lft.soft_use_expires_seconds = use_lifetime;
+ req.u.p.lft.soft_byte_limit = XFRM_INF;
+ req.u.p.lft.soft_packet_limit = XFRM_INF;
+ req.u.p.lft.hard_byte_limit = XFRM_INF;
+ req.u.p.lft.hard_packet_limit = XFRM_INF;
+
+ req.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
+ if (op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
+ {
+ req.n.nlmsg_type = XFRM_MSG_UPDPOLICY;
+ }
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p)));
}
- attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
- attr->rta_type = XFRMA_TMPL;
- attr->rta_len = i * sizeof(tmpl[0]);
- memcpy(RTA_DATA(attr), tmpl, attr->rta_len);
- attr->rta_len = RTA_LENGTH(attr->rta_len);
- req.n.nlmsg_len += attr->rta_len;
- }
-
- enoent_ok = FALSE;
- if (op == ERO_DEL_INBOUND)
- {
- enoent_ok = TRUE;
- }
- else if (op == ERO_DELETE && ntohl(spi) == SPI_HOLD)
- {
- enoent_ok = TRUE;
- }
-
- ok = netlink_policy(&req.n, enoent_ok, text_said);
- switch (dir)
- {
- case XFRM_POLICY_IN:
- if (req.n.nlmsg_type == XFRM_MSG_DELPOLICY)
+ if (policy == IPSEC_POLICY_IPSEC && (op & ERO_MASK) != ERO_DELETE)
{
- req.u.id.dir = XFRM_POLICY_FWD;
+ struct rtattr *attr;
+ struct xfrm_user_tmpl tmpl[4];
+ int i;
+
+ memset(tmpl, 0, sizeof(tmpl));
+ for (i = 0; proto_info[i].proto; i++)
+ {
+ tmpl[i].reqid = proto_info[i].reqid;
+ tmpl[i].id.proto = proto_info[i].proto;
+ tmpl[i].optional =
+ proto_info[i].proto == IPPROTO_COMP && dir != XFRM_POLICY_OUT;
+ tmpl[i].aalgos = tmpl[i].ealgos = tmpl[i].calgos = ~0;
+ tmpl[i].mode =
+ proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
+
+ if (!tmpl[i].mode)
+ {
+ continue;
+ }
+
+ ip2xfrm(this_host, &tmpl[i].saddr);
+ ip2xfrm(that_host, &tmpl[i].id.daddr);
+ }
+
+ attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
+ attr->rta_type = XFRMA_TMPL;
+ attr->rta_len = i * sizeof(tmpl[0]);
+ memcpy(RTA_DATA(attr), tmpl, attr->rta_len);
+ attr->rta_len = RTA_LENGTH(attr->rta_len);
+ req.n.nlmsg_len += attr->rta_len;
}
- else if (!ok)
+
+ enoent_ok = FALSE;
+ if (op == ERO_DEL_INBOUND)
{
- break;
+ enoent_ok = TRUE;
}
- else if (proto_info[0].encapsulation != ENCAPSULATION_MODE_TUNNEL
- && satype != SADB_X_SATYPE_INT)
+ else if (op == ERO_DELETE && ntohl(spi) == SPI_HOLD)
{
- break;
+ enoent_ok = TRUE;
}
- else
+
+ ok = netlink_policy(&req.n, enoent_ok, text_said);
+ switch (dir)
{
- req.u.p.dir = XFRM_POLICY_FWD;
+ case XFRM_POLICY_IN:
+ if (req.n.nlmsg_type == XFRM_MSG_DELPOLICY)
+ {
+ req.u.id.dir = XFRM_POLICY_FWD;
+ }
+ else if (!ok)
+ {
+ break;
+ }
+ else if (proto_info[0].encapsulation != ENCAPSULATION_MODE_TUNNEL
+ && satype != SADB_X_SATYPE_INT)
+ {
+ break;
+ }
+ else
+ {
+ req.u.p.dir = XFRM_POLICY_FWD;
+ }
+ ok &= netlink_policy(&req.n, enoent_ok, text_said);
+ break;
}
- ok &= netlink_policy(&req.n, enoent_ok, text_said);
- break;
- }
- return ok;
+ return ok;
}
/** netlink_add_sa - Add an SA into the kernel SPDB via netlink
@@ -573,130 +571,130 @@ netlink_raw_eroute(const ip_address *this_host
static bool
netlink_add_sa(const struct kernel_sa *sa, bool replace)
{
- struct {
- struct nlmsghdr n;
- struct xfrm_usersa_info p;
- char data[1024];
- } req;
- struct rtattr *attr;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- req.n.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
-
- ip2xfrm(sa->src, &req.p.saddr);
- ip2xfrm(sa->dst, &req.p.id.daddr);
-
- req.p.id.spi = sa->spi;
- req.p.id.proto = satype2proto(sa->satype);
- req.p.family = sa->src->u.v4.sin_family;
- req.p.mode = (sa->encapsulation == ENCAPSULATION_MODE_TUNNEL);
- req.p.replay_window = sa->replay_window;
- req.p.reqid = sa->reqid;
- req.p.lft.soft_byte_limit = XFRM_INF;
- req.p.lft.soft_packet_limit = XFRM_INF;
- req.p.lft.hard_byte_limit = XFRM_INF;
- req.p.lft.hard_packet_limit = XFRM_INF;
-
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.p)));
-
- attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
-
- if (sa->authalg)
- {
- struct xfrm_algo algo;
- const char *name;
-
- name = sparse_name(aalg_list, sa->authalg);
- if (!name) {
- loglog(RC_LOG_SERIOUS, "unknown authentication algorithm: %u"
- , sa->authalg);
- return FALSE;
- }
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_info p;
+ char data[1024];
+ } req;
+ struct rtattr *attr;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.n.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
- strcpy(algo.alg_name, name);
- algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE;
+ ip2xfrm(sa->src, &req.p.saddr);
+ ip2xfrm(sa->dst, &req.p.id.daddr);
- attr->rta_type = XFRMA_ALG_AUTH;
- attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen);
+ req.p.id.spi = sa->spi;
+ req.p.id.proto = satype2proto(sa->satype);
+ req.p.family = sa->src->u.v4.sin_family;
+ req.p.mode = (sa->encapsulation == ENCAPSULATION_MODE_TUNNEL);
+ req.p.replay_window = sa->replay_window;
+ req.p.reqid = sa->reqid;
+ req.p.lft.soft_byte_limit = XFRM_INF;
+ req.p.lft.soft_packet_limit = XFRM_INF;
+ req.p.lft.hard_byte_limit = XFRM_INF;
+ req.p.lft.hard_packet_limit = XFRM_INF;
- memcpy(RTA_DATA(attr), &algo, sizeof(algo));
- memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->authkey
- , sa->authkeylen);
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.p)));
- req.n.nlmsg_len += attr->rta_len;
- attr = (struct rtattr *)((char *)attr + attr->rta_len);
- }
+ attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
+
+ if (sa->authalg)
+ {
+ struct xfrm_algo algo;
+ const char *name;
- if (sa->encalg)
- {
- struct xfrm_algo algo;
- const char *name;
+ name = sparse_name(aalg_list, sa->authalg);
+ if (!name) {
+ loglog(RC_LOG_SERIOUS, "unknown authentication algorithm: %u"
+ , sa->authalg);
+ return FALSE;
+ }
- name = sparse_name(ealg_list, sa->encalg);
- if (!name) {
- loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u"
- , sa->encalg);
- return FALSE;
+ strcpy(algo.alg_name, name);
+ algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE;
+
+ attr->rta_type = XFRMA_ALG_AUTH;
+ attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen);
+
+ memcpy(RTA_DATA(attr), &algo, sizeof(algo));
+ memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->authkey
+ , sa->authkeylen);
+
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)attr + attr->rta_len);
}
- strcpy(algo.alg_name, name);
- algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE;
+ if (sa->encalg)
+ {
+ struct xfrm_algo algo;
+ const char *name;
- attr->rta_type = XFRMA_ALG_CRYPT;
- attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen);
+ name = sparse_name(ealg_list, sa->encalg);
+ if (!name) {
+ loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u"
+ , sa->encalg);
+ return FALSE;
+ }
- memcpy(RTA_DATA(attr), &algo, sizeof(algo));
- memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->enckey
- , sa->enckeylen);
+ strcpy(algo.alg_name, name);
+ algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE;
- req.n.nlmsg_len += attr->rta_len;
- attr = (struct rtattr *)((char *)attr + attr->rta_len);
- }
+ attr->rta_type = XFRMA_ALG_CRYPT;
+ attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen);
- if (sa->compalg)
- {
- struct xfrm_algo algo;
- const char *name;
+ memcpy(RTA_DATA(attr), &algo, sizeof(algo));
+ memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->enckey
+ , sa->enckeylen);
- name = sparse_name(calg_list, sa->compalg);
- if (!name) {
- loglog(RC_LOG_SERIOUS, "unknown compression algorithm: %u"
- , sa->compalg);
- return FALSE;
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)attr + attr->rta_len);
}
- strcpy(algo.alg_name, name);
- algo.alg_key_len = 0;
+ if (sa->compalg)
+ {
+ struct xfrm_algo algo;
+ const char *name;
- attr->rta_type = XFRMA_ALG_COMP;
- attr->rta_len = RTA_LENGTH(sizeof(algo));
+ name = sparse_name(calg_list, sa->compalg);
+ if (!name) {
+ loglog(RC_LOG_SERIOUS, "unknown compression algorithm: %u"
+ , sa->compalg);
+ return FALSE;
+ }
- memcpy(RTA_DATA(attr), &algo, sizeof(algo));
+ strcpy(algo.alg_name, name);
+ algo.alg_key_len = 0;
- req.n.nlmsg_len += attr->rta_len;
- attr = (struct rtattr *)((char *)attr + attr->rta_len);
- }
+ attr->rta_type = XFRMA_ALG_COMP;
+ attr->rta_len = RTA_LENGTH(sizeof(algo));
- if (sa->natt_type)
- {
- struct xfrm_encap_tmpl natt;
+ memcpy(RTA_DATA(attr), &algo, sizeof(algo));
- natt.encap_type = sa->natt_type;
- natt.encap_sport = ntohs(sa->natt_sport);
- natt.encap_dport = ntohs(sa->natt_dport);
- memset (&natt.encap_oa, 0, sizeof (natt.encap_oa));
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)attr + attr->rta_len);
+ }
- attr->rta_type = XFRMA_ENCAP;
- attr->rta_len = RTA_LENGTH(sizeof(natt));
+ if (sa->natt_type)
+ {
+ struct xfrm_encap_tmpl natt;
+
+ natt.encap_type = sa->natt_type;
+ natt.encap_sport = ntohs(sa->natt_sport);
+ natt.encap_dport = ntohs(sa->natt_dport);
+ memset (&natt.encap_oa, 0, sizeof (natt.encap_oa));
- memcpy(RTA_DATA(attr), &natt, sizeof(natt));
+ attr->rta_type = XFRMA_ENCAP;
+ attr->rta_len = RTA_LENGTH(sizeof(natt));
- req.n.nlmsg_len += attr->rta_len;
- attr = (struct rtattr *)((char *)attr + attr->rta_len);
- }
+ memcpy(RTA_DATA(attr), &natt, sizeof(natt));
- return send_netlink_msg(&req.n, NULL, 0, "Add SA", sa->text_said);
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)attr + attr->rta_len);
+ }
+
+ return send_netlink_msg(&req.n, NULL, 0, "Add SA", sa->text_said);
}
/** netlink_del_sa - Delete an SA from the Kernel
@@ -707,113 +705,113 @@ netlink_add_sa(const struct kernel_sa *sa, bool replace)
static bool
netlink_del_sa(const struct kernel_sa *sa)
{
- struct {
- struct nlmsghdr n;
- struct xfrm_usersa_id id;
- char data[1024];
- } req;
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_id id;
+ char data[1024];
+ } req;
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- req.n.nlmsg_type = XFRM_MSG_DELSA;
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.n.nlmsg_type = XFRM_MSG_DELSA;
- ip2xfrm(sa->dst, &req.id.daddr);
+ ip2xfrm(sa->dst, &req.id.daddr);
- req.id.spi = sa->spi;
- req.id.family = sa->src->u.v4.sin_family;
- req.id.proto = sa->proto;
+ req.id.spi = sa->spi;
+ req.id.family = sa->src->u.v4.sin_family;
+ req.id.proto = sa->proto;
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
- return send_netlink_msg(&req.n, NULL, 0, "Del SA", sa->text_said);
+ return send_netlink_msg(&req.n, NULL, 0, "Del SA", sa->text_said);
}
static bool
netlink_error(const char *req_type, const struct nlmsghdr *n
, const struct nlmsgerr *e, int rsp_size)
{
- if (n->nlmsg_type == NLMSG_ERROR)
- {
- DBG(DBG_KLIPS,
- DBG_log("%s returned with errno %d: %s"
- , req_type
- , -e->error
- , strerror(-e->error))
- )
- return TRUE;
- }
- if (n->nlmsg_len < NLMSG_LENGTH(rsp_size))
- {
- plog("%s returned message with length %lu < %lu bytes"
- , req_type
- , (unsigned long) n->nlmsg_len
- , (unsigned long) rsp_size);
- return TRUE;
- }
- return FALSE;
+ if (n->nlmsg_type == NLMSG_ERROR)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("%s returned with errno %d: %s"
+ , req_type
+ , -e->error
+ , strerror(-e->error))
+ )
+ return TRUE;
+ }
+ if (n->nlmsg_len < NLMSG_LENGTH(rsp_size))
+ {
+ plog("%s returned message with length %lu < %lu bytes"
+ , req_type
+ , (unsigned long) n->nlmsg_len
+ , (unsigned long) rsp_size);
+ return TRUE;
+ }
+ return FALSE;
}
static bool
netlink_get_policy(const struct kernel_sa *sa, bool inbound, time_t *use_time)
{
- struct {
- struct nlmsghdr n;
- struct xfrm_userpolicy_id id;
- } req;
-
- struct {
- struct nlmsghdr n;
- union {
- struct nlmsgerr e;
- struct xfrm_userpolicy_info info;
- } u;
- char data[1024];
- } rsp;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_type = XFRM_MSG_GETPOLICY;
-
- req.id.sel.sport = portof(&sa->src_client->addr);
- req.id.sel.dport = portof(&sa->dst_client->addr);
- req.id.sel.sport_mask = (req.id.sel.sport) ? ~0:0;
- req.id.sel.dport_mask = (req.id.sel.dport) ? ~0:0;
- ip2xfrm(&sa->src_client->addr, &req.id.sel.saddr);
- ip2xfrm(&sa->dst_client->addr, &req.id.sel.daddr);
- req.id.sel.prefixlen_s = sa->src_client->maskbits;
- req.id.sel.prefixlen_d = sa->dst_client->maskbits;
- req.id.sel.proto = sa->transport_proto;
- req.id.sel.family = sa->dst_client->addr.u.v4.sin_family;
-
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
- rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
-
- req.id.dir = (inbound)? XFRM_POLICY_IN:XFRM_POLICY_OUT;
-
- if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
- return FALSE;
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_userpolicy_id id;
+ } req;
+
+ struct {
+ struct nlmsghdr n;
+ union {
+ struct nlmsgerr e;
+ struct xfrm_userpolicy_info info;
+ } u;
+ char data[1024];
+ } rsp;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_GETPOLICY;
+
+ req.id.sel.sport = portof(&sa->src_client->addr);
+ req.id.sel.dport = portof(&sa->dst_client->addr);
+ req.id.sel.sport_mask = (req.id.sel.sport) ? ~0:0;
+ req.id.sel.dport_mask = (req.id.sel.dport) ? ~0:0;
+ ip2xfrm(&sa->src_client->addr, &req.id.sel.saddr);
+ ip2xfrm(&sa->dst_client->addr, &req.id.sel.daddr);
+ req.id.sel.prefixlen_s = sa->src_client->maskbits;
+ req.id.sel.prefixlen_d = sa->dst_client->maskbits;
+ req.id.sel.proto = sa->transport_proto;
+ req.id.sel.family = sa->dst_client->addr.u.v4.sin_family;
+
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
+ rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
+
+ req.id.dir = (inbound)? XFRM_POLICY_IN:XFRM_POLICY_OUT;
- if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info)))
- return FALSE;
+ if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
+ return FALSE;
+
+ if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info)))
+ return FALSE;
- *use_time = (time_t)rsp.u.info.curlft.use_time;
+ *use_time = (time_t)rsp.u.info.curlft.use_time;
- if (inbound && sa->encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- time_t use_time_fwd;
+ if (inbound && sa->encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ {
+ time_t use_time_fwd;
- req.id.dir = XFRM_POLICY_FWD;
+ req.id.dir = XFRM_POLICY_FWD;
- if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
- return FALSE;
+ if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
+ return FALSE;
- if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info)))
- return FALSE;
+ if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info)))
+ return FALSE;
- use_time_fwd = (time_t)rsp.u.info.curlft.use_time;
- *use_time = (*use_time > use_time_fwd)? *use_time : use_time_fwd;
- }
- return TRUE;
+ use_time_fwd = (time_t)rsp.u.info.curlft.use_time;
+ *use_time = (*use_time > use_time_fwd)? *use_time : use_time_fwd;
+ }
+ return TRUE;
}
@@ -825,60 +823,60 @@ netlink_get_policy(const struct kernel_sa *sa, bool inbound, time_t *use_time)
static bool
netlink_get_sa(const struct kernel_sa *sa, u_int *bytes)
{
- struct {
- struct nlmsghdr n;
- struct xfrm_usersa_id id;
- } req;
-
- struct {
- struct nlmsghdr n;
- union {
- struct nlmsgerr e;
- struct xfrm_usersa_info info;
- } u;
- char data[1024];
- } rsp;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_type = XFRM_MSG_GETSA;
-
- ip2xfrm(sa->dst, &req.id.daddr);
-
- req.id.spi = sa->spi;
- req.id.family = sa->src->u.v4.sin_family;
- req.id.proto = sa->proto;
-
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
- rsp.n.nlmsg_type = XFRM_MSG_NEWSA;
-
- if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SA", sa->text_said))
- return FALSE;
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_id id;
+ } req;
- if (netlink_error("XFRM_MSG_GETSA", &rsp.n, &rsp.u.e, sizeof(rsp.u.info)))
- return FALSE;
+ struct {
+ struct nlmsghdr n;
+ union {
+ struct nlmsgerr e;
+ struct xfrm_usersa_info info;
+ } u;
+ char data[1024];
+ } rsp;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_GETSA;
+
+ ip2xfrm(sa->dst, &req.id.daddr);
- *bytes = (u_int) rsp.u.info.curlft.bytes;
+ req.id.spi = sa->spi;
+ req.id.family = sa->src->u.v4.sin_family;
+ req.id.proto = sa->proto;
- return TRUE;
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
+ rsp.n.nlmsg_type = XFRM_MSG_NEWSA;
+
+ if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SA", sa->text_said))
+ return FALSE;
+
+ if (netlink_error("XFRM_MSG_GETSA", &rsp.n, &rsp.u.e, sizeof(rsp.u.info)))
+ return FALSE;
+
+ *bytes = (u_int) rsp.u.info.curlft.bytes;
+
+ return TRUE;
}
static void
linux_pfkey_register_response(const struct sadb_msg *msg)
{
- switch (msg->sadb_msg_satype)
- {
- case SADB_SATYPE_ESP:
+ switch (msg->sadb_msg_satype)
+ {
+ case SADB_SATYPE_ESP:
#ifndef NO_KERNEL_ALG
- kernel_alg_register_pfkey(msg, msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+ kernel_alg_register_pfkey(msg, msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
#endif
- break;
- case SADB_X_SATYPE_IPCOMP:
- can_do_IPcomp = TRUE;
- break;
- default:
- break;
- }
+ break;
+ case SADB_X_SATYPE_IPCOMP:
+ can_do_IPcomp = TRUE;
+ break;
+ default:
+ break;
+ }
}
/** linux_pfkey_register - Register via PFKEY our capabilities
@@ -887,10 +885,10 @@ linux_pfkey_register_response(const struct sadb_msg *msg)
static void
linux_pfkey_register(void)
{
- pfkey_register_proto(SADB_SATYPE_AH, "AH");
- pfkey_register_proto(SADB_SATYPE_ESP, "ESP");
- pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP");
- pfkey_close();
+ pfkey_register_proto(SADB_SATYPE_AH, "AH");
+ pfkey_register_proto(SADB_SATYPE_ESP, "ESP");
+ pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP");
+ pfkey_close();
}
/** Create ip_address out of xfrm_address_t.
@@ -903,18 +901,18 @@ linux_pfkey_register(void)
static err_t
xfrm_to_ip_address(unsigned family, const xfrm_address_t *src, ip_address *dst)
{
- switch (family)
- {
- case AF_INET: /* IPv4 */
- case AF_UNSPEC: /* Unspecified, we assume IPv4 */
- initaddr((const void *) &src->a4, sizeof(src->a4), AF_INET, dst);
- return NULL;
- case AF_INET6: /* IPv6 */
- initaddr((const void *) &src->a6, sizeof(src->a6), AF_INET6, dst);
- return NULL;
- default:
- return "unknown address family";
- }
+ switch (family)
+ {
+ case AF_INET: /* IPv4 */
+ case AF_UNSPEC: /* Unspecified, we assume IPv4 */
+ initaddr((const void *) &src->a4, sizeof(src->a4), AF_INET, dst);
+ return NULL;
+ case AF_INET6: /* IPv6 */
+ initaddr((const void *) &src->a6, sizeof(src->a6), AF_INET6, dst);
+ return NULL;
+ default:
+ return "unknown address family";
+ }
}
/* Create a pair of ip_address's out of xfrm_sel.
@@ -926,29 +924,29 @@ xfrm_to_ip_address(unsigned family, const xfrm_address_t *src, ip_address *dst)
*/
static err_t
xfrm_sel_to_ip_pair(const struct xfrm_selector *sel
- , ip_address *src
- , ip_address *dst)
+ , ip_address *src
+ , ip_address *dst)
{
- int family;
- err_t ugh;
-
- family = sel->family;
-
- if ((ugh = xfrm_to_ip_address(family, &sel->saddr, src))
- || (ugh = xfrm_to_ip_address(family, &sel->daddr, dst)))
- return ugh;
-
- /* family has been verified in xfrm_to_ip_address. */
- if (family == AF_INET)
- {
- src->u.v4.sin_port = sel->sport;
- dst->u.v4.sin_port = sel->dport;
- }
- else
- {
- src->u.v6.sin6_port = sel->sport;
- dst->u.v6.sin6_port = sel->dport;
- }
+ int family;
+ err_t ugh;
+
+ family = sel->family;
+
+ if ((ugh = xfrm_to_ip_address(family, &sel->saddr, src))
+ || (ugh = xfrm_to_ip_address(family, &sel->daddr, dst)))
+ return ugh;
+
+ /* family has been verified in xfrm_to_ip_address. */
+ if (family == AF_INET)
+ {
+ src->u.v4.sin_port = sel->sport;
+ dst->u.v4.sin_port = sel->dport;
+ }
+ else
+ {
+ src->u.v6.sin6_port = sel->sport;
+ dst->u.v6.sin6_port = sel->dport;
+ }
return NULL;
}
@@ -956,194 +954,194 @@ xfrm_sel_to_ip_pair(const struct xfrm_selector *sel
static void
netlink_acquire(struct nlmsghdr *n)
{
- struct xfrm_user_acquire *acquire;
- ip_address src, dst;
- ip_subnet ours, his;
- unsigned transport_proto;
- err_t ugh = NULL;
-
- if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire)))
- {
- plog("netlink_acquire got message with length %lu < %lu bytes; ignore message"
- , (unsigned long) n->nlmsg_len
- , (unsigned long) sizeof(*acquire));
- return;
- }
-
- acquire = NLMSG_DATA(n);
- transport_proto = acquire->sel.proto;
-
- /* XXX also the type of src/dst should be checked to make sure
- * that they aren't v4 to v6 or something goofy
- */
-
- if (!(ugh = xfrm_sel_to_ip_pair(&acquire->sel, &src, &dst))
- && !(ugh = addrtosubnet(&src, &ours))
- && !(ugh = addrtosubnet(&dst, &his)))
- record_and_initiate_opportunistic(&ours, &his, transport_proto
- , "%acquire-netlink");
-
- if (ugh != NULL)
- plog("XFRM_MSG_ACQUIRE message from kernel malformed: %s", ugh);
+ struct xfrm_user_acquire *acquire;
+ ip_address src, dst;
+ ip_subnet ours, his;
+ unsigned transport_proto;
+ err_t ugh = NULL;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire)))
+ {
+ plog("netlink_acquire got message with length %lu < %lu bytes; ignore message"
+ , (unsigned long) n->nlmsg_len
+ , (unsigned long) sizeof(*acquire));
+ return;
+ }
+
+ acquire = NLMSG_DATA(n);
+ transport_proto = acquire->sel.proto;
+
+ /* XXX also the type of src/dst should be checked to make sure
+ * that they aren't v4 to v6 or something goofy
+ */
+
+ if (!(ugh = xfrm_sel_to_ip_pair(&acquire->sel, &src, &dst))
+ && !(ugh = addrtosubnet(&src, &ours))
+ && !(ugh = addrtosubnet(&dst, &his)))
+ record_and_initiate_opportunistic(&ours, &his, transport_proto
+ , "%acquire-netlink");
+
+ if (ugh != NULL)
+ plog("XFRM_MSG_ACQUIRE message from kernel malformed: %s", ugh);
}
static void
netlink_shunt_expire(struct xfrm_userpolicy_info *pol)
{
- ip_address src, dst;
- unsigned transport_proto;
- err_t ugh = NULL;
-
- transport_proto = pol->sel.proto;
-
- if (!(ugh = xfrm_sel_to_ip_pair(&pol->sel, &src, &dst)))
- {
- plog("XFRM_MSG_POLEXPIRE message from kernel malformed: %s", ugh);
- return;
- }
-
- replace_bare_shunt(&src, &dst, BOTTOM_PRIO, SPI_PASS, FALSE, transport_proto
- , "delete expired bare shunt");
+ ip_address src, dst;
+ unsigned transport_proto;
+ err_t ugh = NULL;
+
+ transport_proto = pol->sel.proto;
+
+ if (!(ugh = xfrm_sel_to_ip_pair(&pol->sel, &src, &dst)))
+ {
+ plog("XFRM_MSG_POLEXPIRE message from kernel malformed: %s", ugh);
+ return;
+ }
+
+ replace_bare_shunt(&src, &dst, BOTTOM_PRIO, SPI_PASS, FALSE, transport_proto
+ , "delete expired bare shunt");
}
static void
netlink_policy_expire(struct nlmsghdr *n)
{
- struct xfrm_user_polexpire *upe;
- struct {
- struct nlmsghdr n;
- struct xfrm_userpolicy_id id;
- } req;
-
- struct {
- struct nlmsghdr n;
- union {
- struct nlmsgerr e;
- struct xfrm_userpolicy_info pol;
- } u;
- char data[1024];
- } rsp;
-
- if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe)))
- {
- plog("netlink_policy_expire got message with length %lu < %lu bytes; ignore message"
- , (unsigned long) n->nlmsg_len
- , (unsigned long) sizeof(*upe));
- return;
- }
-
- upe = NLMSG_DATA(n);
- req.id.dir = upe->pol.dir;
- req.id.index = upe->pol.index;
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_type = XFRM_MSG_GETPOLICY;
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
-
- rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
-
- if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
- return;
-
- if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.pol)))
- return;
-
- if (req.id.index != rsp.u.pol.index)
- {
- DBG(DBG_KLIPS,
- DBG_log("netlink_policy_expire: policy was replaced: "
- "dir=%d, oldindex=%d, newindex=%d"
- , req.id.dir, req.id.index, rsp.u.pol.index));
- return;
- }
-
- if (upe->pol.curlft.add_time != rsp.u.pol.curlft.add_time)
- {
- DBG(DBG_KLIPS,
- DBG_log("netlink_policy_expire: policy was replaced "
- " and you have won the lottery: "
- "dir=%d, index=%d"
- , req.id.dir, req.id.index));
- return;
- }
-
- switch (upe->pol.dir)
- {
- case XFRM_POLICY_OUT:
- netlink_shunt_expire(&rsp.u.pol);
- break;
- }
+ struct xfrm_user_polexpire *upe;
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_userpolicy_id id;
+ } req;
+
+ struct {
+ struct nlmsghdr n;
+ union {
+ struct nlmsgerr e;
+ struct xfrm_userpolicy_info pol;
+ } u;
+ char data[1024];
+ } rsp;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe)))
+ {
+ plog("netlink_policy_expire got message with length %lu < %lu bytes; ignore message"
+ , (unsigned long) n->nlmsg_len
+ , (unsigned long) sizeof(*upe));
+ return;
+ }
+
+ upe = NLMSG_DATA(n);
+ req.id.dir = upe->pol.dir;
+ req.id.index = upe->pol.index;
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_GETPOLICY;
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));
+
+ rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
+
+ if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
+ return;
+
+ if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.pol)))
+ return;
+
+ if (req.id.index != rsp.u.pol.index)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("netlink_policy_expire: policy was replaced: "
+ "dir=%d, oldindex=%d, newindex=%d"
+ , req.id.dir, req.id.index, rsp.u.pol.index));
+ return;
+ }
+
+ if (upe->pol.curlft.add_time != rsp.u.pol.curlft.add_time)
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("netlink_policy_expire: policy was replaced "
+ " and you have won the lottery: "
+ "dir=%d, index=%d"
+ , req.id.dir, req.id.index));
+ return;
+ }
+
+ switch (upe->pol.dir)
+ {
+ case XFRM_POLICY_OUT:
+ netlink_shunt_expire(&rsp.u.pol);
+ break;
+ }
}
static bool
netlink_get(void)
{
- struct {
- struct nlmsghdr n;
- char data[1024];
- } rsp;
- ssize_t r;
- struct sockaddr_nl addr;
- socklen_t alen;
-
- alen = sizeof(addr);
- r = recvfrom(netlink_bcast_fd, &rsp, sizeof(rsp), 0
- , (struct sockaddr *)&addr, &alen);
- if (r < 0)
- {
- if (errno == EAGAIN)
- return FALSE;
- if (errno != EINTR)
- log_errno((e, "recvfrom() failed in netlink_get"));
- return TRUE;
- }
- else if ((size_t) r < sizeof(rsp.n))
- {
- plog("netlink_get read truncated message: %ld bytes; ignore message"
- , (long) r);
- return TRUE;
- }
- else if (addr.nl_pid != 0)
- {
- /* not for us: ignore */
+ struct {
+ struct nlmsghdr n;
+ char data[1024];
+ } rsp;
+ ssize_t r;
+ struct sockaddr_nl addr;
+ socklen_t alen;
+
+ alen = sizeof(addr);
+ r = recvfrom(netlink_bcast_fd, &rsp, sizeof(rsp), 0
+ , (struct sockaddr *)&addr, &alen);
+ if (r < 0)
+ {
+ if (errno == EAGAIN)
+ return FALSE;
+ if (errno != EINTR)
+ log_errno((e, "recvfrom() failed in netlink_get"));
+ return TRUE;
+ }
+ else if ((size_t) r < sizeof(rsp.n))
+ {
+ plog("netlink_get read truncated message: %ld bytes; ignore message"
+ , (long) r);
+ return TRUE;
+ }
+ else if (addr.nl_pid != 0)
+ {
+ /* not for us: ignore */
+ DBG(DBG_KLIPS,
+ DBG_log("netlink_get: ignoring %s message from process %u"
+ , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)
+ , addr.nl_pid));
+ return TRUE;
+ }
+ else if ((size_t) r != rsp.n.nlmsg_len)
+ {
+ plog("netlink_get read message with length %ld that doesn't equal nlmsg_len %lu bytes; ignore message"
+ , (long) r
+ , (unsigned long) rsp.n.nlmsg_len);
+ return TRUE;
+ }
+
DBG(DBG_KLIPS,
- DBG_log("netlink_get: ignoring %s message from process %u"
- , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)
- , addr.nl_pid));
- return TRUE;
- }
- else if ((size_t) r != rsp.n.nlmsg_len)
- {
- plog("netlink_get read message with length %ld that doesn't equal nlmsg_len %lu bytes; ignore message"
- , (long) r
- , (unsigned long) rsp.n.nlmsg_len);
+ DBG_log("netlink_get: %s message"
+ , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)));
+
+ switch (rsp.n.nlmsg_type)
+ {
+ case XFRM_MSG_ACQUIRE:
+ netlink_acquire(&rsp.n);
+ break;
+ case XFRM_MSG_POLEXPIRE:
+ netlink_policy_expire(&rsp.n);
+ break;
+ default:
+ /* ignored */
+ break;
+ }
+
return TRUE;
- }
-
- DBG(DBG_KLIPS,
- DBG_log("netlink_get: %s message"
- , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)));
-
- switch (rsp.n.nlmsg_type)
- {
- case XFRM_MSG_ACQUIRE:
- netlink_acquire(&rsp.n);
- break;
- case XFRM_MSG_POLEXPIRE:
- netlink_policy_expire(&rsp.n);
- break;
- default:
- /* ignored */
- break;
- }
-
- return TRUE;
}
static void
netlink_process_msg(void)
{
- while (netlink_get())
- ;
+ while (netlink_get())
+ ;
}
static ipsec_spi_t
@@ -1156,65 +1154,65 @@ netlink_get_spi(const ip_address *src
, ipsec_spi_t max
, const char *text_said)
{
- struct {
- struct nlmsghdr n;
- struct xfrm_userspi_info spi;
- } req;
-
- struct {
- struct nlmsghdr n;
- union {
- struct nlmsgerr e;
- struct xfrm_usersa_info sa;
- } u;
- char data[1024];
- } rsp;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_type = XFRM_MSG_ALLOCSPI;
-
- ip2xfrm(src, &req.spi.info.saddr);
- ip2xfrm(dst, &req.spi.info.id.daddr);
- req.spi.info.mode = tunnel_mode;
- req.spi.info.reqid = reqid;
- req.spi.info.id.proto = proto;
- req.spi.info.family = src->u.v4.sin_family;
- req.spi.min = min;
- req.spi.max = max;
-
- req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.spi)));
- rsp.n.nlmsg_type = XFRM_MSG_NEWSA;
-
- if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SPI", text_said))
- return 0;
-
- if (netlink_error("XFRM_MSG_ALLOCSPI", &rsp.n, &rsp.u.e, sizeof(rsp.u.sa)))
- return 0;
-
- DBG(DBG_KLIPS,
- DBG_log("netlink_get_spi: allocated 0x%x for %s"
- , ntohl(rsp.u.sa.id.spi), text_said));
- return rsp.u.sa.id.spi;
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_userspi_info spi;
+ } req;
+
+ struct {
+ struct nlmsghdr n;
+ union {
+ struct nlmsgerr e;
+ struct xfrm_usersa_info sa;
+ } u;
+ char data[1024];
+ } rsp;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_ALLOCSPI;
+
+ ip2xfrm(src, &req.spi.info.saddr);
+ ip2xfrm(dst, &req.spi.info.id.daddr);
+ req.spi.info.mode = tunnel_mode;
+ req.spi.info.reqid = reqid;
+ req.spi.info.id.proto = proto;
+ req.spi.info.family = src->u.v4.sin_family;
+ req.spi.min = min;
+ req.spi.max = max;
+
+ req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.spi)));
+ rsp.n.nlmsg_type = XFRM_MSG_NEWSA;
+
+ if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SPI", text_said))
+ return 0;
+
+ if (netlink_error("XFRM_MSG_ALLOCSPI", &rsp.n, &rsp.u.e, sizeof(rsp.u.sa)))
+ return 0;
+
+ DBG(DBG_KLIPS,
+ DBG_log("netlink_get_spi: allocated 0x%x for %s"
+ , ntohl(rsp.u.sa.id.spi), text_said));
+ return rsp.u.sa.id.spi;
}
const struct kernel_ops linux_kernel_ops = {
- type: KERNEL_TYPE_LINUX,
- inbound_eroute: 1,
- policy_lifetime: 1,
- async_fdp: &netlink_bcast_fd,
-
- init: init_netlink,
- pfkey_register: linux_pfkey_register,
- pfkey_register_response: linux_pfkey_register_response,
- process_msg: netlink_process_msg,
- raw_eroute: netlink_raw_eroute,
- get_policy: netlink_get_policy,
- add_sa: netlink_add_sa,
- del_sa: netlink_del_sa,
- get_sa: netlink_get_sa,
- process_queue: NULL,
- grp_sa: NULL,
- get_spi: netlink_get_spi,
+ type: KERNEL_TYPE_LINUX,
+ inbound_eroute: 1,
+ policy_lifetime: 1,
+ async_fdp: &netlink_bcast_fd,
+
+ init: init_netlink,
+ pfkey_register: linux_pfkey_register,
+ pfkey_register_response: linux_pfkey_register_response,
+ process_msg: netlink_process_msg,
+ raw_eroute: netlink_raw_eroute,
+ get_policy: netlink_get_policy,
+ add_sa: netlink_add_sa,
+ del_sa: netlink_del_sa,
+ get_sa: netlink_get_sa,
+ process_queue: NULL,
+ grp_sa: NULL,
+ get_spi: netlink_get_spi,
};
#endif /* linux && KLIPS */
diff --git a/src/pluto/kernel_netlink.h b/src/pluto/kernel_netlink.h
index 91ba71c5c..65163c966 100644
--- a/src/pluto/kernel_netlink.h
+++ b/src/pluto/kernel_netlink.h
@@ -11,8 +11,6 @@
* 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: kernel_netlink.h 3252 2007-10-06 21:24:50Z andreas $
*/
#if defined(KLIPS) && defined(linux)
diff --git a/src/pluto/kernel_noklips.c b/src/pluto/kernel_noklips.c
index 4ac3eb153..82a6ab648 100644
--- a/src/pluto/kernel_noklips.c
+++ b/src/pluto/kernel_noklips.c
@@ -13,8 +13,6 @@
* 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: kernel_noklips.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <errno.h>
@@ -39,7 +37,7 @@
#include "kernel.h"
#include "kernel_noklips.h"
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
void
init_noklips(void)
@@ -71,30 +69,30 @@ noklips_register(void)
static bool
noklips_raw_eroute(const ip_address *this_host UNUSED
- , const ip_subnet *this_client UNUSED
- , const ip_address *that_host UNUSED
- , const ip_subnet *that_client UNUSED
- , ipsec_spi_t spi UNUSED
- , unsigned int satype UNUSED
- , unsigned int transport_proto UNUSED
- , const struct pfkey_proto_info *proto_info UNUSED
- , time_t use_lifetime UNUSED
- , unsigned int op UNUSED
- , const char *text_said UNUSED)
+ , const ip_subnet *this_client UNUSED
+ , const ip_address *that_host UNUSED
+ , const ip_subnet *that_client UNUSED
+ , ipsec_spi_t spi UNUSED
+ , unsigned int satype UNUSED
+ , unsigned int transport_proto UNUSED
+ , const struct pfkey_proto_info *proto_info UNUSED
+ , time_t use_lifetime UNUSED
+ , unsigned int op UNUSED
+ , const char *text_said UNUSED)
{
return TRUE;
}
static bool
noklips_add_sa(const struct kernel_sa *sa UNUSED
- , bool replace UNUSED)
+ , bool replace UNUSED)
{
return TRUE;
}
static bool
noklips_grp_sa(const struct kernel_sa *sa0 UNUSED
- , const struct kernel_sa *sa1 UNUSED)
+ , const struct kernel_sa *sa1 UNUSED)
{
return TRUE;
}
@@ -107,20 +105,20 @@ noklips_del_sa(const struct kernel_sa *sa UNUSED)
const struct kernel_ops noklips_kernel_ops = {
- type: KERNEL_TYPE_NONE,
- async_fdp: NULL,
-
- init: init_noklips,
- pfkey_register: noklips_register,
- pfkey_register_response: noklips_register_response,
- process_queue: noklips_dequeue,
- process_msg: noklips_event,
- raw_eroute: noklips_raw_eroute,
- add_sa: noklips_add_sa,
- grp_sa: noklips_grp_sa,
- del_sa: noklips_del_sa,
- get_sa: NULL,
- get_spi: NULL,
- inbound_eroute: FALSE,
- policy_lifetime: FALSE
+ type: KERNEL_TYPE_NONE,
+ async_fdp: NULL,
+
+ init: init_noklips,
+ pfkey_register: noklips_register,
+ pfkey_register_response: noklips_register_response,
+ process_queue: noklips_dequeue,
+ process_msg: noklips_event,
+ raw_eroute: noklips_raw_eroute,
+ add_sa: noklips_add_sa,
+ grp_sa: noklips_grp_sa,
+ del_sa: noklips_del_sa,
+ get_sa: NULL,
+ get_spi: NULL,
+ inbound_eroute: FALSE,
+ policy_lifetime: FALSE
};
diff --git a/src/pluto/kernel_noklips.h b/src/pluto/kernel_noklips.h
index db819eed7..3da55d80b 100644
--- a/src/pluto/kernel_noklips.h
+++ b/src/pluto/kernel_noklips.h
@@ -11,8 +11,6 @@
* 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: kernel_noklips.h 3252 2007-10-06 21:24:50Z andreas $
*/
extern void init_noklips(void);
diff --git a/src/pluto/kernel_pfkey.c b/src/pluto/kernel_pfkey.c
index 742afaf52..7ac405fd4 100644
--- a/src/pluto/kernel_pfkey.c
+++ b/src/pluto/kernel_pfkey.c
@@ -12,8 +12,6 @@
* 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: kernel_pfkey.c 3252 2007-10-06 21:24:50Z andreas $
*/
#ifdef KLIPS
@@ -40,7 +38,7 @@
#include "kernel.h"
#include "kernel_pfkey.h"
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include "demux.h"
#include "nat_traversal.h"
#include "alg_info.h"
@@ -50,64 +48,64 @@
static int pfkeyfd = NULL_FD;
typedef u_int32_t pfkey_seq_t;
-static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */
+static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */
static pid_t pid;
-#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
+#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
static sparse_names pfkey_type_names = {
- NE(SADB_RESERVED),
- NE(SADB_GETSPI),
- NE(SADB_UPDATE),
- NE(SADB_ADD),
- NE(SADB_DELETE),
- NE(SADB_GET),
- NE(SADB_ACQUIRE),
- NE(SADB_REGISTER),
- NE(SADB_EXPIRE),
- NE(SADB_FLUSH),
- NE(SADB_DUMP),
- NE(SADB_X_PROMISC),
- NE(SADB_X_PCHANGE),
- NE(SADB_X_GRPSA),
- NE(SADB_X_ADDFLOW),
- NE(SADB_X_DELFLOW),
- NE(SADB_X_DEBUG),
- NE(SADB_X_NAT_T_NEW_MAPPING),
- NE(SADB_MAX),
- { 0, sparse_end }
+ NE(SADB_RESERVED),
+ NE(SADB_GETSPI),
+ NE(SADB_UPDATE),
+ NE(SADB_ADD),
+ NE(SADB_DELETE),
+ NE(SADB_GET),
+ NE(SADB_ACQUIRE),
+ NE(SADB_REGISTER),
+ NE(SADB_EXPIRE),
+ NE(SADB_FLUSH),
+ NE(SADB_DUMP),
+ NE(SADB_X_PROMISC),
+ NE(SADB_X_PCHANGE),
+ NE(SADB_X_GRPSA),
+ NE(SADB_X_ADDFLOW),
+ NE(SADB_X_DELFLOW),
+ NE(SADB_X_DEBUG),
+ NE(SADB_X_NAT_T_NEW_MAPPING),
+ NE(SADB_MAX),
+ { 0, sparse_end }
};
#ifdef NEVER /* not needed yet */
static sparse_names pfkey_ext_names = {
- NE(SADB_EXT_RESERVED),
- NE(SADB_EXT_SA),
- NE(SADB_EXT_LIFETIME_CURRENT),
- NE(SADB_EXT_LIFETIME_HARD),
- NE(SADB_EXT_LIFETIME_SOFT),
- NE(SADB_EXT_ADDRESS_SRC),
- NE(SADB_EXT_ADDRESS_DST),
- NE(SADB_EXT_ADDRESS_PROXY),
- NE(SADB_EXT_KEY_AUTH),
- NE(SADB_EXT_KEY_ENCRYPT),
- NE(SADB_EXT_IDENTITY_SRC),
- NE(SADB_EXT_IDENTITY_DST),
- NE(SADB_EXT_SENSITIVITY),
- NE(SADB_EXT_PROPOSAL),
- NE(SADB_EXT_SUPPORTED_AUTH),
- NE(SADB_EXT_SUPPORTED_ENCRYPT),
- NE(SADB_EXT_SPIRANGE),
- NE(SADB_X_EXT_KMPRIVATE),
- NE(SADB_X_EXT_SATYPE2),
- NE(SADB_X_EXT_SA2),
- NE(SADB_X_EXT_ADDRESS_DST2),
- NE(SADB_X_EXT_ADDRESS_SRC_FLOW),
- NE(SADB_X_EXT_ADDRESS_DST_FLOW),
- NE(SADB_X_EXT_ADDRESS_SRC_MASK),
- NE(SADB_X_EXT_ADDRESS_DST_MASK),
- NE(SADB_X_EXT_DEBUG),
- { 0, sparse_end }
+ NE(SADB_EXT_RESERVED),
+ NE(SADB_EXT_SA),
+ NE(SADB_EXT_LIFETIME_CURRENT),
+ NE(SADB_EXT_LIFETIME_HARD),
+ NE(SADB_EXT_LIFETIME_SOFT),
+ NE(SADB_EXT_ADDRESS_SRC),
+ NE(SADB_EXT_ADDRESS_DST),
+ NE(SADB_EXT_ADDRESS_PROXY),
+ NE(SADB_EXT_KEY_AUTH),
+ NE(SADB_EXT_KEY_ENCRYPT),
+ NE(SADB_EXT_IDENTITY_SRC),
+ NE(SADB_EXT_IDENTITY_DST),
+ NE(SADB_EXT_SENSITIVITY),
+ NE(SADB_EXT_PROPOSAL),
+ NE(SADB_EXT_SUPPORTED_AUTH),
+ NE(SADB_EXT_SUPPORTED_ENCRYPT),
+ NE(SADB_EXT_SPIRANGE),
+ NE(SADB_X_EXT_KMPRIVATE),
+ NE(SADB_X_EXT_SATYPE2),
+ NE(SADB_X_EXT_SA2),
+ NE(SADB_X_EXT_ADDRESS_DST2),
+ NE(SADB_X_EXT_ADDRESS_SRC_FLOW),
+ NE(SADB_X_EXT_ADDRESS_DST_FLOW),
+ NE(SADB_X_EXT_ADDRESS_SRC_MASK),
+ NE(SADB_X_EXT_ADDRESS_DST_MASK),
+ NE(SADB_X_EXT_DEBUG),
+ { 0, sparse_end }
};
#endif /* NEVER */
@@ -116,24 +114,24 @@ static sparse_names pfkey_ext_names = {
void
init_pfkey(void)
{
- pid = getpid();
+ pid = getpid();
- /* open PF_KEY socket */
+ /* open PF_KEY socket */
- pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
- if (pfkeyfd == -1)
- exit_log_errno((e, "socket() in init_pfkeyfd()"));
+ if (pfkeyfd == -1)
+ exit_log_errno((e, "socket() in init_pfkeyfd()"));
-#ifdef NEVER /* apparently unsupported! */
- if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0)
- exit_log_errno((e, "fcntl(O_NONBLOCK) in init_pfkeyfd()"));
+#ifdef NEVER /* apparently unsupported! */
+ if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0)
+ exit_log_errno((e, "fcntl(O_NONBLOCK) in init_pfkeyfd()"));
#endif
- if (fcntl(pfkeyfd, F_SETFD, FD_CLOEXEC) != 0)
- exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_pfkeyfd()"));
+ if (fcntl(pfkeyfd, F_SETFD, FD_CLOEXEC) != 0)
+ exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_pfkeyfd()"));
- DBG(DBG_KLIPS,
- DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd));
+ DBG(DBG_KLIPS,
+ DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd));
}
/* Kinds of PF_KEY message from the kernel:
@@ -153,9 +151,9 @@ init_pfkey(void)
*/
typedef union {
- unsigned char bytes[PFKEYv2_MAX_MSGSIZE];
- struct sadb_msg msg;
- } pfkey_buf;
+ unsigned char bytes[PFKEYv2_MAX_MSGSIZE];
+ struct sadb_msg msg;
+ } pfkey_buf;
/* queue of unprocessed PF_KEY messages input from kernel
* Note that the pfkey_buf may be partly allocated, reflecting
@@ -163,41 +161,41 @@ typedef union {
* must come first.
*/
typedef struct pfkey_item {
- struct pfkey_item *next;
- pfkey_buf buf;
- } pfkey_item;
+ struct pfkey_item *next;
+ pfkey_buf buf;
+ } pfkey_item;
-static pfkey_item *pfkey_iq_head = NULL; /* oldest */
-static pfkey_item *pfkey_iq_tail; /* youngest */
+static pfkey_item *pfkey_iq_head = NULL; /* oldest */
+static pfkey_item *pfkey_iq_tail; /* youngest */
static bool
pfkey_input_ready(void)
{
- fd_set readfds;
- int ndes;
- struct timeval tm;
+ fd_set readfds;
+ int ndes;
+ struct timeval tm;
- tm.tv_sec = 0; /* don't wait at all */
- tm.tv_usec = 0;
+ tm.tv_sec = 0; /* don't wait at all */
+ tm.tv_usec = 0;
- FD_ZERO(&readfds); /* we only care about pfkeyfd */
- FD_SET(pfkeyfd, &readfds);
+ FD_ZERO(&readfds); /* we only care about pfkeyfd */
+ FD_SET(pfkeyfd, &readfds);
- do {
- ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm);
- } while (ndes == -1 && errno == EINTR);
+ do {
+ ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm);
+ } while (ndes == -1 && errno == EINTR);
- if (ndes < 0)
- {
- log_errno((e, "select() failed in pfkey_get()"));
- return FALSE;
- }
+ if (ndes < 0)
+ {
+ log_errno((e, "select() failed in pfkey_get()"));
+ return FALSE;
+ }
- if (ndes == 0)
- return FALSE; /* nothing to read */
+ if (ndes == 0)
+ return FALSE; /* nothing to read */
- passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds));
- return TRUE;
+ passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds));
+ return TRUE;
}
/* get a PF_KEY message from kernel.
@@ -210,93 +208,93 @@ pfkey_input_ready(void)
static bool
pfkey_get(pfkey_buf *buf)
{
- for (;;)
- {
- /* len must be less than PFKEYv2_MAX_MSGSIZE,
- * so it should fit in an int. We use this fact when printing it.
- */
- ssize_t len;
+ for (;;)
+ {
+ /* len must be less than PFKEYv2_MAX_MSGSIZE,
+ * so it should fit in an int. We use this fact when printing it.
+ */
+ ssize_t len;
- if (!pfkey_input_ready())
- return FALSE;
+ if (!pfkey_input_ready())
+ return FALSE;
- len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes));
+ len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes));
- if (len < 0)
- {
- if (errno == EAGAIN)
- return FALSE;
+ if (len < 0)
+ {
+ if (errno == EAGAIN)
+ return FALSE;
- log_errno((e, "read() failed in pfkey_get()"));
- return FALSE;
- }
- else if ((size_t) len < sizeof(buf->msg))
- {
- plog("pfkey_get read truncated PF_KEY message: %d bytes; ignoring message"
- , (int) len);
- }
- else if ((size_t) len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
- {
- plog("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %u; ignoring message"
- , (int) len
- , (unsigned) buf->msg.sadb_msg_len
- , (unsigned) IPSEC_PFKEYv2_ALIGN);
- }
- else if (!(buf->msg.sadb_msg_pid == (unsigned)pid
- || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE)
- || (buf->msg.sadb_msg_type == SADB_REGISTER)
- || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING)))
- {
- /* not for us: ignore */
- DBG(DBG_KLIPS,
- DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process %u"
- , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
- , buf->msg.sadb_msg_seq
- , buf->msg.sadb_msg_pid));
- }
- else
- {
- DBG(DBG_KLIPS,
- DBG_log("pfkey_get: %s message %u"
- , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
- , buf->msg.sadb_msg_seq));
- return TRUE;
+ log_errno((e, "read() failed in pfkey_get()"));
+ return FALSE;
+ }
+ else if ((size_t) len < sizeof(buf->msg))
+ {
+ plog("pfkey_get read truncated PF_KEY message: %d bytes; ignoring message"
+ , (int) len);
+ }
+ else if ((size_t) len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
+ {
+ plog("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %u; ignoring message"
+ , (int) len
+ , (unsigned) buf->msg.sadb_msg_len
+ , (unsigned) IPSEC_PFKEYv2_ALIGN);
+ }
+ else if (!(buf->msg.sadb_msg_pid == (unsigned)pid
+ || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE)
+ || (buf->msg.sadb_msg_type == SADB_REGISTER)
+ || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING)))
+ {
+ /* not for us: ignore */
+ DBG(DBG_KLIPS,
+ DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process %u"
+ , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
+ , buf->msg.sadb_msg_seq
+ , buf->msg.sadb_msg_pid));
+ }
+ else
+ {
+ DBG(DBG_KLIPS,
+ DBG_log("pfkey_get: %s message %u"
+ , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
+ , buf->msg.sadb_msg_seq));
+ return TRUE;
+ }
}
- }
}
/* get a response to a specific message */
static bool
pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq)
{
- while (pfkey_get(buf))
- {
- if (buf->msg.sadb_msg_pid == (unsigned)pid
- && buf->msg.sadb_msg_seq == seq)
+ while (pfkey_get(buf))
{
- return TRUE;
- }
- else
- {
- /* Not for us: queue it. */
- size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
- pfkey_item *it = alloc_bytes(offsetof(pfkey_item, buf) + bl, "pfkey_item");
-
- memcpy(&it->buf, buf, bl);
-
- it->next = NULL;
- if (pfkey_iq_head == NULL)
- {
- pfkey_iq_head = it;
- }
- else
- {
- pfkey_iq_tail->next = it;
- }
- pfkey_iq_tail = it;
+ if (buf->msg.sadb_msg_pid == (unsigned)pid
+ && buf->msg.sadb_msg_seq == seq)
+ {
+ return TRUE;
+ }
+ else
+ {
+ /* Not for us: queue it. */
+ size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
+ pfkey_item *it = malloc(offsetof(pfkey_item, buf) + bl);
+
+ memcpy(&it->buf, buf, bl);
+
+ it->next = NULL;
+ if (pfkey_iq_head == NULL)
+ {
+ pfkey_iq_head = it;
+ }
+ else
+ {
+ pfkey_iq_tail->next = it;
+ }
+ pfkey_iq_tail = it;
+ }
}
- }
- return FALSE;
+ return FALSE;
}
/* Process a SADB_REGISTER message from the kernel.
@@ -307,34 +305,34 @@ pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq)
static void
klips_pfkey_register_response(const struct sadb_msg *msg)
{
- /* Find out what the kernel can support.
- * In fact, the only question at the moment
- * is whether it can support IPcomp.
- * So we ignore the rest.
- * ??? we really should pay attention to what transforms are supported.
- */
- switch (msg->sadb_msg_satype)
- {
- case SADB_SATYPE_AH:
- break;
- case SADB_SATYPE_ESP:
+ /* Find out what the kernel can support.
+ * In fact, the only question at the moment
+ * is whether it can support IPcomp.
+ * So we ignore the rest.
+ * ??? we really should pay attention to what transforms are supported.
+ */
+ switch (msg->sadb_msg_satype)
+ {
+ case SADB_SATYPE_AH:
+ break;
+ case SADB_SATYPE_ESP:
#ifndef NO_KERNEL_ALG
- kernel_alg_register_pfkey(msg, sizeof (pfkey_buf));
+ kernel_alg_register_pfkey(msg, sizeof (pfkey_buf));
#endif
- break;
- case SADB_X_SATYPE_COMP:
- /* ??? There ought to be an extension to list the
- * supported algorithms, but RFC 2367 doesn't
- * list one for IPcomp. KLIPS uses SADB_X_CALG_DEFLATE.
- * Since we only implement deflate, we'll assume this.
- */
- can_do_IPcomp = TRUE;
- break;
- case SADB_X_SATYPE_IPIP:
- break;
- default:
- break;
- }
+ break;
+ case SADB_X_SATYPE_COMP:
+ /* ??? There ought to be an extension to list the
+ * supported algorithms, but RFC 2367 doesn't
+ * list one for IPcomp. KLIPS uses SADB_X_CALG_DEFLATE.
+ * Since we only implement deflate, we'll assume this.
+ */
+ can_do_IPcomp = TRUE;
+ break;
+ case SADB_X_SATYPE_IPIP:
+ break;
+ default:
+ break;
+ }
}
/* Processs a SADB_ACQUIRE message from KLIPS.
@@ -357,33 +355,33 @@ klips_pfkey_register_response(const struct sadb_msg *msg)
static void
process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
- struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
- int src_proto = srcx->sadb_address_proto;
- int dst_proto = dstx->sadb_address_proto;
- ip_address *src = (ip_address*)&srcx[1];
- ip_address *dst = (ip_address*)&dstx[1];
- ip_subnet ours, his;
- err_t ugh = NULL;
-
- /* assumption: we're only catching our own outgoing packets
- * so source is our end and destination is the other end.
- * Verifying this is not actually convenient.
- *
- * This stylized control structure yields a complaint or
- * desired results. For compactness, a pointer value is
- * treated as a boolean. Logically, the structure is:
- * keep going as long as things are OK.
- */
- if (buf->msg.sadb_msg_pid == 0 /* we only wish to hear from kernel */
- && !(ugh = src_proto == dst_proto? NULL : "src and dst protocols differ")
- && !(ugh = addrtypeof(src) == addrtypeof(dst)? NULL : "conflicting address types")
- && !(ugh = addrtosubnet(src, &ours))
- && !(ugh = addrtosubnet(dst, &his)))
- record_and_initiate_opportunistic(&ours, &his, src_proto, "%acquire");
-
- if (ugh != NULL)
- plog("SADB_ACQUIRE message from KLIPS malformed: %s", ugh);
+ struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
+ struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
+ int src_proto = srcx->sadb_address_proto;
+ int dst_proto = dstx->sadb_address_proto;
+ ip_address *src = (ip_address*)&srcx[1];
+ ip_address *dst = (ip_address*)&dstx[1];
+ ip_subnet ours, his;
+ err_t ugh = NULL;
+
+ /* assumption: we're only catching our own outgoing packets
+ * so source is our end and destination is the other end.
+ * Verifying this is not actually convenient.
+ *
+ * This stylized control structure yields a complaint or
+ * desired results. For compactness, a pointer value is
+ * treated as a boolean. Logically, the structure is:
+ * keep going as long as things are OK.
+ */
+ if (buf->msg.sadb_msg_pid == 0 /* we only wish to hear from kernel */
+ && !(ugh = src_proto == dst_proto? NULL : "src and dst protocols differ")
+ && !(ugh = addrtypeof(src) == addrtypeof(dst)? NULL : "conflicting address types")
+ && !(ugh = addrtosubnet(src, &ours))
+ && !(ugh = addrtosubnet(dst, &his)))
+ record_and_initiate_opportunistic(&ours, &his, src_proto, "%acquire");
+
+ if (ugh != NULL)
+ plog("SADB_ACQUIRE message from KLIPS malformed: %s", ugh);
}
@@ -394,73 +392,73 @@ process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX +
static void
pfkey_async(pfkey_buf *buf)
{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
-
- if (pfkey_msg_parse(&buf->msg, NULL, extensions, EXT_BITS_OUT))
- {
- plog("pfkey_async:"
- " unparseable PF_KEY message:"
- " %s len=%d, errno=%d, seq=%d, pid=%d; message ignored"
- , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
- , buf->msg.sadb_msg_len
- , buf->msg.sadb_msg_errno
- , buf->msg.sadb_msg_seq
- , buf->msg.sadb_msg_pid);
- }
- else
- {
- DBG(DBG_CONTROL | DBG_KLIPS, DBG_log("pfkey_async:"
- " %s len=%u, errno=%u, satype=%u, seq=%u, pid=%u"
- , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
- , buf->msg.sadb_msg_len
- , buf->msg.sadb_msg_errno
- , buf->msg.sadb_msg_satype
- , buf->msg.sadb_msg_seq
- , buf->msg.sadb_msg_pid));
-
- switch (buf->msg.sadb_msg_type)
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+
+ if (pfkey_msg_parse(&buf->msg, NULL, extensions, EXT_BITS_OUT))
{
- case SADB_REGISTER:
- kernel_ops->pfkey_register_response(&buf->msg);
- break;
- case SADB_ACQUIRE:
- /* to simulate loss of ACQUIRE, delete this call */
- process_pfkey_acquire(buf, extensions);
- break;
- case SADB_X_NAT_T_NEW_MAPPING:
- process_pfkey_nat_t_new_mapping(&(buf->msg), extensions);
- break;
- default:
- /* ignored */
- break;
+ plog("pfkey_async:"
+ " unparseable PF_KEY message:"
+ " %s len=%d, errno=%d, seq=%d, pid=%d; message ignored"
+ , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
+ , buf->msg.sadb_msg_len
+ , buf->msg.sadb_msg_errno
+ , buf->msg.sadb_msg_seq
+ , buf->msg.sadb_msg_pid);
+ }
+ else
+ {
+ DBG(DBG_CONTROL | DBG_KLIPS, DBG_log("pfkey_async:"
+ " %s len=%u, errno=%u, satype=%u, seq=%u, pid=%u"
+ , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
+ , buf->msg.sadb_msg_len
+ , buf->msg.sadb_msg_errno
+ , buf->msg.sadb_msg_satype
+ , buf->msg.sadb_msg_seq
+ , buf->msg.sadb_msg_pid));
+
+ switch (buf->msg.sadb_msg_type)
+ {
+ case SADB_REGISTER:
+ kernel_ops->pfkey_register_response(&buf->msg);
+ break;
+ case SADB_ACQUIRE:
+ /* to simulate loss of ACQUIRE, delete this call */
+ process_pfkey_acquire(buf, extensions);
+ break;
+ case SADB_X_NAT_T_NEW_MAPPING:
+ process_pfkey_nat_t_new_mapping(&(buf->msg), extensions);
+ break;
+ default:
+ /* ignored */
+ break;
+ }
}
- }
}
/* asynchronous messages from our queue */
static void
pfkey_dequeue(void)
{
- while (pfkey_iq_head != NULL)
- {
- pfkey_item *it = pfkey_iq_head;
-
- pfkey_async(&it->buf);
- pfkey_iq_head = it->next;
- pfree(it);
- }
-
- /* Handle any orphaned holds, but only if no pfkey input is pending.
- * For each, we initiate Opportunistic.
- * note: we don't need to advance the pointer because
- * record_and_initiate_opportunistic will remove the current
- * record each time we call it.
- */
- while (orphaned_holds != NULL && !pfkey_input_ready())
- record_and_initiate_opportunistic(&orphaned_holds->ours
- , &orphaned_holds->his
- , orphaned_holds->transport_proto
- , "%hold found-pfkey");
+ while (pfkey_iq_head != NULL)
+ {
+ pfkey_item *it = pfkey_iq_head;
+
+ pfkey_async(&it->buf);
+ pfkey_iq_head = it->next;
+ free(it);
+ }
+
+ /* Handle any orphaned holds, but only if no pfkey input is pending.
+ * For each, we initiate Opportunistic.
+ * note: we don't need to advance the pointer because
+ * record_and_initiate_opportunistic will remove the current
+ * record each time we call it.
+ */
+ while (orphaned_holds != NULL && !pfkey_input_ready())
+ record_and_initiate_opportunistic(&orphaned_holds->ours
+ , &orphaned_holds->his
+ , orphaned_holds->transport_proto
+ , "%hold found-pfkey");
}
@@ -468,10 +466,10 @@ pfkey_dequeue(void)
static void
pfkey_event(void)
{
- pfkey_buf buf;
+ pfkey_buf buf;
- if (pfkey_get(&buf))
- pfkey_async(&buf);
+ if (pfkey_get(&buf))
+ pfkey_async(&buf);
}
static bool
@@ -480,17 +478,17 @@ pfkey_build(int error
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- if (error == 0)
- {
- return TRUE;
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d"
- , description, text_said, error);
- pfkey_extensions_free(extensions);
- return FALSE;
- }
+ if (error == 0)
+ {
+ return TRUE;
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d"
+ , description, text_said, error);
+ pfkey_extensions_free(extensions);
+ return FALSE;
+ }
}
/* pfkey_extensions_init + pfkey_build + pfkey_msg_hdr_build */
@@ -501,10 +499,10 @@ pfkey_msg_start(u_int8_t msg_type
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- pfkey_extensions_init(extensions);
- return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type
- , satype, 0, ++pfkey_seq, pid)
- , description, text_said, extensions);
+ pfkey_extensions_init(extensions);
+ return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type
+ , satype, 0, ++pfkey_seq, pid)
+ , description, text_said, extensions);
}
/* pfkey_build + pfkey_address_build */
@@ -515,15 +513,15 @@ pfkeyext_address(u_int16_t exttype
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- /* the following variable is only needed to silence
- * a warning caused by the fact that the argument
- * to sockaddrof is NOT pointer to const!
- */
- ip_address t = *address;
-
- return pfkey_build(pfkey_address_build(extensions + exttype
- , exttype, 0, 0, sockaddrof(&t))
- , description, text_said, extensions);
+ /* the following variable is only needed to silence
+ * a warning caused by the fact that the argument
+ * to sockaddrof is NOT pointer to const!
+ */
+ ip_address t = *address;
+
+ return pfkey_build(pfkey_address_build(extensions + exttype
+ , exttype, 0, 0, sockaddrof(&t))
+ , description, text_said, extensions);
}
/* pfkey_build + pfkey_x_protocol_build */
@@ -533,10 +531,10 @@ pfkeyext_protocol(int transport_proto
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- return (transport_proto == 0)? TRUE
- : pfkey_build(
- pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL, transport_proto)
- , description, text_said, extensions);
+ return (transport_proto == 0)? TRUE
+ : pfkey_build(
+ pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL, transport_proto)
+ , description, text_said, extensions);
}
@@ -551,376 +549,376 @@ finish_pfkey_msg(struct sadb_ext *extensions[SADB_EXT_MAX + 1]
, const char *text_said
, pfkey_buf *response)
{
- struct sadb_msg *pfkey_msg;
- bool success = TRUE;
- int error;
-
- error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
-
- if (error != 0)
- {
- loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d"
- , description, text_said, error);
- success = FALSE;
- }
- else
- {
- size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
+ struct sadb_msg *pfkey_msg;
+ bool success = TRUE;
+ int error;
- DBG(DBG_KLIPS,
- DBG_log("finish_pfkey_msg: %s message %u for %s %s"
- , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
- , pfkey_msg->sadb_msg_seq
- , description, text_said);
- DBG_dump(NULL, (void *) pfkey_msg, len));
+ error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
- if (!no_klips)
+ if (error != 0)
{
- ssize_t r = write(pfkeyfd, pfkey_msg, len);
-
- if (r != (ssize_t)len)
- {
- if (r < 0)
- {
- log_errno((e
- , "pfkey write() of %s message %u"
- " for %s %s failed"
- , sparse_val_show(pfkey_type_names
- , pfkey_msg->sadb_msg_type)
- , pfkey_msg->sadb_msg_seq
- , description, text_said));
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR: pfkey write() of %s message %u"
- " for %s %s truncated: %ld instead of %ld"
- , sparse_val_show(pfkey_type_names
- , pfkey_msg->sadb_msg_type)
- , pfkey_msg->sadb_msg_seq
- , description, text_said
- , (long)r, (long)len);
- }
+ loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d"
+ , description, text_said, error);
success = FALSE;
+ }
+ else
+ {
+ size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
- /* if we were compiled with debugging, but we haven't already
- * dumped the KLIPS command, do so.
- */
-#ifdef DEBUG
- if ((cur_debugging & DBG_KLIPS) == 0)
- DBG_dump(NULL, (void *) pfkey_msg, len);
-#endif
- }
- else
- {
- /* Check response from KLIPS.
- * It ought to be an echo, perhaps with additional info.
- * If the caller wants it, response will point to space.
- */
- pfkey_buf b;
- pfkey_buf *bp = response != NULL? response : &b;
+ DBG(DBG_KLIPS,
+ DBG_log("finish_pfkey_msg: %s message %u for %s %s"
+ , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
+ , pfkey_msg->sadb_msg_seq
+ , description, text_said);
+ DBG_dump(NULL, (void *) pfkey_msg, len));
- if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq))
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR: no response to our PF_KEY %s message for %s %s"
- , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
- , description, text_said);
- success = FALSE;
- }
- else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type)
- {
- loglog(RC_LOG_SERIOUS
- , "FreeS/WAN ERROR: response to our PF_KEY %s message for %s %s was of wrong type (%s)"
- , sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type)
- , description, text_said
- , sparse_val_show(pfkey_type_names, bp->msg.sadb_msg_type));
- success = FALSE;
- }
- else if (response == NULL && bp->msg.sadb_msg_errno != 0)
+ if (!no_klips)
{
- /* KLIPS is signalling a problem */
- loglog(RC_LOG_SERIOUS
- , "ERROR: PF_KEY %s response for %s %s included errno %u: %s"
- , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
- , description, text_said
- , (unsigned) bp->msg.sadb_msg_errno
- , strerror(bp->msg.sadb_msg_errno));
- success = FALSE;
+ ssize_t r = write(pfkeyfd, pfkey_msg, len);
+
+ if (r != (ssize_t)len)
+ {
+ if (r < 0)
+ {
+ log_errno((e
+ , "pfkey write() of %s message %u"
+ " for %s %s failed"
+ , sparse_val_show(pfkey_type_names
+ , pfkey_msg->sadb_msg_type)
+ , pfkey_msg->sadb_msg_seq
+ , description, text_said));
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ERROR: pfkey write() of %s message %u"
+ " for %s %s truncated: %ld instead of %ld"
+ , sparse_val_show(pfkey_type_names
+ , pfkey_msg->sadb_msg_type)
+ , pfkey_msg->sadb_msg_seq
+ , description, text_said
+ , (long)r, (long)len);
+ }
+ success = FALSE;
+
+ /* if we were compiled with debugging, but we haven't already
+ * dumped the KLIPS command, do so.
+ */
+#ifdef DEBUG
+ if ((cur_debugging & DBG_KLIPS) == 0)
+ DBG_dump(NULL, (void *) pfkey_msg, len);
+#endif
+ }
+ else
+ {
+ /* Check response from KLIPS.
+ * It ought to be an echo, perhaps with additional info.
+ * If the caller wants it, response will point to space.
+ */
+ pfkey_buf b;
+ pfkey_buf *bp = response != NULL? response : &b;
+
+ if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq))
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ERROR: no response to our PF_KEY %s message for %s %s"
+ , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
+ , description, text_said);
+ success = FALSE;
+ }
+ else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "FreeS/WAN ERROR: response to our PF_KEY %s message for %s %s was of wrong type (%s)"
+ , sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type)
+ , description, text_said
+ , sparse_val_show(pfkey_type_names, bp->msg.sadb_msg_type));
+ success = FALSE;
+ }
+ else if (response == NULL && bp->msg.sadb_msg_errno != 0)
+ {
+ /* KLIPS is signalling a problem */
+ loglog(RC_LOG_SERIOUS
+ , "ERROR: PF_KEY %s response for %s %s included errno %u: %s"
+ , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
+ , description, text_said
+ , (unsigned) bp->msg.sadb_msg_errno
+ , strerror(bp->msg.sadb_msg_errno));
+ success = FALSE;
+ }
+ }
}
- }
}
- }
- /* all paths must exit this way to free resources */
- pfkey_extensions_free(extensions);
- pfkey_msg_free(&pfkey_msg);
- return success;
+ /* all paths must exit this way to free resources */
+ pfkey_extensions_free(extensions);
+ pfkey_msg_free(&pfkey_msg);
+ return success;
}
/* register SA types that can be negotiated */
void
pfkey_register_proto(unsigned satype, const char *satypename)
{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
- pfkey_buf pfb;
-
- if (!(pfkey_msg_start(SADB_REGISTER
- , satype
- , satypename, NULL, extensions)
- && finish_pfkey_msg(extensions, satypename, "", &pfb)))
- {
- /* ??? should this be loglog */
- plog("no KLIPS support for %s", satypename);
- }
- else
- {
- kernel_ops->pfkey_register_response(&pfb.msg);
- DBG(DBG_KLIPS,
- DBG_log("%s registered with kernel.", satypename));
- }
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+ pfkey_buf pfb;
+
+ if (!(pfkey_msg_start(SADB_REGISTER
+ , satype
+ , satypename, NULL, extensions)
+ && finish_pfkey_msg(extensions, satypename, "", &pfb)))
+ {
+ /* ??? should this be loglog */
+ plog("no KLIPS support for %s", satypename);
+ }
+ else
+ {
+ kernel_ops->pfkey_register_response(&pfb.msg);
+ DBG(DBG_KLIPS,
+ DBG_log("%s registered with kernel.", satypename));
+ }
}
static void
klips_pfkey_register(void)
{
- pfkey_register_proto(SADB_SATYPE_AH, "AH");
- pfkey_register_proto(SADB_SATYPE_ESP, "ESP");
- can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
- pfkey_register_proto(SADB_X_SATYPE_COMP, "IPCOMP");
- pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP");
+ pfkey_register_proto(SADB_SATYPE_AH, "AH");
+ pfkey_register_proto(SADB_SATYPE_ESP, "ESP");
+ can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
+ pfkey_register_proto(SADB_X_SATYPE_COMP, "IPCOMP");
+ pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP");
}
static bool
pfkey_raw_eroute(const ip_address *this_host
- , const ip_subnet *this_client
- , const ip_address *that_host
- , const ip_subnet *that_client
- , ipsec_spi_t spi
- , unsigned int satype
- , unsigned int transport_proto
- , const struct pfkey_proto_info *proto_info UNUSED
- , time_t use_lifetime UNUSED
- , unsigned int op
- , const char *text_said)
+ , const ip_subnet *this_client
+ , const ip_address *that_host
+ , const ip_subnet *that_client
+ , ipsec_spi_t spi
+ , unsigned int satype
+ , unsigned int transport_proto
+ , const struct pfkey_proto_info *proto_info UNUSED
+ , time_t use_lifetime UNUSED
+ , unsigned int op
+ , const char *text_said)
{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
- ip_address
- sflow_ska,
- dflow_ska,
- smask_ska,
- dmask_ska;
- int sport = ntohs(portof(&this_client->addr));
- int dport = ntohs(portof(&that_client->addr));
-
- networkof(this_client, &sflow_ska);
- maskof(this_client, &smask_ska);
- setportof(sport ? ~0:0, &smask_ska);
-
- networkof(that_client, &dflow_ska);
- maskof(that_client, &dmask_ska);
- setportof(dport ? ~0:0, &dmask_ska);
-
- if (!pfkey_msg_start(op & ERO_MASK, satype
- , "pfkey_msg_hdr flow", text_said, extensions))
- {
- return FALSE;
- }
-
- if (op != ERO_DELETE)
- {
- if (!(pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
- , SADB_EXT_SA
- , spi /* in network order */
- , 0, 0, 0, 0, op >> ERO_FLAG_SHIFT)
- , "pfkey_sa add flow", text_said, extensions)
-
- && pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host
- , "pfkey_addr_s add flow", text_said, extensions)
-
- && pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host
- , "pfkey_addr_d add flow", text_said
- , extensions)))
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+ ip_address
+ sflow_ska,
+ dflow_ska,
+ smask_ska,
+ dmask_ska;
+ int sport = ntohs(portof(&this_client->addr));
+ int dport = ntohs(portof(&that_client->addr));
+
+ networkof(this_client, &sflow_ska);
+ maskof(this_client, &smask_ska);
+ setportof(sport ? ~0:0, &smask_ska);
+
+ networkof(that_client, &dflow_ska);
+ maskof(that_client, &dmask_ska);
+ setportof(dport ? ~0:0, &dmask_ska);
+
+ if (!pfkey_msg_start(op & ERO_MASK, satype
+ , "pfkey_msg_hdr flow", text_said, extensions))
{
- return FALSE;
+ return FALSE;
}
- }
- if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska
- , "pfkey_addr_sflow", text_said, extensions))
- {
- return FALSE;
- }
+ if (op != ERO_DELETE)
+ {
+ if (!(pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
+ , SADB_EXT_SA
+ , spi /* in network order */
+ , 0, 0, 0, 0, op >> ERO_FLAG_SHIFT)
+ , "pfkey_sa add flow", text_said, extensions)
+
+ && pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host
+ , "pfkey_addr_s add flow", text_said, extensions)
+
+ && pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host
+ , "pfkey_addr_d add flow", text_said
+ , extensions)))
+ {
+ return FALSE;
+ }
+ }
- if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska
- , "pfkey_addr_dflow", text_said, extensions))
- {
- return FALSE;
- }
+ if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska
+ , "pfkey_addr_sflow", text_said, extensions))
+ {
+ return FALSE;
+ }
- if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska
- , "pfkey_addr_smask", text_said, extensions))
- {
- return FALSE;
- }
+ if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska
+ , "pfkey_addr_dflow", text_said, extensions))
+ {
+ return FALSE;
+ }
- if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska
- , "pfkey_addr_dmask", text_said, extensions))
- {
- return FALSE;
- }
+ if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska
+ , "pfkey_addr_smask", text_said, extensions))
+ {
+ return FALSE;
+ }
- if (!pfkeyext_protocol(transport_proto
- , "pfkey_x_protocol", text_said, extensions))
- {
- return FALSE;
- }
+ if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska
+ , "pfkey_addr_dmask", text_said, extensions))
+ {
+ return FALSE;
+ }
+
+ if (!pfkeyext_protocol(transport_proto
+ , "pfkey_x_protocol", text_said, extensions))
+ {
+ return FALSE;
+ }
- return finish_pfkey_msg(extensions, "flow", text_said, NULL);
+ return finish_pfkey_msg(extensions, "flow", text_said, NULL);
}
static bool
pfkey_add_sa(const struct kernel_sa *sa, bool replace)
{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
-
- return pfkey_msg_start(replace ? SADB_UPDATE : SADB_ADD, sa->satype
- , "pfkey_msg_hdr Add SA", sa->text_said, extensions)
-
- && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
- , SADB_EXT_SA
- , sa->spi /* in network order */
- , sa->replay_window, SADB_SASTATE_MATURE
- , sa->authalg, sa->encalg ? sa->encalg: sa->compalg, 0)
- , "pfkey_sa Add SA", sa->text_said, extensions)
-
- && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src
- , "pfkey_addr_s Add SA", sa->text_said, extensions)
-
- && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst
- , "pfkey_addr_d Add SA", sa->text_said, extensions)
-
- && (sa->authkeylen == 0
- || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH]
- , SADB_EXT_KEY_AUTH, sa->authkeylen * BITS_PER_BYTE
- , sa->authkey)
- , "pfkey_key_a Add SA", sa->text_said, extensions))
-
- && (sa->enckeylen == 0
- || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT]
- , SADB_EXT_KEY_ENCRYPT, sa->enckeylen * BITS_PER_BYTE
- , sa->enckey)
- , "pfkey_key_e Add SA", sa->text_said, extensions))
-
- && (sa->natt_type == 0
- || pfkey_build(pfkey_x_nat_t_type_build(
- &extensions[SADB_X_EXT_NAT_T_TYPE], sa->natt_type),
- "pfkey_nat_t_type Add ESP SA", sa->text_said, extensions))
- && (sa->natt_sport == 0
- || pfkey_build(pfkey_x_nat_t_port_build(
- &extensions[SADB_X_EXT_NAT_T_SPORT], SADB_X_EXT_NAT_T_SPORT,
- sa->natt_sport), "pfkey_nat_t_sport Add ESP SA", sa->text_said,
- extensions))
- && (sa->natt_dport == 0
- || pfkey_build(pfkey_x_nat_t_port_build(
- &extensions[SADB_X_EXT_NAT_T_DPORT], SADB_X_EXT_NAT_T_DPORT,
- sa->natt_dport), "pfkey_nat_t_dport Add ESP SA", sa->text_said,
- extensions))
- && (sa->natt_type == 0 || isanyaddr(sa->natt_oa)
- || pfkeyext_address(SADB_X_EXT_NAT_T_OA, sa->natt_oa
- , "pfkey_nat_t_oa Add ESP SA", sa->text_said, extensions))
-
- && finish_pfkey_msg(extensions, "Add SA", sa->text_said, NULL);
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+
+ return pfkey_msg_start(replace ? SADB_UPDATE : SADB_ADD, sa->satype
+ , "pfkey_msg_hdr Add SA", sa->text_said, extensions)
+
+ && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
+ , SADB_EXT_SA
+ , sa->spi /* in network order */
+ , sa->replay_window, SADB_SASTATE_MATURE
+ , sa->authalg, sa->encalg ? sa->encalg: sa->compalg, 0)
+ , "pfkey_sa Add SA", sa->text_said, extensions)
+
+ && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src
+ , "pfkey_addr_s Add SA", sa->text_said, extensions)
+
+ && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst
+ , "pfkey_addr_d Add SA", sa->text_said, extensions)
+
+ && (sa->authkeylen == 0
+ || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH]
+ , SADB_EXT_KEY_AUTH, sa->authkeylen * BITS_PER_BYTE
+ , sa->authkey)
+ , "pfkey_key_a Add SA", sa->text_said, extensions))
+
+ && (sa->enckeylen == 0
+ || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT]
+ , SADB_EXT_KEY_ENCRYPT, sa->enckeylen * BITS_PER_BYTE
+ , sa->enckey)
+ , "pfkey_key_e Add SA", sa->text_said, extensions))
+
+ && (sa->natt_type == 0
+ || pfkey_build(pfkey_x_nat_t_type_build(
+ &extensions[SADB_X_EXT_NAT_T_TYPE], sa->natt_type),
+ "pfkey_nat_t_type Add ESP SA", sa->text_said, extensions))
+ && (sa->natt_sport == 0
+ || pfkey_build(pfkey_x_nat_t_port_build(
+ &extensions[SADB_X_EXT_NAT_T_SPORT], SADB_X_EXT_NAT_T_SPORT,
+ sa->natt_sport), "pfkey_nat_t_sport Add ESP SA", sa->text_said,
+ extensions))
+ && (sa->natt_dport == 0
+ || pfkey_build(pfkey_x_nat_t_port_build(
+ &extensions[SADB_X_EXT_NAT_T_DPORT], SADB_X_EXT_NAT_T_DPORT,
+ sa->natt_dport), "pfkey_nat_t_dport Add ESP SA", sa->text_said,
+ extensions))
+ && (sa->natt_type == 0 || isanyaddr(sa->natt_oa)
+ || pfkeyext_address(SADB_X_EXT_NAT_T_OA, sa->natt_oa
+ , "pfkey_nat_t_oa Add ESP SA", sa->text_said, extensions))
+
+ && finish_pfkey_msg(extensions, "Add SA", sa->text_said, NULL);
}
static bool
pfkey_grp_sa(const struct kernel_sa *sa0, const struct kernel_sa *sa1)
{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
- return pfkey_msg_start(SADB_X_GRPSA, sa1->satype
- , "pfkey_msg_hdr group", sa1->text_said, extensions)
+ return pfkey_msg_start(SADB_X_GRPSA, sa1->satype
+ , "pfkey_msg_hdr group", sa1->text_said, extensions)
- && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
- , SADB_EXT_SA
- , sa1->spi /* in network order */
- , 0, 0, 0, 0, 0)
- , "pfkey_sa group", sa1->text_said, extensions)
+ && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
+ , SADB_EXT_SA
+ , sa1->spi /* in network order */
+ , 0, 0, 0, 0, 0)
+ , "pfkey_sa group", sa1->text_said, extensions)
- && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa1->dst
- , "pfkey_addr_d group", sa1->text_said, extensions)
+ && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa1->dst
+ , "pfkey_addr_d group", sa1->text_said, extensions)
- && pfkey_build(pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2]
- , sa0->satype)
- , "pfkey_satype group", sa0->text_said, extensions)
+ && pfkey_build(pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2]
+ , sa0->satype)
+ , "pfkey_satype group", sa0->text_said, extensions)
- && pfkey_build(pfkey_sa_build(&extensions[SADB_X_EXT_SA2]
- , SADB_X_EXT_SA2
- , sa0->spi /* in network order */
- , 0, 0, 0, 0, 0)
- , "pfkey_sa2 group", sa0->text_said, extensions)
+ && pfkey_build(pfkey_sa_build(&extensions[SADB_X_EXT_SA2]
+ , SADB_X_EXT_SA2
+ , sa0->spi /* in network order */
+ , 0, 0, 0, 0, 0)
+ , "pfkey_sa2 group", sa0->text_said, extensions)
- && pfkeyext_address(SADB_X_EXT_ADDRESS_DST2, sa0->dst
- , "pfkey_addr_d2 group", sa0->text_said, extensions)
+ && pfkeyext_address(SADB_X_EXT_ADDRESS_DST2, sa0->dst
+ , "pfkey_addr_d2 group", sa0->text_said, extensions)
- && finish_pfkey_msg(extensions, "group", sa1->text_said, NULL);
+ && finish_pfkey_msg(extensions, "group", sa1->text_said, NULL);
}
static bool
pfkey_del_sa(const struct kernel_sa *sa)
{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
- return pfkey_msg_start(SADB_DELETE, proto2satype(sa->proto)
- , "pfkey_msg_hdr delete SA", sa->text_said, extensions)
+ return pfkey_msg_start(SADB_DELETE, proto2satype(sa->proto)
+ , "pfkey_msg_hdr delete SA", sa->text_said, extensions)
- && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
- , SADB_EXT_SA
- , sa->spi /* in host order */
- , 0, SADB_SASTATE_MATURE, 0, 0, 0)
- , "pfkey_sa delete SA", sa->text_said, extensions)
+ && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
+ , SADB_EXT_SA
+ , sa->spi /* in host order */
+ , 0, SADB_SASTATE_MATURE, 0, 0, 0)
+ , "pfkey_sa delete SA", sa->text_said, extensions)
- && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src
- , "pfkey_addr_s delete SA", sa->text_said, extensions)
+ && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src
+ , "pfkey_addr_s delete SA", sa->text_said, extensions)
- && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst
- , "pfkey_addr_d delete SA", sa->text_said, extensions)
+ && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst
+ , "pfkey_addr_d delete SA", sa->text_said, extensions)
- && finish_pfkey_msg(extensions, "Delete SA", sa->text_said, NULL);
+ && finish_pfkey_msg(extensions, "Delete SA", sa->text_said, NULL);
}
void
pfkey_close(void)
{
- while (pfkey_iq_head != NULL)
- {
- pfkey_item *it = pfkey_iq_head;
+ while (pfkey_iq_head != NULL)
+ {
+ pfkey_item *it = pfkey_iq_head;
- pfkey_iq_head = it->next;
- pfree(it);
- }
+ pfkey_iq_head = it->next;
+ free(it);
+ }
- close(pfkeyfd);
- pfkeyfd = NULL_FD;
+ close(pfkeyfd);
+ pfkeyfd = NULL_FD;
}
const struct kernel_ops klips_kernel_ops = {
- type: KERNEL_TYPE_KLIPS,
- async_fdp: &pfkeyfd,
-
- pfkey_register: klips_pfkey_register,
- pfkey_register_response: klips_pfkey_register_response,
- process_queue: pfkey_dequeue,
- process_msg: pfkey_event,
- raw_eroute: pfkey_raw_eroute,
- add_sa: pfkey_add_sa,
- grp_sa: pfkey_grp_sa,
- del_sa: pfkey_del_sa,
- get_sa: NULL,
- get_spi: NULL,
- inbound_eroute: FALSE,
- policy_lifetime: FALSE,
- init: NULL
+ type: KERNEL_TYPE_KLIPS,
+ async_fdp: &pfkeyfd,
+
+ pfkey_register: klips_pfkey_register,
+ pfkey_register_response: klips_pfkey_register_response,
+ process_queue: pfkey_dequeue,
+ process_msg: pfkey_event,
+ raw_eroute: pfkey_raw_eroute,
+ add_sa: pfkey_add_sa,
+ grp_sa: pfkey_grp_sa,
+ del_sa: pfkey_del_sa,
+ get_sa: NULL,
+ get_spi: NULL,
+ inbound_eroute: FALSE,
+ policy_lifetime: FALSE,
+ init: NULL
};
#endif /* KLIPS */
diff --git a/src/pluto/kernel_pfkey.h b/src/pluto/kernel_pfkey.h
index 23ac982e8..ad20a5888 100644
--- a/src/pluto/kernel_pfkey.h
+++ b/src/pluto/kernel_pfkey.h
@@ -11,8 +11,6 @@
* 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: kernel_pfkey.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifdef KLIPS
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index 1aed7a63f..6dfbd6732 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -10,8 +10,6 @@
* 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: keys.c 3738 2008-04-02 19:04:45Z andreas $
*/
#include <stddef.h>
@@ -25,33 +23,34 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <glob.h>
#ifndef GLOB_ABORTED
-# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */
+# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */
#endif
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <library.h>
+#include <asn1/asn1.h>
#include "constants.h"
#include "defs.h"
-#include "mp_defs.h"
#include "id.h"
#include "x509.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "smartcard.h"
#include "connections.h"
#include "state.h"
#include "lex.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include "timer.h"
#include "fetch.h"
#include "xauth.h"
@@ -61,77 +60,34 @@ const char *shared_secrets_file = SHARED_SECRETS_FILE;
typedef struct id_list id_list_t;
struct id_list {
- struct id id;
- id_list_t *next;
+ struct id id;
+ id_list_t *next;
};
typedef struct secret secret_t;
struct secret {
- id_list_t *ids;
- enum PrivateKeyKind kind;
- union {
- chunk_t preshared_secret;
- RSA_private_key_t RSA_private_key;
- xauth_t xauth_secret;
- smartcard_t *smartcard;
- } u;
- secret_t *next;
+ id_list_t *ids;
+ enum PrivateKeyKind kind;
+ union {
+ chunk_t preshared_secret;
+ xauth_t xauth_secret;
+ private_key_t *private_key;
+ smartcard_t *smartcard;
+ } u;
+ secret_t *next;
};
-static pubkey_t*
-allocate_RSA_public_key(const cert_t cert)
-{
- pubkey_t *pk = alloc_thing(pubkey_t, "pubkey");
- chunk_t e = empty_chunk, n = empty_chunk;
-
- switch (cert.type)
- {
- case CERT_PGP:
- e = cert.u.pgp->publicExponent;
- n = cert.u.pgp->modulus;
- break;
- case CERT_X509_SIGNATURE:
- e = cert.u.x509->publicExponent;
- n = cert.u.x509->modulus;
- break;
- default:
- plog("RSA public key allocation error");
- }
-
- init_RSA_public_key(&pk->u.rsa, e, n);
- DBG(DBG_RAW,
- RSA_show_public_key(&pk->u.rsa)
- )
-
- pk->alg = PUBKEY_ALG_RSA;
- pk->id = empty_id;
- pk->issuer = empty_chunk;
- pk->serial = empty_chunk;
-
- return pk;
-}
-
/*
* free a public key struct
*/
-static void
-free_public_key(pubkey_t *pk)
+static void free_public_key(pubkey_t *pk)
{
- free_id_content(&pk->id);
- freeanychunk(pk->issuer);
- freeanychunk(pk->serial);
-
- /* algorithm-specific freeing */
- switch (pk->alg)
- {
- case PUBKEY_ALG_RSA:
- free_RSA_public_content(&pk->u.rsa);
- break;
- default:
- bad_case(pk->alg);
- }
- pfree(pk);
+ DESTROY_IF(pk->public_key);
+ free_id_content(&pk->id);
+ free(pk->issuer.ptr);
+ free(pk->serial.ptr);
+ free(pk);
}
secret_t *secrets = NULL;
@@ -140,227 +96,215 @@ secret_t *secrets = NULL;
* me and the peer. We match the Id (if none, the IP address).
* Failure is indicated by a NULL.
*/
-static const secret_t *
-get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
+static const secret_t* get_secret(const struct connection *c,
+ enum PrivateKeyKind kind, bool asym)
{
- enum { /* bits */
- match_default = 01,
- match_him = 02,
- match_me = 04
- };
-
- unsigned int best_match = 0;
- secret_t *best = NULL;
- secret_t *s;
- const struct id *my_id = &c->spd.this.id
- , *his_id = &c->spd.that.id;
- struct id rw_id;
-
- /* is there a certificate assigned to this connection? */
- if (kind == PPK_RSA && c->spd.this.cert.type != CERT_NONE)
- {
- pubkey_t *my_public_key = allocate_RSA_public_key(c->spd.this.cert);
-
- for (s = secrets; s != NULL; s = s->next)
+ enum { /* bits */
+ match_default = 0x01,
+ match_him = 0x02,
+ match_me = 0x04
+ };
+
+ unsigned int best_match = 0;
+ secret_t *best = NULL;
+ secret_t *s;
+ const struct id *my_id = &c->spd.this.id
+ , *his_id = &c->spd.that.id;
+ struct id rw_id;
+
+ /* is there a certificate assigned to this connection? */
+ if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
{
- if (s->kind == kind &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &my_public_key->u.rsa))
- {
- best = s;
- break; /* we have found the private key - no sense in searching further */
- }
- }
- free_public_key(my_public_key);
- return best;
- }
-
- if (his_id_was_instantiated(c))
- {
- /* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = c->spd.that.id.kind;
- rw_id.name = empty_chunk;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
- }
- else if (kind == PPK_PSK
- && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
- && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) ||
- (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
- {
- /* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = ID_IPV4_ADDR;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
- }
-
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == kind)
- {
- unsigned int match = 0;
+ public_key_t *pub_key = cert_get_public_key(c->spd.this.cert);
- if (s->ids == NULL)
- {
- /* a default (signified by lack of ids):
- * accept if no more specific match found
- */
- match = match_default;
- }
- else
- {
- /* check if both ends match ids */
- id_list_t *i;
-
- for (i = s->ids; i != NULL; i = i->next)
+ for (s = secrets; s != NULL; s = s->next)
{
- if (same_id(my_id, &i->id))
- match |= match_me;
-
- if (same_id(his_id, &i->id))
- match |= match_him;
+ if (s->kind == kind &&
+ s->u.private_key->belongs_to(s->u.private_key, pub_key))
+ {
+ best = s;
+ break; /* we have found the private key - no sense in searching further */
+ }
}
+ return best;
+ }
- /* If our end matched the only id in the list,
- * default to matching any peer.
- * A more specific match will trump this.
- */
- if (match == match_me
- && s->ids->next == NULL)
- match |= match_default;
- }
-
- switch (match)
- {
- case match_me:
- /* if this is an asymmetric (eg. public key) system,
- * allow this-side-only match to count, even if
- * there are other ids in the list.
- */
- if (!asym)
- break;
- /* FALLTHROUGH */
- case match_default: /* default all */
- case match_me | match_default: /* default peer */
- case match_me | match_him: /* explicit */
- if (match == best_match)
- {
- /* two good matches are equally good:
- * do they agree?
- */
- bool same = FALSE;
-
- switch (kind)
- {
- case PPK_PSK:
- same = s->u.preshared_secret.len == best->u.preshared_secret.len
- && memcmp(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len) == 0;
- break;
- case PPK_RSA:
- /* Dirty trick: since we have code to compare
- * RSA public keys, but not private keys, we
- * make the assumption that equal public keys
- * mean equal private keys. This ought to work.
- */
- same = same_RSA_public_key(&s->u.RSA_private_key.pub
- , &best->u.RSA_private_key.pub);
- break;
- default:
- bad_case(kind);
- }
- if (!same)
- {
- loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:"
- " first secret used");
- best = s; /* list is backwards: take latest in list */
- }
- }
- else if (match > best_match)
+ if (his_id_was_instantiated(c))
+ {
+ /* roadwarrior: replace him with 0.0.0.0 */
+ rw_id.kind = c->spd.that.id.kind;
+ rw_id.name = chunk_empty;
+ happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
+ his_id = &rw_id;
+ }
+ else if (kind == PPK_PSK
+ && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
+ && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_ANY) ||
+ (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
+ {
+ /* roadwarrior: replace him with 0.0.0.0 */
+ rw_id.kind = ID_IPV4_ADDR;
+ happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
+ his_id = &rw_id;
+ }
+
+ for (s = secrets; s != NULL; s = s->next)
+ {
+ if (s->kind == kind)
{
- /* this is the best match so far */
- best_match = match;
- best = s;
+ unsigned int match = 0;
+
+ if (s->ids == NULL)
+ {
+ /* a default (signified by lack of ids):
+ * accept if no more specific match found
+ */
+ match = match_default;
+ }
+ else
+ {
+ /* check if both ends match ids */
+ id_list_t *i;
+
+ for (i = s->ids; i != NULL; i = i->next)
+ {
+ if (same_id(my_id, &i->id))
+ {
+ match |= match_me;
+ }
+ if (same_id(his_id, &i->id))
+ {
+ match |= match_him;
+ }
+ }
+
+ /* If our end matched the only id in the list,
+ * default to matching any peer.
+ * A more specific match will trump this.
+ */
+ if (match == match_me && s->ids->next == NULL)
+ {
+ match |= match_default;
+ }
+ }
+
+ switch (match)
+ {
+ case match_me:
+ /* if this is an asymmetric (eg. public key) system,
+ * allow this-side-only match to count, even if
+ * there are other ids in the list.
+ */
+ if (!asym)
+ {
+ break;
+ }
+ /* FALLTHROUGH */
+ case match_default: /* default all */
+ case match_me | match_default: /* default peer */
+ case match_me | match_him: /* explicit */
+ if (match == best_match)
+ {
+ /* two good matches are equally good:
+ * do they agree?
+ */
+ bool same = FALSE;
+
+ switch (kind)
+ {
+ case PPK_PSK:
+ same = s->u.preshared_secret.len == best->u.preshared_secret.len
+ && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len);
+ break;
+ case PPK_PUBKEY:
+ same = s->u.private_key->equals(s->u.private_key, best->u.private_key);
+ break;
+ default:
+ bad_case(kind);
+ }
+ if (!same)
+ {
+ loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:"
+ " first secret used");
+ best = s; /* list is backwards: take latest in list */
+ }
+ }
+ else if (match > best_match)
+ {
+ /* this is the best match so far */
+ best_match = match;
+ best = s;
+ }
+ }
}
- }
}
- }
- return best;
+ return best;
}
/* find the appropriate preshared key (see get_secret).
* Failure is indicated by a NULL pointer.
* Note: the result is not to be freed by the caller.
*/
-const chunk_t *
-get_preshared_secret(const struct connection *c)
+const chunk_t* get_preshared_secret(const struct connection *c)
{
- const secret_t *s = get_secret(c, PPK_PSK, FALSE);
+ const secret_t *s = get_secret(c, PPK_PSK, FALSE);
- DBG(DBG_PRIVATE,
- if (s == NULL)
- DBG_log("no Preshared Key Found");
- else
- DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
- )
- return s == NULL? NULL : &s->u.preshared_secret;
+ DBG(DBG_PRIVATE,
+ if (s == NULL)
+ DBG_log("no Preshared Key Found");
+ else
+ DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
+ )
+ return s == NULL? NULL : &s->u.preshared_secret;
}
-/* check the existence of an RSA private key matching an RSA public
- * key contained in an X.509 or OpenPGP certificate
+/* check the existence of a private key matching a public key contained
+ * in an X.509 or OpenPGP certificate
*/
-bool
-has_private_key(cert_t cert)
+bool has_private_key(cert_t cert)
{
- secret_t *s;
- bool has_key = FALSE;
- pubkey_t *pubkey = allocate_RSA_public_key(cert);
-
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_RSA &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))
+ secret_t *s;
+ bool has_key = FALSE;
+ public_key_t *pub_key = cert_get_public_key(cert);
+
+ for (s = secrets; s != NULL; s = s->next)
{
- has_key = TRUE;
- break;
+ if (s->kind == PPK_PUBKEY &&
+ s->u.private_key->belongs_to(s->u.private_key, pub_key))
+ {
+ has_key = TRUE;
+ break;
+ }
}
- }
- free_public_key(pubkey);
- return has_key;
+ return has_key;
}
/*
- * get the matching RSA private key belonging to a given X.509 certificate
+ * get the matching private key belonging to a given X.509 certificate
*/
-const RSA_private_key_t*
-get_x509_private_key(const x509cert_t *cert)
+private_key_t* get_x509_private_key(const x509cert_t *cert)
{
- secret_t *s;
- const RSA_private_key_t *pri = NULL;
- const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}};
-
- pubkey_t *pubkey = allocate_RSA_public_key(c);
+ secret_t *s;
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_RSA &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))
+ for (s = secrets; s != NULL; s = s->next)
{
- pri = &s->u.RSA_private_key;
- break;
+ if (s->kind == PPK_PUBKEY &&
+ s->u.private_key->belongs_to(s->u.private_key, cert->public_key))
+ {
+ return s->u.private_key;
+ }
}
- }
- free_public_key(pubkey);
- return pri;
+ return NULL;
}
-/* find the appropriate RSA private key (see get_secret).
+/* find the appropriate private key (see get_secret).
* Failure is indicated by a NULL pointer.
*/
-const RSA_private_key_t *
-get_RSA_private_key(const struct connection *c)
+private_key_t* get_private_key(const struct connection *c)
{
- const secret_t *s = get_secret(c, PPK_RSA, TRUE);
+ const secret_t *s = get_secret(c, PPK_PUBKEY, TRUE);
- return s == NULL? NULL : &s->u.RSA_private_key;
+ return s == NULL? NULL : s->u.private_key;
}
/* digest a secrets file
@@ -403,1100 +347,1071 @@ get_RSA_private_key(const struct connection *c)
*/
/* parse PSK from file */
-static err_t
-process_psk_secret(chunk_t *psk)
+static err_t process_psk_secret(chunk_t *psk)
{
- err_t ugh = NULL;
-
- if (*tok == '"' || *tok == '\'')
- {
- clonetochunk(*psk, tok+1, flp->cur - tok - 2, "PSK");
- (void) shift();
- }
- else
- {
- char buf[BUF_LEN]; /* limit on size of binary representation of key */
- size_t sz;
-
- ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
- , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
- if (ugh != NULL)
+ err_t ugh = NULL;
+
+ if (*tok == '"' || *tok == '\'')
{
- /* ttodata didn't like PSK data */
- ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);
+ chunk_t secret = { tok + 1, flp->cur - tok -2 };
+
+ *psk = chunk_clone(secret);
+ (void) shift();
}
else
{
- clonetochunk(*psk, buf, sz, "PSK");
- (void) shift();
+ char buf[BUF_LEN]; /* limit on size of binary representation of key */
+ size_t sz;
+
+ ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
+ , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh != NULL)
+ {
+ /* ttodata didn't like PSK data */
+ ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);
+ }
+ else
+ {
+ chunk_t secret = { buf, sz };
+ *psk = chunk_clone(secret);
+ (void) shift();
+ }
}
- }
- return ugh;
+ return ugh;
}
-/* Parse fields of RSA private key.
- * A braced list of keyword and value pairs.
- * At the moment, each field is required, in order.
- * The fields come from BIND 8.2's representation
+typedef enum rsa_private_key_part_t rsa_private_key_part_t;
+
+enum rsa_private_key_part_t {
+ RSA_PART_MODULUS = 0,
+ RSA_PART_PUBLIC_EXPONENT = 1,
+ RSA_PART_PRIVATE_EXPONENT = 2,
+ RSA_PART_PRIME1 = 3,
+ RSA_PART_PRIME2 = 4,
+ RSA_PART_EXPONENT1 = 5,
+ RSA_PART_EXPONENT2 = 6,
+ RSA_PART_COEFFICIENT = 7
+};
+
+const char *rsa_private_key_part_names[] = {
+ "Modulus",
+ "PublicExponent",
+ "PrivateExponent",
+ "Prime1",
+ "Prime2",
+ "Exponent1",
+ "Exponent2",
+ "Coefficient"
+};
+
+/**
+ * Parse fields of an RSA private key in BIND 8.2's representation
+ * consistiong of a braced list of keyword and value pairs in required order.
+ * Conversion into ASN.1 DER encoded PKCS#1 representation.
*/
-static err_t
-process_rsa_secret(RSA_private_key_t *rsak)
+static err_t process_rsa_secret(private_key_t **key)
{
- char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
- const struct fld *p;
-
- /* save bytes of Modulus and PublicExponent for keyid calculation */
- unsigned char ebytes[sizeof(buf)];
- unsigned char *eb_next = ebytes;
- chunk_t pub_bytes[2];
- chunk_t *pb_next = &pub_bytes[0];
-
- for (p = RSA_private_field; p < &RSA_private_field[RSA_PRIVATE_FIELD_ELEMENTS]; p++)
- {
- size_t sz;
+ chunk_t asn1_chunk[countof(rsa_private_key_part_names)];
+ chunk_t pkcs1_chunk;
+ u_char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
+ rsa_private_key_part_t part, p;
+ size_t sz, len = 0;
err_t ugh;
- if (!shift())
+ for (part = RSA_PART_MODULUS; part <= RSA_PART_COEFFICIENT; part++)
{
- return "premature end of RSA key";
+ chunk_t rsa_private_key_part;
+ const char *keyword = rsa_private_key_part_names[part];
+
+ if (!shift())
+ {
+ ugh = "premature end of RSA key";
+ goto end;
+ }
+ if (!tokeqword(keyword))
+ {
+ ugh = builddiag("%s keyword not found where expected in RSA key"
+ , keyword);
+ goto end;
+ }
+ if (!(shift() && (!tokeq(":") || shift()))) /* ignore optional ":" */
+ {
+ ugh = "premature end of RSA key";
+ goto end;
+ }
+ ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz,
+ diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh)
+ {
+ ugh = builddiag("RSA data malformed (%s): %s", ugh, tok);
+ part++;
+ goto end;
+ }
+ rsa_private_key_part = chunk_create(buf, sz);
+ asn1_chunk[part] = asn1_integer("c", rsa_private_key_part);
+ len += asn1_chunk[part].len;
}
- else if (!tokeqword(p->name))
+
+ /* We require an (indented) '}' and the end of the record.
+ * We break down the test so that the diagnostic will be more helpful.
+ * Some people don't seem to wish to indent the brace!
+ */
+ if (!shift() || !tokeq("}"))
{
- return builddiag("%s keyword not found where expected in RSA key"
- , p->name);
+ ugh = "malformed end of RSA private key -- indented '}' required";
+ goto end;
}
- else if (!(shift()
- && (!tokeq(":") || shift()))) /* ignore optional ":" */
+ if (shift())
{
- return "premature end of RSA key";
+ ugh = "malformed end of RSA private key -- unexpected token after '}'";
+ goto end;
}
- else if (NULL != (ugh = ttodatav(tok, flp->cur - tok
- , 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space)
- , TTODATAV_SPACECOUNTS)))
+
+ pkcs1_chunk = asn1_wrap(ASN1_SEQUENCE, "ccccccccc",
+ ASN1_INTEGER_0,
+ asn1_chunk[RSA_PART_MODULUS],
+ asn1_chunk[RSA_PART_PUBLIC_EXPONENT],
+ asn1_chunk[RSA_PART_PRIVATE_EXPONENT],
+ asn1_chunk[RSA_PART_PRIME1],
+ asn1_chunk[RSA_PART_PRIME2],
+ asn1_chunk[RSA_PART_EXPONENT1],
+ asn1_chunk[RSA_PART_EXPONENT2],
+ asn1_chunk[RSA_PART_COEFFICIENT]);
+
+ *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, pkcs1_chunk,
+ BUILD_END);
+ free(pkcs1_chunk.ptr);
+ if (*key == NULL)
{
- /* in RSA key, ttodata didn't like */
- return builddiag("RSA data malformed (%s): %s", ugh, tok);
+ ugh = "parsing of RSA private key failed";
}
- else
+
+end:
+ /* clean up and return */
+ for (p = RSA_PART_MODULUS ; p < part; p++)
{
- MP_INT *n = (MP_INT *) ((char *)rsak + p->offset);
-
- n_to_mpz(n, buf, sz);
- if (pb_next < &pub_bytes[elemsof(pub_bytes)])
- {
- if (eb_next - ebytes + sz > sizeof(ebytes))
- return "public key takes too many bytes";
-
- setchunk(*pb_next, eb_next, sz);
- memcpy(eb_next, buf, sz);
- eb_next += sz;
- pb_next++;
- }
-#if 0 /* debugging info that compromises security */
- {
- size_t sz = mpz_sizeinbase(n, 16);
- char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */
-
- passert(sz <= sizeof(buf));
- mpz_get_str(buf, 16, n);
-
- loglog(RC_LOG_SERIOUS, "%s: %s", p->name, buf);
- }
-#endif
+ free(asn1_chunk[p].ptr);
}
- }
-
- /* We require an (indented) '}' and the end of the record.
- * We break down the test so that the diagnostic will be
- * more helpful. Some people don't seem to wish to indent
- * the brace!
- */
- if (!shift() || !tokeq("}"))
- {
- return "malformed end of RSA private key -- indented '}' required";
- }
- else if (shift())
- {
- return "malformed end of RSA private key -- unexpected token after '}'";
- }
- else
- {
- unsigned bits = mpz_sizeinbase(&rsak->pub.n, 2);
-
- rsak->pub.k = (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
- rsak->pub.keyid[0] = '\0'; /* in case of splitkeytoid failure */
- splitkeytoid(pub_bytes[1].ptr, pub_bytes[1].len
- , pub_bytes[0].ptr, pub_bytes[0].len
- , rsak->pub.keyid, sizeof(rsak->pub.keyid));
- return RSA_private_key_sanity(rsak);
- }
+ return ugh;
}
-/* process rsa key file protected with optional passphrase which can either be
+/**
+ * process a key file protected with optional passphrase which can either be
* read from ipsec.secrets or prompted for by using whack
*/
-static err_t
-process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
+static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd)
{
- char filename[BUF_LEN];
- prompt_pass_t pass;
-
- memset(filename,'\0', BUF_LEN);
- memset(pass.secret,'\0', sizeof(pass.secret));
- pass.prompt = FALSE;
- pass.fd = whackfd;
+ char filename[BUF_LEN];
+ prompt_pass_t pass;
- /* we expect the filename of a PKCS#1 private key file */
+ memset(filename,'\0', BUF_LEN);
+ memset(pass.secret,'\0', sizeof(pass.secret));
+ pass.prompt = FALSE;
+ pass.fd = whackfd;
- if (*tok == '"' || *tok == '\'') /* quoted filename */
- memcpy(filename, tok+1, flp->cur - tok - 2);
- else
- memcpy(filename, tok, flp->cur - tok);
+ /* we expect the filename of a PKCS#1 private key file */
- if (shift())
- {
- /* we expect an appended passphrase or passphrase prompt*/
- if (tokeqword("%prompt"))
- {
- if (pass.fd == NULL_FD)
- return "RSA private key file -- enter passphrase using 'ipsec secrets'";
- pass.prompt = TRUE;
- }
+ if (*tok == '"' || *tok == '\'') /* quoted filename */
+ memcpy(filename, tok+1, flp->cur - tok - 2);
else
+ memcpy(filename, tok, flp->cur - tok);
+
+ if (shift())
{
- char *passphrase = tok;
- size_t len = flp->cur - passphrase;
-
- if (*tok == '"' || *tok == '\'') /* quoted passphrase */
- {
- passphrase++;
- len -= 2;
- }
- if (len > PROMPT_PASS_LEN)
- return "RSA private key file -- passphrase exceeds 64 characters";
-
- memcpy(pass.secret, passphrase, len);
+ /* we expect an appended passphrase or passphrase prompt*/
+ if (tokeqword("%prompt"))
+ {
+ if (pass.fd == NULL_FD)
+ {
+ return "Private key file -- enter passphrase using 'ipsec secrets'";
+ }
+ pass.prompt = TRUE;
+ }
+ else
+ {
+ char *passphrase = tok;
+ size_t len = flp->cur - passphrase;
+
+ if (*tok == '"' || *tok == '\'') /* quoted passphrase */
+ {
+ passphrase++;
+ len -= 2;
+ }
+ if (len > PROMPT_PASS_LEN)
+ {
+ return "Private key file -- passphrase exceeds 64 characters";
+ }
+ memcpy(pass.secret, passphrase, len);
+ }
+ if (shift())
+ {
+ return "Private key file -- unexpected token after passphrase";
+ }
}
- if (shift())
- return "RSA private key file -- unexpected token after passphrase";
- }
- return load_rsa_private_key(filename, &pass, rsak);
+ *key = load_private_key(filename, &pass, type);
+
+ return key ? NULL : "Private key file -- could not be loaded";
}
-/*
- * process xauth secret read from ipsec.secrets
+/**
+ * Process xauth secret read from ipsec.secrets
*/
-static err_t
-process_xauth(secret_t *s)
+static err_t process_xauth(secret_t *s)
{
- chunk_t user_name;
-
- s->kind = PPK_XAUTH;
-
- if (!shift())
- return "missing xauth user name";
- if (*tok == '"' || *tok == '\'') /* quoted user name */
- {
- user_name.ptr = tok + 1;
- user_name.len = flp->cur - tok - 2;
- }
- else
- {
- user_name.ptr = tok;
- user_name.len = flp->cur - tok;
- }
- plog(" loaded xauth credentials of user '%.*s'"
- , user_name.len
- , user_name.ptr);
- clonetochunk(s->u.xauth_secret.user_name
- , user_name.ptr, user_name.len, "xauth user name");
-
- if (!shift())
- return "missing xauth user password";
- return process_psk_secret(&s->u.xauth_secret.user_password);
+ chunk_t user_name;
+
+ s->kind = PPK_XAUTH;
+
+ if (!shift())
+ return "missing xauth user name";
+ if (*tok == '"' || *tok == '\'') /* quoted user name */
+ {
+ user_name.ptr = tok + 1;
+ user_name.len = flp->cur - tok - 2;
+ }
+ else
+ {
+ user_name.ptr = tok;
+ user_name.len = flp->cur - tok;
+ }
+ plog(" loaded xauth credentials of user '%.*s'"
+ , user_name.len
+ , user_name.ptr);
+ s->u.xauth_secret.user_name = chunk_clone(user_name);
+
+ if (!shift())
+ return "missing xauth user password";
+ return process_psk_secret(&s->u.xauth_secret.user_password);
}
-/* get XAUTH secret from chained secrets lists
+/**
+ * Get XAUTH secret from chained secrets lists
* only one entry is currently supported
*/
-static bool
-xauth_get_secret(xauth_t *xauth_secret)
+static bool xauth_get_secret(xauth_t *xauth_secret)
{
- secret_t *s;
- bool found = FALSE;
+ secret_t *s;
+ bool found = FALSE;
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_XAUTH)
+ for (s = secrets; s != NULL; s = s->next)
{
- if (found)
- {
- plog("found multiple xauth secrets - first selected");
- }
- else
- {
- found = TRUE;
- *xauth_secret = s->u.xauth_secret;
- }
+ if (s->kind == PPK_XAUTH)
+ {
+ if (found)
+ {
+ plog("found multiple xauth secrets - first selected");
+ }
+ else
+ {
+ found = TRUE;
+ *xauth_secret = s->u.xauth_secret;
+ }
+ }
}
- }
- return found;
+ return found;
}
-/*
+/**
* find a matching secret
*/
-static bool
-xauth_verify_secret(const xauth_peer_t *peer, const xauth_t *xauth_secret)
+static bool xauth_verify_secret(const xauth_peer_t *peer,
+ const xauth_t *xauth_secret)
{
- bool found = FALSE;
- secret_t *s;
+ bool found = FALSE;
+ secret_t *s;
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == PPK_XAUTH)
+ for (s = secrets; s != NULL; s = s->next)
{
- if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name))
- continue;
- found = TRUE;
- if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password))
- return TRUE;
+ if (s->kind == PPK_XAUTH)
+ {
+ if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name))
+ {
+ continue;
+ }
+ found = TRUE;
+ if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password))
+ {
+ return TRUE;
+ }
+ }
}
- }
- plog("xauth user '%.*s' %s"
- , xauth_secret->user_name.len, xauth_secret->user_name.ptr
- , found? "sent wrong password":"not found");
- return FALSE;
+ plog("xauth user '%.*s' %s"
+ , xauth_secret->user_name.len, xauth_secret->user_name.ptr
+ , found? "sent wrong password":"not found");
+ return FALSE;
}
-/*
+/**
* the global xauth_module struct is defined here
*/
xauth_module_t xauth_module;
-/*
- * assign the default xauth functions to any null function pointers
+/**
+ * Assign the default xauth functions to any null function pointers
*/
-void
-xauth_defaults(void)
+void xauth_defaults(void)
{
- if (xauth_module.get_secret == NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("xauth module: using default get_secret() function")
- )
- xauth_module.get_secret = xauth_get_secret;
- }
- if (xauth_module.verify_secret == NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("xauth module: using default verify_secret() function")
- )
- xauth_module.verify_secret = xauth_verify_secret;
- }
+ if (xauth_module.get_secret == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module: using default get_secret() function")
+ )
+ xauth_module.get_secret = xauth_get_secret;
+ }
+ if (xauth_module.verify_secret == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module: using default verify_secret() function")
+ )
+ xauth_module.verify_secret = xauth_verify_secret;
+ }
};
-/*
- * process pin read from ipsec.secrets or prompted for it using whack
+/**
+ * Process pin read from ipsec.secrets or prompted for it using whack
*/
-static err_t
-process_pin(secret_t *s, int whackfd)
+static err_t process_pin(secret_t *s, int whackfd)
{
- smartcard_t *sc;
- const char *pin_status = "no pin";
-
- s->kind = PPK_PIN;
-
- /* looking for the smartcard keyword */
- if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0)
- return "PIN keyword must be followed by %smartcard<reader>:<id>";
-
- sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN)));
- s->u.smartcard = sc;
- scx_share(sc);
- if (sc->pin.ptr != NULL)
- {
- scx_release_context(sc);
- scx_free_pin(&sc->pin);
- }
- sc->valid = FALSE;
-
- if (!shift())
- return "PIN statement must be terminated either by <pin code>, %pinpad or %prompt";
-
- if (tokeqword("%prompt"))
- {
- shift();
- /* if whackfd exists, whack will be used to prompt for a pin */
- if (whackfd != NULL_FD)
- pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin";
+ smartcard_t *sc;
+ const char *pin_status = "no pin";
+
+ s->kind = PPK_PIN;
+
+ /* looking for the smartcard keyword */
+ if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0)
+ return "PIN keyword must be followed by %smartcard<reader>:<id>";
+
+ sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN)));
+ s->u.smartcard = sc;
+ scx_share(sc);
+ if (sc->pin.ptr != NULL)
+ {
+ scx_release_context(sc);
+ scx_free_pin(&sc->pin);
+ }
+ sc->valid = FALSE;
+
+ if (!shift())
+ return "PIN statement must be terminated either by <pin code>, %pinpad or %prompt";
+
+ if (tokeqword("%prompt"))
+ {
+ shift();
+ /* if whackfd exists, whack will be used to prompt for a pin */
+ if (whackfd != NULL_FD)
+ pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin";
+ else
+ pin_status = "pin entry via prompt";
+ }
+ else if (tokeqword("%pinpad"))
+ {
+ chunk_t empty_pin = { "", 0 };
+
+ shift();
+
+ /* pin will be entered via pin pad during verification */
+ sc->pin = chunk_clone(empty_pin);
+ sc->pinpad = TRUE;
+ sc->valid = TRUE;
+ pin_status = "pin entry via pad";
+ if (pkcs11_keep_state)
+ {
+ scx_verify_pin(sc);
+ }
+ }
else
- pin_status = "pin entry via prompt";
- }
- else if (tokeqword("%pinpad"))
- {
- shift();
- /* pin will be entered via pin pad during verification */
- clonetochunk(sc->pin, "", 0, "empty pin");
- sc->pinpad = TRUE;
- sc->valid = TRUE;
- pin_status = "pin entry via pad";
- if (pkcs11_keep_state)
- scx_verify_pin(sc);
- }
- else
- {
- /* we read the pin directly from ipsec.secrets */
- err_t ugh = process_psk_secret(&sc->pin);
- if (ugh != NULL)
- return ugh;
- /* verify the pin */
- pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN";
- }
+ {
+ /* we read the pin directly from ipsec.secrets */
+ err_t ugh = process_psk_secret(&sc->pin);
+ if (ugh != NULL)
+ return ugh;
+ /* verify the pin */
+ pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN";
+ }
#ifdef SMARTCARD
- {
- char buf[BUF_LEN];
+ {
+ char buf[BUF_LEN];
- if (sc->any_slot)
- snprintf(buf, BUF_LEN, "any slot");
- else
- snprintf(buf, BUF_LEN, "slot: %lu", sc->slot);
+ if (sc->any_slot)
+ snprintf(buf, BUF_LEN, "any slot");
+ else
+ snprintf(buf, BUF_LEN, "slot: %lu", sc->slot);
- plog(" %s for #%d (%s, id: %s)"
- , pin_status, sc->number, scx_print_slot(sc, ""), sc->id);
- }
+ plog(" %s for #%d (%s, id: %s)"
+ , pin_status, sc->number, scx_print_slot(sc, ""), sc->id);
+ }
#else
- plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
+ plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
#endif
- return NULL;
+ return NULL;
}
-static void
-log_psk(secret_t *s)
+static void log_psk(secret_t *s)
{
- int n = 0;
- char buf[BUF_LEN];
- id_list_t *id_list = s->ids;
-
- if (id_list == NULL)
- {
- n = snprintf(buf, BUF_LEN, "%%any");
- }
- else
- {
- do
+ int n = 0;
+ char buf[BUF_LEN];
+ id_list_t *id_list = s->ids;
+
+ if (id_list == NULL)
{
- n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
- if (n >= BUF_LEN)
- {
- n = BUF_LEN - 1;
- break;
- }
- else if (n < BUF_LEN - 1)
- {
- n += snprintf(buf + n, BUF_LEN - n, " ");
- }
- id_list = id_list->next;
+ n = snprintf(buf, BUF_LEN, "%%any");
}
- while (id_list);
- }
- plog(" loaded shared key for %.*s", n, buf);
+ else
+ {
+ do
+ {
+ n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
+ if (n >= BUF_LEN)
+ {
+ n = BUF_LEN - 1;
+ break;
+ }
+ else if (n < BUF_LEN - 1)
+ {
+ n += snprintf(buf + n, BUF_LEN - n, " ");
+ }
+ id_list = id_list->next;
+ }
+ while (id_list);
+ }
+ plog(" loaded shared key for %.*s", n, buf);
}
-static void
-process_secret(secret_t *s, int whackfd)
+static void process_secret(secret_t *s, int whackfd)
{
- err_t ugh = NULL;
-
- s->kind = PPK_PSK; /* default */
- if (*tok == '"' || *tok == '\'')
- {
- /* old PSK format: just a string */
- log_psk(s);
- ugh = process_psk_secret(&s->u.preshared_secret);
- }
- else if (tokeqword("psk"))
- {
- /* preshared key: quoted string or ttodata format */
- log_psk(s);
- ugh = !shift()? "unexpected end of record in PSK"
- : process_psk_secret(&s->u.preshared_secret);
- }
- else if (tokeqword("rsa"))
- {
- /* RSA key: the fun begins.
- * A braced list of keyword and value pairs.
- */
- s->kind = PPK_RSA;
- if (!shift())
+ err_t ugh = NULL;
+
+ s->kind = PPK_PSK; /* default */
+ if (*tok == '"' || *tok == '\'')
+ {
+ /* old PSK format: just a string */
+ log_psk(s);
+ ugh = process_psk_secret(&s->u.preshared_secret);
+ }
+ else if (tokeqword("psk"))
+ {
+ /* preshared key: quoted string or ttodata format */
+ log_psk(s);
+ ugh = !shift()? "unexpected end of record in PSK"
+ : process_psk_secret(&s->u.preshared_secret);
+ }
+ else if (tokeqword("rsa"))
+ {
+ /* RSA key: the fun begins.
+ * A braced list of keyword and value pairs.
+ */
+ s->kind = PPK_PUBKEY;
+ if (!shift())
+ {
+ ugh = "bad RSA key syntax";
+ }
+ else if (tokeq("{"))
+ {
+ ugh = process_rsa_secret(&s->u.private_key);
+ }
+ else
+ {
+ ugh = process_keyfile(&s->u.private_key, KEY_RSA, whackfd);
+ }
+ }
+ else if (tokeqword("ecdsa"))
+ {
+ s->kind = PPK_PUBKEY;
+ if (!shift())
+ {
+ ugh = "bad ECDSA key syntax";
+ }
+ else
+ {
+ ugh = process_keyfile(&s->u.private_key, KEY_ECDSA, whackfd);
+ }
+ }
+ else if (tokeqword("xauth"))
{
- ugh = "bad RSA key syntax";
+ ugh = process_xauth(s);
}
- else if (tokeq("{"))
+ else if (tokeqword("pin"))
{
- ugh = process_rsa_secret(&s->u.RSA_private_key);
+ ugh = process_pin(s, whackfd);
}
else
{
- ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd);
+ ugh = builddiag("unrecognized key format: %s", tok);
}
- }
- else if (tokeqword("xauth"))
- {
- ugh = process_xauth(s);
- }
- else if (tokeqword("pin"))
- {
- ugh = process_pin(s, whackfd);
- }
- else
- {
- ugh = builddiag("unrecognized key format: %s", tok);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"
- , flp->filename, flp->lino, ugh);
- pfree(s);
- }
- else if (flushline("expected record boundary in key"))
- {
- /* gauntlet has been run: install new secret */
- lock_certs_and_keys("process_secret");
- s->next = secrets;
- secrets = s;
- unlock_certs_and_keys("process_secrets");
- }
-}
-
-static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */
-
-static void
-process_secret_records(int whackfd)
-{
- /* read records from ipsec.secrets and load them into our table */
- for (;;)
- {
- (void)flushline(NULL); /* silently ditch leftovers, if any */
- if (flp->bdry == B_file)
- break;
-
- flp->bdry = B_none; /* eat the Record Boundary */
- (void)shift(); /* get real first token */
- if (tokeqword("include"))
+ if (ugh != NULL)
{
- /* an include directive */
- char fn[MAX_TOK_LEN]; /* space for filename (I hope) */
- char *p = fn;
- char *end_prefix = strrchr(flp->filename, '/');
-
- if (!shift())
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive"
- , flp->filename, flp->lino);
- continue; /* abandon this record */
- }
-
- /* if path is relative and including file's pathname has
- * a non-empty dirname, prefix this path with that dirname.
- */
- if (tok[0] != '/' && end_prefix != NULL)
- {
- size_t pl = end_prefix - flp->filename + 1;
-
- /* "clamp" length to prevent problems now;
- * will be rediscovered and reported later.
- */
- if (pl > sizeof(fn))
- pl = sizeof(fn);
- memcpy(fn, flp->filename, pl);
- p += pl;
- }
- if (flp->cur - tok >= &fn[sizeof(fn)] - p)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long"
- , flp->filename, flp->lino);
- continue; /* abandon this record */
- }
- strcpy(p, tok);
- (void) shift(); /* move to Record Boundary, we hope */
- if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename"))
- {
- process_secrets_file(fn, whackfd);
- tok = NULL; /* correct, but probably redundant */
- }
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"
+ , flp->filename, flp->lino, ugh);
+ free(s);
}
- else
+ else if (flushline("expected record boundary in key"))
{
- /* expecting a list of indices and then the key info */
- secret_t *s = alloc_thing(secret_t, "secret");
+ /* gauntlet has been run: install new secret */
+ lock_certs_and_keys("process_secret");
+ s->next = secrets;
+ secrets = s;
+ unlock_certs_and_keys("process_secrets");
+ }
+}
- s->ids = NULL;
- s->kind = PPK_PSK; /* default */
- setchunk(s->u.preshared_secret, NULL, 0);
- s->next = NULL;
+static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */
- for (;;)
- {
- if (tok[0] == '"' || tok[0] == '\'')
+static void process_secret_records(int whackfd)
+{
+ /* read records from ipsec.secrets and load them into our table */
+ for (;;)
+ {
+ (void)flushline(NULL); /* silently ditch leftovers, if any */
+ if (flp->bdry == B_file)
{
- /* found key part */
- process_secret(s, whackfd);
- break;
+ break;
}
- else if (tokeq(":"))
+ flp->bdry = B_none; /* eat the Record Boundary */
+ (void)shift(); /* get real first token */
+
+ if (tokeqword("include"))
{
- /* found key part */
- shift(); /* discard explicit separator */
- process_secret(s, whackfd);
- break;
+ /* an include directive */
+ char fn[MAX_TOK_LEN]; /* space for filename (I hope) */
+ char *p = fn;
+ char *end_prefix = strrchr(flp->filename, '/');
+
+ if (!shift())
+ {
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive"
+ , flp->filename, flp->lino);
+ continue; /* abandon this record */
+ }
+
+ /* if path is relative and including file's pathname has
+ * a non-empty dirname, prefix this path with that dirname.
+ */
+ if (tok[0] != '/' && end_prefix != NULL)
+ {
+ size_t pl = end_prefix - flp->filename + 1;
+
+ /* "clamp" length to prevent problems now;
+ * will be rediscovered and reported later.
+ */
+ if (pl > sizeof(fn))
+ {
+ pl = sizeof(fn);
+ }
+ memcpy(fn, flp->filename, pl);
+ p += pl;
+ }
+ if (flp->cur - tok >= &fn[sizeof(fn)] - p)
+ {
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long"
+ , flp->filename, flp->lino);
+ continue; /* abandon this record */
+ }
+ strcpy(p, tok);
+ (void) shift(); /* move to Record Boundary, we hope */
+ if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename"))
+ {
+ process_secrets_file(fn, whackfd);
+ tok = NULL; /* correct, but probably redundant */
+ }
}
else
{
- /* an id
- * See RFC2407 IPsec Domain of Interpretation 4.6.2
- */
- struct id id;
- err_t ugh;
-
- if (tokeq("%any"))
- {
- id = empty_id;
- id.kind = ID_IPV4_ADDR;
- ugh = anyaddr(AF_INET, &id.ip_addr);
- }
- else if (tokeq("%any6"))
- {
- id = empty_id;
- id.kind = ID_IPV6_ADDR;
- ugh = anyaddr(AF_INET6, &id.ip_addr);
- }
- else
- {
- ugh = atoid(tok, &id, FALSE);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR \"%s\" line %d: index \"%s\" %s"
- , flp->filename, flp->lino, tok, ugh);
- }
- else
- {
- id_list_t *i = alloc_thing(id_list_t
- , "id_list");
-
- i->id = id;
- unshare_id_content(&i->id);
- i->next = s->ids;
- s->ids = i;
- /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */
- }
- if (!shift())
- {
- /* unexpected Record Boundary or EOF */
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list"
- , flp->filename, flp->lino);
- break;
- }
+ /* expecting a list of indices and then the key info */
+ secret_t *s = malloc_thing(secret_t);
+
+ zero(s);
+ s->ids = NULL;
+ s->kind = PPK_PSK; /* default */
+ s->u.preshared_secret = chunk_empty;
+ s->next = NULL;
+
+ for (;;)
+ {
+ if (tok[0] == '"' || tok[0] == '\'')
+ {
+ /* found key part */
+ process_secret(s, whackfd);
+ break;
+ }
+ else if (tokeq(":"))
+ {
+ /* found key part */
+ shift(); /* discard explicit separator */
+ process_secret(s, whackfd);
+ break;
+ }
+ else
+ {
+ /* an id
+ * See RFC2407 IPsec Domain of Interpretation 4.6.2
+ */
+ struct id id;
+ err_t ugh;
+
+ if (tokeq("%any"))
+ {
+ id = empty_id;
+ id.kind = ID_IPV4_ADDR;
+ ugh = anyaddr(AF_INET, &id.ip_addr);
+ }
+ else if (tokeq("%any6"))
+ {
+ id = empty_id;
+ id.kind = ID_IPV6_ADDR;
+ ugh = anyaddr(AF_INET6, &id.ip_addr);
+ }
+ else
+ {
+ ugh = atoid(tok, &id, FALSE);
+ }
+
+ if (ugh != NULL)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ERROR \"%s\" line %d: index \"%s\" %s"
+ , flp->filename, flp->lino, tok, ugh);
+ }
+ else
+ {
+ id_list_t *i = malloc_thing(id_list_t);
+
+ i->id = id;
+ unshare_id_content(&i->id);
+ i->next = s->ids;
+ s->ids = i;
+ /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */
+ }
+ if (!shift())
+ {
+ /* unexpected Record Boundary or EOF */
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list"
+ , flp->filename, flp->lino);
+ break;
+ }
+ }
+ }
}
- }
}
- }
}
-static int
-globugh(const char *epath, int eerrno)
+static int globugh(const char *epath, int eerrno)
{
- log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath);
- return 1; /* stop glob */
+ log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath);
+ return 1; /* stop glob */
}
-static void
-process_secrets_file(const char *file_pat, int whackfd)
+static void process_secrets_file(const char *file_pat, int whackfd)
{
- struct file_lex_position pos;
- char **fnp;
- glob_t globbuf;
-
- pos.depth = flp == NULL? 0 : flp->depth + 1;
+ struct file_lex_position pos;
+ char **fnp;
+ glob_t globbuf;
- if (pos.depth > 10)
- {
- loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat);
- return;
- }
+ pos.depth = flp == NULL? 0 : flp->depth + 1;
- /* do globbing */
- {
- int r = glob(file_pat, GLOB_ERR, globugh, &globbuf);
+ if (pos.depth > 10)
+ {
+ loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat);
+ return;
+ }
- if (r != 0)
+ /* do globbing */
{
- switch (r)
- {
- case GLOB_NOSPACE:
- loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat);
- break;
- case GLOB_ABORTED:
- break; /* already logged */
- case GLOB_NOMATCH:
- loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat);
- break;
- default:
- loglog(RC_LOG_SERIOUS, "unknown glob error %d", r);
- break;
- }
- globfree(&globbuf);
- return;
+ int r = glob(file_pat, GLOB_ERR, globugh, &globbuf);
+
+ if (r != 0)
+ {
+ switch (r)
+ {
+ case GLOB_NOSPACE:
+ loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat);
+ break;
+ case GLOB_ABORTED:
+ break; /* already logged */
+ case GLOB_NOMATCH:
+ loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat);
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "unknown glob error %d", r);
+ break;
+ }
+ globfree(&globbuf);
+ return;
+ }
}
- }
- /* for each file... */
- for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++)
- {
- if (lexopen(&pos, *fnp, FALSE))
+ /* for each file... */
+ for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++)
{
- plog("loading secrets from \"%s\"", *fnp);
- (void) flushline("file starts with indentation (continuation notation)");
- process_secret_records(whackfd);
- lexclose();
+ if (lexopen(&pos, *fnp, FALSE))
+ {
+ plog("loading secrets from \"%s\"", *fnp);
+ (void) flushline("file starts with indentation (continuation notation)");
+ process_secret_records(whackfd);
+ lexclose();
+ }
}
- }
- globfree(&globbuf);
+ globfree(&globbuf);
}
-void
-free_preshared_secrets(void)
+void free_preshared_secrets(void)
{
- lock_certs_and_keys("free_preshared_secrets");
+ lock_certs_and_keys("free_preshared_secrets");
- if (secrets != NULL)
- {
- secret_t *s, *ns;
+ if (secrets != NULL)
+ {
+ secret_t *s, *ns;
- plog("forgetting secrets");
+ plog("forgetting secrets");
- for (s = secrets; s != NULL; s = ns)
- {
- id_list_t *i, *ni;
-
- ns = s->next; /* grab before freeing s */
- for (i = s->ids; i != NULL; i = ni)
- {
- ni = i->next; /* grab before freeing i */
- free_id_content(&i->id);
- pfree(i);
- }
- switch (s->kind)
- {
- case PPK_PSK:
- pfree(s->u.preshared_secret.ptr);
- break;
- case PPK_RSA:
- free_RSA_private_content(&s->u.RSA_private_key);
- break;
- case PPK_XAUTH:
- pfree(s->u.xauth_secret.user_name.ptr);
- pfree(s->u.xauth_secret.user_password.ptr);
- break;
- case PPK_PIN:
- scx_release(s->u.smartcard);
- break;
- default:
- bad_case(s->kind);
- }
- pfree(s);
+ for (s = secrets; s != NULL; s = ns)
+ {
+ id_list_t *i, *ni;
+
+ ns = s->next; /* grab before freeing s */
+ for (i = s->ids; i != NULL; i = ni)
+ {
+ ni = i->next; /* grab before freeing i */
+ free_id_content(&i->id);
+ free(i);
+ }
+ switch (s->kind)
+ {
+ case PPK_PSK:
+ free(s->u.preshared_secret.ptr);
+ break;
+ case PPK_PUBKEY:
+ DESTROY_IF(s->u.private_key);
+ break;
+ case PPK_XAUTH:
+ free(s->u.xauth_secret.user_name.ptr);
+ free(s->u.xauth_secret.user_password.ptr);
+ break;
+ case PPK_PIN:
+ scx_release(s->u.smartcard);
+ break;
+ default:
+ bad_case(s->kind);
+ }
+ free(s);
+ }
+ secrets = NULL;
}
- secrets = NULL;
- }
- unlock_certs_and_keys("free_preshard_secrets");
+ unlock_certs_and_keys("free_preshard_secrets");
}
-void
-load_preshared_secrets(int whackfd)
+void load_preshared_secrets(int whackfd)
{
- free_preshared_secrets();
- (void) process_secrets_file(shared_secrets_file, whackfd);
+ free_preshared_secrets();
+ (void) process_secrets_file(shared_secrets_file, whackfd);
}
/* public key machinery
* Note: caller must set dns_auth_level.
*/
-pubkey_t *
-public_key_from_rsa(const RSA_public_key_t *k)
+pubkey_t* public_key_from_rsa(public_key_t *key)
{
- pubkey_t *p = alloc_thing(pubkey_t, "pubkey");
-
- p->id = empty_id; /* don't know, doesn't matter */
- p->issuer = empty_chunk;
- p->serial = empty_chunk;
- p->alg = PUBKEY_ALG_RSA;
-
- memcpy(p->u.rsa.keyid, k->keyid, sizeof(p->u.rsa.keyid));
- p->u.rsa.k = k->k;
- mpz_init_set(&p->u.rsa.e, &k->e);
- mpz_init_set(&p->u.rsa.n, &k->n);
-
- /* note that we return a 1 reference count upon creation:
- * invariant: recount > 0.
- */
- p->refcnt = 1;
- time(&p->installed_time);
- return p;
+ pubkey_t *p = malloc_thing(pubkey_t);
+
+ zero(p);
+ p->id = empty_id; /* don't know, doesn't matter */
+ p->issuer = chunk_empty;
+ p->serial = chunk_empty;
+ p->public_key = key;
+
+ /* note that we return a 1 reference count upon creation:
+ * invariant: recount > 0.
+ */
+ p->refcnt = 1;
+ time(&p->installed_time);
+ return p;
}
/* Free a public key record.
* As a convenience, this returns a pointer to next.
*/
-pubkey_list_t *
-free_public_keyentry(pubkey_list_t *p)
+pubkey_list_t* free_public_keyentry(pubkey_list_t *p)
{
- pubkey_list_t *nxt = p->next;
+ pubkey_list_t *nxt = p->next;
- if (p->key != NULL)
- unreference_key(&p->key);
- pfree(p);
- return nxt;
+ if (p->key != NULL)
+ {
+ unreference_key(&p->key);
+ }
+ free(p);
+ return nxt;
}
-void
-free_public_keys(pubkey_list_t **keys)
+void free_public_keys(pubkey_list_t **keys)
{
- while (*keys != NULL)
- *keys = free_public_keyentry(*keys);
+ while (*keys != NULL)
+ {
+ *keys = free_public_keyentry(*keys);
+ }
}
/* root of chained public key list */
-pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */
+pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */
-void
-free_remembered_public_keys(void)
+void free_remembered_public_keys(void)
{
- free_public_keys(&pubkeys);
+ free_public_keys(&pubkeys);
}
-/* transfer public keys from *keys list to front of pubkeys list */
-void
-transfer_to_public_keys(struct gw_info *gateways_from_dns
+/**
+ * Transfer public keys from *keys list to front of pubkeys list
+ */
+void transfer_to_public_keys(struct gw_info *gateways_from_dns
#ifdef USE_KEYRR
, pubkey_list_t **keys
#endif /* USE_KEYRR */
)
{
- {
- struct gw_info *gwp;
-
- for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
{
- pubkey_list_t *pl = alloc_thing(pubkey_list_t, "from TXT");
+ struct gw_info *gwp;
- pl->key = gwp->key; /* note: this is a transfer */
- gwp->key = NULL; /* really, it is! */
- pl->next = pubkeys;
- pubkeys = pl;
+ for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ pubkey_list_t *pl = malloc_thing(pubkey_list_t);
+
+ pl->key = gwp->key; /* note: this is a transfer */
+ gwp->key = NULL; /* really, it is! */
+ pl->next = pubkeys;
+ pubkeys = pl;
+ }
}
- }
#ifdef USE_KEYRR
- {
- pubkey_list_t **pp = keys;
-
- while (*pp != NULL)
- pp = &(*pp)->next;
- *pp = pubkeys;
- pubkeys = *keys;
- *keys = NULL;
- }
+ {
+ pubkey_list_t **pp = keys;
+
+ while (*pp != NULL)
+ {
+ pp = &(*pp)->next;
+ }
+ *pp = pubkeys;
+ pubkeys = *keys;
+ *keys = NULL;
+ }
#endif /* USE_KEYRR */
}
-/* decode of RSA pubkey chunk
- * - format specified in RFC 2537 RSA/MD5 Keys and SIGs in the DNS
- * - exponent length in bytes (1 or 3 octets)
- * + 1 byte if in [1, 255]
- * + otherwise 0x00 followed by 2 bytes of length
- * - exponent
- * - modulus
- */
-err_t
-unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey)
-{
- chunk_t exp;
- chunk_t mod;
-
- if (pubkey->len < 3)
- return "RSA public key blob way to short"; /* not even room for length! */
-
- if (pubkey->ptr[0] != 0x00)
- {
- setchunk(exp, pubkey->ptr + 1, pubkey->ptr[0]);
- }
- else
- {
- setchunk(exp, pubkey->ptr + 3
- , (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]);
- }
-
- if (pubkey->len - (exp.ptr - pubkey->ptr) < exp.len + RSA_MIN_OCTETS_RFC)
- return "RSA public key blob too short";
-
- mod.ptr = exp.ptr + exp.len;
- mod.len = &pubkey->ptr[pubkey->len] - mod.ptr;
-
- if (mod.len < RSA_MIN_OCTETS)
- return RSA_MIN_OCTETS_UGH;
-
- if (mod.len > RSA_MAX_OCTETS)
- return RSA_MAX_OCTETS_UGH;
-
- init_RSA_public_key(rsa, exp, mod);
- rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */
- rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */
- DBG(DBG_RAW,
- RSA_show_public_key(rsa)
- )
-
- if (rsa->k != mod.len)
- {
- mpz_clear(&rsa->e);
- mpz_clear(&rsa->n);
- return "RSA modulus shorter than specified";
- }
-
- return NULL;
-}
-static void
-install_public_key(pubkey_t *pk, pubkey_list_t **head)
+static void install_public_key(pubkey_t *pk, pubkey_list_t **head)
{
- pubkey_list_t *p = alloc_thing(pubkey_list_t, "pubkey entry");
+ pubkey_list_t *p = malloc_thing(pubkey_list_t);
- unshare_id_content(&pk->id);
+ unshare_id_content(&pk->id);
- /* copy issuer dn */
- if (pk->issuer.ptr != NULL)
- pk->issuer.ptr = clone_bytes(pk->issuer.ptr, pk->issuer.len, "issuer dn");
+ /* copy issuer dn */
+ pk->issuer = chunk_clone(pk->issuer);
- /* copy serial number */
- if (pk->serial.ptr != NULL)
- pk->serial.ptr = clone_bytes(pk->serial.ptr, pk->serial.len, "serialNumber");
+ /* copy serial number */
+ pk->serial = chunk_clone(pk->serial);
- /* store the time the public key was installed */
- time(&pk->installed_time);
+ /* store the time the public key was installed */
+ time(&pk->installed_time);
- /* install new key at front */
- p->key = reference_key(pk);
- p->next = *head;
- *head = p;
+ /* install new key at front */
+ p->key = reference_key(pk);
+ p->next = *head;
+ *head = p;
}
-
-void
-delete_public_keys(const struct id *id, enum pubkey_alg alg
-, chunk_t issuer, chunk_t serial)
+void delete_public_keys(const struct id *id, key_type_t type,
+ chunk_t issuer, chunk_t serial)
{
- pubkey_list_t **pp, *p;
- pubkey_t *pk;
-
- for (pp = &pubkeys; (p = *pp) != NULL; )
- {
- pk = p->key;
-
- if (same_id(id, &pk->id) && pk->alg == alg
- && (issuer.ptr == NULL || pk->issuer.ptr == NULL
- || same_dn(issuer, pk->issuer))
- && same_serial(serial, pk->serial))
- *pp = free_public_keyentry(p);
- else
- pp = &p->next;
- }
+ pubkey_list_t **pp, *p;
+ pubkey_t *pk;
+ key_type_t pk_type;
+
+ for (pp = &pubkeys; (p = *pp) != NULL; )
+ {
+ pk = p->key;
+ pk_type = pk->public_key->get_type(pk->public_key);
+
+ if (same_id(id, &pk->id) && pk_type == type
+ && (issuer.ptr == NULL || pk->issuer.ptr == NULL
+ || same_dn(issuer, pk->issuer))
+ && same_serial(serial, pk->serial))
+ {
+ *pp = free_public_keyentry(p);
+ }
+ else
+ {
+ pp = &p->next;
+ }
+ }
}
-pubkey_t *
-reference_key(pubkey_t *pk)
+pubkey_t* reference_key(pubkey_t *pk)
{
- pk->refcnt++;
- return pk;
+ pk->refcnt++;
+ return pk;
}
void
unreference_key(pubkey_t **pkp)
{
- pubkey_t *pk = *pkp;
- char b[BUF_LEN];
+ pubkey_t *pk = *pkp;
+ char b[BUF_LEN];
- if (pk == NULL)
- return;
+ if (pk == NULL)
+ {
+ return;
+ }
- /* print stuff */
- DBG(DBG_CONTROLMORE,
- idtoa(&pk->id, b, sizeof(b));
- DBG_log("unreference key: %p %s cnt %d--", pk, b, pk->refcnt)
- )
+ /* print stuff */
+ DBG(DBG_CONTROLMORE,
+ idtoa(&pk->id, b, sizeof(b));
+ DBG_log("unreference key: %p %s cnt %d--", pk, b, pk->refcnt)
+ )
- /* cancel out the pointer */
- *pkp = NULL;
+ /* cancel out the pointer */
+ *pkp = NULL;
- passert(pk->refcnt != 0);
- pk->refcnt--;
- if (pk->refcnt == 0)
- free_public_key(pk);
+ passert(pk->refcnt != 0);
+ pk->refcnt--;
+ if (pk->refcnt == 0)
+ {
+ free_public_key(pk);
+ }
}
-err_t
-add_public_key(const struct id *id
-, enum dns_auth_level dns_auth_level
-, enum pubkey_alg alg
-, const chunk_t *key
-, pubkey_list_t **head)
+bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
+ enum pubkey_alg alg, chunk_t rfc3110_key,
+ pubkey_list_t **head)
{
- pubkey_t *pk = alloc_thing(pubkey_t, "pubkey");
+ public_key_t *key = NULL;
+ pubkey_t *pk;
- /* first: algorithm-specific decoding of key chunk */
- switch (alg)
- {
- case PUBKEY_ALG_RSA:
+ /* first: algorithm-specific decoding of key chunk */
+ switch (alg)
{
- err_t ugh = unpack_RSA_public_key(&pk->u.rsa, key);
-
- if (ugh != NULL)
- {
- pfree(pk);
- return ugh;
- }
+ case PUBKEY_ALG_RSA:
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_RFC_3110, rfc3110_key,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return FALSE;
+ }
+ break;
+ default:
+ bad_case(alg);
}
- break;
- default:
- bad_case(alg);
- }
-
- pk->id = *id;
- pk->dns_auth_level = dns_auth_level;
- pk->alg = alg;
- pk->until_time = UNDEFINED_TIME;
- pk->issuer = empty_chunk;
- pk->serial = empty_chunk;
-
- install_public_key(pk, head);
- return NULL;
+
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = key;
+ pk->id = *id;
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = UNDEFINED_TIME;
+ pk->issuer = chunk_empty;
+ pk->serial = chunk_empty;
+ install_public_key(pk, head);
+ return TRUE;
}
/* extract id and public key from x.509 certificate and
* insert it into a pubkeyrec
*/
-void
-add_x509_public_key(x509cert_t *cert , time_t until
- , enum dns_auth_level dns_auth_level)
+void add_x509_public_key(x509cert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
- generalName_t *gn;
- pubkey_t *pk;
- cert_t c = { CERT_X509_SIGNATURE, {cert} };
-
- /* we support RSA only */
- if (cert->subjectPublicKeyAlgorithm != PUBKEY_ALG_RSA)
- return;
-
- /* ID type: ID_DER_ASN1_DN (X.509 subject field) */
- pk = allocate_RSA_public_key(c);
- pk->id.kind = ID_DER_ASN1_DN;
- pk->id.name = cert->subject;
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- pk->issuer = cert->issuer;
- pk->serial = cert->serialNumber;
- delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
-
- gn = cert->subjectAltName;
-
- while (gn != NULL) /* insert all subjectAltNames */
- {
- struct id id = empty_id;
-
- gntoid(&id, gn);
- if (id.kind != ID_NONE)
+ generalName_t *gn;
+ pubkey_t *pk;
+ key_type_t pk_type;
+
+ /* ID type: ID_DER_ASN1_DN (X.509 subject field) */
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
+ pk->id.kind = ID_DER_ASN1_DN;
+ pk->id.name = cert->subject;
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk->issuer = cert->issuer;
+ pk->serial = cert->serialNumber;
+ pk_type = pk->public_key->get_type(pk->public_key);
+ delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
+
+ gn = cert->subjectAltName;
+
+ while (gn != NULL) /* insert all subjectAltNames */
{
- pk = allocate_RSA_public_key(c);
- pk->id = id;
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- pk->issuer = cert->issuer;
- pk->serial = cert->serialNumber;
- delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
+ struct id id = empty_id;
+
+ gntoid(&id, gn);
+ if (id.kind != ID_ANY)
+ {
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
+ pk->id = id;
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk->issuer = cert->issuer;
+ pk->serial = cert->serialNumber;
+ delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
+ }
+ gn = gn->next;
}
- gn = gn->next;
- }
}
/* extract id and public key from OpenPGP certificate and
* insert it into a pubkeyrec
*/
-void
-add_pgp_public_key(pgpcert_t *cert , time_t until
- , enum dns_auth_level dns_auth_level)
+void add_pgp_public_key(pgpcert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
- pubkey_t *pk;
- cert_t c;
-
- c.type = CERT_PGP;
- c.u.pgp = cert;
-
- /* we support RSA only */
- if (cert->pubkeyAlg != PUBKEY_ALG_RSA)
- {
- plog(" RSA public keys supported only");
- return;
- }
-
- pk = allocate_RSA_public_key(c);
- pk->id.kind = ID_KEY_ID;
- pk->id.name.ptr = cert->fingerprint;
- pk->id.name.len = PGP_FINGERPRINT_SIZE;
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- delete_public_keys(&pk->id, pk->alg, empty_chunk, empty_chunk);
- install_public_key(pk, &pubkeys);
+ pubkey_t *pk;
+ key_type_t pk_type;
+
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
+ pk->id.kind = ID_KEY_ID;
+ pk->id.name = cert->fingerprint->get_encoding(cert->fingerprint);
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk_type = pk->public_key->get_type(pk->public_key);
+ delete_public_keys(&pk->id, pk_type, chunk_empty, chunk_empty);
+ install_public_key(pk, &pubkeys);
}
/* when a X.509 certificate gets revoked, all instances of
* the corresponding public key must be removed
*/
-void
-remove_x509_public_key(const x509cert_t *cert)
+void remove_x509_public_key(const x509cert_t *cert)
{
- const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}};
- pubkey_list_t *p, **pp;
- pubkey_t *revoked_pk;
+ public_key_t *revoked_key = cert->public_key;
+ pubkey_list_t *p, **pp;
- revoked_pk = allocate_RSA_public_key(c);
- p = pubkeys;
- pp = &pubkeys;
+ p = pubkeys;
+ pp = &pubkeys;
- while(p != NULL)
- {
- if (same_RSA_public_key(&p->key->u.rsa, &revoked_pk->u.rsa))
- {
- /* remove p from list and free memory */
- *pp = free_public_keyentry(p);
- loglog(RC_LOG_SERIOUS,
- "invalid RSA public key deleted");
- }
- else
+ while(p != NULL)
{
- pp = &p->next;
+ if (revoked_key->equals(revoked_key, p->key->public_key))
+ {
+ /* remove p from list and free memory */
+ *pp = free_public_keyentry(p);
+ loglog(RC_LOG_SERIOUS, "invalid public key deleted");
+ }
+ else
+ {
+ pp = &p->next;
+ }
+ p =*pp;
}
- p =*pp;
- }
- free_public_key(revoked_pk);
}
/*
@@ -1504,45 +1419,41 @@ remove_x509_public_key(const x509cert_t *cert)
*/
void list_public_keys(bool utc)
{
- pubkey_list_t *p = pubkeys;
-
- if (p != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of Public Keys:");
- whack_log(RC_COMMENT, " ");
- }
+ pubkey_list_t *p = pubkeys;
- while (p != NULL)
- {
- pubkey_t *key = p->key;
+ if (p != NULL)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of Public Keys:");
+ whack_log(RC_COMMENT, " ");
+ }
- if (key->alg == PUBKEY_ALG_RSA)
+ while (p != NULL)
{
- char buf[BUF_LEN];
- char expires_buf[TIMETOA_BUF];
-
- idtoa(&key->id, buf, BUF_LEN);
- strcpy(expires_buf, timetoa(&key->until_time, utc));
- whack_log(RC_COMMENT, "%s, %4d RSA Key %s, until %s %s",
-
- timetoa(&key->installed_time, utc), 8*key->u.rsa.k, key->u.rsa.keyid,
- expires_buf,
- check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
- whack_log(RC_COMMENT," %s '%s'",
- enum_show(&ident_names, key->id.kind), buf);
- if (key->issuer.len > 0)
- {
- dntoa(buf, BUF_LEN, key->issuer);
- whack_log(RC_COMMENT," issuer: '%s'", buf);
- }
- if (key->serial.len > 0)
- {
- datatot(key->serial.ptr, key->serial.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT," serial: %s", buf);
- }
+ pubkey_t *key = p->key;
+ public_key_t *public = key->public_key;
+ identification_t *keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
+ char buf[BUF_LEN];
+
+ idtoa(&key->id, buf, BUF_LEN);
+ whack_log(RC_COMMENT,"%T, '%s'", &key->installed_time, utc, buf);
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits, until %T %s",
+ key_type_names, public->get_type(public),
+ public->get_keysize(public) * BITS_PER_BYTE,
+ &key->until_time, utc,
+ check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
+ whack_log(RC_COMMENT," keyid: %Y", keyid);
+ if (key->issuer.len > 0)
+ {
+ dntoa(buf, BUF_LEN, key->issuer);
+ whack_log(RC_COMMENT," issuer: '%s'", buf);
+ }
+ if (key->serial.len > 0)
+ {
+ datatot(key->serial.ptr, key->serial.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT," serial: %s", buf);
+ }
+ p = p->next;
}
- p = p->next;
- }
}
diff --git a/src/pluto/keys.h b/src/pluto/keys.h
index b06e536a5..8bc94d839 100644
--- a/src/pluto/keys.h
+++ b/src/pluto/keys.h
@@ -1,5 +1,6 @@
/* mechanisms for preshared keys (public, private, and preshared secrets)
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen, Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,16 +11,14 @@
* 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: keys.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _KEYS_H
#define _KEYS_H
-#include <gmp.h> /* GNU Multi-Precision library */
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
-#include "pkcs1.h"
#include "certs.h"
#ifndef SHARED_SECRETS_FILE
@@ -32,11 +31,10 @@ extern void load_preshared_secrets(int whackfd);
extern void free_preshared_secrets(void);
enum PrivateKeyKind {
- PPK_PSK,
- /* PPK_DSS, */ /* not implemented */
- PPK_RSA,
- PPK_XAUTH,
- PPK_PIN
+ PPK_PSK,
+ PPK_PUBKEY,
+ PPK_XAUTH,
+ PPK_PIN
};
extern void xauth_defaults(void);
@@ -45,69 +43,64 @@ extern void xauth_defaults(void);
struct connection;
extern const chunk_t *get_preshared_secret(const struct connection *c);
-extern err_t unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey);
-extern const RSA_private_key_t *get_RSA_private_key(const struct connection *c);
-extern const RSA_private_key_t *get_x509_private_key(const x509cert_t *cert);
+extern private_key_t *get_private_key(const struct connection *c);
+extern private_key_t *get_x509_private_key(const x509cert_t *cert);
/* public key machinery */
typedef struct pubkey pubkey_t;
struct pubkey {
- struct id id;
- unsigned refcnt; /* reference counted! */
- enum dns_auth_level dns_auth_level;
- char *dns_sig;
- time_t installed_time
- , last_tried_time
- , last_worked_time
- , until_time;
- chunk_t issuer;
- chunk_t serial;
- enum pubkey_alg alg;
- union {
- RSA_public_key_t rsa;
- } u;
+ struct id id;
+ unsigned refcnt; /* reference counted! */
+ enum dns_auth_level dns_auth_level;
+ char *dns_sig;
+ time_t installed_time
+ , last_tried_time
+ , last_worked_time
+ , until_time;
+ chunk_t issuer;
+ chunk_t serial;
+ public_key_t *public_key;
};
typedef struct pubkey_list pubkey_list_t;
struct pubkey_list {
- pubkey_t *key;
- pubkey_list_t *next;
+ pubkey_t *key;
+ pubkey_list_t *next;
};
-extern pubkey_list_t *pubkeys; /* keys from ipsec.conf or from certs */
+extern pubkey_list_t *pubkeys; /* keys from ipsec.conf or from certs */
-extern pubkey_t *public_key_from_rsa(const RSA_public_key_t *k);
+extern pubkey_t *public_key_from_rsa(public_key_t *key);
extern pubkey_list_t *free_public_keyentry(pubkey_list_t *p);
extern void free_public_keys(pubkey_list_t **keys);
extern void free_remembered_public_keys(void);
-extern void delete_public_keys(const struct id *id, enum pubkey_alg alg
- , chunk_t issuer, chunk_t serial);
-
+extern void delete_public_keys(const struct id *id, key_type_t type,
+ chunk_t issuer, chunk_t serial);
extern pubkey_t *reference_key(pubkey_t *pk);
extern void unreference_key(pubkey_t **pkp);
-extern err_t add_public_key(const struct id *id
- , enum dns_auth_level dns_auth_level
- , enum pubkey_alg alg
- , const chunk_t *key
- , pubkey_list_t **head);
+extern bool add_public_key(const struct id *id,
+ enum dns_auth_level dns_auth_level,
+ enum pubkey_alg alg,
+ chunk_t rfc3110_key,
+ pubkey_list_t **head);
extern bool has_private_key(cert_t cert);
extern void add_x509_public_key(x509cert_t *cert, time_t until
- , enum dns_auth_level dns_auth_level);
+ , enum dns_auth_level dns_auth_level);
extern void add_pgp_public_key(pgpcert_t *cert, time_t until
- , enum dns_auth_level dns_auth_level);
+ , enum dns_auth_level dns_auth_level);
extern void remove_x509_public_key(const x509cert_t *cert);
extern void list_public_keys(bool utc);
-struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
+struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
extern void transfer_to_public_keys(struct gw_info *gateways_from_dns
#ifdef USE_KEYRR
- , pubkey_list_t **keys
+ , pubkey_list_t **keys
#endif /* USE_KEYRR */
- );
+ );
#endif /* _KEYS_H */
diff --git a/src/pluto/lex.c b/src/pluto/lex.c
index 08ab43876..f48d24a54 100644
--- a/src/pluto/lex.c
+++ b/src/pluto/lex.c
@@ -10,8 +10,6 @@
* 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: lex.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -27,7 +25,7 @@
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include "lex.h"
struct file_lex_position *flp = NULL;
@@ -39,36 +37,36 @@ struct file_lex_position *flp = NULL;
bool
lexopen(struct file_lex_position *new_flp, const char *name, bool optional)
{
- FILE *f = fopen(name, "r");
-
- if (f == NULL)
- {
- if (!optional || errno != ENOENT)
- log_errno((e, "could not open \"%s\"", name));
- return FALSE;
- }
- else
- {
- new_flp->previous = flp;
- flp = new_flp;
- flp->filename = name;
- flp->fp = f;
- flp->lino = 0;
- flp->bdry = B_none;
-
- flp->cur = flp->buffer; /* nothing loaded yet */
- flp->under = *flp->cur = '\0';
-
- (void) shift(); /* prime tok */
- return TRUE;
- }
+ FILE *f = fopen(name, "r");
+
+ if (f == NULL)
+ {
+ if (!optional || errno != ENOENT)
+ log_errno((e, "could not open \"%s\"", name));
+ return FALSE;
+ }
+ else
+ {
+ new_flp->previous = flp;
+ flp = new_flp;
+ flp->filename = name;
+ flp->fp = f;
+ flp->lino = 0;
+ flp->bdry = B_none;
+
+ flp->cur = flp->buffer; /* nothing loaded yet */
+ flp->under = *flp->cur = '\0';
+
+ (void) shift(); /* prime tok */
+ return TRUE;
+ }
}
void
lexclose(void)
{
- fclose(flp->fp);
- flp = flp->previous;
+ fclose(flp->fp);
+ flp = flp->previous;
}
/* Token decoding: shift() loads the next token into tok.
@@ -88,110 +86,110 @@ char *tok;
bool
shift(void)
{
- char *p = flp->cur;
- char *sor = NULL; /* start of record for any new lines */
+ char *p = flp->cur;
+ char *sor = NULL; /* start of record for any new lines */
- passert(flp->bdry == B_none);
+ passert(flp->bdry == B_none);
- *p = flp->under;
- flp->under = '\0';
+ *p = flp->under;
+ flp->under = '\0';
- for (;;)
- {
- switch (*p)
+ for (;;)
{
- case '\0': /* end of line */
- case '#': /* comment to end of line: treat as end of line */
- /* get the next line */
- if (fgets(flp->buffer, sizeof(flp->buffer)-1, flp->fp) == NULL)
- {
- flp->bdry = B_file;
- tok = flp->cur = NULL;
- return FALSE;
- }
- else
- {
- /* strip trailing whitespace, including \n */
-
- for (p = flp->buffer+strlen(flp->buffer)-1
- ; p>flp->buffer && isspace(p[-1]); p--)
- ;
- *p = '\0';
-
- flp->lino++;
- sor = p = flp->buffer;
- }
- break; /* try again for a token */
-
- case ' ': /* whitespace */
- case '\t':
- p++;
- break; /* try again for a token */
-
- case '"': /* quoted token */
- case '\'':
- if (p != sor)
- {
- /* we have a quoted token: note and advance to its end */
- tok = p;
- p = strchr(p+1, *p);
- if (p == NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unterminated string"
- , flp->filename, flp->lino);
- p = tok + strlen(tok);
- }
- else
- {
- p++; /* include delimiter in token */
- }
-
- /* remember token delimiter and replace with '\0' */
- flp->under = *p;
- *p = '\0';
- flp->cur = p;
- return TRUE;
- }
- /* FALL THROUGH */
- default:
- if (p != sor)
- {
- /* we seem to have a token: note and advance to its end */
- tok = p;
-
- if (p[0] == '0' && p[1] == 't')
+ switch (*p)
{
- /* 0t... token goes to end of line */
- p += strlen(p);
- }
- else
- {
- /* "ordinary" token: up to whitespace or end of line */
- do {
+ case '\0': /* end of line */
+ case '#': /* comment to end of line: treat as end of line */
+ /* get the next line */
+ if (fgets(flp->buffer, sizeof(flp->buffer)-1, flp->fp) == NULL)
+ {
+ flp->bdry = B_file;
+ tok = flp->cur = NULL;
+ return FALSE;
+ }
+ else
+ {
+ /* strip trailing whitespace, including \n */
+
+ for (p = flp->buffer+strlen(flp->buffer)-1
+ ; p>flp->buffer && isspace(p[-1]); p--)
+ ;
+ *p = '\0';
+
+ flp->lino++;
+ sor = p = flp->buffer;
+ }
+ break; /* try again for a token */
+
+ case ' ': /* whitespace */
+ case '\t':
p++;
- } while (*p != '\0' && !isspace(*p))
- ;
-
- /* fudge to separate ':' from a preceding adjacent token */
- if (p-1 > tok && p[-1] == ':')
- p--;
+ break; /* try again for a token */
+
+ case '"': /* quoted token */
+ case '\'':
+ if (p != sor)
+ {
+ /* we have a quoted token: note and advance to its end */
+ tok = p;
+ p = strchr(p+1, *p);
+ if (p == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unterminated string"
+ , flp->filename, flp->lino);
+ p = tok + strlen(tok);
+ }
+ else
+ {
+ p++; /* include delimiter in token */
+ }
+
+ /* remember token delimiter and replace with '\0' */
+ flp->under = *p;
+ *p = '\0';
+ flp->cur = p;
+ return TRUE;
+ }
+ /* FALL THROUGH */
+ default:
+ if (p != sor)
+ {
+ /* we seem to have a token: note and advance to its end */
+ tok = p;
+
+ if (p[0] == '0' && p[1] == 't')
+ {
+ /* 0t... token goes to end of line */
+ p += strlen(p);
+ }
+ else
+ {
+ /* "ordinary" token: up to whitespace or end of line */
+ do {
+ p++;
+ } while (*p != '\0' && !isspace(*p))
+ ;
+
+ /* fudge to separate ':' from a preceding adjacent token */
+ if (p-1 > tok && p[-1] == ':')
+ p--;
+ }
+
+ /* remember token delimiter and replace with '\0' */
+ flp->under = *p;
+ *p = '\0';
+ flp->cur = p;
+ return TRUE;
+ }
+
+ /* we have a start-of-record: return it, deferring "real" token */
+ flp->bdry = B_record;
+ tok = NULL;
+ flp->under = *p;
+ flp->cur = p;
+ return FALSE;
}
-
- /* remember token delimiter and replace with '\0' */
- flp->under = *p;
- *p = '\0';
- flp->cur = p;
- return TRUE;
- }
-
- /* we have a start-of-record: return it, deferring "real" token */
- flp->bdry = B_record;
- tok = NULL;
- flp->under = *p;
- flp->cur = p;
- return FALSE;
}
- }
}
/* ensures we are at a Record (or File) boundary, optionally warning if not */
@@ -199,15 +197,15 @@ shift(void)
bool
flushline(const char *m)
{
- if (flp->bdry != B_none)
- {
- return TRUE;
- }
- else
- {
- if (m != NULL)
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m);
- do ; while (shift());
- return FALSE;
- }
+ if (flp->bdry != B_none)
+ {
+ return TRUE;
+ }
+ else
+ {
+ if (m != NULL)
+ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m);
+ do ; while (shift());
+ return FALSE;
+ }
}
diff --git a/src/pluto/lex.h b/src/pluto/lex.h
index 450149c64..f16769144 100644
--- a/src/pluto/lex.h
+++ b/src/pluto/lex.h
@@ -10,22 +10,20 @@
* 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: lex.h 3252 2007-10-06 21:24:50Z andreas $
*/
#define MAX_TOK_LEN 2048 /* includes terminal '\0' */
struct file_lex_position
{
- int depth; /* how deeply we are nested */
- const char *filename;
- FILE *fp;
- enum { B_none, B_record, B_file } bdry; /* current boundary */
- int lino; /* line number in file */
- char buffer[MAX_TOK_LEN + 1]; /* note: one extra char for our use (jamming '"') */
- char *cur; /* cursor */
- char under; /* except in shift(): character orignally at *cur */
- struct file_lex_position *previous;
+ int depth; /* how deeply we are nested */
+ const char *filename;
+ FILE *fp;
+ enum { B_none, B_record, B_file } bdry; /* current boundary */
+ int lino; /* line number in file */
+ char buffer[MAX_TOK_LEN + 1]; /* note: one extra char for our use (jamming '"') */
+ char *cur; /* cursor */
+ char under; /* except in shift(): character orignally at *cur */
+ struct file_lex_position *previous;
};
extern struct file_lex_position *flp;
diff --git a/src/pluto/log.c b/src/pluto/log.c
index b7c1ba8b8..e34409f1c 100644
--- a/src/pluto/log.c
+++ b/src/pluto/log.c
@@ -1,6 +1,7 @@
/* error logging functions
* Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
+ * Copyright (C) 1998-2001 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,8 +12,6 @@
* 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: log.c 4246 2008-08-03 18:01:21Z andreas $
*/
#include <stdio.h>
@@ -23,13 +22,15 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
-#include <signal.h> /* used only if MSG_NOSIGNAL not defined */
+#include <signal.h> /* used only if MSG_NOSIGNAL not defined */
#include <sys/queue.h>
#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <freeswan.h>
+#include <library.h>
+#include <debug.h>
#include "constants.h"
#include "defs.h"
@@ -38,27 +39,27 @@
#include "state.h"
#include "connections.h"
#include "kernel.h"
-#include "whack.h" /* needs connections.h */
+#include "whack.h" /* needs connections.h */
#include "timer.h"
/* close one per-peer log */
-static void perpeer_logclose(struct connection *c); /* forward */
+static void perpeer_logclose(struct connection *c); /* forward */
bool
- log_to_stderr = TRUE, /* should log go to stderr? */
- log_to_syslog = TRUE, /* should log go to syslog? */
- log_to_perpeer= FALSE; /* should log go to per-IP file? */
+ log_to_stderr = TRUE, /* should log go to stderr? */
+ log_to_syslog = TRUE, /* should log go to syslog? */
+ log_to_perpeer= FALSE; /* should log go to per-IP file? */
bool
- logged_txt_warning = FALSE; /* should we complain about finding KEY? */
+ logged_txt_warning = FALSE; /* should we complain about finding KEY? */
/* should we complain when we find no local id */
bool
- logged_myid_fqdn_txt_warning = FALSE,
- logged_myid_ip_txt_warning = FALSE,
- logged_myid_fqdn_key_warning = FALSE,
- logged_myid_ip_key_warning = FALSE;
+ logged_myid_fqdn_txt_warning = FALSE,
+ logged_myid_ip_txt_warning = FALSE,
+ logged_myid_fqdn_key_warning = FALSE,
+ logged_myid_ip_key_warning = FALSE;
/* may include trailing / */
const char *base_perpeer_logdir = PERPEERLOGDIR;
@@ -74,42 +75,110 @@ static TAILQ_HEAD(perpeer, connection) perpeer_list;
* If the context provides a whack file descriptor, messages
* should be copied to it -- see whack_log()
*/
-int whack_log_fd = NULL_FD; /* only set during whack_handle() */
-struct state *cur_state = NULL; /* current state, for diagnostics */
-struct connection *cur_connection = NULL; /* current connection, for diagnostics */
-const ip_address *cur_from = NULL; /* source of current current message */
-u_int16_t cur_from_port; /* host order */
+int whack_log_fd = NULL_FD; /* only set during whack_handle() */
+struct state *cur_state = NULL; /* current state, for diagnostics */
+struct connection *cur_connection = NULL; /* current connection, for diagnostics */
+const ip_address *cur_from = NULL; /* source of current current message */
+u_int16_t cur_from_port; /* host order */
+
+/**
+ * pluto dbg function for libstrongswan
+ */
+static void pluto_dbg(int level, char *fmt, ...)
+{
+ int priority = LOG_INFO;
+ int debug_level;
+ char buffer[8192];
+ char *current = buffer, *next;
+ va_list args;
+
+ if (cur_debugging & DBG_PRIVATE)
+ {
+ debug_level = 4;
+ }
+ else if (cur_debugging & DBG_RAW)
+ {
+ debug_level = 3;
+ }
+ else if (cur_debugging & DBG_PARSING)
+ {
+ debug_level = 2;
+ }
+ else
+ {
+ debug_level = 1;
+ }
+
+ if (level <= debug_level)
+ {
+ va_start(args, fmt);
+
+ if (log_to_stderr)
+ {
+ if (level > 1)
+ {
+ fprintf(stderr, "| ");
+ }
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ }
+ if (log_to_syslog)
+ {
+ /* write in memory buffer first */
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+
+ /* do a syslog with every line */
+ while (current)
+ {
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ syslog(priority, "%s%s\n", (level > 1)? "| ":"", current);
+ current = next;
+ }
+ }
+ va_end(args);
+ }
+}
void
init_log(const char *program)
{
- if (log_to_stderr)
- setbuf(stderr, NULL);
- if (log_to_syslog)
- openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
+ /* enable pluto debugging hook for libstrongswan */
+ dbg = pluto_dbg;
- TAILQ_INIT(&perpeer_list);
+ if (log_to_stderr)
+ {
+ setbuf(stderr, NULL);
+ }
+ if (log_to_syslog)
+ {
+ openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
+ }
+ TAILQ_INIT(&perpeer_list);
}
void
close_peerlog(void)
{
- /* exit if the queue has not been initialized */
- if (perpeer_list.tqh_first == NULL)
- return;
+ /* exit if the queue has not been initialized */
+ if (perpeer_list.tqh_first == NULL)
+ return;
- /* end of queue is given by pointer to "HEAD" */
- while (TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list)
- perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
+ /* end of queue is given by pointer to "HEAD" */
+ while (TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list)
+ perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
}
void
close_log(void)
{
- if (log_to_syslog)
- closelog();
+ if (log_to_syslog)
+ closelog();
- close_peerlog();
+ close_peerlog();
}
/* Sanitize character string in situ: turns dangerous characters into \OOO.
@@ -120,50 +189,50 @@ close_log(void)
static size_t
sanitize(char *buf, size_t size)
{
-# define UGLY_WIDTH 4 /* width for ugly character: \OOO */
- size_t len;
- size_t added = 0;
- char *p;
-
- passert(size >= UGLY_WIDTH); /* need room to swing cat */
-
- /* find right side of string to be sanitized and count
- * number of columns to be added. Stop on end of string
- * or lack of room for more result.
- */
- for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; )
- {
- unsigned char c = *p++;
-
- if (c == '\\' || !isprint(c))
- added += UGLY_WIDTH - 1;
- }
-
- /* at this point, p points after last original character to be
- * included. added is how many characters are added to sanitize.
- * so p[added] will point after last sanitized character.
- */
-
- p[added] = '\0';
- len = &p[added] - buf;
-
- /* scan backwards, copying characters to their new home
- * and inserting the expansions for ugly characters.
- * It is finished when no more shifting is required.
- * This is a predecrement loop.
- */
- while (added != 0)
- {
- char fmtd[UGLY_WIDTH + 1];
- unsigned char c;
-
- while ((c = *--p) != '\\' && isprint(c))
- p[added] = c;
- added -= UGLY_WIDTH - 1;
- snprintf(fmtd, sizeof(fmtd), "\\%03o", c);
- memcpy(p + added, fmtd, UGLY_WIDTH);
- }
- return len;
+# define UGLY_WIDTH 4 /* width for ugly character: \OOO */
+ size_t len;
+ size_t added = 0;
+ char *p;
+
+ passert(size >= UGLY_WIDTH); /* need room to swing cat */
+
+ /* find right side of string to be sanitized and count
+ * number of columns to be added. Stop on end of string
+ * or lack of room for more result.
+ */
+ for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; )
+ {
+ unsigned char c = *p++;
+
+ if (c == '\\' || !isprint(c))
+ added += UGLY_WIDTH - 1;
+ }
+
+ /* at this point, p points after last original character to be
+ * included. added is how many characters are added to sanitize.
+ * so p[added] will point after last sanitized character.
+ */
+
+ p[added] = '\0';
+ len = &p[added] - buf;
+
+ /* scan backwards, copying characters to their new home
+ * and inserting the expansions for ugly characters.
+ * It is finished when no more shifting is required.
+ * This is a predecrement loop.
+ */
+ while (added != 0)
+ {
+ char fmtd[UGLY_WIDTH + 1];
+ unsigned char c;
+
+ while ((c = *--p) != '\\' && isprint(c))
+ p[added] = c;
+ added -= UGLY_WIDTH - 1;
+ snprintf(fmtd, sizeof(fmtd), "\\%03o", c);
+ memcpy(p + added, fmtd, UGLY_WIDTH);
+ }
+ return len;
# undef UGLY_WIDTH
}
@@ -174,349 +243,348 @@ sanitize(char *buf, size_t size)
static void
fmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap)
{
- bool reproc = *fmt == '~';
- size_t ps;
- struct connection *c = cur_state != NULL ? cur_state->st_connection
- : cur_connection;
-
- buf[0] = '\0';
- if (reproc)
- fmt++; /* ~ at start of format suppresses this prefix */
- else if (c != NULL)
- {
- /* start with name of connection */
- char *const be = buf + buf_len;
- char *bp = buf;
-
- snprintf(bp, be - bp, "\"%s\"", c->name);
- bp += strlen(bp);
-
- /* if it fits, put in any connection instance information */
- if (be - bp > CONN_INST_BUF)
+ bool reproc = *fmt == '~';
+ size_t ps;
+ struct connection *c = cur_state != NULL ? cur_state->st_connection
+ : cur_connection;
+
+ buf[0] = '\0';
+ if (reproc)
+ fmt++; /* ~ at start of format suppresses this prefix */
+ else if (c != NULL)
{
- fmt_conn_instance(c, bp);
- bp += strlen(bp);
- }
+ /* start with name of connection */
+ char *const be = buf + buf_len;
+ char *bp = buf;
+
+ snprintf(bp, be - bp, "\"%s\"", c->name);
+ bp += strlen(bp);
+
+ /* if it fits, put in any connection instance information */
+ if (be - bp > CONN_INST_BUF)
+ {
+ fmt_conn_instance(c, bp);
+ bp += strlen(bp);
+ }
- if (cur_state != NULL)
+ if (cur_state != NULL)
+ {
+ /* state number */
+ snprintf(bp, be - bp, " #%lu", cur_state->st_serialno);
+ bp += strlen(bp);
+ }
+ snprintf(bp, be - bp, ": ");
+ }
+ else if (cur_from != NULL)
{
- /* state number */
- snprintf(bp, be - bp, " #%lu", cur_state->st_serialno);
- bp += strlen(bp);
+ /* peer's IP address */
+ /* Note: must not use ip_str() because our caller might! */
+ char ab[ADDRTOT_BUF];
+
+ (void) addrtot(cur_from, 0, ab, sizeof(ab));
+ snprintf(buf, buf_len, "packet from %s:%u: "
+ , ab, (unsigned)cur_from_port);
}
- snprintf(bp, be - bp, ": ");
- }
- else if (cur_from != NULL)
- {
- /* peer's IP address */
- /* Note: must not use ip_str() because our caller might! */
- char ab[ADDRTOT_BUF];
-
- (void) addrtot(cur_from, 0, ab, sizeof(ab));
- snprintf(buf, buf_len, "packet from %s:%u: "
- , ab, (unsigned)cur_from_port);
- }
-
- ps = strlen(buf);
- vsnprintf(buf + ps, buf_len - ps, fmt, ap);
- if (!reproc)
- (void)sanitize(buf, buf_len);
+
+ ps = strlen(buf);
+ vsnprintf(buf + ps, buf_len - ps, fmt, ap);
+ if (!reproc)
+ (void)sanitize(buf, buf_len);
}
static void
perpeer_logclose(struct connection *c)
{
- /* only free/close things if we had used them! */
- if (c->log_file != NULL)
- {
- passert(perpeer_count > 0);
-
- TAILQ_REMOVE(&perpeer_list, c, log_link);
- perpeer_count--;
- fclose(c->log_file);
- c->log_file=NULL;
- }
+ /* only free/close things if we had used them! */
+ if (c->log_file != NULL)
+ {
+ passert(perpeer_count > 0);
+
+ TAILQ_REMOVE(&perpeer_list, c, log_link);
+ perpeer_count--;
+ fclose(c->log_file);
+ c->log_file=NULL;
+ }
}
void
perpeer_logfree(struct connection *c)
{
- perpeer_logclose(c);
- if (c->log_file_name != NULL)
- {
- pfree(c->log_file_name);
- c->log_file_name = NULL;
- c->log_file_err = FALSE;
- }
+ perpeer_logclose(c);
+ if (c->log_file_name != NULL)
+ {
+ free(c->log_file_name);
+ c->log_file_name = NULL;
+ c->log_file_err = FALSE;
+ }
}
/* open the per-peer log */
static void
open_peerlog(struct connection *c)
{
- syslog(LOG_INFO, "opening log file for conn %s", c->name);
+ syslog(LOG_INFO, "opening log file for conn %s", c->name);
- if (c->log_file_name == NULL)
- {
- char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF];
- int peernamelen, lf_len;
-
- addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername));
- peernamelen = strlen(peername);
-
- /* copy IP address, turning : and . into / */
+ if (c->log_file_name == NULL)
{
- char c, *p, *q;
-
- p = peername;
- q = dname;
- do {
- c = *p++;
- if (c == '.' || c == ':')
- c = '/';
- *q++ = c;
- } while (c != '\0');
- }
-
- lf_len = peernamelen * 2
- + strlen(base_perpeer_logdir)
- + sizeof("//.log")
- + 1;
- c->log_file_name = alloc_bytes(lf_len, "per-peer log file name");
-
- fprintf(stderr, "base dir |%s| dname |%s| peername |%s|"
- , base_perpeer_logdir, dname, peername);
- snprintf(c->log_file_name, lf_len, "%s/%s/%s.log"
- , base_perpeer_logdir, dname, peername);
+ char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF];
+ int peernamelen, lf_len;
- syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name);
- }
+ addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername));
+ peernamelen = strlen(peername);
- /* now open the file, creating directories if necessary */
-
- { /* create the directory */
- char *dname;
- int bpl_len = strlen(base_perpeer_logdir);
- char *slashloc;
-
- dname = clone_str(c->log_file_name, "temp copy of file name");
- dname = dirname(dname);
-
- if (access(dname, W_OK) != 0)
- {
- if (errno != ENOENT)
- {
- if (c->log_file_err)
+ /* copy IP address, turning : and . into / */
{
- syslog(LOG_CRIT, "can not write to %s: %s"
- , dname, strerror(errno));
- c->log_file_err = TRUE;
- pfree(dname);
- return;
+ char c, *p, *q;
+
+ p = peername;
+ q = dname;
+ do {
+ c = *p++;
+ if (c == '.' || c == ':')
+ c = '/';
+ *q++ = c;
+ } while (c != '\0');
}
- }
- /* directory does not exist, walk path creating dirs */
- /* start at base_perpeer_logdir */
- slashloc = dname + bpl_len;
- slashloc++; /* since, by construction there is a slash
- right there */
+ lf_len = peernamelen * 2
+ + strlen(base_perpeer_logdir)
+ + sizeof("//.log")
+ + 1;
+ c->log_file_name = malloc(lf_len);
+
+ fprintf(stderr, "base dir |%s| dname |%s| peername |%s|"
+ , base_perpeer_logdir, dname, peername);
+ snprintf(c->log_file_name, lf_len, "%s/%s/%s.log"
+ , base_perpeer_logdir, dname, peername);
- while (*slashloc != '\0')
- {
- char saveslash;
+ syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name);
+ }
- /* look for next slash */
- while (*slashloc != '\0' && *slashloc != '/') slashloc++;
+ /* now open the file, creating directories if necessary */
- saveslash = *slashloc;
+ { /* create the directory */
+ char *dname;
+ int bpl_len = strlen(base_perpeer_logdir);
+ char *slashloc;
- *slashloc = '\0';
+ dname = clone_str(c->log_file_name);
+ dname = dirname(dname);
- if (mkdir(dname, 0750) != 0 && errno != EEXIST)
+ if (access(dname, W_OK) != 0)
{
- syslog(LOG_CRIT, "can not create dir %s: %s"
- , dname, strerror(errno));
- c->log_file_err = TRUE;
- pfree(dname);
- return;
+ if (errno != ENOENT)
+ {
+ if (c->log_file_err)
+ {
+ syslog(LOG_CRIT, "can not write to %s: %s"
+ , dname, strerror(errno));
+ c->log_file_err = TRUE;
+ free(dname);
+ return;
+ }
+ }
+
+ /* directory does not exist, walk path creating dirs */
+ /* start at base_perpeer_logdir */
+ slashloc = dname + bpl_len;
+ slashloc++; /* since, by construction there is a slash
+ right there */
+
+ while (*slashloc != '\0')
+ {
+ char saveslash;
+
+ /* look for next slash */
+ while (*slashloc != '\0' && *slashloc != '/') slashloc++;
+
+ saveslash = *slashloc;
+
+ *slashloc = '\0';
+
+ if (mkdir(dname, 0750) != 0 && errno != EEXIST)
+ {
+ syslog(LOG_CRIT, "can not create dir %s: %s"
+ , dname, strerror(errno));
+ c->log_file_err = TRUE;
+ free(dname);
+ return;
+ }
+ syslog(LOG_DEBUG, "created new directory %s", dname);
+ *slashloc = saveslash;
+ slashloc++;
+ }
}
- syslog(LOG_DEBUG, "created new directory %s", dname);
- *slashloc = saveslash;
- slashloc++;
- }
+ free(dname);
}
- pfree(dname);
- }
+ c->log_file = fopen(c->log_file_name, "a");
+ if (c->log_file == NULL)
+ {
+ if (c->log_file_err)
+ {
+ syslog(LOG_CRIT, "logging system can not open %s: %s"
+ , c->log_file_name, strerror(errno));
+ c->log_file_err = TRUE;
+ }
+ return;
+ }
- c->log_file = fopen(c->log_file_name, "a");
- if (c->log_file == NULL)
- {
- if (c->log_file_err)
+ /* look for a connection to close! */
+ while (perpeer_count >= MAX_PEERLOG_COUNT)
{
- syslog(LOG_CRIT, "logging system can not open %s: %s"
- , c->log_file_name, strerror(errno));
- c->log_file_err = TRUE;
+ /* can not be NULL because perpeer_count > 0 */
+ passert(TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list);
+
+ perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
}
- return;
- }
-
- /* look for a connection to close! */
- while (perpeer_count >= MAX_PEERLOG_COUNT)
- {
- /* can not be NULL because perpeer_count > 0 */
- passert(TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list);
-
- perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
- }
-
- /* insert this into the list */
- TAILQ_INSERT_HEAD(&perpeer_list, c, log_link);
- passert(c->log_file != NULL);
- perpeer_count++;
+
+ /* insert this into the list */
+ TAILQ_INSERT_HEAD(&perpeer_list, c, log_link);
+ passert(c->log_file != NULL);
+ perpeer_count++;
}
/* log a line to cur_connection's log */
static void
peerlog(const char *prefix, const char *m)
{
- if (cur_connection == NULL)
- {
- /* we can not log it in this case. Oh well. */
- return;
- }
-
- if (cur_connection->log_file == NULL)
- {
- open_peerlog(cur_connection);
- }
-
- /* despite our attempts above, we may not be able to open the file. */
- if (cur_connection->log_file != NULL)
- {
- char datebuf[32];
- time_t n;
- struct tm *t;
-
- time(&n);
- t = localtime(&n);
-
- strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t);
- fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m);
-
- /* now move it to the front of the list */
- TAILQ_REMOVE(&perpeer_list, cur_connection, log_link);
- TAILQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link);
- }
+ if (cur_connection == NULL)
+ {
+ /* we can not log it in this case. Oh well. */
+ return;
+ }
+
+ if (cur_connection->log_file == NULL)
+ {
+ open_peerlog(cur_connection);
+ }
+
+ /* despite our attempts above, we may not be able to open the file. */
+ if (cur_connection->log_file != NULL)
+ {
+ char datebuf[32];
+ time_t n;
+ struct tm *t;
+
+ time(&n);
+ t = localtime(&n);
+
+ strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t);
+ fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m);
+
+ /* now move it to the front of the list */
+ TAILQ_REMOVE(&perpeer_list, cur_connection, log_link);
+ TAILQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link);
+ }
}
void
plog(const char *message, ...)
{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
+ va_start(args, message);
+ fmt_log(m, sizeof(m), message, args);
+ va_end(args);
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
- if (log_to_perpeer)
- peerlog("", m);
+ if (log_to_stderr)
+ fprintf(stderr, "%s\n", m);
+ if (log_to_syslog)
+ syslog(LOG_WARNING, "%s", m);
+ if (log_to_perpeer)
+ peerlog("", m);
- whack_log(RC_LOG, "~%s", m);
+ whack_log(RC_LOG, "~%s", m);
}
void
loglog(int mess_no, const char *message, ...)
{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
+ va_start(args, message);
+ fmt_log(m, sizeof(m), message, args);
+ va_end(args);
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
- if (log_to_perpeer)
- peerlog("", m);
+ if (log_to_stderr)
+ fprintf(stderr, "%s\n", m);
+ if (log_to_syslog)
+ syslog(LOG_WARNING, "%s", m);
+ if (log_to_perpeer)
+ peerlog("", m);
- whack_log(mess_no, "~%s", m);
+ whack_log(mess_no, "~%s", m);
}
void
log_errno_routine(int e, const char *message, ...)
{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
- if (log_to_perpeer)
- {
- peerlog(strerror(e), m);
- }
-
- whack_log(RC_LOG_SERIOUS
- , "~ERROR: %s. Errno %d: %s", m, e, strerror(e));
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
+
+ va_start(args, message);
+ fmt_log(m, sizeof(m), message, args);
+ va_end(args);
+
+ if (log_to_stderr)
+ fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
+ if (log_to_syslog)
+ syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
+ if (log_to_perpeer)
+ {
+ peerlog(strerror(e), m);
+ }
+
+ whack_log(RC_LOG_SERIOUS
+ , "~ERROR: %s. Errno %d: %s", m, e, strerror(e));
}
void
exit_log(const char *message, ...)
{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
+ va_start(args, message);
+ fmt_log(m, sizeof(m), message, args);
+ va_end(args);
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s\n", m);
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s", m);
- if (log_to_perpeer)
- peerlog("FATAL ERROR: ", m);
+ if (log_to_stderr)
+ fprintf(stderr, "FATAL ERROR: %s\n", m);
+ if (log_to_syslog)
+ syslog(LOG_ERR, "FATAL ERROR: %s", m);
+ if (log_to_perpeer)
+ peerlog("FATAL ERROR: ", m);
- whack_log(RC_LOG_SERIOUS, "~FATAL ERROR: %s", m);
+ whack_log(RC_LOG_SERIOUS, "~FATAL ERROR: %s", m);
- exit_pluto(1);
+ exit_pluto(1);
}
void
exit_log_errno_routine(int e, const char *message, ...)
{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
+ va_start(args, message);
+ fmt_log(m, sizeof(m), message, args);
+ va_end(args);
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
- if (log_to_perpeer)
- peerlog(strerror(e), m);
+ if (log_to_stderr)
+ fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
+ if (log_to_syslog)
+ syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
+ if (log_to_perpeer)
+ peerlog(strerror(e), m);
- whack_log(RC_LOG_SERIOUS
- , "~FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
+ whack_log(RC_LOG_SERIOUS
+ , "~FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
- exit_pluto(1);
+ exit_pluto(1);
}
/* emit message to whack.
@@ -531,65 +599,65 @@ static volatile sig_atomic_t dying_breath = FALSE;
void
whack_log(int mess_no, const char *message, ...)
{
- int wfd = whack_log_fd != NULL_FD ? whack_log_fd
- : cur_state != NULL ? cur_state->st_whack_sock
- : NULL_FD;
+ int wfd = whack_log_fd != NULL_FD ? whack_log_fd
+ : cur_state != NULL ? cur_state->st_whack_sock
+ : NULL_FD;
- if (wfd != NULL_FD
+ if (wfd != NULL_FD
#ifdef DEBUG
- || dying_breath
+ || dying_breath
#endif
- )
- {
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
- int prelen = snprintf(m, sizeof(m), "%03d ", mess_no);
+ )
+ {
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
+ int prelen = snprintf(m, sizeof(m), "%03d ", mess_no);
- passert(prelen >= 0);
+ passert(prelen >= 0);
- va_start(args, message);
- fmt_log(m+prelen, sizeof(m)-prelen, message, args);
- va_end(args);
+ va_start(args, message);
+ fmt_log(m+prelen, sizeof(m)-prelen, message, args);
+ va_end(args);
#if DEBUG
- if (dying_breath)
- {
- /* status output copied to log */
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m + prelen);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m + prelen);
- if (log_to_perpeer)
- peerlog("", m);
- }
+ if (dying_breath)
+ {
+ /* status output copied to log */
+ if (log_to_stderr)
+ fprintf(stderr, "%s\n", m + prelen);
+ if (log_to_syslog)
+ syslog(LOG_WARNING, "%s", m + prelen);
+ if (log_to_perpeer)
+ peerlog("", m);
+ }
#endif
- if (wfd != NULL_FD)
- {
- /* write to whack socket, but suppress possible SIGPIPE */
- size_t len = strlen(m);
-#ifdef MSG_NOSIGNAL /* depends on version of glibc??? */
- m[len] = '\n'; /* don't need NUL, do need NL */
- (void) send(wfd, m, len + 1, MSG_NOSIGNAL);
+ if (wfd != NULL_FD)
+ {
+ /* write to whack socket, but suppress possible SIGPIPE */
+ size_t len = strlen(m);
+#ifdef MSG_NOSIGNAL /* depends on version of glibc??? */
+ m[len] = '\n'; /* don't need NUL, do need NL */
+ (void) send(wfd, m, len + 1, MSG_NOSIGNAL);
#else /* !MSG_NOSIGNAL */
- int r;
- struct sigaction act
- , oldact;
+ int r;
+ struct sigaction act
+ , oldact;
- m[len] = '\n'; /* don't need NUL, do need NL */
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0; /* no nothing */
- r = sigaction(SIGPIPE, &act, &oldact);
- passert(r == 0);
+ m[len] = '\n'; /* don't need NUL, do need NL */
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0; /* no nothing */
+ r = sigaction(SIGPIPE, &act, &oldact);
+ passert(r == 0);
- (void) write(wfd, m, len + 1);
+ (void) write(wfd, m, len + 1);
- r = sigaction(SIGPIPE, &oldact, NULL);
- passert(r == 0);
+ r = sigaction(SIGPIPE, &oldact, NULL);
+ passert(r == 0);
#endif /* !MSG_NOSIGNAL */
+ }
}
- }
}
/* Build up a diagnostic in a static buffer.
@@ -607,16 +675,16 @@ char diag_space[sizeof(diag_space)];
err_t
builddiag(const char *fmt, ...)
{
- static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
- char t[sizeof(diag_space)]; /* build result here first */
- va_list args;
-
- va_start(args, fmt);
- t[0] = '\0'; /* in case nothing terminates string */
- vsnprintf(t, sizeof(t), fmt, args);
- va_end(args);
- strcpy(diag_space, t);
- return diag_space;
+ static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
+ char t[sizeof(diag_space)]; /* build result here first */
+ va_list args;
+
+ va_start(args, fmt);
+ t[0] = '\0'; /* in case nothing terminates string */
+ vsnprintf(t, sizeof(t), fmt, args);
+ va_end(args);
+ strcpy(diag_space, t);
+ return diag_space;
}
/* Debugging message support */
@@ -626,51 +694,51 @@ builddiag(const char *fmt, ...)
void
switch_fail(int n, const char *file_str, unsigned long line_no)
{
- char buf[30];
+ char buf[30];
- snprintf(buf, sizeof(buf), "case %d unexpected", n);
- passert_fail(buf, file_str, line_no);
+ snprintf(buf, sizeof(buf), "case %d unexpected", n);
+ passert_fail(buf, file_str, line_no);
}
void
passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
- if (!dying_breath)
- {
- dying_breath = TRUE;
- show_status(TRUE, NULL);
- }
- abort(); /* exiting correctly doesn't always work */
+ /* we will get a possibly unplanned prefix. Hope it works */
+ loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
+ if (!dying_breath)
+ {
+ dying_breath = TRUE;
+ show_status(TRUE, NULL);
+ }
+ abort(); /* exiting correctly doesn't always work */
}
void
pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
+ /* we will get a possibly unplanned prefix. Hope it works */
+ loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
}
lset_t
- base_debugging = DBG_NONE, /* default to reporting nothing */
- cur_debugging = DBG_NONE;
+ base_debugging = DBG_NONE, /* default to reporting nothing */
+ cur_debugging = DBG_NONE;
void
extra_debugging(const struct connection *c)
{
- if(c == NULL)
- {
- reset_debugging();
- return;
- }
-
- if (c!= NULL && c->extra_debugging != 0)
- {
- plog("enabling for connection: %s"
- , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging));
- cur_debugging |= c->extra_debugging;
- }
+ if(c == NULL)
+ {
+ reset_debugging();
+ return;
+ }
+
+ if (c!= NULL && c->extra_debugging != 0)
+ {
+ plog("enabling for connection: %s"
+ , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging));
+ cur_debugging |= c->extra_debugging;
+ }
}
/* log a debugging message (prefixed by "| ") */
@@ -678,21 +746,21 @@ extra_debugging(const struct connection *c)
void
DBG_log(const char *message, ...)
{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
+ va_list args;
+ char m[LOG_WIDTH]; /* longer messages will be truncated */
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
+ va_start(args, message);
+ vsnprintf(m, sizeof(m), message, args);
+ va_end(args);
- (void)sanitize(m, sizeof(m));
+ (void)sanitize(m, sizeof(m));
- if (log_to_stderr)
- fprintf(stderr, "| %s\n", m);
- if (log_to_syslog)
- syslog(LOG_DEBUG, "| %s", m);
- if (log_to_perpeer)
- peerlog("| ", m);
+ if (log_to_stderr)
+ fprintf(stderr, "| %s\n", m);
+ if (log_to_syslog)
+ syslog(LOG_DEBUG, "| %s", m);
+ if (log_to_perpeer)
+ peerlog("| ", m);
}
/* dump raw bytes in hex to stderr (for lack of any better destination) */
@@ -700,82 +768,99 @@ DBG_log(const char *message, ...)
void
DBG_dump(const char *label, const void *p, size_t len)
{
-# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
-# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
- char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
- char *bp;
- const unsigned char *cp = p;
-
- bp = buf;
+# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
+# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
+ char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
+ char *bp;
+ const unsigned char *cp = p;
- if (label != NULL && label[0] != '\0')
- {
- /* Handle the label. Care must be taken to avoid buffer overrun. */
- size_t llen = strlen(label);
+ bp = buf;
- if (llen + 1 > sizeof(buf))
+ if (label != NULL && label[0] != '\0')
{
- DBG_log("%s", label);
- }
- else
- {
- strcpy(buf, label);
- if (buf[llen-1] == '\n')
- {
- buf[llen-1] = '\0'; /* get rid of newline */
- DBG_log("%s", buf);
- }
- else if (llen < DUMP_LABEL_WIDTH)
- {
- bp = buf + llen;
- }
- else
- {
- DBG_log("%s", buf);
- }
+ /* Handle the label. Care must be taken to avoid buffer overrun. */
+ size_t llen = strlen(label);
+
+ if (llen + 1 > sizeof(buf))
+ {
+ DBG_log("%s", label);
+ }
+ else
+ {
+ strcpy(buf, label);
+ if (buf[llen-1] == '\n')
+ {
+ buf[llen-1] = '\0'; /* get rid of newline */
+ DBG_log("%s", buf);
+ }
+ else if (llen < DUMP_LABEL_WIDTH)
+ {
+ bp = buf + llen;
+ }
+ else
+ {
+ DBG_log("%s", buf);
+ }
+ }
}
- }
- do {
- int i, j;
+ do {
+ int i, j;
- for (i = 0; len!=0 && i!=4; i++)
- {
- *bp++ = ' ';
- for (j = 0; len!=0 && j!=4; len--, j++)
- {
- static const char hexdig[] = "0123456789abcdef";
-
- *bp++ = ' ';
- *bp++ = hexdig[(*cp >> 4) & 0xF];
- *bp++ = hexdig[*cp & 0xF];
- cp++;
- }
- }
- *bp = '\0';
- DBG_log("%s", buf);
- bp = buf;
- } while (len != 0);
+ for (i = 0; len!=0 && i!=4; i++)
+ {
+ *bp++ = ' ';
+ for (j = 0; len!=0 && j!=4; len--, j++)
+ {
+ static const char hexdig[] = "0123456789abcdef";
+
+ *bp++ = ' ';
+ *bp++ = hexdig[(*cp >> 4) & 0xF];
+ *bp++ = hexdig[*cp & 0xF];
+ cp++;
+ }
+ }
+ *bp = '\0';
+ DBG_log("%s", buf);
+ bp = buf;
+ } while (len != 0);
# undef DUMP_LABEL_WIDTH
# undef DUMP_WIDTH
}
#endif /* DEBUG */
-void
-show_status(bool all, const char *name)
+static void show_loaded_plugins()
{
- if (all)
- {
- show_ifaces_status();
- show_myid_status();
- show_debug_status();
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
- }
- show_connections_status(all, name);
- show_states_status(all, name);
+ char buf[BUF_LEN], *plugin;
+ int len = 0;
+ enumerator_t *enumerator;
+
+ buf[0] = '\0';
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (len < BUF_LEN && enumerator->enumerate(enumerator, &plugin))
+ {
+ len += snprintf(&buf[len], BUF_LEN-len, "%s ", plugin);
+ }
+ enumerator->destroy(enumerator);
+ whack_log(RC_COMMENT, "loaded plugins: %s", buf);
+}
+
+void show_status(bool all, const char *name)
+{
+ if (all)
+ {
+ whack_log(RC_COMMENT, "Status of IKEv1 pluto daemon (strongSwan "VERSION"):");
+ show_ifaces_status();
+ show_myid_status();
+ show_loaded_plugins();
+ show_debug_status();
+ whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
+ }
+ show_connections_status(all, name);
+ show_states_status(all, name);
#ifdef KLIPS
- show_shunt_status();
+ show_shunt_status();
#endif
}
@@ -788,10 +873,10 @@ show_status(bool all, const char *name)
const char *
ip_str(const ip_address *src)
{
- static char buf[ADDRTOT_BUF];
+ static char buf[ADDRTOT_BUF];
- addrtot(src, 0, buf, sizeof(buf));
- return buf;
+ addrtot(src, 0, buf, sizeof(buf));
+ return buf;
}
/*
@@ -802,35 +887,31 @@ ip_str(const ip_address *src)
void
daily_log_reset(void)
{
- /* now perform actions */
- logged_txt_warning = FALSE;
+ /* now perform actions */
+ logged_txt_warning = FALSE;
- logged_myid_fqdn_txt_warning = FALSE;
- logged_myid_ip_txt_warning = FALSE;
- logged_myid_fqdn_key_warning = FALSE;
- logged_myid_ip_key_warning = FALSE;
+ logged_myid_fqdn_txt_warning = FALSE;
+ logged_myid_ip_txt_warning = FALSE;
+ logged_myid_fqdn_key_warning = FALSE;
+ logged_myid_ip_key_warning = FALSE;
}
void
daily_log_event(void)
{
- struct tm *ltime;
- time_t n, interval;
-
- /* attempt to schedule oneself to midnight, local time
- * do this by getting seconds in the day, and delaying
- * by 86400 - hour*3600+minutes*60+seconds.
- */
- time(&n);
- ltime = localtime(&n);
- interval = (24 * 60 * 60)
- - (ltime->tm_sec
- + ltime->tm_min * 60
- + ltime->tm_hour * 3600);
-
- event_schedule(EVENT_LOG_DAILY, interval, NULL);
-
- daily_log_reset();
+ struct tm lt;
+ time_t t, interval;
+
+ /* attempt to schedule oneself to midnight, local time
+ * do this by getting seconds in the day, and delaying
+ * by 86400 - 3600*hours - 60*minutes - seconds.
+ */
+ time(&t);
+ localtime_r(&t, &lt);
+ interval = 3600 * (24 - lt.tm_hour) - 60 * lt.tm_min - lt.tm_sec;
+
+ event_schedule(EVENT_LOG_DAILY, interval, NULL);
+ daily_log_reset();
}
/*
diff --git a/src/pluto/log.h b/src/pluto/log.h
index db0fb0202..52c01bbd4 100644
--- a/src/pluto/log.h
+++ b/src/pluto/log.h
@@ -10,8 +10,6 @@
* 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: log.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include <freeswan.h>
@@ -27,49 +25,49 @@
#ifdef DEBUG
extern void passert_fail(const char *pred_str
- , const char *file_str, unsigned long line_no) NEVER_RETURNS;
+ , const char *file_str, unsigned long line_no) NEVER_RETURNS;
extern void pexpect_log(const char *pred_str
- , const char *file_str, unsigned long line_no);
+ , const char *file_str, unsigned long line_no);
# define impossible() passert_fail("impossible", __FILE__, __LINE__)
extern void switch_fail(int n
- , const char *file_str, unsigned long line_no) NEVER_RETURNS;
+ , const char *file_str, unsigned long line_no) NEVER_RETURNS;
# define bad_case(n) switch_fail((int) n, __FILE__, __LINE__)
# define passert(pred) { \
- if (!(pred)) \
- passert_fail(#pred, __FILE__, __LINE__); \
- }
+ if (!(pred)) \
+ passert_fail(#pred, __FILE__, __LINE__); \
+ }
# define pexpect(pred) { \
- if (!(pred)) \
- pexpect_log(#pred, __FILE__, __LINE__); \
- }
+ if (!(pred)) \
+ pexpect_log(#pred, __FILE__, __LINE__); \
+ }
/* assert that an err_t is NULL; evaluate exactly once */
# define happy(x) { \
- err_t ugh = x; \
- if (ugh != NULL) \
- passert_fail(ugh, __FILE__, __LINE__); \
- }
+ err_t ugh = x; \
+ if (ugh != NULL) \
+ passert_fail(ugh, __FILE__, __LINE__); \
+ }
#else /*!DEBUG*/
# define impossible() abort()
# define bad_case(n) abort()
-# define passert(pred) { } /* do nothing */
-# define happy(x) { (void) x; } /* evaluate non-judgementally */
+# define passert(pred) { } /* do nothing */
+# define happy(x) { (void) x; } /* evaluate non-judgementally */
#endif /*!DEBUG*/
extern bool
- log_to_stderr, /* should log go to stderr? */
- log_to_syslog, /* should log go to syslog? */
- log_to_perpeer; /* should log go to per-IP file? */
+ log_to_stderr, /* should log go to stderr? */
+ log_to_syslog, /* should log go to syslog? */
+ log_to_perpeer; /* should log go to per-IP file? */
extern const char *base_perpeer_logdir;
@@ -84,25 +82,25 @@ extern const char *base_perpeer_logdir;
* If the context provides a whack file descriptor, messages
* should be copied to it -- see whack_log()
*/
-extern int whack_log_fd; /* only set during whack_handle() */
-extern struct state *cur_state; /* current state, for diagnostics */
-extern struct connection *cur_connection; /* current connection, for diagnostics */
-extern const ip_address *cur_from; /* source of current current message */
-extern u_int16_t cur_from_port; /* host order */
+extern int whack_log_fd; /* only set during whack_handle() */
+extern struct state *cur_state; /* current state, for diagnostics */
+extern struct connection *cur_connection; /* current connection, for diagnostics */
+extern const ip_address *cur_from; /* source of current current message */
+extern u_int16_t cur_from_port; /* host order */
#ifdef DEBUG
- extern lset_t cur_debugging; /* current debugging level */
+ extern lset_t cur_debugging; /* current debugging level */
extern void extra_debugging(const struct connection *c);
# define reset_debugging() { cur_debugging = base_debugging; }
# define GLOBALS_ARE_RESET() (whack_log_fd == NULL_FD \
- && cur_state == NULL \
- && cur_connection == NULL \
- && cur_from == NULL \
- && cur_debugging == base_debugging)
+ && cur_state == NULL \
+ && cur_connection == NULL \
+ && cur_from == NULL \
+ && cur_debugging == base_debugging)
#else /*!DEBUG*/
@@ -111,40 +109,40 @@ extern u_int16_t cur_from_port; /* host order */
# define reset_debugging() { }
# define GLOBALS_ARE_RESET() (whack_log_fd == NULL_FD \
- && cur_state == NULL \
- && cur_connection == NULL \
- && cur_from == NULL)
+ && cur_state == NULL \
+ && cur_connection == NULL \
+ && cur_from == NULL)
#endif /*!DEBUG*/
#define reset_globals() { \
- whack_log_fd = NULL_FD; \
- cur_state = NULL; \
- cur_from = NULL; \
- reset_cur_connection(); \
- }
+ whack_log_fd = NULL_FD; \
+ cur_state = NULL; \
+ cur_from = NULL; \
+ reset_cur_connection(); \
+ }
#define set_cur_connection(c) { \
- cur_connection = (c); \
- extra_debugging(c); \
- }
+ cur_connection = (c); \
+ extra_debugging(c); \
+ }
#define reset_cur_connection() { \
- cur_connection = NULL; \
- reset_debugging(); \
- }
+ cur_connection = NULL; \
+ reset_debugging(); \
+ }
#define set_cur_state(s) { \
- cur_state = (s); \
- extra_debugging((s)->st_connection); \
- }
+ cur_state = (s); \
+ extra_debugging((s)->st_connection); \
+ }
#define reset_cur_state() { \
- cur_state = NULL; \
- reset_debugging(); \
- }
+ cur_state = NULL; \
+ reset_debugging(); \
+ }
extern void init_log(const char *program);
extern void close_log(void);
@@ -188,12 +186,12 @@ extern void show_status(bool all, const char *name);
* restriction is not checked in any way: violators will produce
* confusing results (without crashing!).
*/
-extern char diag_space[LOG_WIDTH]; /* output buffer, but can be occupied at call */
+extern char diag_space[LOG_WIDTH]; /* output buffer, but can be occupied at call */
extern err_t builddiag(const char *fmt, ...) PRINTF_LIKE(1);
#ifdef DEBUG
-extern lset_t base_debugging; /* bits selecting what to report */
+extern lset_t base_debugging; /* bits selecting what to report */
#define DBGP(cond) (cur_debugging & (cond))
#define DBG(cond, action) { if (DBGP(cond)) { action ; } }
@@ -204,7 +202,7 @@ extern void DBG_dump(const char *label, const void *p, size_t len);
#else /*!DEBUG*/
-#define DBG(cond, action) { } /* do nothing */
+#define DBG(cond, action) { } /* do nothing */
#endif /*!DEBUG*/
diff --git a/src/pluto/md2.c b/src/pluto/md2.c
deleted file mode 100644
index d6465477d..000000000
--- a/src/pluto/md2.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
- */
-
-/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
- rights reserved.
-
- License to copy and use this software is granted for
- non-commercial Internet Privacy-Enhanced Mail provided that it is
- identified as the "RSA Data Security, Inc. MD2 Message Digest
- Algorithm" in all material mentioning or referencing this software
- or this function.
-
- RSA Data Security, Inc. makes no representations concerning either
- the merchantability of this software or the suitability of this
- software for any particular purpose. It is provided "as is"
- without express or implied warranty of any kind.
-
- These notices must be retained in any copies of any part of this
- documentation and/or software.
- */
-
-#include "md2.h"
-
-#define HAVEMEMCOPY 1 /* use ISO C's memcpy and memset */
-
-static void MD2Transform PROTO_LIST
- ((unsigned char [16], unsigned char [16], const unsigned char [16]));
-
-#ifdef HAVEMEMCOPY
-#include <memory.h>
-#define MD2_memcpy memcpy
-#define MD2_memset memset
-#else
-#ifdef HAVEBCOPY
-#define MD2_memcpy(_a,_b,_c) memcpy((_a), (_b),(_c))
-#define MD2_memset(_a,_b,_c) memset((_a), '\0',(_c))
-#else
-static void MD2_memcpy PROTO_LIST ((POINTER, CONST_POINTER, unsigned int));
-static void MD2_memset PROTO_LIST ((POINTER, int, unsigned int));
-#endif
-#endif
-
-/* Permutation of 0..255 constructed from the digits of pi. It gives a
- "random" nonlinear byte substitution operation.
- */
-static unsigned char PI_SUBST[256] = {
- 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
- 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
- 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
- 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
- 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
- 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
- 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
- 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
- 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
- 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
- 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
- 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
- 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
- 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
- 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
- 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
- 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
- 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
-};
-
-static const unsigned char *PADDING[] = {
- (const unsigned char *)"",
- (const unsigned char *)"\001",
- (const unsigned char *)"\002\002",
- (const unsigned char *)"\003\003\003",
- (const unsigned char *)"\004\004\004\004",
- (const unsigned char *)"\005\005\005\005\005",
- (const unsigned char *)"\006\006\006\006\006\006",
- (const unsigned char *)"\007\007\007\007\007\007\007",
- (const unsigned char *)"\010\010\010\010\010\010\010\010",
- (const unsigned char *)"\011\011\011\011\011\011\011\011\011",
- (const unsigned char *)"\012\012\012\012\012\012\012\012\012\012",
- (const unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013",
- (const unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014",
- (const unsigned char *)
- "\015\015\015\015\015\015\015\015\015\015\015\015\015",
- (const unsigned char *)
- "\016\016\016\016\016\016\016\016\016\016\016\016\016\016",
- (const unsigned char *)
- "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017",
- (const unsigned char *)
- "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020"
-};
-
-/* MD2 initialization. Begins an MD2 operation, writing a new context.
- */
-void MD2Init (context)
-MD2_CTX *context; /* context */
-{
- context->count = 0;
- MD2_memset ((POINTER)context->state, 0, sizeof (context->state));
- MD2_memset
- ((POINTER)context->checksum, 0, sizeof (context->checksum));
-}
-
-/* MD2 block update operation. Continues an MD2 message-digest
- operation, processing another message block, and updating the
- context.
- */
-void MD2Update (context, input, inputLen)
-MD2_CTX *context; /* context */
-const unsigned char *input; /* input block */
-unsigned int inputLen; /* length of input block */
-{
- unsigned int i, index, partLen;
-
- /* Update number of bytes mod 16 */
- index = context->count;
- context->count = (index + inputLen) & 0xf;
-
- partLen = 16 - index;
-
- /* Transform as many times as possible.
- */
- if (inputLen >= partLen) {
- MD2_memcpy
- ((POINTER)&context->buffer[index], (CONST_POINTER)input, partLen);
- MD2Transform (context->state, context->checksum, context->buffer);
-
- for (i = partLen; i + 15 < inputLen; i += 16)
- MD2Transform (context->state, context->checksum, &input[i]);
-
- index = 0;
- }
- else
- i = 0;
-
- /* Buffer remaining input */
- MD2_memcpy
- ((POINTER)&context->buffer[index], (CONST_POINTER)&input[i],
- inputLen-i);
-}
-
-/* MD2 finalization. Ends an MD2 message-digest operation, writing the
- message digest and zeroizing the context.
- */
-void MD2Final (digest, context)
-
-unsigned char digest[16]; /* message digest */
-MD2_CTX *context; /* context */
-{
- unsigned int index, padLen;
-
- /* Pad out to multiple of 16.
- */
- index = context->count;
- padLen = 16 - index;
- MD2Update (context, PADDING[padLen], padLen);
-
- /* Extend with checksum */
- MD2Update (context, context->checksum, 16);
-
- /* Store state in digest */
- MD2_memcpy ((POINTER)digest, (POINTER)context->state, 16);
-
- /* Zeroize sensitive information.
- */
- MD2_memset ((POINTER)context, 0, sizeof (*context));
-}
-
-/* MD2 basic transformation. Transforms state and updates checksum
- based on block.
- */
-static void MD2Transform (state, checksum, block)
-unsigned char state[16];
-unsigned char checksum[16];
-const unsigned char block[16];
-{
- unsigned int i, j, t;
- unsigned char x[48];
-
- /* Form encryption block from state, block, state ^ block.
- */
- MD2_memcpy ((POINTER)x, (CONST_POINTER)state, 16);
- MD2_memcpy ((POINTER)x+16, (CONST_POINTER)block, 16);
- for (i = 0; i < 16; i++)
- x[i+32] = state[i] ^ block[i];
-
- /* Encrypt block (18 rounds).
- */
- t = 0;
- for (i = 0; i < 18; i++) {
- for (j = 0; j < 48; j++)
- t = x[j] ^= PI_SUBST[t];
- t = (t + i) & 0xff;
- }
-
- /* Save new state */
- MD2_memcpy ((POINTER)state, (POINTER)x, 16);
-
- /* Update checksum.
- */
- t = checksum[15];
- for (i = 0; i < 16; i++)
- t = checksum[i] ^= PI_SUBST[block[i] ^ t];
-
- /* Zeroize sensitive information.
- */
- MD2_memset ((POINTER)x, 0, sizeof (x));
-}
-
-#ifndef HAVEMEMCOPY
-#ifndef HAVEBCOPY
-/* Note: Replace "for loop" with standard memcpy if possible.
- */
-static void MD2_memcpy (output, input, len)
-POINTER output;
-POINTER input;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
- output[i] = input[i];
-}
-
-/* Note: Replace "for loop" with standard memset if possible.
- */
-static void MD2_memset (output, value, len)
-POINTER output;
-int value;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
- ((char *)output)[i] = (char)value;
-}
-#endif
-#endif
-
diff --git a/src/pluto/md2.h b/src/pluto/md2.h
deleted file mode 100644
index b3b48dd92..000000000
--- a/src/pluto/md2.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _GLOBAL_H_
-#define _GLOBAL_H_
-/* GLOBAL.H - RSAREF types and constants
- */
-
-/* PROTOTYPES should be set to one if and only if the compiler supports
- function argument prototyping.
- The following makes PROTOTYPES default to 0 if it has not already
- been defined with C compiler flags.
- */
-#ifndef PROTOTYPES
-#define PROTOTYPES 1
-#endif
-
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-typedef const unsigned char *CONST_POINTER;
-
-/* UINT2 defines a two byte word */
-typedef unsigned short int UINT2;
-
-/* UINT4 defines a four byte word */
-typedef unsigned long int UINT4;
-
-/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
- If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
- returns an empty list.
- */
-
-#if PROTOTYPES
-#define PROTO_LIST(list) list
-#else
-#define PROTO_LIST(list) ()
-#endif
-
-#endif
-
-/* MD2.H - header file for MD2C.C
- */
-
-/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
- rights reserved.
-
- License to copy and use this software is granted for
- non-commercial Internet Privacy-Enhanced Mail provided that it is
- identified as the "RSA Data Security, Inc. MD2 Message Digest
- Algorithm" in all material mentioning or referencing this software
- or this function.
-
- RSA Data Security, Inc. makes no representations concerning either
- the merchantability of this software or the suitability of this
- software for any particular purpose. It is provided "as is"
- without express or implied warranty of any kind.
-
- These notices must be retained in any copies of any part of this
- documentation and/or software.
- */
-
-/* MD2 context. */
-typedef struct {
- unsigned char state[16]; /* state */
- unsigned char checksum[16]; /* checksum */
- unsigned int count; /* number of bytes, modulo 16 */
- unsigned char buffer[16]; /* input buffer */
-} MD2_CTX;
-
-void MD2Init PROTO_LIST ((MD2_CTX *));
-void MD2Update PROTO_LIST
- ((MD2_CTX *, const unsigned char *, unsigned int));
-void MD2Final PROTO_LIST ((unsigned char [16], MD2_CTX *));
-
-#define _MD2_H_
diff --git a/src/pluto/md5.c b/src/pluto/md5.c
deleted file mode 100644
index 5d75e38a4..000000000
--- a/src/pluto/md5.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic
- * changes to accomodate it in the kernel by ji.
- * Minor changes to make 64 bit clean by Peter Onion (i.e. using u_int*_t).
- */
-
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/*
- * Additions by JI
- *
- * HAVEMEMCOPY is defined if mem* routines are available
- *
- * HAVEHTON is defined if htons() and htonl() can be used
- * for big/little endian conversions
- *
- */
-
-#include <stddef.h>
-#include <string.h>
-#include <sys/types.h> /* for u_int*_t */
-#include <endian.h> /* sets BYTE_ORDER, LITTLE_ENDIAN, and BIG_ENDIAN */
-
-#include "md5.h"
-
-#define HAVEMEMCOPY 1 /* use ISO C's memcpy and memset */
-
-/* Constants for MD5Transform routine.
- */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-#define MD5Transform _MD5Transform
-
-static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define Encode MD5_memcpy
-#define Decode MD5_memcpy
-#else
-static void Encode PROTO_LIST
- ((unsigned char *, UINT4 *, unsigned int));
-static void Decode PROTO_LIST
- ((UINT4 *, unsigned char *, unsigned int));
-#endif
-
-#ifdef HAVEMEMCOPY
-#include <memory.h>
-#define MD5_memcpy memcpy
-#define MD5_memset memset
-#else
-#ifdef HAVEBCOPY
-#define MD5_memcpy(_a,_b,_c) memcpy((_a), (_b),(_c))
-#define MD5_memset(_a,_b,_c) memset((_a), '\0',(_c))
-#else
-static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
-static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
-#endif
-#endif
-static unsigned char PADDING[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-void MD5Init (context)
-MD5_CTX *context; /* context */
-{
- context->count[0] = context->count[1] = 0;
- /* Load magic initialization constants.
-*/
- context->state[0] = 0x67452301;
- context->state[1] = 0xefcdab89;
- context->state[2] = 0x98badcfe;
- context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
- operation, processing another message block, and updating the
- context.
- */
-void MD5Update (context, input, inputLen)
-MD5_CTX *context; /* context */
-const unsigned char *input; /* input block */
-UINT4 inputLen; /* length of input block */
-{
- UINT4 i;
- unsigned int index, partLen;
-
- /* Compute number of bytes mod 64 */
- index = (unsigned int)((context->count[0] >> 3) & 0x3F);
-
- /* Update number of bits */
- if ((context->count[0] += (inputLen << 3)) < (inputLen << 3))
- context->count[1]++;
- context->count[1] += (inputLen >> 29);
-
- partLen = 64 - index;
-
- /* Transform as many times as possible. */
- if (inputLen >= partLen) {
- MD5_memcpy((POINTER)&context->buffer[index], (CONSTPOINTER)input, partLen);
- MD5Transform (context->state, context->buffer);
-
- for (i = partLen; i + 63 < inputLen; i += 64)
- MD5Transform (context->state, &input[i]);
-
- index = 0;
- }
- else
- i = 0;
-
- /* Buffer remaining input */
- MD5_memcpy((POINTER)&context->buffer[index], (CONSTPOINTER)&input[i], inputLen-i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
- the message digest and zeroizing the context.
- */
-void MD5Final (digest, context)
-unsigned char digest[16]; /* message digest */
-MD5_CTX *context; /* context */
-{
- unsigned char bits[8];
- unsigned int index, padLen;
-
- /* Save number of bits */
- Encode (bits, context->count, 8);
-
- /* Pad out to 56 mod 64.
-*/
- index = (unsigned int)((context->count[0] >> 3) & 0x3f);
- padLen = (index < 56) ? (56 - index) : (120 - index);
- MD5Update (context, PADDING, padLen);
-
- /* Append length (before padding) */
- MD5Update (context, bits, 8);
-
- if (digest != NULL) /* Bill Simpson's padding */
- {
- /* store state in digest */
- Encode (digest, context->state, 16);
-
- /* Zeroize sensitive information.
- */
- MD5_memset ((POINTER)context, 0, sizeof (*context));
- }
-}
-
-/* MD5 basic transformation. Transforms state based on block.
- */
-static void MD5Transform (state, block)
-UINT4 state[4];
-const unsigned char block[64];
-{
- UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
- Decode (x, block, 64);
-
- /* Round 1 */
- FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
- GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
- HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-
- /* Zeroize sensitive information.
-*/
- MD5_memset ((POINTER)x, 0, sizeof (x));
-}
-
-#if BYTE_ORDER != LITTLE_ENDIAN
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
- a multiple of 4.
- */
-static void Encode (output, input, len)
-unsigned char *output;
-UINT4 *input;
-unsigned int len;
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
- }
-}
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
- a multiple of 4.
- */
-static void Decode (output, input, len)
-UINT4 *output;
-unsigned char *input;
-unsigned int len;
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
- (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
-}
-
-#endif
-
-#ifndef HAVEMEMCOPY
-#ifndef HAVEBCOPY
-/* Note: Replace "for loop" with standard memcpy if possible.
- */
-
-static void MD5_memcpy (output, input, len)
-POINTER output;
-POINTER input;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
-
- output[i] = input[i];
-}
-
-/* Note: Replace "for loop" with standard memset if possible.
- */
-static void MD5_memset (output, value, len)
-POINTER output;
-int value;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
- ((char *)output)[i] = (char)value;
-}
-#endif
-#endif
-
diff --git a/src/pluto/md5.h b/src/pluto/md5.h
deleted file mode 100644
index 9b29bc46e..000000000
--- a/src/pluto/md5.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef _GLOBAL_H_
-#define _GLOBAL_H_
-/* GLOBAL.H - RSAREF types and constants
- */
-
-/* PROTOTYPES should be set to one if and only if the compiler supports
- function argument prototyping.
- The following makes PROTOTYPES default to 0 if it has not already
- been defined with C compiler flags.
- */
-#ifndef PROTOTYPES
-#define PROTOTYPES 1
-#endif
-
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-typedef const unsigned char *CONSTPOINTER;
-
-/* UINT2 defines a two byte word */
-typedef u_int16_t UINT2;
-
-/* UINT4 defines a four byte word */
-typedef u_int32_t UINT4;
-
-/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
- If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
- returns an empty list.
- */
-
-#if PROTOTYPES
-#define PROTO_LIST(list) list
-#else
-#define PROTO_LIST(list) ()
-#endif
-
-#endif
-
-/* MD5.H - header file for MD5C.C
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/* MD5 context. */
-typedef struct {
- UINT4 state[4]; /* state (ABCD) */
- UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
- unsigned char buffer[64]; /* input buffer */
-} MD5_CTX;
-
-void MD5Init PROTO_LIST ((MD5_CTX *));
-void MD5Update PROTO_LIST
- ((MD5_CTX *, const unsigned char *, UINT4));
-void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
-
-#define _MD5_H_
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
index 93624588a..228827f2a 100644
--- a/src/pluto/modecfg.c
+++ b/src/pluto/modecfg.c
@@ -2,7 +2,7 @@
* Copyright (C) 2001-2002 Colubris Networks
* Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc.
* Copyright (C) 2003-2004 Xelerance Corporation
- * Copyright (C) 2006-2007 Andreas Steffen - Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2006-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -14,8 +14,6 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: modecfg.c 3738 2008-04-02 19:04:45Z andreas $
- *
* This code originally written by Colubris Networks, Inc.
* Extraction of patch and porting to 1.99 codebases by Xelerance Corporation
* Porting to 2.x by Sean Mathews
@@ -27,6 +25,9 @@
#include <freeswan.h>
+#include <library.h>
+#include <crypto/prfs/prf.h>
+
#include "constants.h"
#include "defs.h"
#include "state.h"
@@ -34,21 +35,23 @@
#include "timer.h"
#include "ipsec_doi.h"
#include "log.h"
-#include "md5.h"
-#include "sha1.h"
#include "crypto.h"
#include "modecfg.h"
#include "whack.h"
#include "xauth.h"
-#define MAX_XAUTH_TRIES 3
+#define MAX_XAUTH_TRIES 3
+#define DNS_SERVER_MAX 2
+#define NBNS_SERVER_MAX 2
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
- | LELEM(INTERNAL_IP4_NETMASK) \
- | LELEM(INTERNAL_IP4_DNS) \
- | LELEM(INTERNAL_IP4_NBNS) \
- | LELEM(APPLICATION_VERSION) \
- )
+ | LELEM(INTERNAL_IP4_NETMASK) \
+ | LELEM(INTERNAL_IP4_DNS) \
+ | LELEM(INTERNAL_IP4_NBNS) \
+ | LELEM(APPLICATION_VERSION) \
+ | LELEM(INTERNAL_IP6_DNS) \
+ | LELEM(INTERNAL_IP6_NBNS) \
+ )
#define SUPPORTED_UNITY_ATTR_SET ( LELEM(UNITY_BANNER - UNITY_BASE) )
@@ -61,21 +64,21 @@ typedef struct internal_addr internal_addr_t;
struct internal_addr
{
- lset_t attr_set;
- lset_t xauth_attr_set;
- lset_t unity_attr_set;
+ lset_t attr_set;
+ lset_t xauth_attr_set;
+ lset_t unity_attr_set;
- /* ModeCfg variables */
- ip_address ipaddr;
- ip_address dns[2];
- ip_address wins[2];
+ /* ModeCfg variables */
+ ip_address ipaddr;
+ ip_address dns[DNS_SERVER_MAX];
+ ip_address nbns[NBNS_SERVER_MAX];
- char *unity_banner;
+ char *unity_banner;
- /* XAUTH variables */
- u_int16_t xauth_type;
- xauth_t xauth_secret;
- bool xauth_status;
+ /* XAUTH variables */
+ u_int16_t xauth_type;
+ xauth_t xauth_secret;
+ bool xauth_status;
};
/*
@@ -84,20 +87,30 @@ struct internal_addr
static void
init_internal_addr(internal_addr_t *ia)
{
- ia->attr_set = LEMPTY;
- ia->xauth_attr_set = LEMPTY;
- ia->xauth_secret.user_name = empty_chunk;
- ia->xauth_secret.user_password = empty_chunk;
- ia->xauth_type = XAUTH_TYPE_GENERIC;
- ia->xauth_status = XAUTH_STATUS_FAIL;
- ia->unity_attr_set = LEMPTY;
- ia->unity_banner = NULL;
-
- anyaddr(AF_INET, &ia->ipaddr);
- anyaddr(AF_INET, &ia->dns[0]);
- anyaddr(AF_INET, &ia->dns[1]);
- anyaddr(AF_INET, &ia->wins[0]);
- anyaddr(AF_INET, &ia->wins[1]);
+ int i;
+
+ ia->attr_set = LEMPTY;
+ ia->xauth_attr_set = LEMPTY;
+ ia->xauth_secret.user_name = chunk_empty;
+ ia->xauth_secret.user_password = chunk_empty;
+ ia->xauth_type = XAUTH_TYPE_GENERIC;
+ ia->xauth_status = XAUTH_STATUS_FAIL;
+ ia->unity_attr_set = LEMPTY;
+ ia->unity_banner = NULL;
+
+ anyaddr(AF_INET, &ia->ipaddr);
+
+ /* initialize DNS server information */
+ for (i = 0; i < DNS_SERVER_MAX; i++)
+ {
+ anyaddr(AF_INET, &ia->dns[i]);
+ }
+
+ /* initialize WINS server information */
+ for (i = 0; i < NBNS_SERVER_MAX; i++)
+ {
+ anyaddr(AF_INET, &ia->nbns[i]);
+ }
}
/*
@@ -106,97 +119,152 @@ init_internal_addr(internal_addr_t *ia)
static void
get_internal_addr(struct connection *c, internal_addr_t *ia)
{
- if (isanyaddr(&c->spd.that.host_srcip))
- {
- /* not defined in connection - fetch it from LDAP */
- }
- else
- {
- char srcip[ADDRTOT_BUF];
-
- ia->ipaddr = c->spd.that.host_srcip;
-
- addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
- plog("assigning virtual IP source address %s", srcip);
- }
-
- if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
- {
- c->spd.that.client.addr = ia->ipaddr;
- c->spd.that.client.maskbits = 32;
- c->spd.that.has_client = TRUE;
-
- ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS)
- | LELEM(INTERNAL_IP4_NETMASK);
- }
-
- if (!isanyaddr(&ia->dns[0])) /* We got DNS addresses, send them */
- ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
-
- if (!isanyaddr(&ia->wins[0])) /* We got WINS addresses, send them */
- ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ int i, dns_idx = 0, nbns_idx = 0;
+
+ if (isanyaddr(&c->spd.that.host_srcip))
+ {
+ /* not defined in connection - fetch it from LDAP */
+ }
+ else
+ {
+ char srcip[ADDRTOT_BUF];
+
+ ia->ipaddr = c->spd.that.host_srcip;
+
+ addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
+ plog("assigning virtual IP source address %s", srcip);
+ }
+
+ if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
+ {
+ c->spd.that.client.addr = ia->ipaddr;
+ c->spd.that.client.maskbits = 32;
+ c->spd.that.has_client = TRUE;
+
+ ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS)
+ | LELEM(INTERNAL_IP4_NETMASK);
+ }
+
+ /* assign DNS servers */
+ for (i = 1; i <= DNS_SERVER_MAX; i++)
+ {
+ char dns_key[16], *dns_str;
+
+ snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i);
+ dns_str = lib->settings->get_str(lib->settings, dns_key, NULL);
+ if (dns_str)
+ {
+ err_t ugh;
+ sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET;
+
+ ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]);
+ if (ugh != NULL)
+ {
+ plog("error in DNS server address: %s", ugh);
+ continue;
+ }
+ plog("assigning DNS server %s to peer", dns_str);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
+ dns_idx++;
+ }
+ }
+
+ /* assign WINS servers */
+ for (i = 1; i <= NBNS_SERVER_MAX; i++)
+ {
+ char nbns_key[16], *nbns_str;
+
+ snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i);
+ nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL);
+ if (nbns_str)
+ {
+ err_t ugh;
+ sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET;
+
+ ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]);
+ if (ugh != NULL)
+ {
+ plog("error in WINS server address: %s", ugh);
+ continue;
+ }
+ plog("assigning NBNS server %s to peer", nbns_str);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ nbns_idx++;
+ }
+ }
}
+
/*
* Set srcip and client subnet to internal IP address
*/
static bool
set_internal_addr(struct connection *c, internal_addr_t *ia)
{
- if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
- && !isanyaddr(&ia->ipaddr))
- {
- if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
- || isanyaddr(&c->spd.this.host_srcip)
- || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr))
+ if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
+ && !isanyaddr(&ia->ipaddr))
{
- char srcip[ADDRTOT_BUF];
+ if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
+ || isanyaddr(&c->spd.this.host_srcip)
+ || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr))
+ {
+ char srcip[ADDRTOT_BUF];
- addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
- plog("setting virtual IP source address to %s", srcip);
- }
- else
- {
- char old_srcip[ADDRTOT_BUF];
- char new_srcip[ADDRTOT_BUF];
+ addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
+ plog("setting virtual IP source address to %s", srcip);
+ }
+ else
+ {
+ char old_srcip[ADDRTOT_BUF];
+ char new_srcip[ADDRTOT_BUF];
- addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip));
- addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip));
- plog("replacing virtual IP source address %s by %s"
- , old_srcip, new_srcip);
+ addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip));
+ addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip));
+ plog("replacing virtual IP source address %s by %s"
+ , old_srcip, new_srcip);
+ }
+
+ /* setting srcip */
+ c->spd.this.host_srcip = ia->ipaddr;
+
+ /* setting client subnet to srcip/32 */
+ addrtosubnet(&ia->ipaddr, &c->spd.this.client);
+ setportof(0, &c->spd.this.client.addr);
+ c->spd.this.has_client = TRUE;
+ return TRUE;
}
-
- /* setting srcip */
- c->spd.this.host_srcip = ia->ipaddr;
-
- /* setting client subnet to srcip/32 */
- addrtosubnet(&ia->ipaddr, &c->spd.this.client);
- setportof(0, &c->spd.this.client.addr);
- c->spd.this.has_client = TRUE;
- return TRUE;
- }
- return FALSE;
+ return FALSE;
}
/*
* Compute HASH of Mode Config.
*/
-static size_t
-modecfg_hash(u_char *dest, const u_char *start, const u_char *roof
- , const struct state *st)
+static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
+ const struct state *st)
{
- struct hmac_ctx ctx;
-
- hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
- hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid));
- hmac_update(&ctx, start, roof-start);
- hmac_final(dest, &ctx);
-
- DBG(DBG_CRYPT,
- DBG_log("ModeCfg HASH computed:");
- DBG_dump("", dest, ctx.hmac_digest_size)
- )
- return ctx.hmac_digest_size;
+ chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
+ chunk_t msg_chunk = { start, roof - start };
+ size_t prf_block_size;
+ pseudo_random_function_t prf_alg;
+ prf_t *prf;
+
+ prf_alg = oakley_to_prf(st->st_oakley.hash);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ prf->set_key(prf, st->st_skeyid_a);
+ prf->get_bytes(prf, msgid_chunk, NULL);
+ prf->get_bytes(prf, msg_chunk, dest);
+ prf_block_size = prf->get_block_size(prf);
+ prf->destroy(prf);
+
+ DBG(DBG_CRYPT,
+ DBG_log("ModeCfg HASH computed:");
+ DBG_dump("", dest, prf_block_size)
+ )
+ return prf_block_size;
}
@@ -205,202 +273,222 @@ modecfg_hash(u_char *dest, const u_char *start, const u_char *roof
*/
static stf_status
modecfg_build_msg(struct state *st, pb_stream *rbody
- , u_int16_t msg_type
- , internal_addr_t *ia
- , u_int16_t ap_id)
+ , u_int16_t msg_type
+ , internal_addr_t *ia
+ , u_int16_t ap_id)
{
- u_char *r_hash_start, *r_hashval;
+ u_char *r_hash_start, *r_hashval;
- START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR);
+ START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR);
- /* ATTR out */
- {
- struct isakmp_mode_attr attrh;
- struct isakmp_attribute attr;
- pb_stream strattr,attrval;
- int attr_type;
- int dns_idx, wins_idx;
- bool dont_advance;
- bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
- bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
- lset_t attr_set = ia->attr_set;
-
- attrh.isama_np = ISAKMP_NEXT_NONE;
- attrh.isama_type = msg_type;
- attrh.isama_identifier = ap_id;
-
- if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
- return STF_INTERNAL_ERROR;
-
- attr_type = 0;
- dns_idx = 0;
- wins_idx = 0;
-
- while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set)
+ /* ATTR out */
{
- if (attr_set == LEMPTY)
- {
- if (is_xauth_attr_set)
- {
- attr_set = ia->xauth_attr_set;
- attr_type = XAUTH_BASE;
- is_xauth_attr_set = FALSE;
- }
- else
+ struct isakmp_mode_attr attrh;
+ struct isakmp_attribute attr;
+ pb_stream strattr,attrval;
+ int attr_type, dns_attr_type, nbns_attr_type;
+ int dns_idx, nbns_idx;
+ bool dont_advance;
+ bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
+ bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
+ lset_t attr_set = ia->attr_set;
+
+ attrh.isama_np = ISAKMP_NEXT_NONE;
+ attrh.isama_type = msg_type;
+ attrh.isama_identifier = ap_id;
+
+ if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
{
- attr_set = ia->unity_attr_set;
- attr_type = UNITY_BASE;
- is_unity_attr_set = FALSE;
+ return STF_INTERNAL_ERROR;
}
- }
-
- dont_advance = FALSE;
+ attr_type = 0;
+ dns_idx = 0;
+ nbns_idx = 0;
- if (attr_set & 1)
- {
- const u_char *byte_ptr;
- u_int len;
-
- /* ISAKMP attr out */
- if (attr_type == XAUTH_TYPE)
- {
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = ia->xauth_type;
- }
- else if (attr_type == XAUTH_STATUS)
+ while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set)
{
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = ia->xauth_status;
- }
- else
- {
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
- }
- out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
-
- switch (attr_type)
- {
- case INTERNAL_IP4_ADDRESS:
- if (!isanyaddr(&ia->ipaddr))
- {
- len = addrbytesptr(&ia->ipaddr, &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_addr");
- }
- break;
- case INTERNAL_IP4_NETMASK:
- {
- u_int mask;
-#if 0
- char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
- int t,m=st->st_connection->that.host_addr.maskbit;
- for (t=0; t<4; t++)
+ if (attr_set == LEMPTY)
{
- if (m < 8)
- mask[t] = bits[m];
- else
- mask[t] = 0xff;
- m -= 8;
+ if (is_xauth_attr_set)
+ {
+ attr_set = ia->xauth_attr_set;
+ attr_type = XAUTH_BASE;
+ is_xauth_attr_set = FALSE;
+ }
+ else
+ {
+ attr_set = ia->unity_attr_set;
+ attr_type = UNITY_BASE;
+ is_unity_attr_set = FALSE;
+ }
}
-#endif
- if (st->st_connection->spd.this.client.maskbits == 0)
- mask = 0;
- else
- mask = 0xffffffff * 1;
- out_raw(&mask, 4, &attrval, "IP4_mask");
- }
- break;
- case INTERNAL_IP4_SUBNET:
- {
- char mask[4];
- char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
- int t;
- int m = st->st_connection->spd.this.client.maskbits;
+
+ dont_advance = FALSE;
- for (t = 0; t < 4; t++)
+ if (attr_set & 1)
{
- if (m < 8)
- mask[t] = bits[m];
- else
- mask[t] = 0xff;
- m -= 8;
- if (m < 0)
- m = 0;
+ const u_char *byte_ptr;
+ u_int len;
+
+ /* ISAKMP attr out */
+ if (attr_type == XAUTH_TYPE)
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ia->xauth_type;
+ }
+ else if (attr_type == XAUTH_STATUS)
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ia->xauth_status;
+ }
+ else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx]))
+ {
+ dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ?
+ INTERNAL_IP4_DNS : INTERNAL_IP6_DNS;
+ attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV;
+
+ }
+ else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx]))
+ {
+ nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ?
+ INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS;
+ attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV;
+
+ }
+ else
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
+ }
+ out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
+
+ switch (attr_type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ if (!isanyaddr(&ia->ipaddr))
+ {
+ len = addrbytesptr(&ia->ipaddr, &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP4_addr");
+ }
+ break;
+ case INTERNAL_IP4_NETMASK:
+ {
+ u_int mask;
+#if 0
+ char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
+ int t,m=st->st_connection->that.host_addr.maskbit;
+ for (t=0; t<4; t++)
+ {
+ if (m < 8)
+ mask[t] = bits[m];
+ else
+ mask[t] = 0xff;
+ m -= 8;
+ }
+#endif
+ if (st->st_connection->spd.this.client.maskbits == 0)
+ {
+ mask = 0;
+ }
+ else
+ {
+ mask = 0xffffffff * 1;
+ out_raw(&mask, 4, &attrval, "IP4_mask");
+ }
+ }
+ break;
+ case INTERNAL_IP4_SUBNET:
+ {
+ char mask[4];
+ char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
+ int t;
+ int m = st->st_connection->spd.this.client.maskbits;
+
+ for (t = 0; t < 4; t++)
+ {
+ mask[t] = (m < 8) ? bits[m] : 0xff;
+ m -= 8;
+ if (m < 0)
+ {
+ m = 0;
+ }
+ }
+ len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP4_subnet");
+ out_raw(mask, sizeof(mask), &attrval, "IP4_submsk");
+ }
+ break;
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP6_DNS:
+ if (!isanyaddr(&ia->dns[dns_idx]))
+ {
+ len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP_dns");
+ }
+ if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx]))
+ {
+ dont_advance = TRUE;
+ }
+ break;
+ case INTERNAL_IP4_NBNS:
+ case INTERNAL_IP6_NBNS:
+ if (!isanyaddr(&ia->nbns[nbns_idx]))
+ {
+ len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP_nbns");
+ }
+ if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx]))
+ {
+ dont_advance = TRUE;
+ }
+ break;
+ case XAUTH_TYPE:
+ break;
+ case XAUTH_USER_NAME:
+ if (ia->xauth_secret.user_name.ptr != NULL)
+ {
+ out_raw(ia->xauth_secret.user_name.ptr
+ , ia->xauth_secret.user_name.len
+ , &attrval, "xauth_user_name");
+ }
+ break;
+ case XAUTH_USER_PASSWORD:
+ if (ia->xauth_secret.user_password.ptr != NULL)
+ {
+ out_raw(ia->xauth_secret.user_password.ptr
+ , ia->xauth_secret.user_password.len
+ , &attrval, "xauth_user_password");
+ }
+ break;
+ case XAUTH_STATUS:
+ break;
+ case UNITY_BANNER:
+ if (ia->unity_banner != NULL)
+ {
+ out_raw(ia->unity_banner
+ , strlen(ia->unity_banner)
+ , &attrval, "UNITY_BANNER");
+ }
+ break;
+ default:
+ plog("attempt to send unsupported mode cfg attribute %s."
+ , enum_show(&modecfg_attr_names, attr_type));
+ break;
+ }
+ close_output_pbs(&attrval);
+ }
+ if (!dont_advance)
+ {
+ attr_type++;
+ attr_set >>= 1;
}
- len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_subnet");
- out_raw(mask, sizeof(mask), &attrval, "IP4_submsk");
- }
- break;
- case INTERNAL_IP4_DNS:
- if (!isanyaddr(&ia->dns[dns_idx]))
- {
- len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_dns");
- }
- if (dns_idx < 2 && !isanyaddr(&ia->dns[dns_idx]))
- {
- dont_advance = TRUE;
- }
- break;
- case INTERNAL_IP4_NBNS:
- if (!isanyaddr(&ia->wins[wins_idx]))
- {
- len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_wins");
- }
- if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx]))
- {
- dont_advance = TRUE;
- }
- break;
- case XAUTH_TYPE:
- break;
- case XAUTH_USER_NAME:
- if (ia->xauth_secret.user_name.ptr != NULL)
- {
- out_raw(ia->xauth_secret.user_name.ptr
- , ia->xauth_secret.user_name.len
- , &attrval, "xauth_user_name");
- }
- break;
- case XAUTH_USER_PASSWORD:
- if (ia->xauth_secret.user_password.ptr != NULL)
- {
- out_raw(ia->xauth_secret.user_password.ptr
- , ia->xauth_secret.user_password.len
- , &attrval, "xauth_user_password");
- }
- break;
- case XAUTH_STATUS:
- break;
- case UNITY_BANNER:
- if (ia->unity_banner != NULL)
- {
- out_raw(ia->unity_banner
- , strlen(ia->unity_banner)
- , &attrval, "UNITY_BANNER");
- }
- break;
- default:
- plog("attempt to send unsupported mode cfg attribute %s."
- , enum_show(&modecfg_attr_names, attr_type));
- break;
}
- close_output_pbs(&attrval);
- }
- if (!dont_advance)
- {
- attr_type++;
- attr_set >>= 1;
- }
+ close_message(&strattr);
}
- close_message(&strattr);
- }
- modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
- close_message(rbody);
- encrypt_message(rbody, st);
- return STF_OK;
+ modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
+ close_message(rbody);
+ encrypt_message(rbody, st);
+ return STF_OK;
}
/*
@@ -409,55 +497,56 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
static stf_status
modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
{
- pb_stream msg;
- pb_stream rbody;
- char buf[BUF_LEN];
-
- /* set up attr */
- init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer");
-
- /* this is the beginning of a new exchange */
- st->st_msgid = generate_msgid(st);
- init_phase2_iv(st, &st->st_msgid);
-
- /* HDR out */
- {
- struct isakmp_hdr hdr;
-
- zero(&hdr); /* default to 0 */
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_HASH;
- hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
- hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- hdr.isa_msgid = st->st_msgid;
-
- if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody))
+ pb_stream msg;
+ pb_stream rbody;
+ char buf[BUF_LEN];
+
+ /* set up attr */
+ init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer");
+
+ /* this is the beginning of a new exchange */
+ st->st_msgid = generate_msgid(st);
+ init_phase2_iv(st, &st->st_msgid);
+
+ /* HDR out */
{
- return STF_INTERNAL_ERROR;
+ struct isakmp_hdr hdr;
+
+ zero(&hdr); /* default to 0 */
+ hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+ hdr.isa_np = ISAKMP_NEXT_HASH;
+ hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
+ hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
+ memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
+ memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
+ hdr.isa_msgid = st->st_msgid;
+
+ if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody))
+ {
+ return STF_INTERNAL_ERROR;
+ }
}
- }
-
- /* ATTR out */
- modecfg_build_msg(st, &rbody
- , isama_type
- , ia
- , 0 /* XXX isama_id */
- );
-
- freeanychunk(st->st_tpacket);
- clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg");
-
- /* Transmit */
- send_packet(st, "ModeCfg msg");
-
- if (st->st_event->ev_type != EVENT_RETRANSMIT)
- {
- delete_event(st);
- event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
- }
- return STF_OK;
+
+ /* ATTR out */
+ modecfg_build_msg(st, &rbody
+ , isama_type
+ , ia
+ , 0 /* XXX isama_id */
+ );
+
+ free(st->st_tpacket.ptr);
+ st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg));
+ st->st_tpacket = chunk_clone(st->st_tpacket);
+
+ /* Transmit */
+ send_packet(st, "ModeCfg msg");
+
+ if (st->st_event->ev_type != EVENT_RETRANSMIT)
+ {
+ delete_event(st);
+ event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
+ }
+ return STF_OK;
}
/*
@@ -466,111 +555,184 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
static stf_status
modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
{
- struct isakmp_attribute attr;
- pb_stream strattr;
-
- while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
- {
- u_int16_t attr_type;
- u_int16_t attr_len;
+ struct isakmp_attribute attr;
+ pb_stream strattr;
+ err_t ugh;
+ char buf[BUF_LEN];
+ int dns_idx = 0;
+ int nbns_idx = 0;
- if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
+ while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
{
- return STF_FAIL;
- }
- attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK;
- attr_len = attr.isaat_lv;
+ u_int16_t attr_type;
+ u_int16_t attr_len;
- switch (attr_type)
- {
- case INTERNAL_IP4_ADDRESS:
- if (attr_len == 4)
- {
- initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr);
- }
- /* fall through to set attribute flag */
- case INTERNAL_IP4_NETMASK:
- case INTERNAL_IP4_DNS:
- case INTERNAL_IP4_SUBNET:
- case INTERNAL_IP4_NBNS:
- case INTERNAL_ADDRESS_EXPIRY:
- case INTERNAL_IP4_DHCP:
- case INTERNAL_IP6_ADDRESS:
- case INTERNAL_IP6_NETMASK:
- case INTERNAL_IP6_DNS:
- case INTERNAL_IP6_NBNS:
- case INTERNAL_IP6_DHCP:
- case SUPPORTED_ATTRIBUTES:
- case INTERNAL_IP6_SUBNET:
- ia->attr_set |= LELEM(attr_type);
- break;
- case APPLICATION_VERSION:
- if (attr_len > 0)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", attr_len, strattr.cur)
- )
- }
- ia->attr_set |= LELEM(attr_type);
- break;
- case XAUTH_TYPE:
- ia->xauth_type = attr.isaat_lv;
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_USER_NAME:
- setchunk(ia->xauth_secret.user_name, strattr.cur, attr_len);
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_USER_PASSWORD:
- setchunk(ia->xauth_secret.user_password, strattr.cur, attr_len);
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_STATUS:
- ia->xauth_status = attr.isaat_lv;
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_MESSAGE:
- if (attr_len > 0)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", attr_len, strattr.cur)
- )
- }
- /* fall through to set attribute flag */
- case XAUTH_PASSCODE:
- case XAUTH_CHALLENGE:
- case XAUTH_DOMAIN:
- case XAUTH_NEXT_PIN:
- case XAUTH_ANSWER:
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case UNITY_DDNS_HOSTNAME:
- if (attr_len > 0)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", attr_len, strattr.cur)
- )
- }
- /* fall through to set attribute flag */
- case UNITY_BANNER:
- case UNITY_SAVE_PASSWD:
- case UNITY_DEF_DOMAIN:
- case UNITY_SPLITDNS_NAME:
- case UNITY_SPLIT_INCLUDE:
- case UNITY_NATT_PORT:
- case UNITY_LOCAL_LAN:
- case UNITY_PFS:
- case UNITY_FW_TYPE:
- case UNITY_BACKUP_SERVERS:
- ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE);
- break;
- default:
- plog("unsupported ModeCfg attribute %s received."
- , enum_show(&modecfg_attr_names, attr_type));
- break;
+ if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
+ {
+ return STF_FAIL;
+ }
+ attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK;
+ attr_len = attr.isaat_lv;
+
+ switch (attr_type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ if (attr_len == 4)
+ {
+ ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr);
+ if (ugh != NULL)
+ {
+ plog("received invalid virtual IPv4 address: %s", ugh);
+ }
+ }
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case INTERNAL_IP4_DNS:
+ if (attr_len == 4 && dns_idx < DNS_SERVER_MAX)
+ {
+ ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->dns[dns_idx]);
+ if (ugh != NULL)
+ {
+ plog("received invalid IPv4 DNS server address: %s", ugh);
+ }
+ else
+ {
+ addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN);
+ plog("received IPv4 DNS server address %s", buf);
+ dns_idx++;
+ }
+ }
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case INTERNAL_IP4_NBNS:
+ if (attr_len == 4 && nbns_idx < NBNS_SERVER_MAX)
+ {
+ ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]);
+ if (ugh != NULL)
+ {
+ plog("received invalid IPv4 WINS server address: %s", ugh);
+ }
+ else
+ {
+ addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN);
+ plog("received IPv4 WINS server address %s", buf);
+ nbns_idx++;
+ }
+ }
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case INTERNAL_IP6_DNS:
+ if (attr_len == 16 && dns_idx < DNS_SERVER_MAX)
+ {
+ ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->dns[dns_idx]);
+ if (ugh != NULL)
+ {
+ plog("received invalid IPv6 DNS server address: %s", ugh);
+ }
+ else
+ {
+ addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN);
+ plog("received IPv6 DNS server address %s", buf);
+ dns_idx++;
+ }
+ }
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case INTERNAL_IP6_NBNS:
+ if (attr_len == 16 && nbns_idx < NBNS_SERVER_MAX)
+ {
+ ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]);
+ if (ugh != NULL)
+ {
+ plog("received invalid IPv6 WINS server address: %s", ugh);
+ }
+ else
+ {
+ addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN);
+ plog("received IPv6 WINS server address %s", buf);
+ nbns_idx++;
+ }
+ }
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case INTERNAL_IP4_NETMASK:
+ case INTERNAL_IP4_SUBNET:
+ case INTERNAL_ADDRESS_EXPIRY:
+ case INTERNAL_IP4_DHCP:
+ case INTERNAL_IP6_ADDRESS:
+ case INTERNAL_IP6_NETMASK:
+ case INTERNAL_IP6_DHCP:
+ case SUPPORTED_ATTRIBUTES:
+ case INTERNAL_IP6_SUBNET:
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case APPLICATION_VERSION:
+ if (attr_len > 0)
+ {
+ DBG(DBG_PARSING,
+ DBG_log(" '%.*s'", attr_len, strattr.cur)
+ )
+ }
+ ia->attr_set |= LELEM(attr_type);
+ break;
+ case XAUTH_TYPE:
+ ia->xauth_type = attr.isaat_lv;
+ ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
+ break;
+ case XAUTH_USER_NAME:
+ ia->xauth_secret.user_name = chunk_create(strattr.cur, attr_len);
+ ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
+ break;
+ case XAUTH_USER_PASSWORD:
+ ia->xauth_secret.user_password = chunk_create(strattr.cur, attr_len);
+ ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
+ break;
+ case XAUTH_STATUS:
+ ia->xauth_status = attr.isaat_lv;
+ ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
+ break;
+ case XAUTH_MESSAGE:
+ if (attr_len > 0)
+ {
+ DBG(DBG_PARSING,
+ DBG_log(" '%.*s'", attr_len, strattr.cur)
+ )
+ }
+ /* fall through to set attribute flag */
+ case XAUTH_PASSCODE:
+ case XAUTH_CHALLENGE:
+ case XAUTH_DOMAIN:
+ case XAUTH_NEXT_PIN:
+ case XAUTH_ANSWER:
+ ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
+ break;
+ case UNITY_DDNS_HOSTNAME:
+ if (attr_len > 0)
+ {
+ DBG(DBG_PARSING,
+ DBG_log(" '%.*s'", attr_len, strattr.cur)
+ )
+ }
+ /* fall through to set attribute flag */
+ case UNITY_BANNER:
+ case UNITY_SAVE_PASSWD:
+ case UNITY_DEF_DOMAIN:
+ case UNITY_SPLITDNS_NAME:
+ case UNITY_SPLIT_INCLUDE:
+ case UNITY_NATT_PORT:
+ case UNITY_LOCAL_LAN:
+ case UNITY_PFS:
+ case UNITY_FW_TYPE:
+ case UNITY_BACKUP_SERVERS:
+ ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE);
+ break;
+ default:
+ plog("unsupported ModeCfg attribute %s received."
+ , enum_show(&modecfg_attr_names, attr_type));
+ break;
+ }
}
- }
- return STF_OK;
+ return STF_OK;
}
/*
@@ -578,50 +740,52 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
*/
static stf_status
modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
- , internal_addr_t *ia)
+ , internal_addr_t *ia)
{
- struct state *const st = md->st;
- struct payload_digest *p;
- stf_status stat;
+ struct state *const st = md->st;
+ struct payload_digest *p;
+ stf_status stat;
- st->st_msgid = md->hdr.isa_msgid;
+ st->st_msgid = md->hdr.isa_msgid;
- CHECK_QUICK_HASH(md, modecfg_hash(hash_val
- , hash_pbs->roof
- , md->message_pbs.roof, st)
- , "MODECFG-HASH", "ISAKMP_CFG_MSG");
+ CHECK_QUICK_HASH(md, modecfg_hash(hash_val
+ , hash_pbs->roof
+ , md->message_pbs.roof, st)
+ , "MODECFG-HASH", "ISAKMP_CFG_MSG");
- /* process the ModeCfg payloads received */
- for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
- {
- internal_addr_t ia_candidate;
+ /* process the ModeCfg payloads received */
+ for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
+ {
+ internal_addr_t ia_candidate;
- init_internal_addr(&ia_candidate);
+ init_internal_addr(&ia_candidate);
- if (p->payload.attribute.isama_type == isama_type)
- {
- *isama_id = p->payload.attribute.isama_identifier;
+ if (p->payload.attribute.isama_type == isama_type)
+ {
+ *isama_id = p->payload.attribute.isama_identifier;
- stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
- if (stat == STF_OK)
- {
- /* return with a valid set of attributes */
- *ia = ia_candidate;
- return STF_OK;
- }
- }
- else
- {
- plog("expected %s, got %s instead (ignored)"
- , enum_name(&attr_msg_type_names, isama_type)
- , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
+ stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
+ if (stat == STF_OK)
+ {
+ /* return with a valid set of attributes */
+ *ia = ia_candidate;
+ return STF_OK;
+ }
+ }
+ else
+ {
+ plog("expected %s, got %s instead (ignored)"
+ , enum_name(&attr_msg_type_names, isama_type)
+ , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
- stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
+ stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
+ }
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
}
- if (stat != STF_OK)
- return stat;
- }
- return STF_IGNORE;
+ return STF_IGNORE;
}
/*
@@ -630,20 +794,22 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
stf_status
modecfg_send_request(struct state *st)
{
- stf_status stat;
- internal_addr_t ia;
+ stf_status stat;
+ internal_addr_t ia;
- init_internal_addr(&ia);
+ init_internal_addr(&ia);
- ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
- | LELEM(INTERNAL_IP4_NETMASK);
+ ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
+ | LELEM(INTERNAL_IP4_NETMASK);
- plog("sending ModeCfg request");
- st->st_state = STATE_MODE_CFG_I1;
- stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
- if (stat == STF_OK)
- st->st_modecfg.started = TRUE;
- return stat;
+ plog("sending ModeCfg request");
+ st->st_state = STATE_MODE_CFG_I1;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ if (stat == STF_OK)
+ {
+ st->st_modecfg.started = TRUE;
+ }
+ return stat;
}
/* STATE_MODE_CFG_R0:
@@ -654,38 +820,40 @@ modecfg_send_request(struct state *st)
stf_status
modecfg_inR0(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- bool want_unity_banner;
- stf_status stat, stat_build;
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
-
- want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ bool want_unity_banner;
+ stf_status stat, stat_build;
- init_internal_addr(&ia);
- get_internal_addr(st->st_connection, &ia);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
- if (want_unity_banner)
- {
- ia.unity_banner = UNITY_BANNER_STR;
- ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
- }
+ want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
+ init_internal_addr(&ia);
+ get_internal_addr(st->st_connection, &ia);
- plog("sending ModeCfg reply");
+ if (want_unity_banner)
+ {
+ ia.unity_banner = UNITY_BANNER_STR;
+ ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
+ }
- stat_build = modecfg_build_msg(st, &md->rbody
- , ISAKMP_CFG_REPLY
- , &ia
- , isama_id);
- if (stat_build != STF_OK)
- return stat_build;
+ plog("sending ModeCfg reply");
- st->st_msgid = 0;
- return STF_OK;
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_REPLY
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ {
+ return stat_build;
+ }
+ st->st_msgid = 0;
+ return STF_OK;
}
/* STATE_MODE_CFG_I1:
@@ -696,20 +864,21 @@ modecfg_inR0(struct msg_digest *md)
stf_status
modecfg_inI1(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- stf_status stat;
-
- plog("parsing ModeCfg reply");
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
+ plog("parsing ModeCfg reply");
- st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
- st->st_msgid = 0;
- return STF_OK;
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
+ st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
+ st->st_msgid = 0;
+ return STF_OK;
}
@@ -719,23 +888,25 @@ modecfg_inI1(struct msg_digest *md)
stf_status
modecfg_send_set(struct state *st)
{
- stf_status stat;
- internal_addr_t ia;
+ stf_status stat;
+ internal_addr_t ia;
- init_internal_addr(&ia);
- get_internal_addr(st->st_connection, &ia);
+ init_internal_addr(&ia);
+ get_internal_addr(st->st_connection, &ia);
#ifdef CISCO_QUIRKS
- ia.unity_banner = UNITY_BANNER_STR;
- ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
+ ia.unity_banner = UNITY_BANNER_STR;
+ ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
#endif
plog("sending ModeCfg set");
- st->st_state = STATE_MODE_CFG_R3;
- stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
- if (stat == STF_OK)
- st->st_modecfg.started = TRUE;
- return stat;
+ st->st_state = STATE_MODE_CFG_R3;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
+ if (stat == STF_OK)
+ {
+ st->st_modecfg.started = TRUE;
+ }
+ return stat;
}
/* STATE_MODE_CFG_I0:
@@ -746,38 +917,40 @@ modecfg_send_set(struct state *st)
stf_status
modecfg_inI0(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- lset_t attr_set, unity_attr_set;
- stf_status stat, stat_build;
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ lset_t attr_set, unity_attr_set;
+ stf_status stat, stat_build;
- plog("parsing ModeCfg set");
+ plog("parsing ModeCfg set");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
-
- st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
-
- /* prepare ModeCfg ack which sends zero length attributes */
- attr_set = ia.attr_set;
- unity_attr_set = ia.unity_attr_set;
- init_internal_addr(&ia);
- ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
- ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET;
-
- plog("sending ModeCfg ack");
-
- stat_build = modecfg_build_msg(st, &md->rbody
- , ISAKMP_CFG_ACK
- , &ia
- , isama_id);
- if (stat_build != STF_OK)
- return stat_build;
-
- st->st_msgid = 0;
- return STF_OK;
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
+ st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
+
+ /* prepare ModeCfg ack which sends zero length attributes */
+ attr_set = ia.attr_set;
+ unity_attr_set = ia.unity_attr_set;
+ init_internal_addr(&ia);
+ ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
+ ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET;
+
+ plog("sending ModeCfg ack");
+
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_ACK
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ {
+ return stat_build;
+ }
+ st->st_msgid = 0;
+ return STF_OK;
}
/* STATE_MODE_CFG_R3:
@@ -788,19 +961,20 @@ modecfg_inI0(struct msg_digest *md)
stf_status
modecfg_inR3(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- stf_status stat;
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
- plog("parsing ModeCfg ack");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
+ plog("parsing ModeCfg ack");
- st->st_msgid = 0;
- return STF_OK;
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
+ st->st_msgid = 0;
+ return STF_OK;
}
/*
@@ -809,19 +983,21 @@ modecfg_inR3(struct msg_digest *md)
stf_status
xauth_send_request(struct state *st)
{
- stf_status stat;
- internal_addr_t ia;
-
- init_internal_addr(&ia);
- ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
- | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
-
- plog("sending XAUTH request");
- st->st_state = STATE_XAUTH_R1;
- stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
- if (stat == STF_OK)
- st->st_xauth.started = TRUE;
- return stat;
+ stf_status stat;
+ internal_addr_t ia;
+
+ init_internal_addr(&ia);
+ ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
+ | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
+
+ plog("sending XAUTH request");
+ st->st_state = STATE_XAUTH_R1;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ if (stat == STF_OK)
+ {
+ st->st_xauth.started = TRUE;
+ }
+ return stat;
}
/* STATE_XAUTH_I0:
@@ -832,97 +1008,102 @@ xauth_send_request(struct state *st)
stf_status
xauth_inI0(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- stf_status stat, stat_build;
- bool xauth_type_present;
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat, stat_build;
+ bool xauth_type_present;
- plog("parsing XAUTH request");
+ plog("parsing XAUTH request");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
-
- /* check XAUTH attributes */
- xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY;
-
- if (xauth_type_present && ia.xauth_type != XAUTH_TYPE_GENERIC)
- {
- plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
- stat = STF_FAIL;
- }
- else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
- {
- plog("user name attribute is missing in XAUTH request");
- stat = STF_FAIL;
- }
- else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
- {
- plog("user password attribute is missing in XAUTH request");
- stat = STF_FAIL;
- }
-
- /* prepare XAUTH reply */
- init_internal_addr(&ia);
-
- if (stat == STF_OK)
- {
- /* get user credentials using a plugin function */
- if (!xauth_module.get_secret(&ia.xauth_secret))
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
+ if (stat != STF_OK)
{
- plog("xauth user credentials not found");
- stat = STF_FAIL;
+ return stat;
}
- }
- if (stat == STF_OK)
- {
- DBG(DBG_CONTROL,
- DBG_log("my xauth user name is '%.*s'"
- , ia.xauth_secret.user_name.len
- , ia.xauth_secret.user_name.ptr)
- )
- DBG(DBG_PRIVATE,
- DBG_log("my xauth user password is '%.*s'"
- , ia.xauth_secret.user_password.len
- , ia.xauth_secret.user_password.ptr)
- )
- ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
- | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
- if (xauth_type_present)
- ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE);
- }
- else
- {
- ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
- ia.xauth_status = XAUTH_STATUS_FAIL;
- }
- plog("sending XAUTH reply");
+ /* check XAUTH attributes */
+ xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY;
- stat_build = modecfg_build_msg(st, &md->rbody
- , ISAKMP_CFG_REPLY
- , &ia
- , isama_id);
- if (stat_build != STF_OK)
- return stat_build;
+ if (xauth_type_present && ia.xauth_type != XAUTH_TYPE_GENERIC)
+ {
+ plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
+ stat = STF_FAIL;
+ }
+ else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
+ {
+ plog("user name attribute is missing in XAUTH request");
+ stat = STF_FAIL;
+ }
+ else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
+ {
+ plog("user password attribute is missing in XAUTH request");
+ stat = STF_FAIL;
+ }
- if (stat == STF_OK)
- {
- st->st_xauth.started = TRUE;
- st->st_msgid = 0;
- return STF_OK;
- }
- else
- {
- /* send XAUTH reply msg and then delete ISAKMP SA */
- freeanychunk(st->st_tpacket);
- clonetochunk(st->st_tpacket, md->reply.start
- , pbs_offset(&md->reply), "XAUTH reply msg");
- send_packet(st, "XAUTH reply msg");
- delete_state(st);
- return STF_IGNORE;
- }
+ /* prepare XAUTH reply */
+ init_internal_addr(&ia);
+
+ if (stat == STF_OK)
+ {
+ /* get user credentials using a plugin function */
+ if (!xauth_module.get_secret(&ia.xauth_secret))
+ {
+ plog("xauth user credentials not found");
+ stat = STF_FAIL;
+ }
+ }
+ if (stat == STF_OK)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("my xauth user name is '%.*s'"
+ , ia.xauth_secret.user_name.len
+ , ia.xauth_secret.user_name.ptr)
+ )
+ DBG(DBG_PRIVATE,
+ DBG_log("my xauth user password is '%.*s'"
+ , ia.xauth_secret.user_password.len
+ , ia.xauth_secret.user_password.ptr)
+ )
+ ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
+ | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
+ if (xauth_type_present)
+ {
+ ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE);
+ }
+ }
+ else
+ {
+ ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
+ ia.xauth_status = XAUTH_STATUS_FAIL;
+ }
+
+ plog("sending XAUTH reply");
+
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_REPLY
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ {
+ return stat_build;
+ }
+ if (stat == STF_OK)
+ {
+ st->st_xauth.started = TRUE;
+ st->st_msgid = 0;
+ return STF_OK;
+ }
+ else
+ {
+ /* send XAUTH reply msg and then delete ISAKMP SA */
+ free(st->st_tpacket.ptr);
+ st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
+ st->st_tpacket = chunk_clone(st->st_tpacket);
+ send_packet(st, "XAUTH reply msg");
+ delete_state(st);
+ return STF_IGNORE;
+ }
}
/* STATE_XAUTH_R1:
@@ -933,72 +1114,76 @@ xauth_inI0(struct msg_digest *md)
stf_status
xauth_inR1(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- stf_status stat, stat_build;
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat, stat_build;
- plog("parsing XAUTH reply");
+ plog("parsing XAUTH reply");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
-
- /* did the client return an XAUTH FAIL status? */
- if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY)
- {
- plog("received FAIL status in XAUTH reply");
-
- /* client is not able to do XAUTH, delete ISAKMP SA */
- delete_state(st);
- return STF_IGNORE;
- }
-
- /* check XAUTH reply */
- if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
- {
- plog("user name attribute is missing in XAUTH reply");
- st->st_xauth.status = FALSE;
- }
- else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
- {
- plog("user password attribute is missing in XAUTH reply");
- st->st_xauth.status = FALSE;
- }
- else
- {
- xauth_peer_t peer;
-
- peer.conn_name = st->st_connection->name;
- addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address));
- idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id));
-
- DBG(DBG_CONTROL,
- DBG_log("peer xauth user name is '%.*s'"
- , ia.xauth_secret.user_name.len
- , ia.xauth_secret.user_name.ptr)
- )
- DBG(DBG_PRIVATE,
- DBG_log("peer xauth user password is '%.*s'"
- , ia.xauth_secret.user_password.len
- , ia.xauth_secret.user_password.ptr)
- )
- /* verify the user credentials using a plugin function */
- st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret);
- plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
- }
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
+
+ /* did the client return an XAUTH FAIL status? */
+ if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY)
+ {
+ plog("received FAIL status in XAUTH reply");
+
+ /* client is not able to do XAUTH, delete ISAKMP SA */
+ delete_state(st);
+ return STF_IGNORE;
+ }
+
+ /* check XAUTH reply */
+ if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
+ {
+ plog("user name attribute is missing in XAUTH reply");
+ st->st_xauth.status = FALSE;
+ }
+ else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
+ {
+ plog("user password attribute is missing in XAUTH reply");
+ st->st_xauth.status = FALSE;
+ }
+ else
+ {
+ xauth_peer_t peer;
+
+ peer.conn_name = st->st_connection->name;
+ addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address));
+ idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id));
+
+ DBG(DBG_CONTROL,
+ DBG_log("peer xauth user name is '%.*s'"
+ , ia.xauth_secret.user_name.len
+ , ia.xauth_secret.user_name.ptr)
+ )
+ DBG(DBG_PRIVATE,
+ DBG_log("peer xauth user password is '%.*s'"
+ , ia.xauth_secret.user_password.len
+ , ia.xauth_secret.user_password.ptr)
+ )
+ /* verify the user credentials using a plugin function */
+ st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret);
+ plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
+ }
- /* prepare XAUTH set which sends the authentication status */
- init_internal_addr(&ia);
- ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
- ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
+ /* prepare XAUTH set which sends the authentication status */
+ init_internal_addr(&ia);
+ ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
+ ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
- plog("sending XAUTH status:");
+ plog("sending XAUTH status:");
- stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
- if (stat_build != STF_OK)
- return stat_build;
- return STF_OK;
+ stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
+ if (stat_build != STF_OK)
+ {
+ return stat_build;
+ }
+ return STF_OK;
}
/* STATE_XAUTH_I1:
@@ -1009,47 +1194,48 @@ xauth_inR1(struct msg_digest *md)
stf_status
xauth_inI1(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- stf_status stat, stat_build;
-
- plog("parsing XAUTH status");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
- if (stat != STF_OK)
- {
- /* notification payload - not exactly the right choice, but okay */
- md->note = ATTRIBUTES_NOT_SUPPORTED;
- return stat;
- }
-
- st->st_xauth.status = ia.xauth_status;
- plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
-
- plog("sending XAUTH ack");
- init_internal_addr(&ia);
- stat_build = modecfg_build_msg(st, &md->rbody
- , ISAKMP_CFG_ACK
- , &ia
- , isama_id);
- if (stat_build != STF_OK)
- return stat_build;
-
- if (st->st_xauth.status)
- {
- st->st_msgid = 0;
- return STF_OK;
- }
- else
- {
- /* send XAUTH ack msg and then delete ISAKMP SA */
- freeanychunk(st->st_tpacket);
- clonetochunk(st->st_tpacket, md->reply.start
- , pbs_offset(&md->reply), "XAUTH ack msg");
- send_packet(st, "XAUTH ack msg");
- delete_state(st);
- return STF_IGNORE;
- }
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat, stat_build;
+
+ plog("parsing XAUTH status");
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ /* notification payload - not exactly the right choice, but okay */
+ md->note = ATTRIBUTES_NOT_SUPPORTED;
+ return stat;
+ }
+
+ st->st_xauth.status = ia.xauth_status;
+ plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
+
+ plog("sending XAUTH ack");
+ init_internal_addr(&ia);
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_ACK
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ {
+ return stat_build;
+ }
+ if (st->st_xauth.status)
+ {
+ st->st_msgid = 0;
+ return STF_OK;
+ }
+ else
+ {
+ /* send XAUTH ack msg and then delete ISAKMP SA */
+ free(st->st_tpacket.ptr);
+ st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
+ st->st_tpacket = chunk_clone(st->st_tpacket);
+ send_packet(st, "XAUTH ack msg");
+ delete_state(st);
+ return STF_IGNORE;
+ }
}
/* STATE_XAUTH_R2:
@@ -1060,25 +1246,26 @@ xauth_inI1(struct msg_digest *md)
stf_status
xauth_inR2(struct msg_digest *md)
{
- struct state *const st = md->st;
- u_int16_t isama_id;
- internal_addr_t ia;
- stf_status stat;
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
- plog("parsing XAUTH ack");
+ plog("parsing XAUTH ack");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
- if (stat != STF_OK)
- return stat;
-
- st->st_msgid = 0;
- if (st->st_xauth.status)
- {
- return STF_OK;
- }
- else
- {
- delete_state(st);
- return STF_IGNORE;
- }
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
+ if (stat != STF_OK)
+ {
+ return stat;
+ }
+ st->st_msgid = 0;
+ if (st->st_xauth.status)
+ {
+ return STF_OK;
+ }
+ else
+ {
+ delete_state(st);
+ return STF_IGNORE;
+ }
}
diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h
index 95481de89..86bfc6ed2 100644
--- a/src/pluto/modecfg.h
+++ b/src/pluto/modecfg.h
@@ -11,8 +11,6 @@
* 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: modecfg.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _MODECFG_H
diff --git a/src/pluto/mp_defs.c b/src/pluto/mp_defs.c
deleted file mode 100644
index cdae8ee79..000000000
--- a/src/pluto/mp_defs.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* some multiprecision utilities
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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: mp_defs.c 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "mp_defs.h"
-#include "log.h"
-
-/* Convert MP_INT to network form (binary octets, big-endian).
- * We do the malloc; caller must eventually do free.
- */
-chunk_t
-mpz_to_n(const MP_INT *mp, size_t bytes)
-{
- chunk_t r;
- MP_INT temp1, temp2;
- int i;
-
- r.len = bytes;
- r.ptr = alloc_bytes(r.len, "host representation of large integer");
-
- mpz_init(&temp1);
- mpz_init(&temp2);
-
- mpz_set(&temp1, mp);
-
- for (i = r.len-1; i >= 0; i--)
- {
- r.ptr[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE);
- mpz_set(&temp1, &temp2);
- }
-
- passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */
- mpz_clear(&temp1);
- mpz_clear(&temp2);
-
- return r;
-}
-
-/* Convert network form (binary bytes, big-endian) to MP_INT.
- * The *mp must not be previously mpz_inited.
- */
-void
-n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen)
-{
- size_t i;
-
- mpz_init_set_ui(mp, 0);
-
- for (i = 0; i != nlen; i++)
- {
- mpz_mul_ui(mp, mp, 1 << BITS_PER_BYTE);
- mpz_add_ui(mp, mp, nbytes[i]);
- }
-}
diff --git a/src/pluto/mp_defs.h b/src/pluto/mp_defs.h
deleted file mode 100644
index e0ec74df8..000000000
--- a/src/pluto/mp_defs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* some multiprecision utilities
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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: mp_defs.h 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#ifndef _MP_DEFS_H
-#define _MP_DEFS_H
-
-#include <gmp.h>
-
-#include "defs.h"
-
-extern void n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen);
-extern chunk_t mpz_to_n(const MP_INT *mp, size_t bytes);
-
-/* var := mod(base ** exp, mod), ensuring var is mpz_inited */
-#define mpz_init_powm(flag, var, base, exp, mod) { \
- if (!(flag)) \
- mpz_init(&(var)); \
- (flag) = TRUE; \
- mpz_powm(&(var), &(base), &(exp), (mod)); \
- }
-
-#endif /* _MP_DEFS_H */
diff --git a/src/pluto/nat_traversal.c b/src/pluto/nat_traversal.c
index 95ce9e32e..de3972fe2 100644
--- a/src/pluto/nat_traversal.c
+++ b/src/pluto/nat_traversal.c
@@ -1,5 +1,6 @@
/* FreeS/WAN NAT-Traversal
* Copyright (C) 2002-2005 Mathieu Lafon - Arkoon Network Security
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +11,6 @@
* 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: nat_traversal.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -26,10 +25,12 @@
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include <pfkeyv2.h>
#include <pfkey.h>
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
#include "constants.h"
#include "defs.h"
#include "log.h"
@@ -42,8 +43,6 @@
#include "whack.h"
#include "timer.h"
#include "cookie.h"
-#include "sha1.h"
-#include "md5.h"
#include "crypto.h"
#include "vendor.h"
#include "ike_alg.h"
@@ -79,81 +78,91 @@ static bool _force_ka = 0;
static const char *natt_version = "0.6c";
void init_nat_traversal (bool activate, unsigned int keep_alive_period,
- bool fka, bool spf)
+ bool fka, bool spf)
{
- nat_traversal_enabled = activate;
- nat_traversal_support_non_ike = activate;
+ nat_traversal_enabled = activate;
+ nat_traversal_support_non_ike = activate;
#ifdef NAT_T_SUPPORT_LAST_DRAFTS
- nat_traversal_support_port_floating = activate ? spf : FALSE;
+ nat_traversal_support_port_floating = activate ? spf : FALSE;
#endif
- _force_ka = fka;
- _kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD;
- plog(" including NAT-Traversal patch (Version %s)%s%s%s"
- , natt_version, activate ? "" : " [disabled]"
- , activate & fka ? " [Force KeepAlive]" : ""
- , activate & !spf ? " [Port Floating disabled]" : "");
+ _force_ka = fka;
+ _kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD;
+ plog(" including NAT-Traversal patch (Version %s)%s%s%s"
+ , natt_version, activate ? "" : " [disabled]"
+ , activate & fka ? " [Force KeepAlive]" : ""
+ , activate & !spf ? " [Port Floating disabled]" : "");
}
static void disable_nat_traversal (int type)
{
- if (type == ESPINUDP_WITH_NON_IKE)
- nat_traversal_support_non_ike = FALSE;
- else
- nat_traversal_support_port_floating = FALSE;
-
- if (!nat_traversal_support_non_ike &&
- !nat_traversal_support_port_floating)
- nat_traversal_enabled = FALSE;
+ if (type == ESPINUDP_WITH_NON_IKE)
+ nat_traversal_support_non_ike = FALSE;
+ else
+ nat_traversal_support_port_floating = FALSE;
+
+ if (!nat_traversal_support_non_ike &&
+ !nat_traversal_support_port_floating)
+ nat_traversal_enabled = FALSE;
}
-static void _natd_hash(const struct hash_desc *hasher, char *hash,
- u_int8_t *icookie, u_int8_t *rcookie,
- const ip_address *ip, u_int16_t port)
+static void _natd_hash(const struct hash_desc *oakley_hasher, char *hash,
+ u_int8_t *icookie, u_int8_t *rcookie,
+ const ip_address *ip, u_int16_t port)
{
- union hash_ctx ctx;
-
- if (is_zero_cookie(icookie))
- DBG_log("_natd_hash: Warning, icookie is zero !!");
- if (is_zero_cookie(rcookie))
- DBG_log("_natd_hash: Warning, rcookie is zero !!");
-
- /**
- * draft-ietf-ipsec-nat-t-ike-01.txt
- *
- * HASH = HASH(CKY-I | CKY-R | IP | Port)
- *
- * All values in network order
- */
- hasher->hash_init(&ctx);
- hasher->hash_update(&ctx, icookie, COOKIE_SIZE);
- hasher->hash_update(&ctx, rcookie, COOKIE_SIZE);
- switch (addrtypeof(ip)) {
- case AF_INET:
- hasher->hash_update(&ctx, (const u_char *)&ip->u.v4.sin_addr.s_addr
- , sizeof(ip->u.v4.sin_addr.s_addr));
- break;
- case AF_INET6:
- hasher->hash_update(&ctx, (const u_char *)&ip->u.v6.sin6_addr.s6_addr
- , sizeof(ip->u.v6.sin6_addr.s6_addr));
- break;
- }
- hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t));
- hasher->hash_final(hash, &ctx);
-#ifdef NAT_D_DEBUG
- DBG(DBG_NATT,
- DBG_log("_natd_hash: hasher=%p(%d)", hasher, (int)hasher->hash_digest_len);
- DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE);
- DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE);
- switch (addrtypeof(ip)) {
- case AF_INET:
- DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr
- , sizeof(ip->u.v4.sin_addr.s_addr));
- break;
+ if (is_zero_cookie(icookie))
+ {
+ DBG_log("_natd_hash: Warning, icookie is zero !!");
}
- DBG_log("_natd_hash: port=%d", port);
- DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len);
- );
+ if (is_zero_cookie(rcookie))
+ {
+ DBG_log("_natd_hash: Warning, rcookie is zero !!");
+ }
+
+ /**
+ * draft-ietf-ipsec-nat-t-ike-01.txt
+ *
+ * HASH = HASH(CKY-I | CKY-R | IP | Port)
+ *
+ * All values in network order
+ */
+ {
+ chunk_t icookie_chunk = { icookie, COOKIE_SIZE };
+ chunk_t rcookie_chunk = { rcookie, COOKIE_SIZE };
+ chunk_t port_chunk = chunk_from_thing(port);
+ chunk_t addr_chunk;
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+ size_t hash_size;
+
+ hash_alg = oakley_to_hash_algorithm(oakley_hasher->algo_id);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ hasher->get_hash(hasher, icookie_chunk, NULL);
+ hasher->get_hash(hasher, rcookie_chunk, NULL);
+ switch (addrtypeof(ip))
+ {
+ case AF_INET:
+ addr_chunk = chunk_from_thing(ip->u.v4.sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ addr_chunk = chunk_from_thing(ip->u.v6.sin6_addr.s6_addr);
+ break;
+ default:
+ addr_chunk = chunk_empty; /* should never occur */
+ }
+ hasher->get_hash(hasher, addr_chunk, NULL);
+ hasher->get_hash(hasher, port_chunk, hash);
+ hash_size = hasher->get_hash_size(hasher);
+ hasher->destroy(hasher);
+#ifdef NAT_D_DEBUG
+ DBG(DBG_NATT,
+ DBG_dump_chunk("_natd_hash: icookie=", icookie_chunk);
+ DBG_dump_chunk("_natd_hash: rcookie=", rcookie_chunk);
+ DBG_dump_chunk("_natd_hash: ip=", addr_chunk);
+ DBG_log("_natd_hash: port=%d", port);
+ DBG_dump("_natd_hash: hash=", hash, hash_size);
+ )
#endif
+ }
}
/* Add NAT-Traversal VIDs (supported ones)
@@ -161,180 +170,180 @@ static void _natd_hash(const struct hash_desc *hasher, char *hash,
*/
bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs)
{
- bool r = TRUE;
-
- if (nat_traversal_support_port_floating)
- {
- u_int8_t last_np = nat_traversal_support_non_ike ?
- ISAKMP_NEXT_VID : np;
-
- if (r)
- r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_RFC);
- if (r)
- r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_03);
- if (r)
- r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_02);
- if (r)
- r = out_vendorid(last_np, outs, VID_NATT_IETF_02_N);
- }
- if (nat_traversal_support_non_ike)
- {
- if (r)
- r = out_vendorid(np, outs, VID_NATT_IETF_00);
- }
- return r;
+ bool r = TRUE;
+
+ if (nat_traversal_support_port_floating)
+ {
+ u_int8_t last_np = nat_traversal_support_non_ike ?
+ ISAKMP_NEXT_VID : np;
+
+ if (r)
+ r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_RFC);
+ if (r)
+ r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_03);
+ if (r)
+ r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_02);
+ if (r)
+ r = out_vendorid(last_np, outs, VID_NATT_IETF_02_N);
+ }
+ if (nat_traversal_support_non_ike)
+ {
+ if (r)
+ r = out_vendorid(np, outs, VID_NATT_IETF_00);
+ }
+ return r;
}
u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid)
{
- switch (nat_t_vid)
- {
- case VID_NATT_IETF_00:
- return LELEM(NAT_TRAVERSAL_IETF_00_01);
- case VID_NATT_IETF_02:
- case VID_NATT_IETF_02_N:
- case VID_NATT_IETF_03:
- return LELEM(NAT_TRAVERSAL_IETF_02_03);
- case VID_NATT_RFC:
- return LELEM(NAT_TRAVERSAL_RFC);
- }
- return 0;
+ switch (nat_t_vid)
+ {
+ case VID_NATT_IETF_00:
+ return LELEM(NAT_TRAVERSAL_IETF_00_01);
+ case VID_NATT_IETF_02:
+ case VID_NATT_IETF_02_N:
+ case VID_NATT_IETF_03:
+ return LELEM(NAT_TRAVERSAL_IETF_02_03);
+ case VID_NATT_RFC:
+ return LELEM(NAT_TRAVERSAL_RFC);
+ }
+ return 0;
}
void nat_traversal_natd_lookup(struct msg_digest *md)
{
- char hash[MAX_DIGEST_LEN];
- struct payload_digest *p;
- struct state *st = md->st;
- int i;
-
- if (!st || !md->iface || !st->st_oakley.hasher)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return;
- }
-
- /** Count NAT-D **/
- for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++);
-
- /*
- * We need at least 2 NAT-D (1 for us, many for peer)
- */
- if (i < 2)
- {
- loglog(RC_LOG_SERIOUS,
- "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negociation", i);
- st->nat_traversal = 0;
- return;
- }
-
- /*
- * First one with my IP & port
- */
- p = md->chain[ISAKMP_NEXT_NATD_RFC];
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
- &(md->iface->addr), ntohs(st->st_connection->spd.this.host_port));
-
- if (!(pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
- memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len) == 0))
- {
+ char hash[MAX_DIGEST_LEN];
+ struct payload_digest *p;
+ struct state *st = md->st;
+ int i;
+
+ if (!st || !md->iface || !st->st_oakley.hasher)
+ {
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
+ , __FILE__, __LINE__);
+ return;
+ }
+
+ /** Count NAT-D **/
+ for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++);
+
+ /*
+ * We need at least 2 NAT-D (1 for us, many for peer)
+ */
+ if (i < 2)
+ {
+ loglog(RC_LOG_SERIOUS,
+ "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negociation", i);
+ st->nat_traversal = 0;
+ return;
+ }
+
+ /*
+ * First one with my IP & port
+ */
+ p = md->chain[ISAKMP_NEXT_NATD_RFC];
+ _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
+ &(md->iface->addr), ntohs(st->st_connection->spd.this.host_port));
+
+ if (!(pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
+ memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)))
+ {
#ifdef NAT_D_DEBUG
- DBG(DBG_NATT,
- DBG_log("NAT_TRAVERSAL_NAT_BHND_ME");
- DBG_dump("expected NAT-D:", hash
- , st->st_oakley.hasher->hash_digest_len);
- DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
- )
+ DBG(DBG_NATT,
+ DBG_log("NAT_TRAVERSAL_NAT_BHND_ME");
+ DBG_dump("expected NAT-D:", hash
+ , st->st_oakley.hasher->hash_digest_len);
+ DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
+ )
#endif
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
- }
-
- /*
- * The others with sender IP & port
- */
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
- &(md->sender), ntohs(md->sender_port));
- for (p = p->next, i=0 ; p != NULL; p = p->next)
- {
- if (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
- memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len) == 0)
- {
- i++;
- }
- }
- if (!i)
- {
+ st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
+ }
+
+ /*
+ * The others with sender IP & port
+ */
+ _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
+ &(md->sender), ntohs(md->sender_port));
+ for (p = p->next, i=0 ; p != NULL; p = p->next)
+ {
+ if (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
+ memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len))
+ {
+ i++;
+ }
+ }
+ if (!i)
+ {
#ifdef NAT_D_DEBUG
- DBG(DBG_NATT,
- DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER");
- DBG_dump("expected NAT-D:", hash
- , st->st_oakley.hasher->hash_digest_len);
- p = md->chain[ISAKMP_NEXT_NATD_RFC];
- for (p = p->next, i=0 ; p != NULL; p = p->next)
- {
- DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
- }
- )
+ DBG(DBG_NATT,
+ DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER");
+ DBG_dump("expected NAT-D:", hash
+ , st->st_oakley.hasher->hash_digest_len);
+ p = md->chain[ISAKMP_NEXT_NATD_RFC];
+ for (p = p->next, i=0 ; p != NULL; p = p->next)
+ {
+ DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
+ }
+ )
#endif
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
- }
+ st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
+ }
#ifdef FORCE_NAT_TRAVERSAL
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
+ st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
+ st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
#endif
}
bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
- struct msg_digest *md)
+ struct msg_digest *md)
{
- char hash[MAX_DIGEST_LEN];
- struct state *st = md->st;
-
- if (!st || !st->st_oakley.hasher)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return FALSE;
- }
-
- DBG(DBG_EMITTING,
- DBG_log("sending NATD payloads")
- )
-
- /*
- * First one with sender IP & port
- */
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
- is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
- &(md->sender),
+ char hash[MAX_DIGEST_LEN];
+ struct state *st = md->st;
+
+ if (!st || !st->st_oakley.hasher)
+ {
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
+ , __FILE__, __LINE__);
+ return FALSE;
+ }
+
+ DBG(DBG_EMITTING,
+ DBG_log("sending NATD payloads")
+ )
+
+ /*
+ * First one with sender IP & port
+ */
+ _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
+ is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
+ &(md->sender),
#ifdef FORCE_NAT_TRAVERSAL
- 0
+ 0
#else
- ntohs(md->sender_port)
+ ntohs(md->sender_port)
#endif
- );
- if (!out_generic_raw((st->nat_traversal & NAT_T_WITH_RFC_VALUES
- ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), &isakmp_nat_d, outs,
- hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"))
- {
- return FALSE;
- }
-
- /*
- * Second one with my IP & port
- */
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
- is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
- &(md->iface->addr),
+ );
+ if (!out_generic_raw((st->nat_traversal & NAT_T_WITH_RFC_VALUES
+ ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), &isakmp_nat_d, outs,
+ hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Second one with my IP & port
+ */
+ _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
+ is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
+ &(md->iface->addr),
#ifdef FORCE_NAT_TRAVERSAL
- 0
+ 0
#else
- ntohs(st->st_connection->spd.this.host_port)
+ ntohs(st->st_connection->spd.this.host_port)
#endif
- );
- return (out_generic_raw(np, &isakmp_nat_d, outs,
- hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
+ );
+ return (out_generic_raw(np, &isakmp_nat_d, outs,
+ hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
}
/*
@@ -344,245 +353,245 @@ bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
*/
void nat_traversal_natoa_lookup(struct msg_digest *md)
{
- struct payload_digest *p;
- struct state *st = md->st;
- int i;
- ip_address ip;
-
- if (!st || !md->iface)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return;
- }
-
- /* Initialize NAT-OA */
- anyaddr(AF_INET, &st->nat_oa);
-
- /* Count NAT-OA **/
- for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++);
-
- DBG(DBG_NATT,
- DBG_log("NAT-Traversal: received %d NAT-OA.", i)
- )
-
- if (i == 0)
- return;
-
- if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)))
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
- "ignored because peer is not NATed", i);
- return;
- }
-
- if (i > 1)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
- "using first, ignoring others", i);
- }
-
- /* Take first */
- p = md->chain[ISAKMP_NEXT_NATOA_RFC];
-
- DBG(DBG_PARSING,
- DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));
- );
-
- switch (p->payload.nat_oa.isanoa_idtype)
- {
- case ID_IPV4_ADDR:
- if (pbs_left(&p->pbs) == sizeof(struct in_addr))
- {
- initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip);
- }
- else
+ struct payload_digest *p;
+ struct state *st = md->st;
+ int i;
+ ip_address ip;
+
+ if (!st || !md->iface)
{
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA "
- "with invalid IP size (%d)", (int)pbs_left(&p->pbs));
- return;
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
+ , __FILE__, __LINE__);
+ return;
}
- break;
- case ID_IPV6_ADDR:
- if (pbs_left(&p->pbs) == sizeof(struct in6_addr))
+
+ /* Initialize NAT-OA */
+ anyaddr(AF_INET, &st->nat_oa);
+
+ /* Count NAT-OA **/
+ for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++);
+
+ DBG(DBG_NATT,
+ DBG_log("NAT-Traversal: received %d NAT-OA.", i)
+ )
+
+ if (i == 0)
+ return;
+
+ if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)))
{
- initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip);
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
+ "ignored because peer is not NATed", i);
+ return;
}
- else
+
+ if (i > 1)
{
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA "
- "with invalid IP size (%d)", (int)pbs_left(&p->pbs));
- return;
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
+ "using first, ignoring others", i);
}
- break;
- default:
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
- "invalid ID Type (%d) in NAT-OA - ignored",
- p->payload.nat_oa.isanoa_idtype);
- return;
- }
- DBG(DBG_NATT,
+ /* Take first */
+ p = md->chain[ISAKMP_NEXT_NATOA_RFC];
+
+ DBG(DBG_PARSING,
+ DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));
+ );
+
+ switch (p->payload.nat_oa.isanoa_idtype)
{
- char ip_t[ADDRTOT_BUF];
- addrtot(&ip, 0, ip_t, sizeof(ip_t));
-
- DBG_log("received NAT-OA: %s", ip_t);
+ case ID_IPV4_ADDR:
+ if (pbs_left(&p->pbs) == sizeof(struct in_addr))
+ {
+ initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip);
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA "
+ "with invalid IP size (%d)", (int)pbs_left(&p->pbs));
+ return;
+ }
+ break;
+ case ID_IPV6_ADDR:
+ if (pbs_left(&p->pbs) == sizeof(struct in6_addr))
+ {
+ initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip);
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA "
+ "with invalid IP size (%d)", (int)pbs_left(&p->pbs));
+ return;
+ }
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
+ "invalid ID Type (%d) in NAT-OA - ignored",
+ p->payload.nat_oa.isanoa_idtype);
+ return;
}
- )
- if (isanyaddr(&ip))
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA...");
- else
- st->nat_oa = ip;
+ DBG(DBG_NATT,
+ {
+ char ip_t[ADDRTOT_BUF];
+ addrtot(&ip, 0, ip_t, sizeof(ip_t));
+
+ DBG_log("received NAT-OA: %s", ip_t);
+ }
+ )
+
+ if (isanyaddr(&ip))
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA...");
+ else
+ st->nat_oa = ip;
}
bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,
- struct state *st)
+ struct state *st)
{
- struct isakmp_nat_oa natoa;
- pb_stream pbs;
- unsigned char ip_val[sizeof(struct in6_addr)];
- size_t ip_len = 0;
- ip_address *ip;
-
- if ((!st) || (!st->st_connection))
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return FALSE;
- }
- ip = &(st->st_connection->spd.this.host_addr);
-
- memset(&natoa, 0, sizeof(natoa));
- natoa.isanoa_np = np;
-
- switch (addrtypeof(ip))
- {
- case AF_INET:
- ip_len = sizeof(ip->u.v4.sin_addr.s_addr);
- memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len);
- natoa.isanoa_idtype = ID_IPV4_ADDR;
- break;
- case AF_INET6:
- ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr);
- memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len);
- natoa.isanoa_idtype = ID_IPV6_ADDR;
- break;
- default:
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
- "invalid addrtypeof()=%d", addrtypeof(ip));
- return FALSE;
- }
-
- if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs))
- return FALSE;
-
- if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA"))
- return FALSE;
-
- DBG(DBG_NATT,
- DBG_dump("NAT-OA (S):", ip_val, ip_len)
- )
-
- close_output_pbs(&pbs);
- return TRUE;
+ struct isakmp_nat_oa natoa;
+ pb_stream pbs;
+ unsigned char ip_val[sizeof(struct in6_addr)];
+ size_t ip_len = 0;
+ ip_address *ip;
+
+ if ((!st) || (!st->st_connection))
+ {
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
+ , __FILE__, __LINE__);
+ return FALSE;
+ }
+ ip = &(st->st_connection->spd.this.host_addr);
+
+ memset(&natoa, 0, sizeof(natoa));
+ natoa.isanoa_np = np;
+
+ switch (addrtypeof(ip))
+ {
+ case AF_INET:
+ ip_len = sizeof(ip->u.v4.sin_addr.s_addr);
+ memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len);
+ natoa.isanoa_idtype = ID_IPV4_ADDR;
+ break;
+ case AF_INET6:
+ ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr);
+ memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len);
+ natoa.isanoa_idtype = ID_IPV6_ADDR;
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
+ "invalid addrtypeof()=%d", addrtypeof(ip));
+ return FALSE;
+ }
+
+ if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs))
+ return FALSE;
+
+ if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA"))
+ return FALSE;
+
+ DBG(DBG_NATT,
+ DBG_dump("NAT-OA (S):", ip_val, ip_len)
+ )
+
+ close_output_pbs(&pbs);
+ return TRUE;
}
void nat_traversal_show_result (u_int32_t nt, u_int16_t sport)
{
- const char *mth = NULL, *rslt = NULL;
-
- switch (nt & NAT_TRAVERSAL_METHOD)
- {
- case LELEM(NAT_TRAVERSAL_IETF_00_01):
- mth = natt_type_bitnames[0];
- break;
- case LELEM(NAT_TRAVERSAL_IETF_02_03):
- mth = natt_type_bitnames[1];
- break;
- case LELEM(NAT_TRAVERSAL_RFC):
- mth = natt_type_bitnames[2];
- break;
- }
-
- switch (nt & NAT_T_DETECTED)
- {
- case 0:
- rslt = "no NAT detected";
- break;
- case LELEM(NAT_TRAVERSAL_NAT_BHND_ME):
- rslt = "i am NATed";
- break;
- case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
- rslt = "peer is NATed";
- break;
- case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
- rslt = "both are NATed";
- break;
- }
-
- loglog(RC_LOG_SERIOUS,
- "NAT-Traversal: Result using %s: %s",
- mth ? mth : "unknown method",
- rslt ? rslt : "unknown result"
- );
-
- if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))
- && (sport == IKE_UDP_PORT)
- && ((nt & NAT_T_WITH_PORT_FLOATING)==0))
- {
+ const char *mth = NULL, *rslt = NULL;
+
+ switch (nt & NAT_TRAVERSAL_METHOD)
+ {
+ case LELEM(NAT_TRAVERSAL_IETF_00_01):
+ mth = natt_type_bitnames[0];
+ break;
+ case LELEM(NAT_TRAVERSAL_IETF_02_03):
+ mth = natt_type_bitnames[1];
+ break;
+ case LELEM(NAT_TRAVERSAL_RFC):
+ mth = natt_type_bitnames[2];
+ break;
+ }
+
+ switch (nt & NAT_T_DETECTED)
+ {
+ case 0:
+ rslt = "no NAT detected";
+ break;
+ case LELEM(NAT_TRAVERSAL_NAT_BHND_ME):
+ rslt = "i am NATed";
+ break;
+ case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
+ rslt = "peer is NATed";
+ break;
+ case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
+ rslt = "both are NATed";
+ break;
+ }
+
loglog(RC_LOG_SERIOUS,
- "Warning: peer is NATed but source port is still udp/%d. "
- "Ipsec-passthrough NAT device suspected -- NAT-T may not work.",
- IKE_UDP_PORT
+ "NAT-Traversal: Result using %s: %s",
+ mth ? mth : "unknown method",
+ rslt ? rslt : "unknown result"
);
- }
+
+ if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))
+ && (sport == IKE_UDP_PORT)
+ && ((nt & NAT_T_WITH_PORT_FLOATING)==0))
+ {
+ loglog(RC_LOG_SERIOUS,
+ "Warning: peer is NATed but source port is still udp/%d. "
+ "Ipsec-passthrough NAT device suspected -- NAT-T may not work.",
+ IKE_UDP_PORT
+ );
+ }
}
int nat_traversal_espinudp_socket (int sk, u_int32_t type)
{
- int r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type));
+ int r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type));
- if (r < 0 && errno == ENOPROTOOPT)
- {
- loglog(RC_LOG_SERIOUS,
- "NAT-Traversal: ESPINUDP(%d) not supported by kernel -- "
- "NAT-T disabled", type);
- disable_nat_traversal(type);
- }
- return r;
+ if (r < 0 && errno == ENOPROTOOPT)
+ {
+ loglog(RC_LOG_SERIOUS,
+ "NAT-Traversal: ESPINUDP(%d) not supported by kernel -- "
+ "NAT-T disabled", type);
+ disable_nat_traversal(type);
+ }
+ return r;
}
void nat_traversal_new_ka_event (void)
{
- if (_ka_evt)
- return; /* event already scheduled */
+ if (_ka_evt)
+ return; /* event already scheduled */
- event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL);
- _ka_evt = 1;
+ event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL);
+ _ka_evt = 1;
}
static void nat_traversal_send_ka (struct state *st)
{
- static unsigned char ka_payload = 0xff;
- chunk_t sav;
+ static unsigned char ka_payload = 0xff;
+ chunk_t sav;
- DBG(DBG_NATT,
- DBG_log("ka_event: send NAT-KA to %s:%d",
- ip_str(&st->st_connection->spd.that.host_addr),
- st->st_connection->spd.that.host_port);
- )
+ DBG(DBG_NATT,
+ DBG_log("ka_event: send NAT-KA to %s:%d",
+ ip_str(&st->st_connection->spd.that.host_addr),
+ st->st_connection->spd.that.host_port);
+ )
- /* save state chunk */
- setchunk(sav, st->st_tpacket.ptr, st->st_tpacket.len);
+ /* save state chunk */
+ sav = st->st_tpacket;
- /* send keep alive */
- setchunk(st->st_tpacket, &ka_payload, 1);
- send_packet(st, "NAT-T Keep Alive");
+ /* send keep alive */
+ st->st_tpacket = chunk_create(&ka_payload, 1);
+ send_packet(st, "NAT-T Keep Alive");
- /* restore state chunk */
- setchunk(st->st_tpacket, sav.ptr, sav.len);
+ /* restore state chunk */
+ st->st_tpacket = sav;
}
/**
@@ -590,277 +599,277 @@ static void nat_traversal_send_ka (struct state *st)
*/
static void nat_traversal_ka_event_state (struct state *st, void *data)
{
- unsigned int *_kap_st = (unsigned int *)data;
- const struct connection *c = st->st_connection;
-
- if (!c)
- return;
+ unsigned int *_kap_st = (unsigned int *)data;
+ const struct connection *c = st->st_connection;
- if ((st->st_state == STATE_MAIN_R3 || st->st_state == STATE_MAIN_I4)
- && (st->nat_traversal & NAT_T_DETECTED)
- && ((st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka))
- {
- /*
- * - ISAKMP established
- * - NAT-Traversal detected
- * - NAT-KeepAlive needed (we are NATed)
- */
- if (c->newest_isakmp_sa != st->st_serialno)
- {
- /*
- * if newest is also valid, ignore this one, we will only use
- * newest.
- */
- struct state *st_newest;
-
- st_newest = state_with_serialno(c->newest_isakmp_sa);
- if (st_newest
- && (st_newest->st_state == STATE_MAIN_R3 || st_newest->st_state == STATE_MAIN_I4)
- && (st_newest->nat_traversal & NAT_T_DETECTED)
- && ((st_newest->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka))
- {
+ if (!c)
return;
- }
+
+ if ((st->st_state == STATE_MAIN_R3 || st->st_state == STATE_MAIN_I4)
+ && (st->nat_traversal & NAT_T_DETECTED)
+ && ((st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka))
+ {
+ /*
+ * - ISAKMP established
+ * - NAT-Traversal detected
+ * - NAT-KeepAlive needed (we are NATed)
+ */
+ if (c->newest_isakmp_sa != st->st_serialno)
+ {
+ /*
+ * if newest is also valid, ignore this one, we will only use
+ * newest.
+ */
+ struct state *st_newest;
+
+ st_newest = state_with_serialno(c->newest_isakmp_sa);
+ if (st_newest
+ && (st_newest->st_state == STATE_MAIN_R3 || st_newest->st_state == STATE_MAIN_I4)
+ && (st_newest->nat_traversal & NAT_T_DETECTED)
+ && ((st_newest->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka))
+ {
+ return;
+ }
+ }
+ set_cur_state(st);
+ nat_traversal_send_ka(st);
+ reset_cur_state();
+ (*_kap_st)++;
}
- set_cur_state(st);
- nat_traversal_send_ka(st);
- reset_cur_state();
- (*_kap_st)++;
- }
}
void nat_traversal_ka_event (void)
{
- unsigned int _kap_st = 0;
+ unsigned int _kap_st = 0;
- _ka_evt = 0; /* ready to be reschedule */
+ _ka_evt = 0; /* ready to be reschedule */
- for_each_state((void *)nat_traversal_ka_event_state, &_kap_st);
+ for_each_state((void *)nat_traversal_ka_event_state, &_kap_st);
- /* if there are still states who needs Keep-Alive, schedule new event */
- if (_kap_st)
- nat_traversal_new_ka_event();
+ /* if there are still states who needs Keep-Alive, schedule new event */
+ if (_kap_st)
+ nat_traversal_new_ka_event();
}
struct _new_mapp_nfo {
- ip_address addr;
- u_int16_t sport, dport;
+ ip_address addr;
+ u_int16_t sport, dport;
};
static void nat_traversal_find_new_mapp_state (struct state *st, void *data)
{
- struct connection *c = st->st_connection;
- struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;
-
- if (c != NULL
- && sameaddr(&c->spd.that.host_addr, &(nfo->addr))
- && c->spd.that.host_port == nfo->sport)
- {
+ struct connection *c = st->st_connection;
+ struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;
- /* change host port */
- c->spd.that.host_port = nfo->dport;
-
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- || IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
+ if (c != NULL
+ && sameaddr(&c->spd.that.host_addr, &(nfo->addr))
+ && c->spd.that.host_port == nfo->sport)
{
- if (!update_ipsec_sa(st))
- {
- /*
- * If ipsec update failed, restore old port or we'll
- * not be able to update anymore.
- */
- c->spd.that.host_port = nfo->sport;
- }
+
+ /* change host port */
+ c->spd.that.host_port = nfo->dport;
+
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ || IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
+ {
+ if (!update_ipsec_sa(st))
+ {
+ /*
+ * If ipsec update failed, restore old port or we'll
+ * not be able to update anymore.
+ */
+ c->spd.that.host_port = nfo->sport;
+ }
+ }
}
- }
}
static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport,
- const ip_address *dst, u_int16_t dport)
+ const ip_address *dst, u_int16_t dport)
{
- char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF];
- struct _new_mapp_nfo nfo;
-
- addrtot(src, 0, srca, ADDRTOT_BUF);
- addrtot(dst, 0, dsta, ADDRTOT_BUF);
-
- if (!sameaddr(src, dst))
- {
- loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: "
- "address change currently not supported [%s:%d,%s:%d]",
- srca, sport, dsta, dport);
- return -1;
- }
-
- if (sport == dport)
- {
- /* no change */
- return 0;
- }
+ char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF];
+ struct _new_mapp_nfo nfo;
- DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport);
+ addrtot(src, 0, srca, ADDRTOT_BUF);
+ addrtot(dst, 0, dsta, ADDRTOT_BUF);
- nfo.addr = *src;
- nfo.sport = sport;
- nfo.dport = dport;
+ if (!sameaddr(src, dst))
+ {
+ loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: "
+ "address change currently not supported [%s:%d,%s:%d]",
+ srca, sport, dsta, dport);
+ return -1;
+ }
+
+ if (sport == dport)
+ {
+ /* no change */
+ return 0;
+ }
- for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo);
+ DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport);
- return 0;
+ nfo.addr = *src;
+ nfo.sport = sport;
+ nfo.dport = dport;
+
+ for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo);
+
+ return 0;
}
void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st)
{
- struct connection *c = st ? st->st_connection : NULL;
- struct iface *i = NULL;
+ struct connection *c = st ? st->st_connection : NULL;
+ struct iface *i = NULL;
- if ((st == NULL) || (c == NULL))
- return;
+ if ((st == NULL) || (c == NULL))
+ return;
- if (md)
- {
- /*
- * If source port has changed, update (including other states and
- * established kernel SA)
- */
- if (c->spd.that.host_port != md->sender_port)
+ if (md)
{
- nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
- &c->spd.that.host_addr, md->sender_port);
+ /*
+ * If source port has changed, update (including other states and
+ * established kernel SA)
+ */
+ if (c->spd.that.host_port != md->sender_port)
+ {
+ nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
+ &c->spd.that.host_addr, md->sender_port);
+ }
+
+ /*
+ * If interface type has changed, update local port (500/4500)
+ */
+ if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !md->iface->ike_float)
+ || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && md->iface->ike_float))
+ {
+ c->spd.this.host_port = (md->iface->ike_float)
+ ? NAT_T_IKE_FLOAT_PORT : pluto_port;
+
+ DBG(DBG_NATT,
+ DBG_log("NAT-T: updating local port to %d", c->spd.this.host_port);
+ );
+ }
}
/*
- * If interface type has changed, update local port (500/4500)
- */
- if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !md->iface->ike_float)
- || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && md->iface->ike_float))
- {
- c->spd.this.host_port = (md->iface->ike_float)
- ? NAT_T_IKE_FLOAT_PORT : pluto_port;
-
- DBG(DBG_NATT,
- DBG_log("NAT-T: updating local port to %d", c->spd.this.host_port);
- );
- }
- }
-
- /*
- * If we're initiator and NAT-T (with port floating) is detected, we
- * need to change port (MAIN_I3 or QUICK_I1)
- */
- if ((st->st_state == STATE_MAIN_I3 || st->st_state == STATE_QUICK_I1)
- && (st->nat_traversal & NAT_T_WITH_PORT_FLOATING)
- && (st->nat_traversal & NAT_T_DETECTED)
- && (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT))
- {
- DBG(DBG_NATT,
- DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT);
- )
- c->spd.this.host_port = NAT_T_IKE_FLOAT_PORT;
- c->spd.that.host_port = NAT_T_IKE_FLOAT_PORT;
- /*
- * Also update pending connections or they will be deleted if uniqueids
- * option is set.
+ * If we're initiator and NAT-T (with port floating) is detected, we
+ * need to change port (MAIN_I3 or QUICK_I1)
*/
- update_pending(st, st);
- }
-
- /*
- * Find valid interface according to local port (500/4500)
- */
- if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !c->interface->ike_float)
- || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && c->interface->ike_float))
- {
- for (i = interfaces; i != NULL; i = i->next)
- {
- if (sameaddr(&c->interface->addr, &i->addr)
- && i->ike_float != c->interface->ike_float)
- {
+ if ((st->st_state == STATE_MAIN_I3 || st->st_state == STATE_QUICK_I1)
+ && (st->nat_traversal & NAT_T_WITH_PORT_FLOATING)
+ && (st->nat_traversal & NAT_T_DETECTED)
+ && (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT))
+ {
DBG(DBG_NATT,
- DBG_log("NAT-T: using interface %s:%d", i->rname,
- i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port);
+ DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT);
)
- c->interface = i;
- break;
- }
+ c->spd.this.host_port = NAT_T_IKE_FLOAT_PORT;
+ c->spd.that.host_port = NAT_T_IKE_FLOAT_PORT;
+ /*
+ * Also update pending connections or they will be deleted if uniqueids
+ * option is set.
+ */
+ update_pending(st, st);
+ }
+
+ /*
+ * Find valid interface according to local port (500/4500)
+ */
+ if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !c->interface->ike_float)
+ || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && c->interface->ike_float))
+ {
+ for (i = interfaces; i != NULL; i = i->next)
+ {
+ if (sameaddr(&c->interface->addr, &i->addr)
+ && i->ike_float != c->interface->ike_float)
+ {
+ DBG(DBG_NATT,
+ DBG_log("NAT-T: using interface %s:%d", i->rname,
+ i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port);
+ )
+ c->interface = i;
+ break;
+ }
+ }
}
- }
}
struct _new_klips_mapp_nfo {
- struct sadb_sa *sa;
- ip_address src, dst;
- u_int16_t sport, dport;
+ struct sadb_sa *sa;
+ ip_address src, dst;
+ u_int16_t sport, dport;
};
static void nat_t_new_klips_mapp (struct state *st, void *data)
{
- struct connection *c = st->st_connection;
- struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;
-
- if (c != NULL && st->st_esp.present
- && sameaddr(&c->spd.that.host_addr, &(nfo->src))
- && st->st_esp.our_spi == nfo->sa->sadb_sa_spi)
- {
- nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
- &(nfo->dst), nfo->dport);
- }
+ struct connection *c = st->st_connection;
+ struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;
+
+ if (c != NULL && st->st_esp.present
+ && sameaddr(&c->spd.that.host_addr, &(nfo->src))
+ && st->st_esp.our_spi == nfo->sa->sadb_sa_spi)
+ {
+ nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
+ &(nfo->dst), nfo->dport);
+ }
}
void process_pfkey_nat_t_new_mapping(
- struct sadb_msg *msg __attribute__ ((unused)),
- struct sadb_ext *extensions[SADB_EXT_MAX + 1])
+ struct sadb_msg *msg __attribute__ ((unused)),
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- struct _new_klips_mapp_nfo nfo;
- struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
- struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
- struct sockaddr *srca, *dsta;
- err_t ugh = NULL;
-
- nfo.sa = (void *) extensions[SADB_EXT_SA];
-
- if (!nfo.sa || !srcx || !dstx)
- {
- plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: "
- "got NULL params");
- return;
- }
-
- srca = ((struct sockaddr *)(void *)&srcx[1]);
- dsta = ((struct sockaddr *)(void *)&dstx[1]);
-
- if (srca->sa_family != AF_INET || dsta->sa_family != AF_INET)
- {
- ugh = "only AF_INET supported";
- }
- else
- {
- char text_said[SATOT_BUF];
- char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF];
- ip_said said;
-
- initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr,
- sizeof(((const struct sockaddr_in *)srca)->sin_addr),
- srca->sa_family, &(nfo.src));
- nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port);
- initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr,
- sizeof(((const struct sockaddr_in *)dsta)->sin_addr),
- dsta->sa_family, &(nfo.dst));
- nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port);
+ struct _new_klips_mapp_nfo nfo;
+ struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
+ struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
+ struct sockaddr *srca, *dsta;
+ err_t ugh = NULL;
- DBG(DBG_NATT,
- initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said);
- satot(&said, 0, text_said, SATOT_BUF);
- addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF);
- addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF);
- DBG_log("new klips mapping %s %s:%d %s:%d",
- text_said, _srca, nfo.sport, _dsta, nfo.dport);
- )
+ nfo.sa = (void *) extensions[SADB_EXT_SA];
- for_each_state((void *)nat_t_new_klips_mapp, &nfo);
- }
+ if (!nfo.sa || !srcx || !dstx)
+ {
+ plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: "
+ "got NULL params");
+ return;
+ }
+
+ srca = ((struct sockaddr *)(void *)&srcx[1]);
+ dsta = ((struct sockaddr *)(void *)&dstx[1]);
+
+ if (srca->sa_family != AF_INET || dsta->sa_family != AF_INET)
+ {
+ ugh = "only AF_INET supported";
+ }
+ else
+ {
+ char text_said[SATOT_BUF];
+ char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF];
+ ip_said said;
+
+ initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr,
+ sizeof(((const struct sockaddr_in *)srca)->sin_addr),
+ srca->sa_family, &(nfo.src));
+ nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port);
+ initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr,
+ sizeof(((const struct sockaddr_in *)dsta)->sin_addr),
+ dsta->sa_family, &(nfo.dst));
+ nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port);
+
+ DBG(DBG_NATT,
+ initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said);
+ satot(&said, 0, text_said, SATOT_BUF);
+ addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF);
+ addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF);
+ DBG_log("new klips mapping %s %s:%d %s:%d",
+ text_said, _srca, nfo.sport, _dsta, nfo.dport);
+ )
+
+ for_each_state((void *)nat_t_new_klips_mapp, &nfo);
+ }
- if (ugh != NULL)
- plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh);
+ if (ugh != NULL)
+ plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh);
}
diff --git a/src/pluto/nat_traversal.h b/src/pluto/nat_traversal.h
index 9041d84de..98b0a2bc0 100644
--- a/src/pluto/nat_traversal.h
+++ b/src/pluto/nat_traversal.h
@@ -10,8 +10,6 @@
* 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: nat_traversal.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _NAT_TRAVERSAL_H
@@ -32,37 +30,37 @@
* NAT-Traversal methods which need NAT-D
*/
#define NAT_T_WITH_NATD \
- ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
+ ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
+ LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal methods which need NAT-OA
*/
#define NAT_T_WITH_NATOA \
- ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
+ ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
+ LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal methods which use NAT-KeepAlive
*/
#define NAT_T_WITH_KA \
- ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
+ ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
+ LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal methods which use floating port
*/
#define NAT_T_WITH_PORT_FLOATING \
- ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_RFC) )
+ ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal methods which use officials values (RFC)
*/
#define NAT_T_WITH_RFC_VALUES \
- ( LELEM(NAT_TRAVERSAL_RFC) )
+ ( LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal detected
*/
#define NAT_T_DETECTED \
- ( LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER) )
+ ( LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER) )
/**
* NAT-T Port Floating
@@ -70,7 +68,7 @@
#define NAT_T_IKE_FLOAT_PORT 4500
void init_nat_traversal (bool activate, unsigned int keep_alive_period,
- bool fka, bool spf);
+ bool fka, bool spf);
extern bool nat_traversal_enabled;
extern bool nat_traversal_support_non_ike;
@@ -82,7 +80,7 @@ extern bool nat_traversal_support_port_floating;
void nat_traversal_natd_lookup(struct msg_digest *md);
#ifndef PB_STREAM_UNDEFINED
bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
- struct msg_digest *md);
+ struct msg_digest *md);
#endif
/**
@@ -91,7 +89,7 @@ bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
void nat_traversal_natoa_lookup(struct msg_digest *md);
#ifndef PB_STREAM_UNDEFINED
bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,
- struct state *st);
+ struct state *st);
#endif
/**
@@ -119,8 +117,8 @@ void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st);
*/
#ifdef __PFKEY_V2_H
void process_pfkey_nat_t_new_mapping(
- struct sadb_msg *,
- struct sadb_ext *[SADB_EXT_MAX + 1]);
+ struct sadb_msg *,
+ struct sadb_ext *[SADB_EXT_MAX + 1]);
#endif
/**
@@ -133,22 +131,22 @@ nat_traversal_port_float(struct state *st, struct msg_digest *md, bool in);
* Encapsulation mode macro (see demux.c)
*/
#define NAT_T_ENCAPSULATION_MODE(st,nat_t_policy) ( \
- ((st)->nat_traversal & NAT_T_DETECTED) \
- ? ( ((nat_t_policy) & POLICY_TUNNEL) \
- ? ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \
- ? (ENCAPSULATION_MODE_UDP_TUNNEL_RFC) \
- : (ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS) \
- ) \
- : ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \
- ? (ENCAPSULATION_MODE_UDP_TRANSPORT_RFC) \
- : (ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS) \
- ) \
- ) \
- : ( ((st)->st_policy & POLICY_TUNNEL) \
- ? (ENCAPSULATION_MODE_TUNNEL) \
- : (ENCAPSULATION_MODE_TRANSPORT) \
- ) \
- )
+ ((st)->nat_traversal & NAT_T_DETECTED) \
+ ? ( ((nat_t_policy) & POLICY_TUNNEL) \
+ ? ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \
+ ? (ENCAPSULATION_MODE_UDP_TUNNEL_RFC) \
+ : (ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS) \
+ ) \
+ : ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \
+ ? (ENCAPSULATION_MODE_UDP_TRANSPORT_RFC) \
+ : (ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS) \
+ ) \
+ ) \
+ : ( ((st)->st_policy & POLICY_TUNNEL) \
+ ? (ENCAPSULATION_MODE_TUNNEL) \
+ : (ENCAPSULATION_MODE_TRANSPORT) \
+ ) \
+ )
#endif /* _NAT_TRAVERSAL_H */
diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c
index 74b86bf19..80164fa1d 100644
--- a/src/pluto/ocsp.c
+++ b/src/pluto/ocsp.c
@@ -11,8 +11,6 @@
* 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: ocsp.c 4827 2009-01-09 01:36:13Z andreas $
*/
#include <unistd.h>
@@ -24,7 +22,13 @@
#include <fcntl.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <library.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
+#include <crypto/rngs/rng.h>
+#include <crypto/hashers/hasher.h>
#include "constants.h"
#include "defs.h"
@@ -32,120 +36,116 @@
#include "x509.h"
#include "crl.h"
#include "ca.h"
-#include "rnd.h"
-#include "asn1.h"
#include "certs.h"
#include "smartcard.h"
-#include <asn1/oid.h>
#include "whack.h"
-#include "pkcs1.h"
#include "keys.h"
#include "fetch.h"
#include "ocsp.h"
-#define NONCE_LENGTH 16
+#define NONCE_LENGTH 16
static const char *const cert_status_names[] = {
- "good",
- "revoked",
- "unknown",
- "undefined"
+ "good",
+ "revoked",
+ "unknown",
+ "undefined"
};
static const char *const response_status_names[] = {
- "successful",
- "malformed request",
- "internal error",
- "try later",
- "status #4",
- "signature required",
- "unauthorized"
+ "successful",
+ "malformed request",
+ "internal error",
+ "try later",
+ "status #4",
+ "signature required",
+ "unauthorized"
};
/* response container */
typedef struct response response_t;
struct response {
- chunk_t tbs;
- chunk_t responder_id_name;
- chunk_t responder_id_key;
- time_t produced_at;
- chunk_t responses;
- chunk_t nonce;
- int algorithm;
- chunk_t signature;
+ chunk_t tbs;
+ chunk_t responder_id_name;
+ chunk_t responder_id_key;
+ time_t produced_at;
+ chunk_t responses;
+ chunk_t nonce;
+ int algorithm;
+ chunk_t signature;
};
const response_t empty_response = {
- { NULL, 0 } , /* tbs */
- { NULL, 0 } , /* responder_id_name */
- { NULL, 0 } , /* responder_id_key */
- UNDEFINED_TIME, /* produced_at */
- { NULL, 0 } , /* single_response */
- { NULL, 0 } , /* nonce */
- OID_UNKNOWN , /* signature_algorithm */
- { NULL, 0 } /* signature */
+ { NULL, 0 } , /* tbs */
+ { NULL, 0 } , /* responder_id_name */
+ { NULL, 0 } , /* responder_id_key */
+ UNDEFINED_TIME, /* produced_at */
+ { NULL, 0 } , /* single_response */
+ { NULL, 0 } , /* nonce */
+ OID_UNKNOWN , /* signature_algorithm */
+ { NULL, 0 } /* signature */
};
/* single response container */
typedef struct single_response single_response_t;
struct single_response {
- single_response_t *next;
- int hash_algorithm;
- chunk_t issuer_name_hash;
- chunk_t issuer_key_hash;
- chunk_t serialNumber;
- cert_status_t status;
- time_t revocationTime;
- crl_reason_t revocationReason;
- time_t thisUpdate;
- time_t nextUpdate;
+ single_response_t *next;
+ int hash_algorithm;
+ chunk_t issuer_name_hash;
+ chunk_t issuer_key_hash;
+ chunk_t serialNumber;
+ cert_status_t status;
+ time_t revocationTime;
+ crl_reason_t revocationReason;
+ time_t thisUpdate;
+ time_t nextUpdate;
};
const single_response_t empty_single_response = {
- NULL , /* *next */
- OID_UNKNOWN , /* hash_algorithm */
- { NULL, 0 } , /* issuer_name_hash */
- { NULL, 0 } , /* issuer_key_hash */
- { NULL, 0 } , /* serial_number */
- CERT_UNDEFINED , /* status */
- UNDEFINED_TIME , /* revocationTime */
- REASON_UNSPECIFIED, /* revocationReason */
- UNDEFINED_TIME , /* this_update */
- UNDEFINED_TIME /* next_update */
+ NULL , /* *next */
+ OID_UNKNOWN , /* hash_algorithm */
+ { NULL, 0 } , /* issuer_name_hash */
+ { NULL, 0 } , /* issuer_key_hash */
+ { NULL, 0 } , /* serial_number */
+ CERT_UNDEFINED , /* status */
+ UNDEFINED_TIME , /* revocationTime */
+ REASON_UNSPECIFIED, /* revocationReason */
+ UNDEFINED_TIME , /* this_update */
+ UNDEFINED_TIME /* next_update */
};
/* list of single requests */
typedef struct request_list request_list_t;
struct request_list {
- chunk_t request;
- request_list_t *next;
+ chunk_t request;
+ request_list_t *next;
};
/* some OCSP specific prefabricated ASN.1 constants */
static u_char ASN1_nonce_oid_str[] = {
- 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
+ 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
};
-static const chunk_t ASN1_nonce_oid = strchunk(ASN1_nonce_oid_str);
+static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str);
static u_char ASN1_response_oid_str[] = {
- 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
+ 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
};
-static const chunk_t ASN1_response_oid = strchunk(ASN1_response_oid_str);
+static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str);
static u_char ASN1_response_content_str[] = {
- 0x04, 0x0D,
- 0x30, 0x0B,
- 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
+ 0x04, 0x0D,
+ 0x30, 0x0B,
+ 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
};
-static const chunk_t ASN1_response_content = strchunk(ASN1_response_content_str);
+static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str);
/* default OCSP uri */
static chunk_t ocsp_default_uri;
@@ -158,57 +158,60 @@ static x509cert_t *ocsp_requestor_cert = NULL;
static smartcard_t *ocsp_requestor_sc = NULL;
-static const struct RSA_private_key *ocsp_requestor_pri = NULL;
-
-/* asn.1 definitions for parsing */
+static private_key_t *ocsp_requestor_key = NULL;
+/**
+ * ASN.1 definition of ocspResponse
+ */
static const asn1Object_t ocspResponseObjects[] = {
- { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
- { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
- { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
- { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
- { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */
+ { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
+ { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
+ { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
+ { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
+ { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define OCSP_RESPONSE_STATUS 1
-#define OCSP_RESPONSE_TYPE 4
-#define OCSP_RESPONSE 5
-#define OCSP_RESPONSE_ROOF 7
+#define OCSP_RESPONSE_TYPE 4
+#define OCSP_RESPONSE 5
+/**
+ * ASN.1 definition of basicResponse
+ */
static const asn1Object_t basicResponseObjects[] = {
- { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
- { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
- ASN1_DEF }, /* 2 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
- { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
- { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
- { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
- { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
- { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
- { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
- { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
- { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
- { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
- { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
- { 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
- ASN1_DEF }, /* 16 */
- { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
- { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
- { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
- { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
- { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
- { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
- { 3, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 24 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */
+ { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
+ { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
+ ASN1_DEF }, /* 2 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
+ { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
+ { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
+ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
+ { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
+ { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
+ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
+ { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
+ { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
+ { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
+ { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
+ { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
+ { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
+ { 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
+ ASN1_DEF }, /* 16 */
+ { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
+ { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
+ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
+ { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
+ { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
+ { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
+ { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */
+ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define BASIC_RESPONSE_TBS_DATA 1
#define BASIC_RESPONSE_VERSION 3
#define BASIC_RESPONSE_ID_BY_NAME 5
@@ -221,1349 +224,1326 @@ static const asn1Object_t basicResponseObjects[] = {
#define BASIC_RESPONSE_ALGORITHM 20
#define BASIC_RESPONSE_SIGNATURE 21
#define BASIC_RESPONSE_CERTIFICATE 24
-#define BASIC_RESPONSE_ROOF 27
+/**
+ * ASN.1 definition of responses
+ */
static const asn1Object_t responsesObjects[] = {
- { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
- { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
- { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */
+ { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
+ { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
+#define RESPONSES_SINGLE_RESPONSE 1
-#define RESPONSES_SINGLE_RESPONSE 1
-#define RESPONSES_ROOF 3
-
+/**
+ * ASN.1 definition of singleResponse
+ */
static const asn1Object_t singleResponseObjects[] = {
- { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */
- { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
- { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
- { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
- { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
- { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */
- { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
- { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */
- { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */
- { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */
- { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
- { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
- { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */
- { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */
- { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
- { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */
- { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */
- { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
- { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */
- { 4, "critical", ASN1_BOOLEAN, ASN1_BODY |
- ASN1_DEF }, /* 24 */
- { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 27 */
+ { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */
+ { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
+ { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
+ { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
+ { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
+ { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */
+ { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
+ { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */
+ { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */
+ { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */
+ { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
+ { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
+ { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */
+ { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */
+ { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
+ { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */
+ { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */
+ { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
+ { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */
+ { 4, "critical", ASN1_BOOLEAN, ASN1_BODY |
+ ASN1_DEF }, /* 24 */
+ { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */
+ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
-#define SINGLE_RESPONSE_ALGORITHM 2
-#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
-#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
-#define SINGLE_RESPONSE_SERIAL_NUMBER 5
-#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
-#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
+#define SINGLE_RESPONSE_ALGORITHM 2
+#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
+#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
+#define SINGLE_RESPONSE_SERIAL_NUMBER 5
+#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
+#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
-#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
-#define SINGLE_RESPONSE_THIS_UPDATE 16
-#define SINGLE_RESPONSE_NEXT_UPDATE 18
-#define SINGLE_RESPONSE_EXT_ID 23
-#define SINGLE_RESPONSE_CRITICAL 24
-#define SINGLE_RESPONSE_EXT_VALUE 25
-#define SINGLE_RESPONSE_ROOF 28
-
-/* build an ocsp location from certificate information
+#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
+#define SINGLE_RESPONSE_THIS_UPDATE 16
+#define SINGLE_RESPONSE_NEXT_UPDATE 18
+#define SINGLE_RESPONSE_EXT_ID 23
+#define SINGLE_RESPONSE_CRITICAL 24
+#define SINGLE_RESPONSE_EXT_VALUE 25
+
+/*
+ * Build an ocsp location from certificate information
* without unsharing its contents
*/
-static bool
-build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location)
+static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location)
{
- static u_char digest[SHA1_DIGEST_SIZE]; /* temporary storage */
+ hasher_t *hasher;
+ static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */
+
+ location->uri = cert->accessLocation;
- location->uri = cert->accessLocation;
+ if (location->uri.ptr == NULL)
+ {
+ ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
+ , cert->authKeyID);
+ if (ca != NULL && ca->ocspuri != NULL)
+ {
+ location->uri = chunk_create(ca->ocspuri, strlen(ca->ocspuri));
+ }
+ else
+ { /* abort if no ocsp location uri is defined */
+ return FALSE;
+ }
+ }
+
+ /* compute authNameID from as SHA-1 hash of issuer DN */
+ location->authNameID = chunk_create(digest, HASH_SIZE_SHA1);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ return FALSE;
+ }
+ hasher->get_hash(hasher, cert->issuer, digest);
+ hasher->destroy(hasher);
- if (location->uri.ptr == NULL)
- {
- ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID);
- if (ca != NULL && ca->ocspuri != NULL)
- setchunk(location->uri, ca->ocspuri, strlen(ca->ocspuri))
- else
- /* abort if no ocsp location uri is defined */
- return FALSE;
- }
-
- setchunk(location->authNameID, digest, SHA1_DIGEST_SIZE);
- compute_digest(cert->issuer, OID_SHA1, &location->authNameID);
-
- location->next = NULL;
- location->issuer = cert->issuer;
- location->authKeyID = cert->authKeyID;
- location->authKeySerialNumber = cert->authKeySerialNumber;
-
- if (cert->authKeyID.ptr == NULL)
- {
- x509cert_t *authcert = get_authcert(cert->issuer
- , cert->authKeySerialNumber, cert->authKeyID, AUTH_CA);
-
- if (authcert != NULL)
+ location->next = NULL;
+ location->issuer = cert->issuer;
+ location->authKeyID = cert->authKeyID;
+ location->authKeySerialNumber = cert->authKeySerialNumber;
+
+ if (cert->authKeyID.ptr == NULL)
{
- location->authKeyID = authcert->subjectKeyID;
- location->authKeySerialNumber = authcert->serialNumber;
+ x509cert_t *authcert = get_authcert(cert->issuer
+ , cert->authKeySerialNumber, cert->authKeyID, AUTH_CA);
+
+ if (authcert != NULL)
+ {
+ location->authKeyID = authcert->subjectKeyID;
+ location->authKeySerialNumber = authcert->serialNumber;
+ }
}
- }
- location->nonce = empty_chunk;
- location->certinfo = NULL;
+ location->nonce = chunk_empty;
+ location->certinfo = NULL;
- return TRUE;
+ return TRUE;
}
-/*
- * compare two ocsp locations for equality
+/**
+ * Compare two ocsp locations for equality
*/
-static bool
-same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b)
+static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b)
{
- return ((a->authKeyID.ptr != NULL)
- ? same_keyid(a->authKeyID, b->authKeyID)
- : (same_dn(a->issuer, b->issuer)
- && same_serial(a->authKeySerialNumber, b->authKeySerialNumber)))
- && same_chunk(a->uri, b->uri);
+ return ((a->authKeyID.ptr != NULL)
+ ? same_keyid(a->authKeyID, b->authKeyID)
+ : (same_dn(a->issuer, b->issuer)
+ && same_serial(a->authKeySerialNumber, b->authKeySerialNumber)))
+ && chunk_equals(a->uri, b->uri);
}
-/*
- * find an existing ocsp location in a chained list
+/**
+ * Find an existing ocsp location in a chained list
*/
-ocsp_location_t*
-get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain)
+ocsp_location_t* get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain)
{
- while (chain != NULL)
- {
- if (same_ocsp_location(loc, chain))
- return chain;
- chain = chain->next;
- }
- return NULL;
+ while (chain != NULL)
+ {
+ if (same_ocsp_location(loc, chain))
+ return chain;
+ chain = chain->next;
+ }
+ return NULL;
}
-
-/* retrieves the status of a cert from the ocsp cache
+
+/**
+ * Retrieves the status of a cert from the ocsp cache
* returns CERT_UNDEFINED if no status is found
*/
-static cert_status_t
-get_ocsp_status(const ocsp_location_t *loc, chunk_t serialNumber
- ,time_t *nextUpdate, time_t *revocationTime, crl_reason_t *revocationReason)
+static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
+ chunk_t serialNumber,
+ time_t *nextUpdate, time_t *revocationTime,
+ crl_reason_t *revocationReason)
{
- ocsp_certinfo_t *certinfo, **certinfop;
- int cmp = -1;
+ ocsp_certinfo_t *certinfo, **certinfop;
+ int cmp = -1;
- /* find location */
- ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache);
+ /* find location */
+ ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache);
- if (location == NULL)
- return CERT_UNDEFINED;
-
- /* traverse list of certinfos in increasing order */
- certinfop = &location->certinfo;
- certinfo = *certinfop;
+ if (location == NULL)
+ return CERT_UNDEFINED;
- while (certinfo != NULL)
- {
- cmp = cmp_chunk(serialNumber, certinfo->serialNumber);
- if (cmp <= 0)
- break;
- certinfop = &certinfo->next;
+ /* traverse list of certinfos in increasing order */
+ certinfop = &location->certinfo;
certinfo = *certinfop;
- }
- if (cmp == 0)
- {
- *nextUpdate = certinfo->nextUpdate;
- *revocationTime = certinfo->revocationTime;
- *revocationReason = certinfo->revocationReason;
- return certinfo->status;
- }
+ while (certinfo != NULL)
+ {
+ cmp = chunk_compare(serialNumber, certinfo->serialNumber);
+ if (cmp <= 0)
+ break;
+ certinfop = &certinfo->next;
+ certinfo = *certinfop;
+ }
+
+ if (cmp == 0)
+ {
+ *nextUpdate = certinfo->nextUpdate;
+ *revocationTime = certinfo->revocationTime;
+ *revocationReason = certinfo->revocationReason;
+ return certinfo->status;
+ }
- return CERT_UNDEFINED;
+ return CERT_UNDEFINED;
}
-/*
- * verify the ocsp status of a certificate
+/**
+ * Verify the ocsp status of a certificate
*/
-cert_status_t
-verify_by_ocsp(const x509cert_t *cert, time_t *until
-, time_t *revocationDate, crl_reason_t *revocationReason)
+cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until,
+ time_t *revocationDate,
+ crl_reason_t *revocationReason)
{
- cert_status_t status;
- ocsp_location_t location;
- time_t nextUpdate = 0;
-
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = REASON_UNSPECIFIED;
-
- /* is an ocsp location defined? */
- if (!build_ocsp_location(cert, &location))
- return CERT_UNDEFINED;
+ cert_status_t status;
+ ocsp_location_t location;
+ time_t nextUpdate = 0;
+
+ *revocationDate = UNDEFINED_TIME;
+ *revocationReason = REASON_UNSPECIFIED;
+
+ /* is an ocsp location defined? */
+ if (!build_ocsp_location(cert, &location))
+ return CERT_UNDEFINED;
+
+ lock_ocsp_cache("verify_by_ocsp");
+ status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate
+ , revocationDate, revocationReason);
+ unlock_ocsp_cache("verify_by_ocsp");
+
+ if (status == CERT_UNDEFINED || nextUpdate < time(NULL))
+ {
+ plog("ocsp status is stale or not in cache");
+ add_ocsp_fetch_request(&location, cert->serialNumber);
- lock_ocsp_cache("verify_by_ocsp");
- status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate
- , revocationDate, revocationReason);
- unlock_ocsp_cache("verify_by_ocsp");
-
- if (status == CERT_UNDEFINED || nextUpdate < time(NULL))
- {
- plog("ocsp status is stale or not in cache");
- add_ocsp_fetch_request(&location, cert->serialNumber);
-
- /* inititate fetching of ocsp status */
- wake_fetch_thread("verify_by_ocsp");
- }
- *until = nextUpdate;
- return status;
+ /* inititate fetching of ocsp status */
+ wake_fetch_thread("verify_by_ocsp");
+ }
+ *until = nextUpdate;
+ return status;
}
-/*
- * check if an ocsp status is about to expire
+/**
+ * Check if an ocsp status is about to expire
*/
-void
-check_ocsp(void)
+void check_ocsp(void)
{
- ocsp_location_t *location;
-
- lock_ocsp_cache("check_ocsp");
- location = ocsp_cache;
-
- while (location != NULL)
- {
- char buf[BUF_LEN];
- bool first = TRUE;
- ocsp_certinfo_t *certinfo = location->certinfo;
+ ocsp_location_t *location;
- while (certinfo != NULL)
+ lock_ocsp_cache("check_ocsp");
+ location = ocsp_cache;
+
+ while (location != NULL)
{
- if (!certinfo->once)
- {
- time_t time_left = certinfo->nextUpdate - time(NULL);
+ char buf[BUF_LEN];
+ bool first = TRUE;
+ ocsp_certinfo_t *certinfo = location->certinfo;
- DBG(DBG_CONTROL,
- if (first)
- {
- dntoa(buf, BUF_LEN, location->issuer);
- DBG_log("issuer: '%s'", buf);
- if (location->authKeyID.ptr != NULL)
+ while (certinfo != NULL)
+ {
+ if (!certinfo->once)
{
- datatot(location->authKeyID.ptr, location->authKeyID.len
- , ':', buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
+ time_t time_left = certinfo->nextUpdate - time(NULL);
+
+ DBG(DBG_CONTROL,
+ if (first)
+ {
+ dntoa(buf, BUF_LEN, location->issuer);
+ DBG_log("issuer: '%s'", buf);
+ if (location->authKeyID.ptr != NULL)
+ {
+ datatot(location->authKeyID.ptr, location->authKeyID.len
+ , ':', buf, BUF_LEN);
+ DBG_log("authkey: %s", buf);
+ }
+ first = FALSE;
+ }
+ datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len
+ , ':', buf, BUF_LEN);
+ DBG_log("serial: %s, %ld seconds left", buf, time_left)
+ )
+
+ if (time_left < 2*crl_check_interval)
+ add_ocsp_fetch_request(location, certinfo->serialNumber);
}
- first = FALSE;
- }
- datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len
- , ':', buf, BUF_LEN);
- DBG_log("serial: %s, %ld seconds left", buf, time_left)
- )
-
- if (time_left < 2*crl_check_interval)
- add_ocsp_fetch_request(location, certinfo->serialNumber);
- }
- certinfo = certinfo->next;
+ certinfo = certinfo->next;
+ }
+ location = location->next;
}
- location = location->next;
- }
- unlock_ocsp_cache("check_ocsp");
+ unlock_ocsp_cache("check_ocsp");
}
-/*
+/**
* frees the allocated memory of a certinfo struct
*/
-static void
-free_certinfo(ocsp_certinfo_t *certinfo)
+static void free_certinfo(ocsp_certinfo_t *certinfo)
{
- freeanychunk(certinfo->serialNumber);
- pfree(certinfo);
+ free(certinfo->serialNumber.ptr);
+ free(certinfo);
}
-/*
+/**
* frees all certinfos in a chained list
*/
-static void
-free_certinfos(ocsp_certinfo_t *chain)
+static void free_certinfos(ocsp_certinfo_t *chain)
{
- ocsp_certinfo_t *certinfo;
+ ocsp_certinfo_t *certinfo;
- while (chain != NULL)
- {
- certinfo = chain;
- chain = chain->next;
- free_certinfo(certinfo);
- }
+ while (chain != NULL)
+ {
+ certinfo = chain;
+ chain = chain->next;
+ free_certinfo(certinfo);
+ }
}
-/*
- * frees the memory allocated to an ocsp location including all certinfos
+/**
+ * Frees the memory allocated to an ocsp location including all certinfos
*/
-static void
-free_ocsp_location(ocsp_location_t* location)
+static void free_ocsp_location(ocsp_location_t* location)
{
- freeanychunk(location->issuer);
- freeanychunk(location->authNameID);
- freeanychunk(location->authKeyID);
- freeanychunk(location->authKeySerialNumber);
- freeanychunk(location->uri);
- free_certinfos(location->certinfo);
- pfree(location);
+ free(location->issuer.ptr);
+ free(location->authNameID.ptr);
+ free(location->authKeyID.ptr);
+ free(location->authKeySerialNumber.ptr);
+ free(location->uri.ptr);
+ free_certinfos(location->certinfo);
+ free(location);
}
/*
- * free a chained list of ocsp locations
+ * Free a chained list of ocsp locations
*/
-void
-free_ocsp_locations(ocsp_location_t **chain)
+void free_ocsp_locations(ocsp_location_t **chain)
{
- while (*chain != NULL)
- {
- ocsp_location_t *location = *chain;
- *chain = location->next;
- free_ocsp_location(location);
- }
+ while (*chain != NULL)
+ {
+ ocsp_location_t *location = *chain;
+ *chain = location->next;
+ free_ocsp_location(location);
+ }
}
-/*
- * free the ocsp cache
+/**
+ * Free the ocsp cache
*/
-void
-free_ocsp_cache(void)
+void free_ocsp_cache(void)
{
- lock_ocsp_cache("free_ocsp_cache");
- free_ocsp_locations(&ocsp_cache);
- unlock_ocsp_cache("free_ocsp_cache");
+ lock_ocsp_cache("free_ocsp_cache");
+ free_ocsp_locations(&ocsp_cache);
+ unlock_ocsp_cache("free_ocsp_cache");
}
-/*
- * frees the ocsp cache and global variables
+/**
+ * Frees the ocsp cache and global variables
*/
-void
-free_ocsp(void)
+void free_ocsp(void)
{
- pfreeany(ocsp_default_uri.ptr);
- free_ocsp_cache();
+ free(ocsp_default_uri.ptr);
+ free_ocsp_cache();
}
-/*
- * list a chained list of ocsp_locations
+/**
+ * List a chained list of ocsp_locations
*/
-void
-list_ocsp_locations(ocsp_location_t *location, bool requests, bool utc
-, bool strict)
+void list_ocsp_locations(ocsp_location_t *location, bool requests,
+ bool utc, bool strict)
{
- bool first = TRUE;
-
- while (location != NULL)
- {
- ocsp_certinfo_t *certinfo = location->certinfo;
+ bool first = TRUE;
- if (certinfo != NULL)
+ while (location != NULL)
{
- u_char buf[BUF_LEN];
-
- if (first)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of OCSP %s:", requests?
- "fetch requests":"responses");
- first = FALSE;
- }
- whack_log(RC_COMMENT, " ");
- if (location->issuer.ptr != NULL)
- {
- dntoa(buf, BUF_LEN, location->issuer);
- whack_log(RC_COMMENT, " issuer: '%s'", buf);
- }
- whack_log(RC_COMMENT, " uri: '%.*s'", (int)location->uri.len
- , location->uri.ptr);
- if (location->authNameID.ptr != NULL)
- {
- datatot(location->authNameID.ptr, location->authNameID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authname: %s", buf);
- }
- if (location->authKeyID.ptr != NULL)
- {
- datatot(location->authKeyID.ptr, location->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
- }
- if (location->authKeySerialNumber.ptr != NULL)
- {
- datatot(location->authKeySerialNumber.ptr
- , location->authKeySerialNumber.len, ':', buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
- }
- while (certinfo != NULL)
- {
- char thisUpdate[TIMETOA_BUF];
-
- strcpy(thisUpdate, timetoa(&certinfo->thisUpdate, utc));
-
- if (requests)
- {
- whack_log(RC_COMMENT, "%s, trials: %d", thisUpdate
- , certinfo->trials);
- }
- else if (certinfo->once)
- {
- whack_log(RC_COMMENT, "%s, onetime use%s", thisUpdate
- , (certinfo->nextUpdate < time(NULL))? " (expired)": "");
- }
- else
+ ocsp_certinfo_t *certinfo = location->certinfo;
+
+ if (certinfo != NULL)
{
- whack_log(RC_COMMENT, "%s, until %s %s", thisUpdate
- , timetoa(&certinfo->nextUpdate, utc)
- , check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict));
+ u_char buf[BUF_LEN];
+
+ if (first)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of OCSP %s:", requests?
+ "fetch requests":"responses");
+ first = FALSE;
+ }
+ whack_log(RC_COMMENT, " ");
+ if (location->issuer.ptr != NULL)
+ {
+ dntoa(buf, BUF_LEN, location->issuer);
+ whack_log(RC_COMMENT, " issuer: '%s'", buf);
+ }
+ whack_log(RC_COMMENT, " uri: '%.*s'", (int)location->uri.len
+ , location->uri.ptr);
+ if (location->authNameID.ptr != NULL)
+ {
+ datatot(location->authNameID.ptr, location->authNameID.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authname: %s", buf);
+ }
+ if (location->authKeyID.ptr != NULL)
+ {
+ datatot(location->authKeyID.ptr, location->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authkey: %s", buf);
+ }
+ if (location->authKeySerialNumber.ptr != NULL)
+ {
+ datatot(location->authKeySerialNumber.ptr
+ , location->authKeySerialNumber.len, ':', buf, BUF_LEN);
+ whack_log(RC_COMMENT, " aserial: %s", buf);
+ }
+ while (certinfo != NULL)
+ {
+ char thisUpdate[BUF_LEN];
+
+ snprintf(thisUpdate, BUF_LEN, "%T", &certinfo->thisUpdate, utc);
+
+ if (requests)
+ {
+ whack_log(RC_COMMENT, "%s, trials: %d", thisUpdate
+ , certinfo->trials);
+ }
+ else if (certinfo->once)
+ {
+ whack_log(RC_COMMENT, "%s, onetime use%s", thisUpdate
+ , (certinfo->nextUpdate < time(NULL))? " (expired)": "");
+ }
+ else
+ {
+ whack_log(RC_COMMENT, "%s, until %T %s", thisUpdate
+ , &certinfo->nextUpdate, utc
+ , check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict));
+ }
+ datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT, " serial: %s, %s", buf
+ , cert_status_names[certinfo->status]);
+ certinfo = certinfo->next;
+ }
}
- datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " serial: %s, %s", buf
- , cert_status_names[certinfo->status]);
- certinfo = certinfo->next;
- }
+ location = location->next;
}
- location = location->next;
- }
}
-/*
- * list the ocsp cache
+/**
+ * List the ocsp cache
*/
-void
-list_ocsp_cache(bool utc, bool strict)
+void list_ocsp_cache(bool utc, bool strict)
{
- lock_ocsp_cache("list_ocsp_cache");
- list_ocsp_locations(ocsp_cache, FALSE, utc, strict);
- unlock_ocsp_cache("list_ocsp_cache");
+ lock_ocsp_cache("list_ocsp_cache");
+ list_ocsp_locations(ocsp_cache, FALSE, utc, strict);
+ unlock_ocsp_cache("list_ocsp_cache");
}
-static bool
-get_ocsp_requestor_cert(ocsp_location_t *location)
+static bool get_ocsp_requestor_cert(ocsp_location_t *location)
{
- x509cert_t *cert = NULL;
+ x509cert_t *cert = NULL;
- /* initialize temporary static storage */
- ocsp_requestor_cert = NULL;
- ocsp_requestor_sc = NULL;
- ocsp_requestor_pri = NULL;
+ /* initialize temporary static storage */
+ ocsp_requestor_cert = NULL;
+ ocsp_requestor_sc = NULL;
+ ocsp_requestor_key = NULL;
- for (;;)
- {
- char buf[BUF_LEN];
-
- /* looking for a certificate from the same issuer */
- cert = get_x509cert(location->issuer, location->authKeySerialNumber
- ,location->authKeyID, cert);
- if (cert == NULL)
- break;
-
- DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, cert->subject);
- DBG_log("candidate: '%s'", buf);
- )
-
- if (cert->smartcard)
+ for (;;)
{
- /* look for a matching private key on a smartcard */
- smartcard_t *sc = scx_get(cert);
+ char buf[BUF_LEN];
+
+ /* looking for a certificate from the same issuer */
+ cert = get_x509cert(location->issuer, location->authKeySerialNumber
+ ,location->authKeyID, cert);
+ if (cert == NULL)
+ break;
- if (sc != NULL)
- {
DBG(DBG_CONTROL,
- DBG_log("matching smartcard found")
+ dntoa(buf, BUF_LEN, cert->subject);
+ DBG_log("candidate: '%s'", buf);
)
- if (sc->valid)
+
+ if (cert->smartcard)
{
- ocsp_requestor_cert = cert;
- ocsp_requestor_sc = sc;
- return TRUE;
+ /* look for a matching private key on a smartcard */
+ smartcard_t *sc = scx_get(cert);
+
+ if (sc != NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("matching smartcard found")
+ )
+ if (sc->valid)
+ {
+ ocsp_requestor_cert = cert;
+ ocsp_requestor_sc = sc;
+ return TRUE;
+ }
+ plog("unable to sign ocsp request without PIN");
+ }
}
- plog("unable to sign ocsp request without PIN");
- }
- }
- else
- {
- /* look for a matching private key in the chained list */
- const struct RSA_private_key *pri = get_x509_private_key(cert);
+ else
+ {
+ /* look for a matching private key in the chained list */
+ private_key_t *private = get_x509_private_key(cert);
- if (pri != NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("matching private key found")
- )
- ocsp_requestor_cert = cert;
- ocsp_requestor_pri = pri;
- return TRUE;
- }
+ if (private != NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("matching private key found")
+ )
+ ocsp_requestor_cert = cert;
+ ocsp_requestor_key = private;
+ return TRUE;
+ }
+ }
}
- }
- return FALSE;
+ return FALSE;
}
-static chunk_t
-generate_signature(chunk_t digest, smartcard_t *sc
- , const RSA_private_key_t *pri)
+static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
{
- chunk_t sigdata;
- u_char *pos;
- size_t siglen = 0;
-
- if (sc != NULL)
- {
- /* RSA signature is done on smartcard */
+ hasher_t *hasher;
+ u_char *pos;
+ u_char digest_buf[HASH_SIZE_SHA1];
+ chunk_t digest = chunk_from_buf(digest_buf);
+ chunk_t digest_info, sigdata;
+ size_t siglen = 0;
if (!scx_establish_context(sc) || !scx_login(sc))
{
- scx_release_context(sc);
- return empty_chunk;
+ scx_release_context(sc);
+ return chunk_empty;
}
siglen = scx_get_keylength(sc);
if (siglen == 0)
{
- plog("failed to get keylength from smartcard");
- scx_release_context(sc);
- return empty_chunk;
+ plog("failed to get keylength from smartcard");
+ scx_release_context(sc);
+ return chunk_empty;
}
DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
+ DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
+ , (int)sc->slot, sc->id)
)
- pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ return chunk_empty;
+ }
+ hasher->get_hash(hasher, tbs, digest_buf);
+ hasher->destroy(hasher);
+
+ /* according to PKCS#1 v2.1 digest must be packaged into
+ * an ASN.1 structure for encryption
+ */
+ digest_info = asn1_wrap(ASN1_SEQUENCE, "cm"
+ , asn1_algorithmIdentifier(OID_SHA1)
+ , asn1_simple_object(ASN1_OCTET_STRING, digest));
+
+ pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
*pos++ = 0x00;
- scx_sign_hash(sc, digest.ptr, digest.len, pos, siglen);
+ scx_sign_hash(sc, digest_info.ptr, digest_info.len, pos, siglen);
+ free(digest_info.ptr);
+
if (!pkcs11_keep_state)
- scx_release_context(sc);
- }
- else
- {
- /* RSA signature is done in software */
- siglen = pri->pub.k;
- pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
- *pos++ = 0x00;
- sign_hash(pri, digest.ptr, digest.len, pos, siglen);
- }
- return sigdata;
+ {
+ scx_release_context(sc);
+ }
+ return sigdata;
}
-/*
- * build signature into ocsp request
- * gets built only if a request cert with
- * a corresponding private key is found
+/**
+ * build signature into ocsp request gets built only if a request cert
+ * with a corresponding private key is found
*/
-static chunk_t
-build_signature(chunk_t tbsRequest)
+static chunk_t build_signature(chunk_t tbsRequest)
{
- chunk_t sigdata, certs;
- chunk_t digest_info;
-
- u_char digest_buf[MAX_DIGEST_LEN];
- chunk_t digest_raw = { digest_buf, MAX_DIGEST_LEN };
-
- if (!compute_digest(tbsRequest, OID_SHA1, &digest_raw))
- return empty_chunk;
-
- /* according to PKCS#1 v2.1 digest must be packaged into
- * an ASN.1 structure for encryption
- */
- digest_info = asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_sha1_id
- , asn1_simple_object(ASN1_OCTET_STRING, digest_raw));
-
- /* generate the RSA signature */
- sigdata = generate_signature(digest_info
- , ocsp_requestor_sc
- , ocsp_requestor_pri);
- freeanychunk(digest_info);
-
- /* has the RSA signature generation been successful? */
- if (sigdata.ptr == NULL)
- return empty_chunk;
-
- /* include our certificate */
- certs = asn1_wrap(ASN1_CONTEXT_C_0, "m"
- , asn1_simple_object(ASN1_SEQUENCE
- , ocsp_requestor_cert->certificate
- )
- );
-
- /* build signature comprising algorithm, signature and cert */
- return asn1_wrap(ASN1_CONTEXT_C_0, "m"
- , asn1_wrap(ASN1_SEQUENCE, "cmm"
- , ASN1_sha1WithRSA_id
- , sigdata
- , certs
- )
- );
+ chunk_t sigdata, certs;
+
+ if (ocsp_requestor_sc != NULL)
+ {
+ /* RSA signature is done on smartcard */
+ sigdata = sc_build_sha1_signature(tbsRequest, ocsp_requestor_sc);
+ }
+ else
+ {
+ /* RSA signature is done in software */
+ sigdata = x509_build_signature(tbsRequest, OID_SHA1, ocsp_requestor_key,
+ TRUE);
+ }
+ if (sigdata.ptr == NULL)
+ {
+ return chunk_empty;
+ }
+
+ /* include our certificate */
+ certs = asn1_wrap(ASN1_CONTEXT_C_0, "m"
+ , asn1_simple_object(ASN1_SEQUENCE
+ , ocsp_requestor_cert->certificate
+ )
+ );
+
+ /* build signature comprising algorithm, signature and cert */
+ return asn1_wrap(ASN1_CONTEXT_C_0, "m"
+ , asn1_wrap(ASN1_SEQUENCE, "cmm"
+ , asn1_algorithmIdentifier(OID_SHA1_WITH_RSA)
+ , sigdata
+ , certs
+ )
+ );
}
-/* build request (into requestList)
+/**
+ * Build request (into requestList)
* no singleRequestExtensions used
*/
-static chunk_t
-build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo)
+static chunk_t build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo)
{
- chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm"
- , ASN1_sha1_id
- , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID)
- , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID)
- , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber));
+ chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm"
+ , asn1_algorithmIdentifier(OID_SHA1)
+ , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID)
+ , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID)
+ , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber));
- return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
+ return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
}
-/*
+/**
* build requestList (into TBSRequest)
*/
-static chunk_t
-build_request_list(ocsp_location_t *location)
+static chunk_t build_request_list(ocsp_location_t *location)
{
- chunk_t requestList;
- request_list_t *reqs = NULL;
- ocsp_certinfo_t *certinfo = location->certinfo;
- u_char *pos;
-
- size_t datalen = 0;
-
- /* build content */
- while (certinfo != NULL)
- {
- /* build request for every certificate in list
- * and store them in a chained list
- */
- request_list_t *req = alloc_thing(request_list_t, "ocsp request");
+ chunk_t requestList;
+ request_list_t *reqs = NULL;
+ ocsp_certinfo_t *certinfo = location->certinfo;
+ u_char *pos;
- req->request = build_request(location, certinfo);
- req->next = reqs;
- reqs = req;
+ size_t datalen = 0;
- datalen += req->request.len;
- certinfo = certinfo->next;
- }
+ /* build content */
+ while (certinfo != NULL)
+ {
+ /* build request for every certificate in list
+ * and store them in a chained list
+ */
+ request_list_t *req = malloc_thing(request_list_t);
+
+ req->request = build_request(location, certinfo);
+ req->next = reqs;
+ reqs = req;
+
+ datalen += req->request.len;
+ certinfo = certinfo->next;
+ }
- pos = build_asn1_object(&requestList, ASN1_SEQUENCE
- , datalen);
+ pos = asn1_build_object(&requestList, ASN1_SEQUENCE, datalen);
- /* copy all in chained list, free list afterwards */
- while (reqs != NULL)
- {
- request_list_t *req = reqs;
+ /* copy all in chained list, free list afterwards */
+ while (reqs != NULL)
+ {
+ request_list_t *req = reqs;
- mv_chunk(&pos, req->request);
- reqs = reqs->next;
- pfree(req);
- }
+ mv_chunk(&pos, req->request);
+ reqs = reqs->next;
+ free(req);
+ }
- return requestList;
+ return requestList;
}
-/*
- * build requestorName (into TBSRequest)
+/**
+ * Build requestorName (into TBSRequest)
*/
-static chunk_t
-build_requestor_name(void)
+static chunk_t build_requestor_name(void)
{
- return asn1_wrap(ASN1_CONTEXT_C_1, "m"
- , asn1_simple_object(ASN1_CONTEXT_C_4
- , ocsp_requestor_cert->subject));
+ return asn1_wrap(ASN1_CONTEXT_C_1, "m"
+ , asn1_simple_object(ASN1_CONTEXT_C_4
+ , ocsp_requestor_cert->subject));
}
-/*
+/**
* build nonce extension (into requestExtensions)
*/
-static chunk_t
-build_nonce_extension(ocsp_location_t *location)
+static chunk_t build_nonce_extension(ocsp_location_t *location)
{
- /* generate a random nonce */
- location->nonce.ptr = alloc_bytes(NONCE_LENGTH, "ocsp nonce"),
- location->nonce.len = NONCE_LENGTH;
- get_rnd_bytes(location->nonce.ptr, NONCE_LENGTH);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_nonce_oid
- , asn1_simple_object(ASN1_OCTET_STRING, location->nonce));
+ rng_t *rng;
+
+ /* generate a random nonce */
+ location->nonce.ptr = malloc(NONCE_LENGTH),
+ location->nonce.len = NONCE_LENGTH;
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ rng->get_bytes(rng, location->nonce.len, location->nonce.ptr);
+ rng->destroy(rng);
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm"
+ , ASN1_nonce_oid
+ , asn1_simple_object(ASN1_OCTET_STRING, location->nonce));
}
-/*
- * build requestExtensions (into TBSRequest)
+/**
+ * Build requestExtensions (into TBSRequest)
*/
-static chunk_t
-build_request_ext(ocsp_location_t *location)
+static chunk_t build_request_ext(ocsp_location_t *location)
{
- return asn1_wrap(ASN1_CONTEXT_C_2, "m"
- , asn1_wrap(ASN1_SEQUENCE, "mm"
- , build_nonce_extension(location)
- , asn1_wrap(ASN1_SEQUENCE, "cc"
- , ASN1_response_oid
- , ASN1_response_content
- )
- )
- );
+ return asn1_wrap(ASN1_CONTEXT_C_2, "m"
+ , asn1_wrap(ASN1_SEQUENCE, "mm"
+ , build_nonce_extension(location)
+ , asn1_wrap(ASN1_SEQUENCE, "cc"
+ , ASN1_response_oid
+ , ASN1_response_content
+ )
+ )
+ );
}
-/*
- * build TBSRequest (into OCSPRequest)
+/**
+ * Build TBSRequest (into OCSPRequest)
*/
-static chunk_t
-build_tbs_request(ocsp_location_t *location, bool has_requestor_cert)
+static chunk_t build_tbs_request(ocsp_location_t *location, bool has_requestor_cert)
{
- /* version is skipped since the default is ok */
- return asn1_wrap(ASN1_SEQUENCE, "mmm"
- , (has_requestor_cert)
- ? build_requestor_name()
- : empty_chunk
- , build_request_list(location)
- , build_request_ext(location));
+ /* version is skipped since the default is ok */
+ return asn1_wrap(ASN1_SEQUENCE, "mmm"
+ , (has_requestor_cert)
+ ? build_requestor_name()
+ : chunk_empty
+ , build_request_list(location)
+ , build_request_ext(location));
}
-/* assembles an ocsp request to given location
+/**
+ * Assembles an ocsp request to given location
* and sets nonce field in location to the sent nonce
*/
-chunk_t
-build_ocsp_request(ocsp_location_t *location)
+chunk_t build_ocsp_request(ocsp_location_t *location)
{
- bool has_requestor_cert;
- chunk_t tbsRequest, signature;
- char buf[BUF_LEN];
-
- DBG(DBG_CONTROL,
- DBG_log("assembling ocsp request");
- dntoa(buf, BUF_LEN, location->issuer);
- DBG_log("issuer: '%s'", buf);
- if (location->authKeyID.ptr != NULL)
- {
- datatot(location->authKeyID.ptr, location->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
- }
- )
- lock_certs_and_keys("build_ocsp_request");
+ bool has_requestor_cert;
+ chunk_t tbsRequest, signature;
+ char buf[BUF_LEN];
- /* looks for requestor cert and matching private key */
- has_requestor_cert = get_ocsp_requestor_cert(location);
+ DBG(DBG_CONTROL,
+ DBG_log("assembling ocsp request");
+ dntoa(buf, BUF_LEN, location->issuer);
+ DBG_log("issuer: '%s'", buf);
+ if (location->authKeyID.ptr != NULL)
+ {
+ datatot(location->authKeyID.ptr, location->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ DBG_log("authkey: %s", buf);
+ }
+ )
+ lock_certs_and_keys("build_ocsp_request");
+
+ /* looks for requestor cert and matching private key */
+ has_requestor_cert = get_ocsp_requestor_cert(location);
- /* build content */
- tbsRequest = build_tbs_request(location, has_requestor_cert);
+ /* build content */
+ tbsRequest = build_tbs_request(location, has_requestor_cert);
- /* sign tbsReuqest */
- signature = (has_requestor_cert)? build_signature(tbsRequest)
- : empty_chunk;
+ /* sign tbsReuqest */
+ signature = (has_requestor_cert)? build_signature(tbsRequest)
+ : chunk_empty;
- unlock_certs_and_keys("build_ocsp_request");
+ unlock_certs_and_keys("build_ocsp_request");
- return asn1_wrap(ASN1_SEQUENCE, "mm"
- , tbsRequest
- , signature);
+ return asn1_wrap(ASN1_SEQUENCE, "mm"
+ , tbsRequest
+ , signature);
}
-/*
- * check if the OCSP response has a valid signature
+/**
+ * Check if the OCSP response has a valid signature
*/
-static bool
-valid_ocsp_response(response_t *res)
+static bool valid_ocsp_response(response_t *res)
{
- int pathlen;
- x509cert_t *authcert;
+ int pathlen;
+ x509cert_t *authcert;
- lock_authcert_list("valid_ocsp_response");
+ lock_authcert_list("valid_ocsp_response");
- authcert = get_authcert(res->responder_id_name, empty_chunk
- , res->responder_id_key, AUTH_OCSP | AUTH_CA);
-
- if (authcert == NULL)
- {
- plog("no matching ocsp signer cert found");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("ocsp signer cert found")
- )
-
- if (!check_signature(res->tbs, res->signature, res->algorithm
- , res->algorithm, authcert))
- {
- plog("signature of ocsp response is invalid");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("signature of ocsp response is valid")
- )
-
-
- for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
- {
- u_char buf[BUF_LEN];
- err_t ugh = NULL;
- time_t until;
-
- x509cert_t *cert = authcert;
-
- DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, cert->subject);
- DBG_log("subject: '%s'",buf);
- dntoa(buf, BUF_LEN, cert->issuer);
- DBG_log("issuer: '%s'",buf);
- if (cert->authKeyID.ptr != NULL)
- {
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
- }
- )
-
- ugh = check_validity(authcert, &until);
-
- if (ugh != NULL)
- {
- plog("%s", ugh);
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
-
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
-
- authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, AUTH_CA);
+ authcert = get_authcert(res->responder_id_name, chunk_empty
+ , res->responder_id_key, AUTH_OCSP | AUTH_CA);
if (authcert == NULL)
{
- plog("issuer cacert not found");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
+ plog("no matching ocsp signer cert found");
+ unlock_authcert_list("valid_ocsp_response");
+ return FALSE;
}
DBG(DBG_CONTROL,
- DBG_log("issuer cacert found")
+ DBG_log("ocsp signer cert found")
)
- if (!check_signature(cert->tbsCertificate, cert->signature
- , cert->algorithm, cert->algorithm, authcert))
+ if (!x509_check_signature(res->tbs, res->signature, res->algorithm, authcert))
{
- plog("certificate signature is invalid");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
+ plog("signature of ocsp response is invalid");
+ unlock_authcert_list("valid_ocsp_response");
+ return FALSE;
}
DBG(DBG_CONTROL,
- DBG_log("certificate signature is valid")
+ DBG_log("signature of ocsp response is valid")
)
- /* check if cert is self-signed */
- if (same_dn(cert->issuer, cert->subject))
+
+ for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
{
- DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca")
- )
- unlock_authcert_list("valid_ocsp_response");
- return TRUE;
+ u_char buf[BUF_LEN];
+ err_t ugh = NULL;
+ time_t until;
+
+ x509cert_t *cert = authcert;
+
+ DBG(DBG_CONTROL,
+ dntoa(buf, BUF_LEN, cert->subject);
+ DBG_log("subject: '%s'",buf);
+ dntoa(buf, BUF_LEN, cert->issuer);
+ DBG_log("issuer: '%s'",buf);
+ if (cert->authKeyID.ptr != NULL)
+ {
+ datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ DBG_log("authkey: %s", buf);
+ }
+ )
+
+ ugh = check_validity(authcert, &until);
+
+ if (ugh != NULL)
+ {
+ plog("%s", ugh);
+ unlock_authcert_list("valid_ocsp_response");
+ return FALSE;
+ }
+
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is valid")
+ )
+
+ authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
+ , cert->authKeyID, AUTH_CA);
+
+ if (authcert == NULL)
+ {
+ plog("issuer cacert not found");
+ unlock_authcert_list("valid_ocsp_response");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("issuer cacert found")
+ )
+
+ if (!x509_check_signature(cert->tbsCertificate, cert->signature,
+ cert->algorithm, authcert))
+ {
+ plog("certificate signature is invalid");
+ unlock_authcert_list("valid_ocsp_response");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("certificate signature is valid")
+ )
+
+ /* check if cert is self-signed */
+ if (same_dn(cert->issuer, cert->subject))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("reached self-signed root ca")
+ )
+ unlock_authcert_list("valid_ocsp_response");
+ return TRUE;
+ }
}
- }
- plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
+ plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ unlock_authcert_list("valid_ocsp_response");
+ return FALSE;
}
-/*
- * parse a basic OCSP response
+/**
+ * Parse a basic OCSP response
*/
-static bool
-parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
+static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
{
- asn1_ctx_t ctx;
- bool critical;
- chunk_t object;
- u_int level, version;
- u_char buf[BUF_LEN];
- int objectID = 0;
- int extn_oid = OID_UNKNOWN;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < BASIC_RESPONSE_ROOF)
- {
- if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx))
- return FALSE;
-
- switch (objectID)
+ asn1_parser_t *parser;
+ chunk_t object;
+ u_int version;
+ u_char buf[BUF_LEN];
+ int objectID;
+ int extn_oid = OID_UNKNOWN;
+ bool success = FALSE;
+ bool critical;
+
+ parser = asn1_parser_create(basicResponseObjects, blob);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
{
- case BASIC_RESPONSE_TBS_DATA:
- res->tbs = object;
- break;
- case BASIC_RESPONSE_VERSION:
- version = (object.len)? (1 + (u_int)*object.ptr) : 1;
- if (version != OCSP_BASIC_RESPONSE_VERSION)
- {
- plog("wrong ocsp basic response version (version= %i)", version);
- return FALSE;
- }
- break;
- case BASIC_RESPONSE_ID_BY_NAME:
- res->responder_id_name = object;
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'",buf)
- )
- break;
- case BASIC_RESPONSE_ID_BY_KEY:
- res->responder_id_key = object;
- break;
- case BASIC_RESPONSE_PRODUCED_AT:
- res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME);
- break;
- case BASIC_RESPONSE_RESPONSES:
- res->responses = object;
- break;
- case BASIC_RESPONSE_EXT_ID:
- extn_oid = known_oid(object);
- break;
- case BASIC_RESPONSE_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- break;
- case BASIC_RESPONSE_EXT_VALUE:
- if (extn_oid == OID_NONCE)
- res->nonce = object;
- break;
- case BASIC_RESPONSE_ALGORITHM:
- res->algorithm = parse_algorithmIdentifier(object, level+1, NULL);
- break;
- case BASIC_RESPONSE_SIGNATURE:
- res->signature = object;
- break;
- case BASIC_RESPONSE_CERTIFICATE:
- {
- chunk_t blob;
- x509cert_t *cert = alloc_thing(x509cert_t, "ocspcert");
-
- clonetochunk(blob, object.ptr, object.len, "ocspcert blob");
- *cert = empty_x509cert;
-
- if (parse_x509cert(blob, level+1, cert)
- && cert->isOcspSigner
- && trust_authcert_candidate(cert, NULL))
+ switch (objectID)
{
- add_authcert(cert, AUTH_OCSP);
- }
- else
- {
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("embedded ocsp certificate rejected")
- )
- free_x509cert(cert);
+ case BASIC_RESPONSE_TBS_DATA:
+ res->tbs = object;
+ break;
+ case BASIC_RESPONSE_VERSION:
+ version = (object.len)? (1 + (u_int)*object.ptr) : 1;
+ if (version != OCSP_BASIC_RESPONSE_VERSION)
+ {
+ plog("wrong ocsp basic response version (version= %i)", version);
+ goto end;
+ }
+ break;
+ case BASIC_RESPONSE_ID_BY_NAME:
+ res->responder_id_name = object;
+ DBG(DBG_PARSING,
+ dntoa(buf, BUF_LEN, object);
+ DBG_log(" '%s'",buf)
+ )
+ break;
+ case BASIC_RESPONSE_ID_BY_KEY:
+ res->responder_id_key = object;
+ break;
+ case BASIC_RESPONSE_PRODUCED_AT:
+ res->produced_at = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
+ break;
+ case BASIC_RESPONSE_RESPONSES:
+ res->responses = object;
+ break;
+ case BASIC_RESPONSE_EXT_ID:
+ extn_oid = asn1_known_oid(object);
+ break;
+ case BASIC_RESPONSE_CRITICAL:
+ critical = object.len && *object.ptr;
+ DBG(DBG_PARSING,
+ DBG_log(" %s",(critical)?"TRUE":"FALSE");
+ )
+ break;
+ case BASIC_RESPONSE_EXT_VALUE:
+ if (extn_oid == OID_NONCE)
+ res->nonce = object;
+ break;
+ case BASIC_RESPONSE_ALGORITHM:
+ res->algorithm = asn1_parse_algorithmIdentifier(object,
+ parser->get_level(parser)+1, NULL);
+ break;
+ case BASIC_RESPONSE_SIGNATURE:
+ res->signature = object;
+ break;
+ case BASIC_RESPONSE_CERTIFICATE:
+ {
+ chunk_t blob = chunk_clone(object);
+ x509cert_t *cert = malloc_thing(x509cert_t);
+
+ *cert = empty_x509cert;
+
+ if (parse_x509cert(blob, parser->get_level(parser)+1, cert)
+ && cert->isOcspSigner
+ && trust_authcert_candidate(cert, NULL))
+ {
+ add_authcert(cert, AUTH_OCSP);
+ }
+ else
+ {
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log("embedded ocsp certificate rejected")
+ )
+ free_x509cert(cert);
+ }
+ }
+ break;
}
- }
- break;
}
- objectID++;
- }
- return TRUE;
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ return success;
+
}
-/*
- * parse an ocsp response and return the result as a response_t struct
+/**
+ * Parse an ocsp response and return the result as a response_t struct
*/
-static response_status
-parse_ocsp_response(chunk_t blob, response_t * res)
+static response_status parse_ocsp_response(chunk_t blob, response_t * res)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
- int ocspResponseType = OID_UNKNOWN;
- response_status rStatus = STATUS_INTERNALERROR;
-
- asn1_init(&ctx, blob, 0, FALSE, DBG_RAW);
-
- while (objectID < OCSP_RESPONSE_ROOF)
- {
- if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx))
- return STATUS_INTERNALERROR;
-
- switch (objectID) {
- case OCSP_RESPONSE_STATUS:
- rStatus = (response_status) *object.ptr;
-
- switch (rStatus)
- {
- case STATUS_SUCCESSFUL:
- break;
- case STATUS_MALFORMEDREQUEST:
- case STATUS_INTERNALERROR:
- case STATUS_TRYLATER:
- case STATUS_SIGREQUIRED:
- case STATUS_UNAUTHORIZED:
- plog("ocsp response: server said '%s'"
- , response_status_names[rStatus]);
- return rStatus;
- default:
- return STATUS_INTERNALERROR;
- }
- break;
- case OCSP_RESPONSE_TYPE:
- ocspResponseType = known_oid(object);
- break;
- case OCSP_RESPONSE:
- {
- switch (ocspResponseType) {
- case OID_BASIC:
- if (!parse_basic_ocsp_response(object, level+1, res))
- return STATUS_INTERNALERROR;
- break;
- default:
- DBG(DBG_CONTROL,
- DBG_log("ocsp response is not of type BASIC");
- DBG_dump_chunk("ocsp response OID: ", object);
- )
- return STATUS_INTERNALERROR;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ int ocspResponseType = OID_UNKNOWN;
+ bool success = FALSE;
+ response_status rStatus = STATUS_INTERNALERROR;
+
+ parser = asn1_parser_create(ocspResponseObjects, blob);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ switch (objectID) {
+ case OCSP_RESPONSE_STATUS:
+ rStatus = (response_status) *object.ptr;
+
+ switch (rStatus)
+ {
+ case STATUS_SUCCESSFUL:
+ break;
+ case STATUS_MALFORMEDREQUEST:
+ case STATUS_INTERNALERROR:
+ case STATUS_TRYLATER:
+ case STATUS_SIGREQUIRED:
+ case STATUS_UNAUTHORIZED:
+ plog("ocsp response: server said '%s'"
+ , response_status_names[rStatus]);
+ goto end;
+ default:
+ goto end;
+ }
+ break;
+ case OCSP_RESPONSE_TYPE:
+ ocspResponseType = asn1_known_oid(object);
+ break;
+ case OCSP_RESPONSE:
+ {
+ switch (ocspResponseType) {
+ case OID_BASIC:
+ success = parse_basic_ocsp_response(object,
+ parser->get_level(parser)+1, res);
+ break;
+ default:
+ DBG(DBG_CONTROL,
+ DBG_log("ocsp response is not of type BASIC");
+ DBG_dump_chunk("ocsp response OID: ", object);
+ )
+ goto end;
+ }
+ }
+ break;
}
- }
- break;
}
- objectID++;
- }
- return rStatus;
+ success &= parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ return rStatus;
}
-/*
- * parse a basic OCSP response
+/**
+ * Parse a basic OCSP response
*/
-static bool
-parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres)
+static bool parse_ocsp_single_response(chunk_t blob, int level0,
+ single_response_t *sres)
{
- u_int level, extn_oid;
- asn1_ctx_t ctx;
- bool critical;
- chunk_t object;
- int objectID = 0;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ asn1_parser_t *parser;
+ chunk_t object;
+ u_int extn_oid;
+ int objectID;
+ bool critical;
+ bool success = FALSE;
- while (objectID < SINGLE_RESPONSE_ROOF)
- {
- if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx))
- return FALSE;
+ parser = asn1_parser_create(singleResponseObjects, blob);
+ parser->set_top_level(parser, level0);
- switch (objectID)
+ while (parser->iterate(parser, &objectID, &object))
{
- case SINGLE_RESPONSE_ALGORITHM:
- sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL);
- break;
- case SINGLE_RESPONSE_ISSUER_NAME_HASH:
- sres->issuer_name_hash = object;
- break;
- case SINGLE_RESPONSE_ISSUER_KEY_HASH:
- sres->issuer_key_hash = object;
- break;
- case SINGLE_RESPONSE_SERIAL_NUMBER:
- sres->serialNumber = object;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_GOOD:
- sres->status = CERT_GOOD;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
- sres->status = CERT_REVOKED;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
- sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME);
- break;
- case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
- sres->revocationReason = (object.len == 1)
- ? *object.ptr : REASON_UNSPECIFIED;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
- sres->status = CERT_UNKNOWN;
- break;
- case SINGLE_RESPONSE_THIS_UPDATE:
- sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
- break;
- case SINGLE_RESPONSE_NEXT_UPDATE:
- sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
- break;
- case SINGLE_RESPONSE_EXT_ID:
- extn_oid = known_oid(object);
- break;
- case SINGLE_RESPONSE_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- case SINGLE_RESPONSE_EXT_VALUE:
- break;
+ switch (objectID)
+ {
+ case SINGLE_RESPONSE_ALGORITHM:
+ sres->hash_algorithm = asn1_parse_algorithmIdentifier(object,
+ parser->get_level(parser)+1, NULL);
+ break;
+ case SINGLE_RESPONSE_ISSUER_NAME_HASH:
+ sres->issuer_name_hash = object;
+ break;
+ case SINGLE_RESPONSE_ISSUER_KEY_HASH:
+ sres->issuer_key_hash = object;
+ break;
+ case SINGLE_RESPONSE_SERIAL_NUMBER:
+ sres->serialNumber = object;
+ break;
+ case SINGLE_RESPONSE_CERT_STATUS_GOOD:
+ sres->status = CERT_GOOD;
+ break;
+ case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
+ sres->status = CERT_REVOKED;
+ break;
+ case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
+ sres->revocationTime = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
+ break;
+ case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
+ sres->revocationReason = (object.len == 1)
+ ? *object.ptr : REASON_UNSPECIFIED;
+ break;
+ case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
+ sres->status = CERT_UNKNOWN;
+ break;
+ case SINGLE_RESPONSE_THIS_UPDATE:
+ sres->thisUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
+ break;
+ case SINGLE_RESPONSE_NEXT_UPDATE:
+ sres->nextUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
+ break;
+ case SINGLE_RESPONSE_EXT_ID:
+ extn_oid = asn1_known_oid(object);
+ break;
+ case SINGLE_RESPONSE_CRITICAL:
+ critical = object.len && *object.ptr;
+ DBG(DBG_PARSING,
+ DBG_log(" %s",(critical)?"TRUE":"FALSE");
+ )
+ case SINGLE_RESPONSE_EXT_VALUE:
+ break;
+ }
}
- objectID++;
- }
- return TRUE;
+ success = parser->success(parser);
+ parser->destroy(parser);
+ return success;
}
-/*
- * add an ocsp location to a chained list
+/**
+ * Add an ocsp location to a chained list
*/
-ocsp_location_t*
-add_ocsp_location(const ocsp_location_t *loc, ocsp_location_t **chain)
+ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc,
+ ocsp_location_t **chain)
{
- ocsp_location_t *location = alloc_thing(ocsp_location_t, "ocsp location");
-
- /* unshare location fields */
- clonetochunk(location->issuer
- , loc->issuer.ptr, loc->issuer.len
- , "ocsp issuer");
-
- clonetochunk(location->authNameID
- , loc->authNameID.ptr, loc->authNameID.len
- , "ocsp authNameID");
-
- if (loc->authKeyID.ptr == NULL)
- location->authKeyID = empty_chunk;
- else
- clonetochunk(location->authKeyID
- , loc->authKeyID.ptr, loc->authKeyID.len
- , "ocsp authKeyID");
-
- if (loc->authKeySerialNumber.ptr == NULL)
- location->authKeySerialNumber = empty_chunk;
- else
- clonetochunk(location->authKeySerialNumber
- , loc->authKeySerialNumber.ptr, loc->authKeySerialNumber.len
- , "ocsp authKeySerialNumber");
-
- clonetochunk(location->uri
- , loc->uri.ptr, loc->uri.len
- , "ocsp uri");
-
- location->certinfo = NULL;
-
- /* insert new ocsp location in front of chain */
- location->next = *chain;
- *chain = location;
-
- DBG(DBG_CONTROL,
- DBG_log("new ocsp location added")
- )
-
- return location;
+ ocsp_location_t *location = malloc_thing(ocsp_location_t);
+
+ /* unshare location fields */
+ location->issuer = chunk_clone(loc->issuer);
+ location->authNameID = chunk_clone(loc->authNameID);
+ location->authKeyID = chunk_clone(loc->authKeyID);
+ location->authKeySerialNumber = chunk_clone(loc->authKeySerialNumber);
+ location->uri = chunk_clone(loc->uri);
+ location->certinfo = NULL;
+
+ /* insert new ocsp location in front of chain */
+ location->next = *chain;
+ *chain = location;
+
+ DBG(DBG_CONTROL,
+ DBG_log("new ocsp location added")
+ )
+
+ return location;
}
-/*
+/**
* add a certinfo struct to a chained list
*/
-void
-add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chain
- , bool request)
+void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
+ ocsp_location_t **chain, bool request)
{
- ocsp_location_t *location;
- ocsp_certinfo_t *certinfo, **certinfop;
- char buf[BUF_LEN];
- time_t now;
- int cmp = -1;
-
- location = get_ocsp_location(loc, *chain);
- if (location == NULL)
- location = add_ocsp_location(loc, chain);
-
- /* traverse list of certinfos in increasing order */
- certinfop = &location->certinfo;
- certinfo = *certinfop;
-
- while (certinfo != NULL)
- {
- cmp = cmp_chunk(info->serialNumber, certinfo->serialNumber);
- if (cmp <= 0)
- break;
- certinfop = &certinfo->next;
+ ocsp_location_t *location;
+ ocsp_certinfo_t *certinfo, **certinfop;
+ char buf[BUF_LEN];
+ time_t now;
+ int cmp = -1;
+
+ location = get_ocsp_location(loc, *chain);
+ if (location == NULL)
+ {
+ location = add_ocsp_location(loc, chain);
+ }
+
+ /* traverse list of certinfos in increasing order */
+ certinfop = &location->certinfo;
certinfo = *certinfop;
- }
-
- if (cmp != 0)
- {
- /* add a new certinfo entry */
- ocsp_certinfo_t *cnew = alloc_thing(ocsp_certinfo_t, "ocsp certinfo");
- clonetochunk(cnew->serialNumber, info->serialNumber.ptr
- , info->serialNumber.len, "serialNumber");
- cnew->next = certinfo;
- *certinfop = cnew;
- certinfo = cnew;
- }
-
- DBG(DBG_CONTROL,
- datatot(info->serialNumber.ptr, info->serialNumber.len, ':'
- , buf, BUF_LEN);
- DBG_log("ocsp %s for serial %s %s"
- , request?"fetch request":"certinfo"
- , buf
- , (cmp == 0)? (request?"already exists":"updated"):"added")
- )
-
- time(&now);
-
- if (request)
- {
- certinfo->status = CERT_UNDEFINED;
-
+
+ while (certinfo != NULL)
+ {
+ cmp = chunk_compare(info->serialNumber, certinfo->serialNumber);
+ if (cmp <= 0)
+ break;
+ certinfop = &certinfo->next;
+ certinfo = *certinfop;
+ }
+
if (cmp != 0)
- certinfo->thisUpdate = now;
-
- certinfo->nextUpdate = UNDEFINED_TIME;
- }
- else
- {
- certinfo->status = info->status;
- certinfo->revocationTime = info->revocationTime;
- certinfo->revocationReason = info->revocationReason;
-
- certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)?
- info->thisUpdate : now;
+ {
+ /* add a new certinfo entry */
+ ocsp_certinfo_t *cnew = malloc_thing(ocsp_certinfo_t);
+
+ cnew->serialNumber = chunk_clone(info->serialNumber);
+ cnew->next = certinfo;
+ *certinfop = cnew;
+ certinfo = cnew;
+ }
+
+ DBG(DBG_CONTROL,
+ datatot(info->serialNumber.ptr, info->serialNumber.len, ':'
+ , buf, BUF_LEN);
+ DBG_log("ocsp %s for serial %s %s"
+ , request?"fetch request":"certinfo"
+ , buf
+ , (cmp == 0)? (request?"already exists":"updated"):"added")
+ )
+
+ time(&now);
+
+ if (request)
+ {
+ certinfo->status = CERT_UNDEFINED;
+
+ if (cmp != 0)
+ {
+ certinfo->thisUpdate = now;
+ }
+ certinfo->nextUpdate = UNDEFINED_TIME;
+ }
+ else
+ {
+ certinfo->status = info->status;
+ certinfo->revocationTime = info->revocationTime;
+ certinfo->revocationReason = info->revocationReason;
+
+ certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)?
+ info->thisUpdate : now;
- certinfo->once = (info->nextUpdate == UNDEFINED_TIME);
+ certinfo->once = (info->nextUpdate == UNDEFINED_TIME);
- certinfo->nextUpdate = (certinfo->once)?
- (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate;
- }
+ certinfo->nextUpdate = (certinfo->once)?
+ (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate;
+ }
}
-/*
- * process received ocsp single response and add it to ocsp cache
+/**
+ * Process received ocsp single response and add it to ocsp cache
*/
-static void
-process_single_response(ocsp_location_t *location, single_response_t *sres)
+static void process_single_response(ocsp_location_t *location,
+ single_response_t *sres)
{
- ocsp_certinfo_t *certinfo, **certinfop;
- int cmp = -1;
-
- if (sres->hash_algorithm != OID_SHA1)
- {
- plog("only SHA-1 hash supported in OCSP single response");
- return;
- }
- if (!(same_chunk(sres->issuer_name_hash, location->authNameID)
- && same_chunk(sres->issuer_key_hash, location->authKeyID)))
- {
- plog("ocsp single response has wrong issuer");
- return;
- }
-
- /* traverse list of certinfos in increasing order */
- certinfop = &location->certinfo;
- certinfo = *certinfop;
-
- while (certinfo != NULL)
- {
- cmp = cmp_chunk(sres->serialNumber, certinfo->serialNumber);
- if (cmp <= 0)
- break;
- certinfop = &certinfo->next;
+ ocsp_certinfo_t *certinfo, **certinfop;
+ int cmp = -1;
+
+ if (sres->hash_algorithm != OID_SHA1)
+ {
+ plog("only SHA-1 hash supported in OCSP single response");
+ return;
+ }
+ if (!(chunk_equals(sres->issuer_name_hash, location->authNameID)
+ && chunk_equals(sres->issuer_key_hash, location->authKeyID)))
+ {
+ plog("ocsp single response has wrong issuer");
+ return;
+ }
+
+ /* traverse list of certinfos in increasing order */
+ certinfop = &location->certinfo;
certinfo = *certinfop;
- }
-
- if (cmp != 0)
- {
- plog("received unrequested cert status from ocsp server");
- return;
- }
-
- /* unlink cert from ocsp fetch request list */
- *certinfop = certinfo->next;
-
- /* update certinfo using the single response information */
- certinfo->thisUpdate = sres->thisUpdate;
- certinfo->nextUpdate = sres->nextUpdate;
- certinfo->status = sres->status;
- certinfo->revocationTime = sres->revocationTime;
- certinfo->revocationReason = sres->revocationReason;
-
- /* add or update certinfo in ocsp cache */
- lock_ocsp_cache("process_single_response");
- add_certinfo(location, certinfo, &ocsp_cache, FALSE);
- unlock_ocsp_cache("process_single_response");
-
- /* free certinfo unlinked from ocsp fetch request list */
- free_certinfo(certinfo);
+ while (certinfo != NULL)
+ {
+ cmp = chunk_compare(sres->serialNumber, certinfo->serialNumber);
+ if (cmp <= 0)
+ break;
+ certinfop = &certinfo->next;
+ certinfo = *certinfop;
+ }
+
+ if (cmp != 0)
+ {
+ plog("received unrequested cert status from ocsp server");
+ return;
+ }
+
+ /* unlink cert from ocsp fetch request list */
+ *certinfop = certinfo->next;
+
+ /* update certinfo using the single response information */
+ certinfo->thisUpdate = sres->thisUpdate;
+ certinfo->nextUpdate = sres->nextUpdate;
+ certinfo->status = sres->status;
+ certinfo->revocationTime = sres->revocationTime;
+ certinfo->revocationReason = sres->revocationReason;
+
+ /* add or update certinfo in ocsp cache */
+ lock_ocsp_cache("process_single_response");
+ add_certinfo(location, certinfo, &ocsp_cache, FALSE);
+ unlock_ocsp_cache("process_single_response");
+
+ /* free certinfo unlinked from ocsp fetch request list */
+ free_certinfo(certinfo);
}
-/*
- * parse and verify ocsp response and update the ocsp cache
+/**
+ * Parse and verify ocsp response and update the ocsp cache
*/
-void
-parse_ocsp(ocsp_location_t *location, chunk_t blob)
+void parse_ocsp(ocsp_location_t *location, chunk_t blob)
{
- response_t res = empty_response;
-
- /* parse the ocsp response without looking at the single responses yet */
- response_status status = parse_ocsp_response(blob, &res);
-
- if (status != STATUS_SUCCESSFUL)
- {
- plog("error in ocsp response");
- return;
- }
- /* check if there was a nonce in the request */
- if (location->nonce.ptr != NULL && res.nonce.ptr == NULL)
- {
- plog("ocsp response contains no nonce, replay attack possible");
- }
- /* check if the nonce is identical */
- if (res.nonce.ptr != NULL && !same_chunk(res.nonce, location->nonce))
- {
- plog("invalid nonce in ocsp response");
- return;
- }
- /* check if the response is signed by a trusted key */
- if (!valid_ocsp_response(&res))
- {
- plog("invalid ocsp response");
- return;
- }
- DBG(DBG_CONTROL,
- DBG_log("valid ocsp response")
- )
-
- /* now parse the single responses one at a time */
- {
- u_int level;
- asn1_ctx_t ctx;
- chunk_t object;
- int objectID = 0;
+ response_t res = empty_response;
- asn1_init(&ctx, res.responses, 0, FALSE, DBG_RAW);
+ /* parse the ocsp response without looking at the single responses yet */
+ response_status status = parse_ocsp_response(blob, &res);
- while (objectID < RESPONSES_ROOF)
+ if (status != STATUS_SUCCESSFUL)
+ {
+ plog("error in ocsp response");
+ return;
+ }
+ /* check if there was a nonce in the request */
+ if (location->nonce.ptr != NULL && res.nonce.ptr == NULL)
+ {
+ plog("ocsp response contains no nonce, replay attack possible");
+ }
+ /* check if the nonce is identical */
+ if (res.nonce.ptr != NULL && !chunk_equals(res.nonce, location->nonce))
+ {
+ plog("invalid nonce in ocsp response");
+ return;
+ }
+ /* check if the response is signed by a trusted key */
+ if (!valid_ocsp_response(&res))
{
- if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx))
+ plog("invalid ocsp response");
return;
-
- if (objectID == RESPONSES_SINGLE_RESPONSE)
- {
- single_response_t sres = empty_single_response;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("valid ocsp response")
+ )
- if (parse_ocsp_single_response(object, level+1, &sres))
+ /* now parse the single responses one at a time */
+ {
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+
+ parser = asn1_parser_create(responsesObjects, res.responses);
+
+ while (parser->iterate(parser, &objectID, &object))
{
- process_single_response(location, &sres);
+ if (objectID == RESPONSES_SINGLE_RESPONSE)
+ {
+ single_response_t sres = empty_single_response;
+
+ if (!parse_ocsp_single_response(object,
+ parser->get_level(parser)+1, &sres))
+ {
+ goto end;
+ }
+ process_single_response(location, &sres);
+ }
}
- }
- objectID++;
+end:
+ parser->destroy(parser);
}
- }
}
diff --git a/src/pluto/ocsp.h b/src/pluto/ocsp.h
index 6bf42831b..d8ee7bd8c 100644
--- a/src/pluto/ocsp.h
+++ b/src/pluto/ocsp.h
@@ -11,27 +11,25 @@
* 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: ocsp.h 3253 2007-10-06 21:39:00Z andreas $
*/
#include "constants.h"
/* constants */
-#define OCSP_BASIC_RESPONSE_VERSION 1
-#define OCSP_DEFAULT_VALID_TIME 120 /* validity of one-time response in seconds */
-#define OCSP_WARNING_INTERVAL 2 /* days */
+#define OCSP_BASIC_RESPONSE_VERSION 1
+#define OCSP_DEFAULT_VALID_TIME 120 /* validity of one-time response in seconds */
+#define OCSP_WARNING_INTERVAL 2 /* days */
/* OCSP response status */
typedef enum {
- STATUS_SUCCESSFUL = 0,
- STATUS_MALFORMEDREQUEST = 1,
- STATUS_INTERNALERROR = 2,
- STATUS_TRYLATER = 3,
- STATUS_SIGREQUIRED = 5,
- STATUS_UNAUTHORIZED= 6
+ STATUS_SUCCESSFUL = 0,
+ STATUS_MALFORMEDREQUEST = 1,
+ STATUS_INTERNALERROR = 2,
+ STATUS_TRYLATER = 3,
+ STATUS_SIGREQUIRED = 5,
+ STATUS_UNAUTHORIZED= 6
} response_status;
/* OCSP access structures */
@@ -39,46 +37,46 @@ typedef enum {
typedef struct ocsp_certinfo ocsp_certinfo_t;
struct ocsp_certinfo {
- ocsp_certinfo_t *next;
- int trials;
- chunk_t serialNumber;
- cert_status_t status;
- bool once;
- crl_reason_t revocationReason;
- time_t revocationTime;
- time_t thisUpdate;
- time_t nextUpdate;
+ ocsp_certinfo_t *next;
+ int trials;
+ chunk_t serialNumber;
+ cert_status_t status;
+ bool once;
+ crl_reason_t revocationReason;
+ time_t revocationTime;
+ time_t thisUpdate;
+ time_t nextUpdate;
};
typedef struct ocsp_location ocsp_location_t;
struct ocsp_location {
- ocsp_location_t *next;
- chunk_t issuer;
- chunk_t authNameID;
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- chunk_t uri;
- chunk_t nonce;
- ocsp_certinfo_t *certinfo;
+ ocsp_location_t *next;
+ chunk_t issuer;
+ chunk_t authNameID;
+ chunk_t authKeyID;
+ chunk_t authKeySerialNumber;
+ chunk_t uri;
+ chunk_t nonce;
+ ocsp_certinfo_t *certinfo;
};
extern ocsp_location_t* get_ocsp_location(const ocsp_location_t *loc
- , ocsp_location_t *chain);
+ , ocsp_location_t *chain);
extern ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc
- , ocsp_location_t **chain);
+ , ocsp_location_t **chain);
extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info
- , ocsp_location_t **chain, bool request);
+ , ocsp_location_t **chain, bool request);
extern void check_ocsp(void);
extern cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until
- , time_t *revocationTime, crl_reason_t *revocationReason);
+ , time_t *revocationTime, crl_reason_t *revocationReason);
extern bool ocsp_set_request_cert(char* path);
extern void ocsp_set_default_uri(char* uri);
extern void ocsp_cache_add_cert(const x509cert_t* cert);
extern chunk_t build_ocsp_request(ocsp_location_t* location);
extern void parse_ocsp(ocsp_location_t* location, chunk_t blob);
extern void list_ocsp_locations(ocsp_location_t *location, bool requests
- , bool utc, bool strict);
+ , bool utc, bool strict);
extern void list_ocsp_cache(bool utc, bool strict);
extern void free_ocsp_locations(ocsp_location_t **chain);
extern void free_ocsp_cache(void);
diff --git a/src/pluto/packet.c b/src/pluto/packet.c
index e8a3a1e11..01967efed 100644
--- a/src/pluto/packet.c
+++ b/src/pluto/packet.c
@@ -11,8 +11,6 @@
* 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: packet.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -27,7 +25,7 @@
#include "defs.h"
#include "log.h"
#include "packet.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "whack.h" /* for RC_LOG_SERIOUS */
/* ISAKMP Header: for all messages
* layout from RFC 2408 "ISAKMP" section 3.1
@@ -49,15 +47,15 @@
*/
static field_desc isa_fields[] = {
- { ft_raw, COOKIE_SIZE, "initiator cookie", NULL },
- { ft_raw, COOKIE_SIZE, "responder cookie", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_enum, 8/BITS_PER_BYTE, "ISAKMP version", &version_names },
- { ft_enum, 8/BITS_PER_BYTE, "exchange type", &exchange_names },
- { ft_set, 8/BITS_PER_BYTE, "flags", flag_bit_names },
- { ft_raw, 32/BITS_PER_BYTE, "message ID", NULL },
- { ft_len, 32/BITS_PER_BYTE, "length", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_raw, COOKIE_SIZE, "initiator cookie", NULL },
+ { ft_raw, COOKIE_SIZE, "responder cookie", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_enum, 8/BITS_PER_BYTE, "ISAKMP version", &version_names },
+ { ft_enum, 8/BITS_PER_BYTE, "exchange type", &exchange_names },
+ { ft_set, 8/BITS_PER_BYTE, "flags", flag_bit_names },
+ { ft_raw, 32/BITS_PER_BYTE, "message ID", NULL },
+ { ft_len, 32/BITS_PER_BYTE, "length", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_hdr_desc = { "ISAKMP Message", isa_fields, sizeof(struct isakmp_hdr) };
@@ -74,10 +72,10 @@ struct_desc isakmp_hdr_desc = { "ISAKMP Message", isa_fields, sizeof(struct isak
*/
static field_desc isag_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_generic_desc = { "ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) };
@@ -100,36 +98,36 @@ struct_desc isakmp_generic_desc = { "ISAKMP Generic Payload", isag_fields, sizeo
/* Oakley Attributes */
static field_desc isaat_fields_oakley[] = {
- { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &oakley_attr_names },
- { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &oakley_attr_names },
+ { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_oakley_attribute_desc = {
- "ISAKMP Oakley attribute",
- isaat_fields_oakley, sizeof(struct isakmp_attribute) };
+ "ISAKMP Oakley attribute",
+ isaat_fields_oakley, sizeof(struct isakmp_attribute) };
/* IPsec DOI Attributes */
static field_desc isaat_fields_ipsec[] = {
- { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &ipsec_attr_names },
- { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &ipsec_attr_names },
+ { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_ipsec_attribute_desc = {
- "ISAKMP IPsec DOI attribute",
- isaat_fields_ipsec, sizeof(struct isakmp_attribute) };
+ "ISAKMP IPsec DOI attribute",
+ isaat_fields_ipsec, sizeof(struct isakmp_attribute) };
/* Mode Config Attributes */
static field_desc isaat_fields_modecfg[] = {
- { ft_af_loose_enum, 16/BITS_PER_BYTE, "ModeCfg attr type", &modecfg_attr_names },
- { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_af_loose_enum, 16/BITS_PER_BYTE, "ModeCfg attr type", &modecfg_attr_names },
+ { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_modecfg_attribute_desc = {
- "ISAKMP ModeCfg attribute",
- isaat_fields_modecfg, sizeof(struct isakmp_attribute) };
+ "ISAKMP ModeCfg attribute",
+ isaat_fields_modecfg, sizeof(struct isakmp_attribute) };
/* ISAKMP Security Association Payload
* layout from RFC 2408 "ISAKMP" section 3.4
@@ -148,18 +146,18 @@ struct_desc isakmp_modecfg_attribute_desc = {
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isasa_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_sa_desc = { "ISAKMP Security Association Payload", isasa_fields, sizeof(struct isakmp_sa) };
static field_desc ipsec_sit_field[] = {
- { ft_set, 32/BITS_PER_BYTE, "IPsec DOI SIT", &sit_bit_names },
- { ft_end, 0, NULL, NULL }
+ { ft_set, 32/BITS_PER_BYTE, "IPsec DOI SIT", &sit_bit_names },
+ { ft_end, 0, NULL, NULL }
};
struct_desc ipsec_sit_desc = { "IPsec DOI SIT", ipsec_sit_field, sizeof(u_int32_t) };
@@ -179,14 +177,14 @@ struct_desc ipsec_sit_desc = { "IPsec DOI SIT", ipsec_sit_field, sizeof(u_int32_
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isap_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "proposal number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "protocol ID", &protocol_names },
- { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "number of transforms", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "proposal number", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "protocol ID", &protocol_names },
+ { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "number of transforms", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_proposal_desc = { "ISAKMP Proposal Payload", isap_fields, sizeof(struct isakmp_proposal) };
@@ -210,63 +208,63 @@ struct_desc isakmp_proposal_desc = { "ISAKMP Proposal Payload", isap_fields, siz
/* PROTO_ISAKMP */
static field_desc isat_fields_isakmp[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &isakmp_transformid_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "transform ID", &isakmp_transformid_names },
+ { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_isakmp_transform_desc = {
- "ISAKMP Transform Payload (ISAKMP)",
- isat_fields_isakmp, sizeof(struct isakmp_transform) };
+ "ISAKMP Transform Payload (ISAKMP)",
+ isat_fields_isakmp, sizeof(struct isakmp_transform) };
/* PROTO_IPSEC_AH */
static field_desc isat_fields_ah[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transformid_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transformid_names },
+ { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_ah_transform_desc = {
- "ISAKMP Transform Payload (AH)",
- isat_fields_ah, sizeof(struct isakmp_transform) };
+ "ISAKMP Transform Payload (AH)",
+ isat_fields_ah, sizeof(struct isakmp_transform) };
/* PROTO_IPSEC_ESP */
static field_desc isat_fields_esp[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transformid_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transformid_names },
+ { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_esp_transform_desc = {
- "ISAKMP Transform Payload (ESP)",
- isat_fields_esp, sizeof(struct isakmp_transform) };
+ "ISAKMP Transform Payload (ESP)",
+ isat_fields_esp, sizeof(struct isakmp_transform) };
/* PROTO_IPCOMP */
static field_desc isat_fields_ipcomp[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ipcomp_transformid_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ipcomp_transformid_names },
+ { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_ipcomp_transform_desc = {
- "ISAKMP Transform Payload (COMP)",
- isat_fields_ipcomp, sizeof(struct isakmp_transform) };
+ "ISAKMP Transform Payload (COMP)",
+ isat_fields_ipcomp, sizeof(struct isakmp_transform) };
/* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones.
@@ -303,13 +301,13 @@ struct_desc isakmp_keyex_desc = { "ISAKMP Key Exchange Payload", isag_fields, si
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isaid_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, /* ??? depends on DOI? */
- { ft_nat, 8/BITS_PER_BYTE, "DOI specific A", NULL }, /* ??? depends on DOI? */
- { ft_nat, 16/BITS_PER_BYTE, "DOI specific B", NULL }, /* ??? depends on DOI? */
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, /* ??? depends on DOI? */
+ { ft_nat, 8/BITS_PER_BYTE, "DOI specific A", NULL }, /* ??? depends on DOI? */
+ { ft_nat, 16/BITS_PER_BYTE, "DOI specific B", NULL }, /* ??? depends on DOI? */
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_identification_desc = { "ISAKMP Identification Payload", isaid_fields, sizeof(struct isakmp_id) };
@@ -330,13 +328,13 @@ struct_desc isakmp_identification_desc = { "ISAKMP Identification Payload", isai
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isaiid_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
- { ft_nat, 8/BITS_PER_BYTE, "Protocol ID", NULL }, /* ??? UDP/TCP or 0? */
- { ft_nat, 16/BITS_PER_BYTE, "port", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
+ { ft_nat, 8/BITS_PER_BYTE, "Protocol ID", NULL }, /* ??? UDP/TCP or 0? */
+ { ft_nat, 16/BITS_PER_BYTE, "port", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_ipsec_identification_desc = { "ISAKMP Identification Payload (IPsec DOI)", isaiid_fields, sizeof(struct isakmp_ipsec_id) };
@@ -357,11 +355,11 @@ struct_desc isakmp_ipsec_identification_desc = { "ISAKMP Identification Payload
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isacert_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "cert encoding", &cert_type_names },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "cert encoding", &cert_type_names },
+ { ft_end, 0, NULL, NULL }
};
/* Note: the size field of isakmp_ipsec_certificate_desc cannot be
@@ -385,11 +383,11 @@ static field_desc isacert_fields[] = {
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isacr_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "cert type", &cert_type_names },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "cert type", &cert_type_names },
+ { ft_end, 0, NULL, NULL }
};
/* Note: the size field of isakmp_ipsec_cert_req_desc cannot be
@@ -469,14 +467,14 @@ struct_desc isakmp_nonce_desc = { "ISAKMP Nonce Payload", isag_fields, sizeof(st
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isan_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
- { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC, ESP, ... */
- { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
- { ft_enum, 16/BITS_PER_BYTE, "Notify Message Type", &notification_names },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
+ { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC, ESP, ... */
+ { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
+ { ft_enum, 16/BITS_PER_BYTE, "Notify Message Type", &notification_names },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_notification_desc = { "ISAKMP Notification Payload", isan_fields, sizeof(struct isakmp_notification) };
@@ -500,14 +498,14 @@ struct_desc isakmp_notification_desc = { "ISAKMP Notification Payload", isan_fie
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isad_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
- { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC */
- { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "number of SPIs", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
+ { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC */
+ { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "number of SPIs", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_delete_desc = { "ISAKMP Delete Payload", isad_fields, sizeof(struct isakmp_delete) };
@@ -532,26 +530,26 @@ struct_desc isakmp_vendor_id_desc = { "ISAKMP Vendor ID Payload", isag_fields, s
/*
* From draft-dukes-ike-mode-cfg
3.2. Attribute Payload
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Next Payload ! RESERVED ! Payload Length !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Type ! RESERVED ! Identifier !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! !
- ~ Attributes ~
- ! !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Type ! RESERVED ! Identifier !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isaattr_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "Attr Msg Type", &attr_msg_type_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Identifier", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "Attr Msg Type", &attr_msg_type_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Identifier", NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_attr_desc = { "ISAKMP Mode Attribute", isaattr_fields, sizeof(struct isakmp_mode_attr) };
@@ -581,12 +579,12 @@ struct_desc isakmp_nat_d = { "ISAKMP NAT-D Payload", isag_fields, sizeof(struct
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static field_desc isanat_oa_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
- { ft_mbz, 24/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
+ { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
+ { ft_len, 16/BITS_PER_BYTE, "length", NULL },
+ { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
+ { ft_mbz, 24/BITS_PER_BYTE, NULL, NULL },
+ { ft_end, 0, NULL, NULL }
};
struct_desc isakmp_nat_oa = { "ISAKMP NAT-OA Payload", isanat_oa_fields, sizeof(struct isakmp_nat_oa) };
@@ -600,40 +598,40 @@ struct_desc isakmp_nat_oa = { "ISAKMP NAT-OA Payload", isanat_oa_fields, sizeof(
* We make all these entries NULL
*/
struct_desc *const payload_descs[ISAKMP_NEXT_ROOF] = {
- NULL, /* 0 ISAKMP_NEXT_NONE (No other payload following) */
- &isakmp_sa_desc, /* 1 ISAKMP_NEXT_SA (Security Association) */
- NULL, /* 2 ISAKMP_NEXT_P (Proposal) */
- NULL, /* 3 ISAKMP_NEXT_T (Transform) */
- &isakmp_keyex_desc, /* 4 ISAKMP_NEXT_KE (Key Exchange) */
- NULL, /* 5 ISAKMP_NEXT_ID (Identification) */
- &isakmp_ipsec_certificate_desc, /* 6 ISAKMP_NEXT_CERT (Certificate) */
- &isakmp_ipsec_cert_req_desc, /* 7 ISAKMP_NEXT_CR (Certificate Request) */
- &isakmp_hash_desc, /* 8 ISAKMP_NEXT_HASH (Hash) */
- &isakmp_signature_desc, /* 9 ISAKMP_NEXT_SIG (Signature) */
- &isakmp_nonce_desc, /* 10 ISAKMP_NEXT_NONCE (Nonce) */
- &isakmp_notification_desc, /* 11 ISAKMP_NEXT_N (Notification) */
- &isakmp_delete_desc, /* 12 ISAKMP_NEXT_D (Delete) */
- &isakmp_vendor_id_desc, /* 13 ISAKMP_NEXT_VID (Vendor ID) */
- &isakmp_attr_desc, /* 14 ISAKMP_NEXT_ATTR (Mode Config) */
- NULL, /* 15 */
- NULL, /* 16 */
- NULL, /* 17 */
- NULL, /* 18 */
- NULL, /* 19 */
- &isakmp_nat_d, /* 20=130 ISAKMP_NEXT_NATD (NAT-D) */
- &isakmp_nat_oa, /* 20=131 ISAKMP_NEXT_NATOA (NAT-OA) */
+ NULL, /* 0 ISAKMP_NEXT_NONE (No other payload following) */
+ &isakmp_sa_desc, /* 1 ISAKMP_NEXT_SA (Security Association) */
+ NULL, /* 2 ISAKMP_NEXT_P (Proposal) */
+ NULL, /* 3 ISAKMP_NEXT_T (Transform) */
+ &isakmp_keyex_desc, /* 4 ISAKMP_NEXT_KE (Key Exchange) */
+ NULL, /* 5 ISAKMP_NEXT_ID (Identification) */
+ &isakmp_ipsec_certificate_desc, /* 6 ISAKMP_NEXT_CERT (Certificate) */
+ &isakmp_ipsec_cert_req_desc, /* 7 ISAKMP_NEXT_CR (Certificate Request) */
+ &isakmp_hash_desc, /* 8 ISAKMP_NEXT_HASH (Hash) */
+ &isakmp_signature_desc, /* 9 ISAKMP_NEXT_SIG (Signature) */
+ &isakmp_nonce_desc, /* 10 ISAKMP_NEXT_NONCE (Nonce) */
+ &isakmp_notification_desc, /* 11 ISAKMP_NEXT_N (Notification) */
+ &isakmp_delete_desc, /* 12 ISAKMP_NEXT_D (Delete) */
+ &isakmp_vendor_id_desc, /* 13 ISAKMP_NEXT_VID (Vendor ID) */
+ &isakmp_attr_desc, /* 14 ISAKMP_NEXT_ATTR (Mode Config) */
+ NULL, /* 15 */
+ NULL, /* 16 */
+ NULL, /* 17 */
+ NULL, /* 18 */
+ NULL, /* 19 */
+ &isakmp_nat_d, /* 20=130 ISAKMP_NEXT_NATD (NAT-D) */
+ &isakmp_nat_oa, /* 20=131 ISAKMP_NEXT_NATOA (NAT-OA) */
};
void
init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name)
{
- pbs->container = NULL;
- pbs->desc = NULL;
- pbs->name = name;
- pbs->start = pbs->cur = start;
- pbs->roof = start + len;
- pbs->lenfld = NULL;
- pbs->lenfld_desc = NULL;
+ pbs->container = NULL;
+ pbs->desc = NULL;
+ pbs->name = name;
+ pbs->start = pbs->cur = start;
+ pbs->roof = start + len;
+ pbs->lenfld = NULL;
+ pbs->lenfld_desc = NULL;
}
#ifdef DEBUG
@@ -648,85 +646,85 @@ void
DBG_print_struct(const char *label, const void *struct_ptr
, struct_desc *sd, bool len_meaningful)
{
- bool immediate = FALSE;
- const u_int8_t *inp = struct_ptr;
- field_desc *fp;
-
- DBG_log("%s%s:", label, sd->name);
+ bool immediate = FALSE;
+ const u_int8_t *inp = struct_ptr;
+ field_desc *fp;
- for (fp = sd->fields; fp->field_type != ft_end; fp++)
- {
- int i = fp->size;
- u_int32_t n = 0;
+ DBG_log("%s%s:", label, sd->name);
- switch (fp->field_type)
+ for (fp = sd->fields; fp->field_type != ft_end; fp++)
{
- case ft_mbz: /* must be zero */
- inp += i;
- break;
- case ft_nat: /* natural number (may be 0) */
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- case ft_set: /* bits representing set */
- switch (i)
- {
- case 8/BITS_PER_BYTE:
- n = *(const u_int8_t *)inp;
- break;
- case 16/BITS_PER_BYTE:
- n = *(const u_int16_t *)inp;
- break;
- case 32/BITS_PER_BYTE:
- n = *(const u_int32_t *)inp;
- break;
- default:
- bad_case(i);
- }
- switch (fp->field_type)
- {
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- if (!immediate && !len_meaningful)
- break;
- /* FALL THROUGH */
- case ft_nat: /* natural number (may be 0) */
- DBG_log(" %s: %lu", fp->name, (unsigned long)n);
- break;
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- /* FALL THROUGH */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- DBG_log(" %s: %s", fp->name, enum_show(fp->desc, n));
- break;
- case ft_set: /* bits representing set */
- DBG_log(" %s: %s", fp->name, bitnamesof(fp->desc, n));
- break;
- default:
- bad_case(fp->field_type);
- }
- inp += i;
- break;
-
- case ft_raw: /* bytes to be left in network-order */
- {
- char m[50]; /* arbitrary limit on name width in log */
-
- snprintf(m, sizeof(m), " %s:", fp->name);
- DBG_dump(m, inp, i);
- inp += i;
- }
- break;
- default:
- bad_case(fp->field_type);
+ int i = fp->size;
+ u_int32_t n = 0;
+
+ switch (fp->field_type)
+ {
+ case ft_mbz: /* must be zero */
+ inp += i;
+ break;
+ case ft_nat: /* natural number (may be 0) */
+ case ft_len: /* length of this struct and any following crud */
+ case ft_lv: /* length/value field of attribute */
+ case ft_enum: /* value from an enumeration */
+ case ft_loose_enum: /* value from an enumeration with only some names known */
+ case ft_af_enum: /* Attribute Format + value from an enumeration */
+ case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
+ case ft_set: /* bits representing set */
+ switch (i)
+ {
+ case 8/BITS_PER_BYTE:
+ n = *(const u_int8_t *)inp;
+ break;
+ case 16/BITS_PER_BYTE:
+ n = *(const u_int16_t *)inp;
+ break;
+ case 32/BITS_PER_BYTE:
+ n = *(const u_int32_t *)inp;
+ break;
+ default:
+ bad_case(i);
+ }
+ switch (fp->field_type)
+ {
+ case ft_len: /* length of this struct and any following crud */
+ case ft_lv: /* length/value field of attribute */
+ if (!immediate && !len_meaningful)
+ break;
+ /* FALL THROUGH */
+ case ft_nat: /* natural number (may be 0) */
+ DBG_log(" %s: %lu", fp->name, (unsigned long)n);
+ break;
+ case ft_af_enum: /* Attribute Format + value from an enumeration */
+ case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
+ if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+ immediate = TRUE;
+ /* FALL THROUGH */
+ case ft_enum: /* value from an enumeration */
+ case ft_loose_enum: /* value from an enumeration with only some names known */
+ DBG_log(" %s: %s", fp->name, enum_show(fp->desc, n));
+ break;
+ case ft_set: /* bits representing set */
+ DBG_log(" %s: %s", fp->name, bitnamesof(fp->desc, n));
+ break;
+ default:
+ bad_case(fp->field_type);
+ }
+ inp += i;
+ break;
+
+ case ft_raw: /* bytes to be left in network-order */
+ {
+ char m[50]; /* arbitrary limit on name width in log */
+
+ snprintf(m, sizeof(m), " %s:", fp->name);
+ DBG_dump(m, inp, i);
+ inp += i;
+ }
+ break;
+ default:
+ bad_case(fp->field_type);
+ }
}
- }
}
static void
@@ -734,35 +732,35 @@ DBG_prefix_print_struct(const pb_stream *pbs
, const char *label, const void *struct_ptr
, struct_desc *sd, bool len_meaningful)
{
- /* print out a title, with a prefix of asterisks to show
- * the nesting level.
- */
- char space[40]; /* arbitrary limit on label+flock-of-* */
- size_t len = strlen(label);
-
- if (sizeof(space) <= len)
- {
- DBG_print_struct(label, struct_ptr, sd, len_meaningful);
- }
- else
- {
- const pb_stream *p = pbs;
- char *pre = &space[sizeof(space) - (len + 1)];
-
- strcpy(pre, label);
-
- /* put at least one * out */
- for (;;)
+ /* print out a title, with a prefix of asterisks to show
+ * the nesting level.
+ */
+ char space[40]; /* arbitrary limit on label+flock-of-* */
+ size_t len = strlen(label);
+
+ if (sizeof(space) <= len)
+ {
+ DBG_print_struct(label, struct_ptr, sd, len_meaningful);
+ }
+ else
{
- if (pre <= space)
- break;
- *--pre = '*';
- if (p == NULL)
- break;
- p = p->container;
+ const pb_stream *p = pbs;
+ char *pre = &space[sizeof(space) - (len + 1)];
+
+ strcpy(pre, label);
+
+ /* put at least one * out */
+ for (;;)
+ {
+ if (pre <= space)
+ break;
+ *--pre = '*';
+ if (p == NULL)
+ break;
+ p = p->container;
+ }
+ DBG_print_struct(pre, struct_ptr, sd, len_meaningful);
}
- DBG_print_struct(pre, struct_ptr, sd, len_meaningful);
- }
}
#endif
@@ -785,191 +783,191 @@ bool
in_struct(void *struct_ptr, struct_desc *sd
, pb_stream *ins, pb_stream *obj_pbs)
{
- err_t ugh = NULL;
- u_int8_t *cur = ins->cur;
-
- if (ins->roof - cur < (ptrdiff_t)sd->size)
- {
- ugh = builddiag("not enough room in input packet for %s", sd->name);
- }
- else
- {
- u_int8_t *roof = cur + sd->size; /* may be changed by a length field */
- u_int8_t *outp = struct_ptr;
- bool immediate = FALSE;
- field_desc *fp;
+ err_t ugh = NULL;
+ u_int8_t *cur = ins->cur;
- for (fp = sd->fields; ugh == NULL; fp++)
+ if (ins->roof - cur < (ptrdiff_t)sd->size)
{
- size_t i = fp->size;
-
- passert(ins->roof - cur >= (ptrdiff_t)i);
- passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
- passert(outp - (cur - ins->cur) == struct_ptr);
-
-#if 0
- DBG(DBG_PARSING, DBG_log("%d %s"
- , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
-#endif
- switch (fp->field_type)
- {
- case ft_mbz: /* must be zero */
- for (; i != 0; i--)
- {
- if (*cur++ != 0)
- {
- ugh = builddiag("byte %d of %s must be zero, but is not"
- , (int) (cur - ins->cur), sd->name);
- break;
- }
- *outp++ = '\0'; /* probably redundant */
- }
- break;
-
- case ft_nat: /* natural number (may be 0) */
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- case ft_set: /* bits representing set */
- {
- u_int32_t n = 0;
-
- for (; i != 0; i--)
- n = (n << BITS_PER_BYTE) | *cur++;
+ ugh = builddiag("not enough room in input packet for %s", sd->name);
+ }
+ else
+ {
+ u_int8_t *roof = cur + sd->size; /* may be changed by a length field */
+ u_int8_t *outp = struct_ptr;
+ bool immediate = FALSE;
+ field_desc *fp;
- switch (fp->field_type)
- {
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- {
- u_int32_t len = fp->field_type == ft_len? n
- : immediate? sd->size : n + sd->size;
-
- if (len < sd->size)
- {
- ugh = builddiag("%s of %s is smaller than minimum"
- , fp->name, sd->name);
- }
- else if (pbs_left(ins) < len)
- {
- ugh = builddiag("%s of %s is larger than can fit"
- , fp->name, sd->name);
- }
- else
- {
- roof = ins->cur + len;
- }
- break;
- }
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- break;
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- /* FALL THROUGH */
- case ft_enum: /* value from an enumeration */
- if (enum_name(fp->desc, n) == NULL)
- {
- ugh = builddiag("%s of %s has an unknown value: %lu"
- , fp->name, sd->name, (unsigned long)n);
- }
- /* FALL THROUGH */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- break;
- case ft_set: /* bits representing set */
- if (!testset(fp->desc, n))
- {
- ugh = builddiag("bitset %s of %s has unknown member(s): %s"
- , fp->name, sd->name, bitnamesof(fp->desc, n));
- }
- break;
- default:
- break;
- }
- i = fp->size;
- switch (i)
+ for (fp = sd->fields; ugh == NULL; fp++)
{
- case 8/BITS_PER_BYTE:
- *(u_int8_t *)outp = n;
- break;
- case 16/BITS_PER_BYTE:
- *(u_int16_t *)outp = n;
- break;
- case 32/BITS_PER_BYTE:
- *(u_int32_t *)outp = n;
- break;
- default:
- bad_case(i);
- }
- outp += i;
- break;
- }
+ size_t i = fp->size;
- case ft_raw: /* bytes to be left in network-order */
- for (; i != 0; i--)
- {
- *outp++ = *cur++;
- }
- break;
+ passert(ins->roof - cur >= (ptrdiff_t)i);
+ passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
+ passert(outp - (cur - ins->cur) == struct_ptr);
- case ft_end: /* end of field list */
- passert(cur == ins->cur + sd->size);
- if (obj_pbs != NULL)
- {
- init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name);
- obj_pbs->container = ins;
- obj_pbs->desc = sd;
- obj_pbs->cur = cur;
+#if 0
+ DBG(DBG_PARSING, DBG_log("%d %s"
+ , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
+#endif
+ switch (fp->field_type)
+ {
+ case ft_mbz: /* must be zero */
+ for (; i != 0; i--)
+ {
+ if (*cur++ != 0)
+ {
+ ugh = builddiag("byte %d of %s must be zero, but is not"
+ , (int) (cur - ins->cur), sd->name);
+ break;
+ }
+ *outp++ = '\0'; /* probably redundant */
+ }
+ break;
+
+ case ft_nat: /* natural number (may be 0) */
+ case ft_len: /* length of this struct and any following crud */
+ case ft_lv: /* length/value field of attribute */
+ case ft_enum: /* value from an enumeration */
+ case ft_loose_enum: /* value from an enumeration with only some names known */
+ case ft_af_enum: /* Attribute Format + value from an enumeration */
+ case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
+ case ft_set: /* bits representing set */
+ {
+ u_int32_t n = 0;
+
+ for (; i != 0; i--)
+ n = (n << BITS_PER_BYTE) | *cur++;
+
+ switch (fp->field_type)
+ {
+ case ft_len: /* length of this struct and any following crud */
+ case ft_lv: /* length/value field of attribute */
+ {
+ u_int32_t len = fp->field_type == ft_len? n
+ : immediate? sd->size : n + sd->size;
+
+ if (len < sd->size)
+ {
+ ugh = builddiag("%s of %s is smaller than minimum"
+ , fp->name, sd->name);
+ }
+ else if (pbs_left(ins) < len)
+ {
+ ugh = builddiag("%s of %s is larger than can fit"
+ , fp->name, sd->name);
+ }
+ else
+ {
+ roof = ins->cur + len;
+ }
+ break;
+ }
+ case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
+ if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+ immediate = TRUE;
+ break;
+ case ft_af_enum: /* Attribute Format + value from an enumeration */
+ if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+ immediate = TRUE;
+ /* FALL THROUGH */
+ case ft_enum: /* value from an enumeration */
+ if (enum_name(fp->desc, n) == NULL)
+ {
+ ugh = builddiag("%s of %s has an unknown value: %lu"
+ , fp->name, sd->name, (unsigned long)n);
+ }
+ /* FALL THROUGH */
+ case ft_loose_enum: /* value from an enumeration with only some names known */
+ break;
+ case ft_set: /* bits representing set */
+ if (!testset(fp->desc, n))
+ {
+ ugh = builddiag("bitset %s of %s has unknown member(s): %s"
+ , fp->name, sd->name, bitnamesof(fp->desc, n));
+ }
+ break;
+ default:
+ break;
+ }
+ i = fp->size;
+ switch (i)
+ {
+ case 8/BITS_PER_BYTE:
+ *(u_int8_t *)outp = n;
+ break;
+ case 16/BITS_PER_BYTE:
+ *(u_int16_t *)outp = n;
+ break;
+ case 32/BITS_PER_BYTE:
+ *(u_int32_t *)outp = n;
+ break;
+ default:
+ bad_case(i);
+ }
+ outp += i;
+ break;
+ }
+
+ case ft_raw: /* bytes to be left in network-order */
+ for (; i != 0; i--)
+ {
+ *outp++ = *cur++;
+ }
+ break;
+
+ case ft_end: /* end of field list */
+ passert(cur == ins->cur + sd->size);
+ if (obj_pbs != NULL)
+ {
+ init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name);
+ obj_pbs->container = ins;
+ obj_pbs->desc = sd;
+ obj_pbs->cur = cur;
+ }
+ ins->cur = roof;
+ DBG(DBG_PARSING
+ , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
+ return TRUE;
+
+ default:
+ bad_case(fp->field_type);
+ }
}
- ins->cur = roof;
- DBG(DBG_PARSING
- , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
- return TRUE;
-
- default:
- bad_case(fp->field_type);
- }
}
- }
- /* some failure got us here: report it */
- loglog(RC_LOG_SERIOUS, ugh);
- return FALSE;
+ /* some failure got us here: report it */
+ loglog(RC_LOG_SERIOUS, ugh);
+ return FALSE;
}
bool
in_raw(void *bytes, size_t len, pb_stream *ins, const char *name)
{
- if (pbs_left(ins) < len)
- {
- loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name);
- return FALSE;
- }
- else
- {
- if (bytes == NULL)
+ if (pbs_left(ins) < len)
{
- DBG(DBG_PARSING
- , DBG_log("skipping %u raw bytes of %s (%s)"
- , (unsigned) len, ins->name, name);
- DBG_dump(name, ins->cur, len));
+ loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name);
+ return FALSE;
}
else
{
- memcpy(bytes, ins->cur, len);
- DBG(DBG_PARSING
- , DBG_log("parsing %u raw bytes of %s into %s"
- , (unsigned) len, ins->name, name);
- DBG_dump(name, bytes, len));
+ if (bytes == NULL)
+ {
+ DBG(DBG_PARSING
+ , DBG_log("skipping %u raw bytes of %s (%s)"
+ , (unsigned) len, ins->name, name);
+ DBG_dump(name, ins->cur, len));
+ }
+ else
+ {
+ memcpy(bytes, ins->cur, len);
+ DBG(DBG_PARSING
+ , DBG_log("parsing %u raw bytes of %s into %s"
+ , (unsigned) len, ins->name, name);
+ DBG_dump(name, bytes, len));
+ }
+ ins->cur += len;
+ return TRUE;
}
- ins->cur += len;
- return TRUE;
- }
}
/* "emit" a host struct into a network packet.
@@ -994,227 +992,227 @@ bool
out_struct(const void *struct_ptr, struct_desc *sd
, pb_stream *outs, pb_stream *obj_pbs)
{
- err_t ugh = NULL;
- const u_int8_t *inp = struct_ptr;
- u_int8_t *cur = outs->cur;
-
- DBG(DBG_EMITTING
- , DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL));
-
- if (outs->roof - cur < (ptrdiff_t)sd->size)
- {
- ugh = builddiag("not enough room left in output packet to place %s"
- , sd->name);
- }
- else
- {
- bool immediate = FALSE;
- pb_stream obj;
- field_desc *fp;
+ err_t ugh = NULL;
+ const u_int8_t *inp = struct_ptr;
+ u_int8_t *cur = outs->cur;
- obj.lenfld = NULL; /* until a length field is discovered */
- obj.lenfld_desc = NULL;
+ DBG(DBG_EMITTING
+ , DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL));
- for (fp = sd->fields; ugh == NULL; fp++)
+ if (outs->roof - cur < (ptrdiff_t)sd->size)
{
- size_t i = fp->size;
-
- passert(outs->roof - cur >= (ptrdiff_t)i);
- passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i));
- passert(inp - (cur - outs->cur) == struct_ptr);
-
-#if 0
- DBG(DBG_EMITTING, DBG_log("%d %s"
- , (int) (cur - outs->cur), fp->name == NULL? "" : fp->name);
-#endif
- switch (fp->field_type)
- {
- case ft_mbz: /* must be zero */
- inp += i;
- for (; i != 0; i--)
- *cur++ = '\0';
- break;
- case ft_nat: /* natural number (may be 0) */
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- case ft_set: /* bits representing set */
- {
- u_int32_t n = 0;
+ ugh = builddiag("not enough room left in output packet to place %s"
+ , sd->name);
+ }
+ else
+ {
+ bool immediate = FALSE;
+ pb_stream obj;
+ field_desc *fp;
- switch (i)
- {
- case 8/BITS_PER_BYTE:
- n = *(const u_int8_t *)inp;
- break;
- case 16/BITS_PER_BYTE:
- n = *(const u_int16_t *)inp;
- break;
- case 32/BITS_PER_BYTE:
- n = *(const u_int32_t *)inp;
- break;
- default:
- bad_case(i);
- }
+ obj.lenfld = NULL; /* until a length field is discovered */
+ obj.lenfld_desc = NULL;
- switch (fp->field_type)
+ for (fp = sd->fields; ugh == NULL; fp++)
{
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- if (immediate)
- break; /* not a length */
- /* We can't check the length because it will likely
- * be filled in after variable part is supplied.
- * We do record where this is so that it can be
- * filled in by a subsequent close_output_pbs().
- */
- passert(obj.lenfld == NULL); /* only one ft_len allowed */
- obj.lenfld = cur;
- obj.lenfld_desc = fp;
- break;
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- break;
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- /* FALL THROUGH */
- case ft_enum: /* value from an enumeration */
- if (enum_name(fp->desc, n) == NULL)
- {
- ugh = builddiag("%s of %s has an unknown value: %lu"
- , fp->name, sd->name, (unsigned long)n);
- }
- /* FALL THROUGH */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- break;
- case ft_set: /* bits representing set */
- if (!testset(fp->desc, n))
- {
- ugh = builddiag("bitset %s of %s has unknown member(s): %s"
- , fp->name, sd->name, bitnamesof(fp->desc, n));
- }
- break;
- default:
- break;
- }
+ size_t i = fp->size;
- while (i-- != 0)
- {
- cur[i] = (u_int8_t)n;
- n >>= BITS_PER_BYTE;
- }
- inp += fp->size;
- cur += fp->size;
- break;
- }
- case ft_raw: /* bytes to be left in network-order */
- for (; i != 0; i--)
- *cur++ = *inp++;
- break;
- case ft_end: /* end of field list */
- passert(cur == outs->cur + sd->size);
-
- obj.container = outs;
- obj.desc = sd;
- obj.name = sd->name;
- obj.start = outs->cur;
- obj.cur = cur;
- obj.roof = outs->roof; /* limit of possible */
- /* obj.lenfld and obj.lenfld_desc already set */
-
- if (obj_pbs == NULL)
- {
- close_output_pbs(&obj); /* fill in length field, if any */
- }
- else
- {
- /* We set outs->cur to outs->roof so that
- * any attempt to output something into outs
- * before obj is closed will trigger an error.
- */
- outs->cur = outs->roof;
+ passert(outs->roof - cur >= (ptrdiff_t)i);
+ passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i));
+ passert(inp - (cur - outs->cur) == struct_ptr);
- *obj_pbs = obj;
+#if 0
+ DBG(DBG_EMITTING, DBG_log("%d %s"
+ , (int) (cur - outs->cur), fp->name == NULL? "" : fp->name);
+#endif
+ switch (fp->field_type)
+ {
+ case ft_mbz: /* must be zero */
+ inp += i;
+ for (; i != 0; i--)
+ *cur++ = '\0';
+ break;
+ case ft_nat: /* natural number (may be 0) */
+ case ft_len: /* length of this struct and any following crud */
+ case ft_lv: /* length/value field of attribute */
+ case ft_enum: /* value from an enumeration */
+ case ft_loose_enum: /* value from an enumeration with only some names known */
+ case ft_af_enum: /* Attribute Format + value from an enumeration */
+ case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
+ case ft_set: /* bits representing set */
+ {
+ u_int32_t n = 0;
+
+ switch (i)
+ {
+ case 8/BITS_PER_BYTE:
+ n = *(const u_int8_t *)inp;
+ break;
+ case 16/BITS_PER_BYTE:
+ n = *(const u_int16_t *)inp;
+ break;
+ case 32/BITS_PER_BYTE:
+ n = *(const u_int32_t *)inp;
+ break;
+ default:
+ bad_case(i);
+ }
+
+ switch (fp->field_type)
+ {
+ case ft_len: /* length of this struct and any following crud */
+ case ft_lv: /* length/value field of attribute */
+ if (immediate)
+ break; /* not a length */
+ /* We can't check the length because it will likely
+ * be filled in after variable part is supplied.
+ * We do record where this is so that it can be
+ * filled in by a subsequent close_output_pbs().
+ */
+ passert(obj.lenfld == NULL); /* only one ft_len allowed */
+ obj.lenfld = cur;
+ obj.lenfld_desc = fp;
+ break;
+ case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
+ if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+ immediate = TRUE;
+ break;
+ case ft_af_enum: /* Attribute Format + value from an enumeration */
+ if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+ immediate = TRUE;
+ /* FALL THROUGH */
+ case ft_enum: /* value from an enumeration */
+ if (enum_name(fp->desc, n) == NULL)
+ {
+ ugh = builddiag("%s of %s has an unknown value: %lu"
+ , fp->name, sd->name, (unsigned long)n);
+ }
+ /* FALL THROUGH */
+ case ft_loose_enum: /* value from an enumeration with only some names known */
+ break;
+ case ft_set: /* bits representing set */
+ if (!testset(fp->desc, n))
+ {
+ ugh = builddiag("bitset %s of %s has unknown member(s): %s"
+ , fp->name, sd->name, bitnamesof(fp->desc, n));
+ }
+ break;
+ default:
+ break;
+ }
+
+ while (i-- != 0)
+ {
+ cur[i] = (u_int8_t)n;
+ n >>= BITS_PER_BYTE;
+ }
+ inp += fp->size;
+ cur += fp->size;
+ break;
+ }
+ case ft_raw: /* bytes to be left in network-order */
+ for (; i != 0; i--)
+ *cur++ = *inp++;
+ break;
+ case ft_end: /* end of field list */
+ passert(cur == outs->cur + sd->size);
+
+ obj.container = outs;
+ obj.desc = sd;
+ obj.name = sd->name;
+ obj.start = outs->cur;
+ obj.cur = cur;
+ obj.roof = outs->roof; /* limit of possible */
+ /* obj.lenfld and obj.lenfld_desc already set */
+
+ if (obj_pbs == NULL)
+ {
+ close_output_pbs(&obj); /* fill in length field, if any */
+ }
+ else
+ {
+ /* We set outs->cur to outs->roof so that
+ * any attempt to output something into outs
+ * before obj is closed will trigger an error.
+ */
+ outs->cur = outs->roof;
+
+ *obj_pbs = obj;
+ }
+ return TRUE;
+
+ default:
+ bad_case(fp->field_type);
+ }
}
- return TRUE;
-
- default:
- bad_case(fp->field_type);
- }
}
- }
- /* some failure got us here: report it */
- loglog(RC_LOG_SERIOUS, ugh); /* ??? serious, but errno not relevant */
- return FALSE;
+ /* some failure got us here: report it */
+ loglog(RC_LOG_SERIOUS, ugh); /* ??? serious, but errno not relevant */
+ return FALSE;
}
bool
out_generic(u_int8_t np, struct_desc *sd
, pb_stream *outs, pb_stream *obj_pbs)
{
- struct isakmp_generic gen;
+ struct isakmp_generic gen;
- passert(sd->fields == isakmp_generic_desc.fields);
- gen.isag_np = np;
- return out_struct(&gen, sd, outs, obj_pbs);
+ passert(sd->fields == isakmp_generic_desc.fields);
+ gen.isag_np = np;
+ return out_struct(&gen, sd, outs, obj_pbs);
}
bool
out_generic_raw(u_int8_t np, struct_desc *sd
, pb_stream *outs, const void *bytes, size_t len, const char *name)
{
- pb_stream pbs;
+ pb_stream pbs;
- if (!out_generic(np, sd, outs, &pbs)
- || !out_raw(bytes, len, &pbs, name))
- return FALSE;
- close_output_pbs(&pbs);
- return TRUE;
+ if (!out_generic(np, sd, outs, &pbs)
+ || !out_raw(bytes, len, &pbs, name))
+ return FALSE;
+ close_output_pbs(&pbs);
+ return TRUE;
}
bool
out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name)
{
- if (pbs_left(outs) < len)
- {
- loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s"
- , (unsigned long) len, name, outs->name);
- return FALSE;
- }
- else
- {
- DBG(DBG_EMITTING
- , DBG_log("emitting %u raw bytes of %s into %s"
- , (unsigned) len, name, outs->name);
- DBG_dump(name, bytes, len));
- memcpy(outs->cur, bytes, len);
- outs->cur += len;
- return TRUE;
- }
+ if (pbs_left(outs) < len)
+ {
+ loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s"
+ , (unsigned long) len, name, outs->name);
+ return FALSE;
+ }
+ else
+ {
+ DBG(DBG_EMITTING
+ , DBG_log("emitting %u raw bytes of %s into %s"
+ , (unsigned) len, name, outs->name);
+ DBG_dump(name, bytes, len));
+ memcpy(outs->cur, bytes, len);
+ outs->cur += len;
+ return TRUE;
+ }
}
bool
out_zero(size_t len, pb_stream *outs, const char *name)
{
- if (pbs_left(outs) < len)
- {
- loglog(RC_LOG_SERIOUS, "not enough room left to place %s in %s", name, outs->name);
- return FALSE;
- }
- else
- {
- DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s"
- , (unsigned) len, name, outs->name));
- memset(outs->cur, 0x00, len);
- outs->cur += len;
- return TRUE;
- }
+ if (pbs_left(outs) < len)
+ {
+ loglog(RC_LOG_SERIOUS, "not enough room left to place %s in %s", name, outs->name);
+ return FALSE;
+ }
+ else
+ {
+ DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s"
+ , (unsigned) len, name, outs->name));
+ memset(outs->cur, 0x00, len);
+ outs->cur += len;
+ return TRUE;
+ }
}
/* Record current length.
@@ -1224,21 +1222,21 @@ out_zero(size_t len, pb_stream *outs, const char *name)
void
close_output_pbs(pb_stream *pbs)
{
- if (pbs->lenfld != NULL)
- {
- u_int32_t len = pbs_offset(pbs);
- int i = pbs->lenfld_desc->size;
-
- if (pbs->lenfld_desc->field_type == ft_lv)
- len -= sizeof(struct isakmp_attribute);
- DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu"
- , pbs->name, (unsigned long) len));
- while (i-- != 0)
+ if (pbs->lenfld != NULL)
{
- pbs->lenfld[i] = (u_int8_t)len;
- len >>= BITS_PER_BYTE;
+ u_int32_t len = pbs_offset(pbs);
+ int i = pbs->lenfld_desc->size;
+
+ if (pbs->lenfld_desc->field_type == ft_lv)
+ len -= sizeof(struct isakmp_attribute);
+ DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu"
+ , pbs->name, (unsigned long) len));
+ while (i-- != 0)
+ {
+ pbs->lenfld[i] = (u_int8_t)len;
+ len >>= BITS_PER_BYTE;
+ }
}
- }
- if (pbs->container != NULL)
- pbs->container->cur = pbs->cur; /* pass space utilization up */
+ if (pbs->container != NULL)
+ pbs->container->cur = pbs->cur; /* pass space utilization up */
}
diff --git a/src/pluto/packet.h b/src/pluto/packet.h
index 1eadf0e02..1510b81a0 100644
--- a/src/pluto/packet.h
+++ b/src/pluto/packet.h
@@ -11,8 +11,6 @@
* 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: packet.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _PACKET_H
@@ -23,9 +21,9 @@
*/
typedef const struct struct_desc {
- const char *name;
- const struct field_desc *fields;
- size_t size;
+ const char *name;
+ const struct field_desc *fields;
+ size_t size;
} struct_desc;
/* Note: if an ft_af_enum field has the ISAKMP_ATTR_AF_TV bit set,
@@ -35,24 +33,24 @@ typedef const struct struct_desc {
*/
enum field_type {
- ft_mbz, /* must be zero */
- ft_nat, /* natural number (may be 0) */
- ft_len, /* length of this struct and any following crud */
- ft_lv, /* length/value field of attribute */
- ft_enum, /* value from an enumeration */
- ft_loose_enum, /* value from an enumeration with only some names known */
- ft_af_loose_enum, /* Attribute Format + enumeration, some names known */
- ft_af_enum, /* Attribute Format + value from an enumeration */
- ft_set, /* bits representing set */
- ft_raw, /* bytes to be left in network-order */
- ft_end, /* end of field list */
+ ft_mbz, /* must be zero */
+ ft_nat, /* natural number (may be 0) */
+ ft_len, /* length of this struct and any following crud */
+ ft_lv, /* length/value field of attribute */
+ ft_enum, /* value from an enumeration */
+ ft_loose_enum, /* value from an enumeration with only some names known */
+ ft_af_loose_enum, /* Attribute Format + enumeration, some names known */
+ ft_af_enum, /* Attribute Format + value from an enumeration */
+ ft_set, /* bits representing set */
+ ft_raw, /* bytes to be left in network-order */
+ ft_end, /* end of field list */
};
typedef const struct field_desc {
- enum field_type field_type;
- int size; /* size, in bytes, of field */
- const char *name;
- const void *desc; /* enum_names for enum or char *[] for bits */
+ enum field_type field_type;
+ int size; /* size, in bytes, of field */
+ const char *name;
+ const void *desc; /* enum_names for enum or char *[] for bits */
} field_desc;
/* The formatting of input and output of packets is done
@@ -62,18 +60,18 @@ typedef const struct field_desc {
* Actual packet transfer is done elsewhere.
*/
typedef struct packet_byte_stream {
- struct packet_byte_stream *container; /* PBS of which we are part */
- struct_desc *desc;
- const char *name; /* what does this PBS represent? */
- u_int8_t
- *start,
- *cur, /* current position in stream */
- *roof; /* byte after last in PBS (actually just a limit on output) */
- /* For an output PBS, the length field will be filled in later so
- * we need to record its particulars. Note: it may not be aligned.
- */
- u_int8_t *lenfld;
- field_desc *lenfld_desc;
+ struct packet_byte_stream *container; /* PBS of which we are part */
+ struct_desc *desc;
+ const char *name; /* what does this PBS represent? */
+ u_int8_t
+ *start,
+ *cur, /* current position in stream */
+ *roof; /* byte after last in PBS (actually just a limit on output) */
+ /* For an output PBS, the length field will be filled in later so
+ * we need to record its particulars. Note: it may not be aligned.
+ */
+ u_int8_t *lenfld;
+ field_desc *lenfld_desc;
} pb_stream;
/* For an input PBS, pbs_offset is amount of stream processed.
@@ -88,17 +86,17 @@ typedef struct packet_byte_stream {
extern void init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name);
extern bool in_struct(void *struct_ptr, struct_desc *sd,
- pb_stream *ins, pb_stream *obj_pbs);
+ pb_stream *ins, pb_stream *obj_pbs);
extern bool in_raw(void *bytes, size_t len, pb_stream *ins, const char *name);
extern bool out_struct(const void *struct_ptr, struct_desc *sd,
- pb_stream *outs, pb_stream *obj_pbs);
+ pb_stream *outs, pb_stream *obj_pbs);
extern bool out_generic(u_int8_t np, struct_desc *sd,
- pb_stream *outs, pb_stream *obj_pbs);
+ pb_stream *outs, pb_stream *obj_pbs);
extern bool out_generic_raw(u_int8_t np, struct_desc *sd,
- pb_stream *outs, const void *bytes, size_t len, const char *name);
+ pb_stream *outs, const void *bytes, size_t len, const char *name);
#define out_generic_chunk(np, sd, outs, ch, name) \
- out_generic_raw(np, sd, outs, (ch).ptr, (ch).len, name)
+ out_generic_raw(np, sd, outs, (ch).ptr, (ch).len, name)
extern bool out_zero(size_t len, pb_stream *outs, const char *name);
extern bool out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name);
#define out_chunk(ch, outs, name) out_raw((ch).ptr, (ch).len, (outs), (name))
@@ -106,7 +104,7 @@ extern void close_output_pbs(pb_stream *pbs);
#ifdef DEBUG
extern void DBG_print_struct(const char *label, const void *struct_ptr,
- struct_desc *sd, bool len_meaningful);
+ struct_desc *sd, bool len_meaningful);
#endif
/* ISAKMP Header: for all messages
@@ -160,16 +158,16 @@ extern void DBG_print_struct(const char *label, const void *struct_ptr,
struct isakmp_hdr
{
- u_int8_t isa_icookie[COOKIE_SIZE];
- u_int8_t isa_rcookie[COOKIE_SIZE];
- u_int8_t isa_np; /* Next payload */
- u_int8_t isa_version; /* high-order 4 bits: Major; low order 4: Minor */
-#define ISA_MAJ_SHIFT 4
-#define ISA_MIN_MASK (~((~0u) << ISA_MAJ_SHIFT))
- u_int8_t isa_xchg; /* Exchange type */
- u_int8_t isa_flags;
- u_int32_t isa_msgid; /* Message ID (RAW) */
- u_int32_t isa_length; /* Length of message */
+ u_int8_t isa_icookie[COOKIE_SIZE];
+ u_int8_t isa_rcookie[COOKIE_SIZE];
+ u_int8_t isa_np; /* Next payload */
+ u_int8_t isa_version; /* high-order 4 bits: Major; low order 4: Minor */
+#define ISA_MAJ_SHIFT 4
+#define ISA_MIN_MASK (~((~0u) << ISA_MAJ_SHIFT))
+ u_int8_t isa_xchg; /* Exchange type */
+ u_int8_t isa_flags;
+ u_int32_t isa_msgid; /* Message ID (RAW) */
+ u_int32_t isa_length; /* Length of message */
};
extern struct_desc isakmp_hdr_desc;
@@ -186,9 +184,9 @@ extern struct_desc isakmp_hdr_desc;
*/
struct isakmp_generic
{
- u_int8_t isag_np;
- u_int8_t isag_reserved;
- u_int16_t isag_length;
+ u_int8_t isag_np;
+ u_int8_t isag_reserved;
+ u_int16_t isag_length;
};
extern struct_desc isakmp_generic_desc;
@@ -209,17 +207,17 @@ extern struct_desc isakmp_generic_desc;
*/
struct isakmp_attribute
{
- /* The high order bit of isaat_af_type is the Attribute Format
- * If it is off, the format is TLV: lv is the length of the following
- * attribute value.
- * If it is on, the format is TV: lv is the value of the attribute.
- * ISAKMP_ATTR_AF_MASK is the mask in host form.
- *
- * The low order 15 bits of isaat_af_type is the Attribute Type.
- * ISAKMP_ATTR_RTYPE_MASK is the mask in host form.
- */
- u_int16_t isaat_af_type; /* high order bit: AF; lower 15: rtype */
- u_int16_t isaat_lv; /* Length or value */
+ /* The high order bit of isaat_af_type is the Attribute Format
+ * If it is off, the format is TLV: lv is the length of the following
+ * attribute value.
+ * If it is on, the format is TV: lv is the value of the attribute.
+ * ISAKMP_ATTR_AF_MASK is the mask in host form.
+ *
+ * The low order 15 bits of isaat_af_type is the Attribute Type.
+ * ISAKMP_ATTR_RTYPE_MASK is the mask in host form.
+ */
+ u_int16_t isaat_af_type; /* high order bit: AF; lower 15: rtype */
+ u_int16_t isaat_lv; /* Length or value */
};
#define ISAKMP_ATTR_AF_MASK 0x8000
@@ -229,8 +227,8 @@ struct isakmp_attribute
#define ISAKMP_ATTR_RTYPE_MASK 0x7FFF
extern struct_desc
- isakmp_oakley_attribute_desc,
- isakmp_ipsec_attribute_desc;
+ isakmp_oakley_attribute_desc,
+ isakmp_ipsec_attribute_desc;
/* ISAKMP Security Association Payload
* layout from RFC 2408 "ISAKMP" section 3.4
@@ -250,10 +248,10 @@ extern struct_desc
*/
struct isakmp_sa
{
- u_int8_t isasa_np; /* Next payload */
- u_int8_t isasa_reserved;
- u_int16_t isasa_length; /* Payload length */
- u_int32_t isasa_doi; /* DOI */
+ u_int8_t isasa_np; /* Next payload */
+ u_int8_t isasa_reserved;
+ u_int16_t isasa_length; /* Payload length */
+ u_int32_t isasa_doi; /* DOI */
};
extern struct_desc isakmp_sa_desc;
@@ -276,13 +274,13 @@ extern struct_desc ipsec_sit_desc;
*/
struct isakmp_proposal
{
- u_int8_t isap_np;
- u_int8_t isap_reserved;
- u_int16_t isap_length;
- u_int8_t isap_proposal;
- u_int8_t isap_protoid;
- u_int8_t isap_spisize;
- u_int8_t isap_notrans; /* Number of transforms */
+ u_int8_t isap_np;
+ u_int8_t isap_reserved;
+ u_int16_t isap_length;
+ u_int8_t isap_proposal;
+ u_int8_t isap_protoid;
+ u_int8_t isap_spisize;
+ u_int8_t isap_notrans; /* Number of transforms */
};
extern struct_desc isakmp_proposal_desc;
@@ -305,19 +303,19 @@ extern struct_desc isakmp_proposal_desc;
*/
struct isakmp_transform
{
- u_int8_t isat_np;
- u_int8_t isat_reserved;
- u_int16_t isat_length;
- u_int8_t isat_transnum; /* Number of the transform */
- u_int8_t isat_transid;
- u_int16_t isat_reserved2;
+ u_int8_t isat_np;
+ u_int8_t isat_reserved;
+ u_int16_t isat_length;
+ u_int8_t isat_transnum; /* Number of the transform */
+ u_int8_t isat_transid;
+ u_int16_t isat_reserved2;
};
extern struct_desc
- isakmp_isakmp_transform_desc,
- isakmp_ah_transform_desc,
- isakmp_esp_transform_desc,
- isakmp_ipcomp_transform_desc;
+ isakmp_isakmp_transform_desc,
+ isakmp_ah_transform_desc,
+ isakmp_esp_transform_desc,
+ isakmp_ipcomp_transform_desc;
/* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones.
* layout from RFC 2408 "ISAKMP" section 3.7
@@ -354,12 +352,12 @@ extern struct_desc isakmp_keyex_desc;
*/
struct isakmp_id
{
- u_int8_t isaid_np;
- u_int8_t isaid_reserved;
- u_int16_t isaid_length;
- u_int8_t isaid_idtype;
- u_int8_t isaid_doi_specific_a;
- u_int16_t isaid_doi_specific_b;
+ u_int8_t isaid_np;
+ u_int8_t isaid_reserved;
+ u_int16_t isaid_length;
+ u_int8_t isaid_idtype;
+ u_int8_t isaid_doi_specific_a;
+ u_int16_t isaid_doi_specific_b;
};
extern struct_desc isakmp_identification_desc;
@@ -381,12 +379,12 @@ extern struct_desc isakmp_identification_desc;
*/
struct isakmp_ipsec_id
{
- u_int8_t isaiid_np;
- u_int8_t isaiid_reserved;
- u_int16_t isaiid_length;
- u_int8_t isaiid_idtype;
- u_int8_t isaiid_protoid;
- u_int16_t isaiid_port;
+ u_int8_t isaiid_np;
+ u_int8_t isaiid_reserved;
+ u_int16_t isaiid_length;
+ u_int8_t isaiid_idtype;
+ u_int8_t isaiid_protoid;
+ u_int16_t isaiid_port;
};
extern struct_desc isakmp_ipsec_identification_desc;
@@ -408,17 +406,17 @@ extern struct_desc isakmp_ipsec_identification_desc;
*/
struct isakmp_cert
{
- u_int8_t isacert_np;
- u_int8_t isacert_reserved;
- u_int16_t isacert_length;
- u_int8_t isacert_type;
+ u_int8_t isacert_np;
+ u_int8_t isacert_reserved;
+ u_int16_t isacert_length;
+ u_int8_t isacert_type;
};
/* NOTE: this packet type has a fixed portion that is not a
* multiple of 4 octets. This means that sizeof(struct isakmp_cert)
* yields the wrong value for the length.
*/
-#define ISAKMP_CERT_SIZE 5
+#define ISAKMP_CERT_SIZE 5
extern struct_desc isakmp_ipsec_certificate_desc;
@@ -439,17 +437,17 @@ extern struct_desc isakmp_ipsec_certificate_desc;
*/
struct isakmp_cr
{
- u_int8_t isacr_np;
- u_int8_t isacr_reserved;
- u_int16_t isacr_length;
- u_int8_t isacr_type;
+ u_int8_t isacr_np;
+ u_int8_t isacr_reserved;
+ u_int16_t isacr_length;
+ u_int8_t isacr_type;
};
/* NOTE: this packet type has a fixed portion that is not a
* multiple of 4 octets. This means that sizeof(struct isakmp_cr)
* yields the wrong value for the length.
*/
-#define ISAKMP_CR_SIZE 5
+#define ISAKMP_CR_SIZE 5
extern struct_desc isakmp_ipsec_cert_req_desc;
@@ -526,13 +524,13 @@ extern struct_desc isakmp_nonce_desc;
*/
struct isakmp_notification
{
- u_int8_t isan_np;
- u_int8_t isan_reserved;
- u_int16_t isan_length;
- u_int32_t isan_doi;
- u_int8_t isan_protoid;
- u_int8_t isan_spisize;
- u_int16_t isan_type;
+ u_int8_t isan_np;
+ u_int8_t isan_reserved;
+ u_int16_t isan_length;
+ u_int32_t isan_doi;
+ u_int8_t isan_protoid;
+ u_int8_t isan_spisize;
+ u_int16_t isan_type;
};
extern struct_desc isakmp_notification_desc;
@@ -557,40 +555,40 @@ extern struct_desc isakmp_notification_desc;
*/
struct isakmp_delete
{
- u_int8_t isad_np;
- u_int8_t isad_reserved;
- u_int16_t isad_length;
- u_int32_t isad_doi;
- u_int8_t isad_protoid;
- u_int8_t isad_spisize;
- u_int16_t isad_nospi;
+ u_int8_t isad_np;
+ u_int8_t isad_reserved;
+ u_int16_t isad_length;
+ u_int32_t isad_doi;
+ u_int8_t isad_protoid;
+ u_int8_t isad_spisize;
+ u_int16_t isad_nospi;
};
extern struct_desc isakmp_delete_desc;
/* From draft-dukes-ike-mode-cfg
3.2. Attribute Payload
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Next Payload ! RESERVED ! Payload Length !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Type ! RESERVED ! Identifier !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! !
- ! !
- ~ Attributes ~
- ! !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Type ! RESERVED ! Identifier !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ! !
+ ~ Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct isakmp_mode_attr
{
- u_int8_t isama_np;
- u_int8_t isama_reserved;
- u_int16_t isama_length;
- u_int8_t isama_type;
- u_int8_t isama_reserved2;
- u_int16_t isama_identifier;
+ u_int8_t isama_np;
+ u_int8_t isama_reserved;
+ u_int16_t isama_length;
+ u_int8_t isama_type;
+ u_int8_t isama_reserved2;
+ u_int16_t isama_identifier;
};
extern struct_desc isakmp_attr_desc;
@@ -614,12 +612,12 @@ extern struct_desc isakmp_vendor_id_desc;
struct isakmp_nat_oa
{
- u_int8_t isanoa_np;
- u_int8_t isanoa_reserved_1;
- u_int16_t isanoa_length;
- u_int8_t isanoa_idtype;
- u_int8_t isanoa_reserved_2;
- u_int16_t isanoa_reserved_3;
+ u_int8_t isanoa_np;
+ u_int8_t isanoa_reserved_1;
+ u_int16_t isanoa_length;
+ u_int8_t isanoa_idtype;
+ u_int8_t isanoa_reserved_2;
+ u_int16_t isanoa_reserved_3;
};
extern struct_desc isakmp_nat_d;
@@ -628,18 +626,18 @@ extern struct_desc isakmp_nat_oa;
/* union of all payloads */
union payload {
- struct isakmp_generic generic;
- struct isakmp_sa sa;
- struct isakmp_proposal proposal;
- struct isakmp_transform transform;
- struct isakmp_id id; /* Main Mode */
- struct isakmp_cert cert;
- struct isakmp_cr cr;
- struct isakmp_ipsec_id ipsec_id; /* Quick Mode */
- struct isakmp_notification notification;
- struct isakmp_delete delete;
- struct isakmp_nat_oa nat_oa;
- struct isakmp_mode_attr attribute;
+ struct isakmp_generic generic;
+ struct isakmp_sa sa;
+ struct isakmp_proposal proposal;
+ struct isakmp_transform transform;
+ struct isakmp_id id; /* Main Mode */
+ struct isakmp_cert cert;
+ struct isakmp_cr cr;
+ struct isakmp_ipsec_id ipsec_id; /* Quick Mode */
+ struct isakmp_notification notification;
+ struct isakmp_delete delete;
+ struct isakmp_nat_oa nat_oa;
+ struct isakmp_mode_attr attribute;
};
/* descriptor for each payload type
diff --git a/src/pluto/pem.c b/src/pluto/pem.c
index 5ebe4b576..646447c1a 100644
--- a/src/pluto/pem.c
+++ b/src/pluto/pem.c
@@ -1,5 +1,6 @@
/* Loading of PEM encoded files with optional encryption
- * Copyright (C) 2001-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2001-2009 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +11,6 @@
* 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: pem.c 3252 2007-10-06 21:24:50Z andreas $
*/
/* decrypt a PEM encoded data block using DES-EDE3-CBC
@@ -27,437 +26,101 @@
#include <sys/types.h>
#include <freeswan.h>
-#define HEADER_DES_LOCL_H /* stupid trick to force prototype decl in <des.h> */
-#include <libdes/des.h>
+
+#include <library.h>
+#include <asn1/pem.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "md5.h"
#include "whack.h"
#include "pem.h"
-/*
- * check the presence of a pattern in a character string
- */
-static bool
-present(const char* pattern, chunk_t* ch)
-{
- u_int pattern_len = strlen(pattern);
-
- if (ch->len >= pattern_len && strncmp(ch->ptr, pattern, pattern_len) == 0)
- {
- ch->ptr += pattern_len;
- ch->len -= pattern_len;
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- * compare string with chunk
- */
-static bool
-match(const char *pattern, const chunk_t *ch)
-{
- return ch->len == strlen(pattern) &&
- strncmp(pattern, ch->ptr, ch->len) == 0;
-}
-
-/*
- * find a boundary of the form -----tag name-----
- */
-static bool
-find_boundary(const char* tag, chunk_t *line)
-{
- chunk_t name = empty_chunk;
-
- if (!present("-----", line))
- return FALSE;
- if (!present(tag, line))
- return FALSE;
- if (*line->ptr != ' ')
- return FALSE;
- line->ptr++; line->len--;
-
- /* extract name */
- name.ptr = line->ptr;
- while (line->len > 0)
- {
- if (present("-----", line))
- {
- DBG(DBG_PARSING,
- DBG_log(" -----%s %.*s-----",
- tag, (int)name.len, name.ptr);
- )
- return TRUE;
- }
- line->ptr++; line->len--; name.len++;
- }
- return FALSE;
-}
-
-/*
- * eat whitespace
- */
-static void
-eat_whitespace(chunk_t *src)
-{
- while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t'))
- {
- src->ptr++; src->len--;
- }
-}
-
-/*
- * extracts a token ending with a given termination symbol
- */
-static bool
-extract_token(chunk_t *token, char termination, chunk_t *src)
-{
- u_char *eot = memchr(src->ptr, termination, src->len);
-
- /* initialize empty token */
- *token = empty_chunk;
-
- if (eot == NULL) /* termination symbol not found */
- return FALSE;
-
- /* extract token */
- token->ptr = src->ptr;
- token->len = (u_int)(eot - src->ptr);
-
- /* advance src pointer after termination symbol */
- src->ptr = eot + 1;
- src->len -= (token->len + 1);
-
- return TRUE;
-}
-
-/*
- * extracts a name: value pair from the PEM header
- */
-static bool
-extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line)
-{
- DBG(DBG_PARSING,
- DBG_log(" %.*s", (int)line->len, line->ptr);
- )
-
- /* extract name */
- if (!extract_token(name,':', line))
- return FALSE;
-
- eat_whitespace(line);
-
- /* extract value */
- *value = *line;
- return TRUE;
-}
-
-/*
- * fetches a new line terminated by \n or \r\n
- */
-static bool
-fetchline(chunk_t *src, chunk_t *line)
-{
- if (src->len == 0) /* end of src reached */
- return FALSE;
-
- if (extract_token(line, '\n', src))
- {
- if (line->len > 0 && *(line->ptr + line->len -1) == '\r')
- line->len--; /* remove optional \r */
- }
- else /*last line ends without newline */
- {
- *line = *src;
- src->ptr += src->len;
- src->len = 0;
- }
- return TRUE;
-}
-
-/*
- * decrypts a DES-EDE-CBC encrypted data block
- */
-static bool
-pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase)
-{
- MD5_CTX context;
- u_char digest[MD5_DIGEST_SIZE];
- u_char des_iv[DES_CBC_BLOCK_SIZE];
- u_char key[24];
- des_cblock *deskey = (des_cblock *)key;
- des_key_schedule ks[3];
- u_char padding, *last_padding_pos, *first_padding_pos;
-
- /* Convert passphrase to 3des key */
- MD5Init(&context);
- MD5Update(&context, passphrase, strlen(passphrase));
- MD5Update(&context, iv->ptr, iv->len);
- MD5Final(digest, &context);
-
- memcpy(key, digest, MD5_DIGEST_SIZE);
-
- MD5Init(&context);
- MD5Update(&context, digest, MD5_DIGEST_SIZE);
- MD5Update(&context, passphrase, strlen(passphrase));
- MD5Update(&context, iv->ptr, iv->len);
- MD5Final(digest, &context);
-
- memcpy(key + MD5_DIGEST_SIZE, digest, 24 - MD5_DIGEST_SIZE);
-
- (void) des_set_key(&deskey[0], ks[0]);
- (void) des_set_key(&deskey[1], ks[1]);
- (void) des_set_key(&deskey[2], ks[2]);
-
- /* decrypt data block */
- memcpy(des_iv, iv->ptr, DES_CBC_BLOCK_SIZE);
- des_ede3_cbc_encrypt((des_cblock *)blob->ptr, (des_cblock *)blob->ptr,
- blob->len, ks[0], ks[1], ks[2], (des_cblock *)des_iv, FALSE);
-
- /* determine amount of padding */
- last_padding_pos = blob->ptr + blob->len - 1;
- padding = *last_padding_pos;
- first_padding_pos = (padding > blob->len)?
- blob->ptr : last_padding_pos - padding;
-
- /* check the padding pattern */
- while (--last_padding_pos > first_padding_pos)
- {
- if (*last_padding_pos != padding)
- return FALSE;
- }
-
- /* remove padding */
- blob->len -= padding;
- return TRUE;
-}
-
-/*
- * optionally prompts for a passphrase before decryption
- * currently we support DES-EDE3-CBC, only
+/**
+ * Converts a PEM encoded file into its binary form
+ * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993
+ * RFC 934 Message Encapsulation, January 1985
*/
-static err_t
-pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label)
+err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
{
- DBG(DBG_CRYPT,
- DBG_log(" decrypting file using 'DES-EDE3-CBC'");
- )
- if (iv->len != DES_CBC_BLOCK_SIZE)
- return "size of DES-EDE3-CBC IV is not 8 bytes";
-
- if (pass == NULL)
- return "no passphrase available";
+ chunk_t password = chunk_empty;
- /* do we prompt for the passphrase? */
- if (pass->prompt && pass->fd != NULL_FD)
- {
- int i;
- chunk_t blob_copy;
- err_t ugh = "invalid passphrase, too many trials";
-
- whack_log(RC_ENTERSECRET, "need passphrase for '%s'", label);
-
- for (i = 0; i < MAX_PROMPT_PASS_TRIALS; i++)
+ /* do we prompt for the passphrase? */
+ if (pass && pass->prompt && pass->fd != NULL_FD)
{
- int n;
-
- if (i > 0)
- whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
-
- n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
-
- if (n == -1)
- {
- err_t ugh = "read(whackfd) failed";
-
- whack_log(RC_LOG_SERIOUS,ugh);
- return ugh;
- }
+ int i;
+ chunk_t blob_copy;
+ err_t ugh = "invalid passphrase, too many trials";
+ status_t status;
- pass->secret[n-1] = '\0';
-
- if (strlen(pass->secret) == 0)
- {
- err_t ugh = "no passphrase entered, aborted";
+ whack_log(RC_ENTERSECRET, "need passphrase for '%s'", label);
+ for (i = 0; i < MAX_PROMPT_PASS_TRIALS; i++)
+ {
+ int n;
+
+ if (i > 0)
+ {
+ whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
+ }
+ n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
+
+ if (n == -1)
+ {
+ err_t ugh = "read(whackfd) failed";
+
+ whack_log(RC_LOG_SERIOUS,ugh);
+ return ugh;
+ }
+
+ pass->secret[n-1] = '\0';
+
+ if (strlen(pass->secret) == 0)
+ {
+ err_t ugh = "no passphrase entered, aborted";
+
+ whack_log(RC_LOG_SERIOUS, ugh);
+ return ugh;
+ }
+
+ blob_copy = chunk_clone(*blob);
+ password = chunk_create(pass->secret, strlen(pass->secret));
+
+ status = pem_to_bin(blob, password, pgp);
+ if (status != INVALID_ARG)
+ {
+ if (status == SUCCESS)
+ {
+ whack_log(RC_SUCCESS, "valid passphrase");
+ }
+ else
+ {
+ whack_log(RC_LOG_SERIOUS, "%N, aborted", status_names, status);
+ }
+ free(blob_copy.ptr);
+ return NULL;
+ }
+
+ /* blob is useless after wrong decryption, restore the original */
+ free(blob->ptr);
+ *blob = blob_copy;
+ }
whack_log(RC_LOG_SERIOUS, ugh);
return ugh;
- }
-
- clonetochunk(blob_copy, blob->ptr, blob->len, "blob copy");
-
- if (pem_decrypt_3des(blob, iv, pass->secret))
- {
- whack_log(RC_SUCCESS, "valid passphrase");
- pfree(blob_copy.ptr);
- return NULL;
- }
-
- /* blob is useless after wrong decryption, restore the original */
- pfree(blob->ptr);
- *blob = blob_copy;
- }
- whack_log(RC_LOG_SERIOUS, ugh);
- return ugh;
- }
- else
- {
- if (pem_decrypt_3des(blob, iv, pass->secret))
- return NULL;
- else
- return "invalid passphrase";
- }
-}
-
-/* Converts a PEM encoded file into its binary form
- *
- * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993
- * RFC 934 Message Encapsulation, January 1985
- */
-err_t
-pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
-{
- typedef enum {
- PEM_PRE = 0,
- PEM_MSG = 1,
- PEM_HEADER = 2,
- PEM_BODY = 3,
- PEM_POST = 4,
- PEM_ABORT = 5
- } state_t;
-
- bool encrypted = FALSE;
-
- state_t state = PEM_PRE;
-
- chunk_t src = *blob;
- chunk_t dst = *blob;
- chunk_t line = empty_chunk;
- chunk_t iv = empty_chunk;
-
- u_char iv_buf[MAX_DIGEST_LEN];
-
- /* zero size of converted blob */
- dst.len = 0;
-
- /* zero size of IV */
- iv.ptr = iv_buf;
- iv.len = 0;
-
- while (fetchline(&src, &line))
- {
- if (state == PEM_PRE)
- {
- if (find_boundary("BEGIN", &line))
- {
- *pgp = FALSE;
- state = PEM_MSG;
- }
- continue;
}
else
{
- if (find_boundary("END", &line))
- {
- state = PEM_POST;
- break;
- }
- if (state == PEM_MSG)
- {
- state = (memchr(line.ptr, ':', line.len) == NULL)?
- PEM_BODY : PEM_HEADER;
- }
- if (state == PEM_HEADER)
- {
- chunk_t name = empty_chunk;
- chunk_t value = empty_chunk;
-
- /* an empty line separates HEADER and BODY */
- if (line.len == 0)
- {
- state = PEM_BODY;
- continue;
- }
-
- /* we are looking for a name: value pair */
- if (!extract_parameter(&name, &value, &line))
- continue;
-
- if (match("Proc-Type", &name) && *value.ptr == '4')
- encrypted = TRUE;
- else if (match("DEK-Info", &name))
+ if (pass)
{
- const char *ugh = NULL;
- size_t len = 0;
- chunk_t dek;
-
- if (!extract_token(&dek, ',', &value))
- dek = value;
-
- /* we support DES-EDE3-CBC encrypted files, only */
- if (!match("DES-EDE3-CBC", &dek))
- return "we support DES-EDE3-CBC encrypted files, only";
-
- eat_whitespace(&value);
- ugh = ttodata(value.ptr, value.len, 16,
- iv.ptr, MAX_DIGEST_LEN, &len);
- if (ugh)
- return "error in IV";
-
- iv.len = len;
+ password = chunk_create(pass->secret, strlen(pass->secret));
}
- }
- else /* state is PEM_BODY */
- {
- const char *ugh = NULL;
- size_t len = 0;
- chunk_t data;
-
- /* remove any trailing whitespace */
- if (!extract_token(&data ,' ', &line))
- data = line;
-
- /* check for PGP armor checksum */
- if (*data.ptr == '=')
+ if (pem_to_bin(blob, password, pgp) == SUCCESS)
{
- *pgp = TRUE;
- data.ptr++;
- data.len--;
- DBG(DBG_PARSING,
- DBG_log(" Armor checksum: %.*s", (int)data.len, data.ptr);
- )
- continue;
- }
-
- ugh = ttodata(data.ptr, data.len, 64,
- dst.ptr, blob->len - dst.len, &len);
- if (ugh)
- {
- DBG(DBG_PARSING,
- DBG_log(" %s", ugh);
- )
- state = PEM_ABORT;
- break;
+ return NULL;
}
else
{
- dst.ptr += len;
- dst.len += len;
+ return "pem to bin conversion failed";
}
- }
- }
- }
- /* set length to size of binary blob */
- blob->len = dst.len;
-
- if (state != PEM_POST)
- return "file coded in unknown format, discarded";
-
- if (encrypted)
- return pem_decrypt(blob, &iv, pass, label);
- else
- return NULL;
+ }
}
diff --git a/src/pluto/pem.h b/src/pluto/pem.h
index e74915cb2..5e97b99ed 100644
--- a/src/pluto/pem.h
+++ b/src/pluto/pem.h
@@ -1,5 +1,7 @@
/* Loading of PEM encoded files with optional encryption
- * Copyright (C) 2001-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2001-2009 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,9 +12,7 @@
* 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: pem.h 3252 2007-10-06 21:24:50Z andreas $
*/
-extern err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label
- , bool *pgp);
+extern err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label,
+ bool *pgp);
diff --git a/src/pluto/pgp.c b/src/pluto/pgp.c
deleted file mode 100644
index b956ce4d7..000000000
--- a/src/pluto/pgp.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/* Support of OpenPGP certificates
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * 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: pgp.c 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <freeswan.h>
-#include <ipsec_policy.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "mp_defs.h"
-#include "log.h"
-#include "id.h"
-#include "pgp.h"
-#include "certs.h"
-#include "md5.h"
-#include "whack.h"
-#include "pkcs1.h"
-#include "keys.h"
-
-/*
- * chained list of OpenPGP end certificates
- */
-static pgpcert_t *pgpcerts = NULL;
-
-/*
- * OpenPGP packet tags defined in section 4.3 of RFC 2440
- */
-#define PGP_PKT_RESERVED 0
-#define PGP_PKT_PUBKEY_ENC_SESSION_KEY 1
-#define PGP_PKT_SIGNATURE 2
-#define PGP_PKT_SYMKEY_ENC_SESSION_KEY 3
-#define PGP_PKT_ONE_PASS_SIGNATURE_PKT 4
-#define PGP_PKT_SECRET_KEY 5
-#define PGP_PKT_PUBLIC_KEY 6
-#define PGP_PKT_SECRET_SUBKEY 7
-#define PGP_PKT_COMPRESSED_DATA 8
-#define PGP_PKT_SYMKEY_ENC_DATA 9
-#define PGP_PKT_MARKER 10
-#define PGP_PKT_LITERAL_DATA 11
-#define PGP_PKT_TRUST 12
-#define PGP_PKT_USER_ID 13
-#define PGP_PKT_PUBLIC_SUBKEY 14
-#define PGP_PKT_ROOF 15
-
-static const char *const pgp_packet_type_name[] = {
- "Reserved",
- "Public-Key Encrypted Session Key Packet",
- "Signature Packet",
- "Symmetric-Key Encrypted Session Key Packet",
- "One-Pass Signature Packet",
- "Secret Key Packet",
- "Public Key Packet",
- "Secret Subkey Packet",
- "Compressed Data Packet",
- "Symmetrically Encrypted Data Packet",
- "Marker Packet",
- "Literal Data Packet",
- "Trust Packet",
- "User ID Packet",
- "Public Subkey Packet"
-};
-
-/*
- * OpenPGP public key algorithms defined in section 9.1 of RFC 2440
- */
-#define PGP_PUBKEY_ALG_RSA 1
-#define PGP_PUBKEY_ALG_RSA_ENC_ONLY 2
-#define PGP_PUBKEY_ALG_RSA_SIGN_ONLY 3
-#define PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY 16
-#define PGP_PUBKEY_ALG_DSA 17
-#define PGP_PUBKEY_ALG_ECC 18
-#define PGP_PUBKEY_ALG_ECDSA 19
-#define PGP_PUBKEY_ALG_ELGAMAL 20
-
-/*
- * OpenPGP symmetric key algorithms defined in section 9.2 of RFC 2440
- */
-#define PGP_SYM_ALG_PLAIN 0
-#define PGP_SYM_ALG_IDEA 1
-#define PGP_SYM_ALG_3DES 2
-#define PGP_SYM_ALG_CAST5 3
-#define PGP_SYM_ALG_BLOWFISH 4
-#define PGP_SYM_ALG_SAFER 5
-#define PGP_SYM_ALG_DES 6
-#define PGP_SYM_ALG_AES 7
-#define PGP_SYM_ALG_AES_192 8
-#define PGP_SYM_ALG_AES_256 9
-#define PGP_SYM_ALG_TWOFISH 10
-#define PGP_SYM_ALG_ROOF 11
-
-static const char *const pgp_sym_alg_name[] = {
- "Plaintext",
- "IDEA",
- "3DES",
- "CAST5",
- "Blowfish",
- "SAFER",
- "DES",
- "AES",
- "AES-192",
- "AES-256",
- "Twofish"
-};
-
-/*
- * Size of PGP Key ID
- */
-#define PGP_KEYID_SIZE 8
-
-const pgpcert_t empty_pgpcert = {
- NULL , /* *next */
- 0 , /* installed */
- 0 , /* count */
- { NULL, 0 }, /* certificate */
- 0 , /* created */
- 0 , /* until */
- 0 , /* pubkeyAlgorithm */
- { NULL, 0 }, /* modulus */
- { NULL, 0 }, /* publicExponent */
- "" /* fingerprint */
-};
-
-static size_t
-pgp_size(chunk_t *blob, int len)
-{
- size_t size = 0;
-
- blob->len -= len;
- while (len-- > 0)
- size = 256*size + *blob->ptr++;
- return size;
-}
-
-/*
- * extracts the length of a PGP packet
- */
-static size_t
-pgp_old_packet_length(chunk_t *blob)
-{
- /* bits 0 and 1 define the packet length type */
- int len_type = 0x03 & *blob->ptr++;
-
- blob->len--;
-
- /* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
- return pgp_size(blob, (len_type == 0)? 1: len_type << 1);
-}
-
-/*
- * extracts PGP packet version (V3 or V4)
- */
-static u_char
-pgp_version(chunk_t *blob)
-{
- u_char version = *blob->ptr++;
- blob->len--;
- DBG(DBG_PARSING,
- DBG_log("L3 - version:");
- DBG_log(" V%d", version)
- )
- return version;
-}
-
-/*
- * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 2440
- */
-static bool
-parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
-{
- u_char version = pgp_version(packet);
-
- if (version < 3 || version > 4)
- {
- plog("PGP packet version V%d not supported", version);
- return FALSE;
- }
-
- /* creation date - 4 bytes */
- cert->created = (time_t)pgp_size(packet, 4);
- DBG(DBG_PARSING,
- DBG_log("L3 - created:");
- DBG_log(" %s", timetoa(&cert->created, TRUE))
- )
-
- if (version == 3)
- {
- /* validity in days - 2 bytes */
- cert->until = (time_t)pgp_size(packet, 2);
-
- /* validity of 0 days means that the key never expires */
- if (cert->until > 0)
- cert->until = cert->created + 24*3600*cert->until;
-
- DBG(DBG_PARSING,
- DBG_log("L3 - until:");
- DBG_log(" %s", timetoa(&cert->until, TRUE));
- )
- }
-
- /* public key algorithm - 1 byte */
- DBG(DBG_PARSING,
- DBG_log("L3 - public key algorithm:")
- )
-
- switch (pgp_size(packet, 1))
- {
- case PGP_PUBKEY_ALG_RSA:
- case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
- cert->pubkeyAlg = PUBKEY_ALG_RSA;
- DBG(DBG_PARSING,
- DBG_log(" RSA")
- )
- /* modulus n */
- cert->modulus.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE;
- cert->modulus.ptr = packet->ptr;
- packet->ptr += cert->modulus.len;
- packet->len -= cert->modulus.len;
- DBG(DBG_PARSING,
- DBG_log("L3 - modulus:")
- )
- DBG_cond_dump_chunk(DBG_RAW, "", cert->modulus);
-
- /* public exponent e */
- cert->publicExponent.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE;
- cert->publicExponent.ptr = packet->ptr;
- packet->ptr += cert->publicExponent.len;
- packet->len -= cert->publicExponent.len;
- DBG(DBG_PARSING,
- DBG_log("L3 - public exponent:")
- )
- DBG_cond_dump_chunk(DBG_RAW, "", cert->publicExponent);
-
- if (version == 3)
- {
- /* a V3 fingerprint is the MD5 hash of modulus and public exponent */
- MD5_CTX context;
- MD5Init(&context);
- MD5Update(&context, cert->modulus.ptr, cert->modulus.len);
- MD5Update(&context, cert->publicExponent.ptr, cert->publicExponent.len);
- MD5Final(cert->fingerprint, &context);
- }
- else
- {
- plog(" computation of V4 key ID not implemented yet");
- }
- break;
- case PGP_PUBKEY_ALG_DSA:
- cert->pubkeyAlg = PUBKEY_ALG_DSA;
- DBG(DBG_PARSING,
- DBG_log(" DSA")
- )
- plog(" DSA public keys not supported");
- return FALSE;
- default:
- cert->pubkeyAlg = 0;
- DBG(DBG_PARSING,
- DBG_log(" other")
- )
- plog(" exotic not RSA public keys not supported");
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * Parse OpenPGP secret key packet defined in section 5.5.3 of RFC 2440
- */
-static bool
-parse_pgp_secretkey_packet(chunk_t *packet, RSA_private_key_t *key)
-{
- int i, s2k;
- pgpcert_t cert = empty_pgpcert;
-
- if (!parse_pgp_pubkey_packet(packet, &cert))
- return FALSE;
-
- init_RSA_public_key((RSA_public_key_t *)key, cert.publicExponent
- , cert.modulus);
-
- /* string-to-key usage */
- s2k = pgp_size(packet, 1);
-
- DBG(DBG_PARSING,
- DBG_log("L3 - string-to-key: %d", s2k)
- )
-
- if (s2k == 255)
- {
- plog(" string-to-key specifiers not supported");
- return FALSE;
- }
-
- if (s2k >= PGP_SYM_ALG_ROOF)
- {
- plog(" undefined symmetric key algorithm");
- return FALSE;
- }
-
- /* a known symmetric key algorithm is specified*/
- DBG(DBG_PARSING,
- DBG_log(" %s", pgp_sym_alg_name[s2k])
- )
-
- /* private key is unencrypted */
- if (s2k == PGP_SYM_ALG_PLAIN)
- {
- for (i = 2; i < RSA_PRIVATE_FIELD_ELEMENTS; i++)
- {
- mpz_t u; /* auxiliary variable */
-
- /* compute offset to private key component i*/
- MP_INT *n = (MP_INT*)((char *)key + RSA_private_field[i].offset);
-
- switch (i)
- {
- case 2:
- case 3:
- case 4:
- {
- size_t len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE;
-
- n_to_mpz(n, packet->ptr, len);
- DBG(DBG_PARSING,
- DBG_log("L3 - %s:", RSA_private_field[i].name)
- )
- DBG_cond_dump(DBG_PRIVATE, "", packet->ptr, len);
- packet->ptr += len;
- packet->len -= len;
- }
- break;
- case 5: /* dP = d mod (p-1) */
- mpz_init(u);
- mpz_sub_ui(u, &key->p, 1);
- mpz_mod(n, &key->d, u);
- mpz_clear(u);
- break;
- case 6: /* dQ = d mod (q-1) */
- mpz_init(u);
- mpz_sub_ui(u, &key->q, 1);
- mpz_mod(n, &key->d, u);
- mpz_clear(u);
- break;
- case 7: /* qInv = (q^-1) mod p */
- mpz_invert(n, &key->q, &key->p);
- if (mpz_cmp_ui(n, 0) < 0)
- mpz_add(n, n, &key->p);
- passert(mpz_cmp(n, &key->p) < 0);
- break;
- }
- }
- return TRUE;
- }
-
- plog(" %s encryption not supported", pgp_sym_alg_name[s2k]);
- return FALSE;
-}
-
-/*
- * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
- */
-static bool
-parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
-{
- time_t created;
- chunk_t keyid;
- u_char sig_type;
- u_char version = pgp_version(packet);
-
- /* we parse only V3 signature packets */
- if (version != 3)
- return TRUE;
-
- /* size byte must have the value 5 */
- if (pgp_size(packet, 1) != 5)
- {
- plog(" size must be 5");
- return FALSE;
- }
-
- /* signature type - 1 byte */
- sig_type = (u_char)pgp_size(packet, 1);
- DBG(DBG_PARSING,
- DBG_log("L3 - signature type: 0x%2x", sig_type)
- )
-
- /* creation date - 4 bytes */
- created = (time_t)pgp_size(packet, 4);
- DBG(DBG_PARSING,
- DBG_log("L3 - created:");
- DBG_log(" %s", timetoa(&cert->created, TRUE))
- )
-
- /* key ID of signer - 8 bytes */
- keyid.ptr = packet->ptr;
- keyid.len = PGP_KEYID_SIZE;
- DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid);
-
- return TRUE;
-}
-
-bool
-parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key)
-{
- DBG(DBG_PARSING,
- DBG_log("L0 - PGP file:")
- )
- DBG_cond_dump_chunk(DBG_RAW, "", blob);
-
- if (cert != NULL)
- {
- /* parse a PGP certificate file */
- cert->certificate = blob;
- time(&cert->installed);
- }
- else if (key == NULL)
- {
- /* should not occur, nothing to parse */
- return FALSE;
- }
-
- while (blob.len > 0)
- {
- chunk_t packet = empty_chunk;
- u_char packet_tag = *blob.ptr;
-
- DBG(DBG_PARSING,
- DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag)
- )
-
- /* bit 7 must be set */
- if (!(packet_tag & 0x80))
- {
- plog(" incorrect Packet Tag");
- return FALSE;
- }
-
- /* bit 6 set defines new packet format */
- if (packet_tag & 0x40)
- {
- plog(" new PGP packet format not supported");
- return FALSE;
- }
- else
- {
- int packet_type = (packet_tag & 0x3C) >> 2;
-
- packet.len = pgp_old_packet_length(&blob);
- packet.ptr = blob.ptr;
- blob.ptr += packet.len;
- blob.len -= packet.len;
- DBG(DBG_PARSING,
- DBG_log(" %s (%d), old format, %d bytes",
- (packet_type < PGP_PKT_ROOF) ?
- pgp_packet_type_name[packet_type] :
- "Undefined Packet Type", packet_type, (int)packet.len);
- DBG_log("L2 - body:")
- )
- DBG_cond_dump_chunk(DBG_RAW, "", packet);
-
- if (cert != NULL)
- {
- /* parse a PGP certificate */
- switch (packet_type)
- {
- case PGP_PKT_PUBLIC_KEY:
- if (!parse_pgp_pubkey_packet(&packet, cert))
- return FALSE;
- break;
- case PGP_PKT_SIGNATURE:
- if (!parse_pgp_signature_packet(&packet, cert))
- return FALSE;
- break;
- case PGP_PKT_USER_ID:
- DBG(DBG_PARSING,
- DBG_log("L3 - user ID:");
- DBG_log(" '%.*s'", (int)packet.len, packet.ptr)
- )
- break;
- default:
- break;
- }
- }
- else
- {
- /* parse a PGP private key file */
- switch (packet_type)
- {
- case PGP_PKT_SECRET_KEY:
- if (!parse_pgp_secretkey_packet(&packet, key))
- return FALSE;
- break;
- default:
- break;
- }
- }
- }
- }
- return TRUE;
-}
-
-/*
- * compare two OpenPGP certificates
- */
-static bool
-same_pgpcert(pgpcert_t *a, pgpcert_t *b)
-{
- return a->certificate.len == b->certificate.len &&
- memcmp(a->certificate.ptr, b->certificate.ptr, b->certificate.len) == 0;
-}
-
-/*
- * for each link pointing to the certificate increase the count by one
- */
-void
-share_pgpcert(pgpcert_t *cert)
-{
- if (cert != NULL)
- cert->count++;
-}
-
-/*
- * select the OpenPGP keyid as ID
- */
-void
-select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
-{
- end_id->kind = ID_KEY_ID;
- end_id->name.len = PGP_FINGERPRINT_SIZE;
- end_id->name.ptr = cert->fingerprint;
- end_id->name.ptr = temporary_cyclic_buffer();
- memcpy(end_id->name.ptr, cert->fingerprint, PGP_FINGERPRINT_SIZE);
-}
-
-/*
- * add an OpenPGP user/host certificate to the chained list
- */
-pgpcert_t*
-add_pgpcert(pgpcert_t *cert)
-{
- pgpcert_t *c = pgpcerts;
-
- while (c != NULL)
- {
- if (same_pgpcert(c, cert)) /* already in chain, free cert */
- {
- free_pgpcert(cert);
- return c;
- }
- c = c->next;
- }
-
- /* insert new cert at the root of the chain */
- cert->next = pgpcerts;
- pgpcerts = cert;
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" pgp cert inserted")
- )
- return cert;
-}
-
-/* release of a certificate decreases the count by one
- " the certificate is freed when the counter reaches zero
- */
-void
-release_pgpcert(pgpcert_t *cert)
-{
- if (cert != NULL && --cert->count == 0)
- {
- pgpcert_t **pp = &pgpcerts;
- while (*pp != cert)
- pp = &(*pp)->next;
- *pp = cert->next;
- free_pgpcert(cert);
- }
-}
-
-/*
- * free a PGP certificate
- */
-void
-free_pgpcert(pgpcert_t *cert)
-{
- if (cert != NULL)
- {
- if (cert->certificate.ptr != NULL)
- pfree(cert->certificate.ptr);
- pfree(cert);
- }
-}
-
-/*
- * list all PGP end certificates in a chained list
- */
-void
-list_pgp_end_certs(bool utc)
-{
- pgpcert_t *cert = pgpcerts;
- time_t now;
-
- /* determine the current time */
- time(&now);
-
- if (cert != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of PGP End certificates:");
- whack_log(RC_COMMENT, " ");
- }
-
- while (cert != NULL)
- {
- unsigned keysize;
- char buf[BUF_LEN];
- cert_t c;
-
- c.type = CERT_PGP;
- c.u.pgp = cert;
-
- whack_log(RC_COMMENT, "%s, count: %d", timetoa(&cert->installed, utc), cert->count);
- datatot(cert->fingerprint, PGP_FINGERPRINT_SIZE, 'x', buf, BUF_LEN);
- whack_log(RC_COMMENT, " fingerprint: %s", buf);
- form_keyid(cert->publicExponent, cert->modulus, buf, &keysize);
- whack_log(RC_COMMENT, " pubkey: %4d RSA Key %s%s", 8*keysize, buf,
- (has_private_key(c))? ", has private key" : "");
- whack_log(RC_COMMENT, " created: %s", timetoa(&cert->created, utc));
- whack_log(RC_COMMENT, " until: %s %s", timetoa(&cert->until, utc),
- check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
- cert = cert->next;
- }
-}
-
diff --git a/src/pluto/pgpcert.c b/src/pluto/pgpcert.c
new file mode 100644
index 000000000..7fb8232d5
--- /dev/null
+++ b/src/pluto/pgpcert.c
@@ -0,0 +1,496 @@
+/* Support of OpenPGP certificates
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <freeswan.h>
+
+#include <library.h>
+#include <pgp/pgp.h>
+#include <crypto/hashers/hasher.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "id.h"
+#include "pgpcert.h"
+#include "certs.h"
+#include "whack.h"
+#include "keys.h"
+
+/**
+ * Chained list of OpenPGP end certificates
+ */
+static pgpcert_t *pgpcerts = NULL;
+
+/**
+ * Size of PGP Key ID
+ */
+#define PGP_KEYID_SIZE 8
+
+const pgpcert_t pgpcert_empty = {
+ NULL , /* next */
+ 0 , /* version */
+ 0 , /* installed */
+ 0 , /* count */
+ { NULL, 0 }, /* certificate */
+ 0 , /* created */
+ 0 , /* until */
+ NULL , /* public key */
+ NULL /* fingerprint */
+};
+
+
+/**
+ * Extracts the length of a PGP packet
+ */
+static size_t pgp_old_packet_length(chunk_t *blob)
+{
+ /* bits 0 and 1 define the packet length type */
+ int len_type = 0x03 & *blob->ptr++;
+
+ blob->len--;
+
+ /* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
+ return pgp_length(blob, (len_type == 0)? 1: len_type << 1);
+}
+
+/**
+ * Extracts PGP packet version (V3 or V4)
+ */
+static u_char pgp_version(chunk_t *blob)
+{
+ u_char version = *blob->ptr++;
+ blob->len--;
+ DBG(DBG_PARSING,
+ DBG_log("L3 - version:");
+ DBG_log(" V%d", version)
+ )
+ return version;
+}
+
+/**
+ * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
+ */
+static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
+{
+ time_t created;
+ chunk_t keyid;
+ u_char sig_type;
+ u_char version = pgp_version(packet);
+
+ /* we parse only V3 signature packets */
+ if (version != 3)
+ {
+ return TRUE;
+ }
+
+ /* size byte must have the value 5 */
+ if (pgp_length(packet, 1) != 5)
+ {
+ plog(" size must be 5");
+ return FALSE;
+ }
+
+ /* signature type - 1 byte */
+ sig_type = (u_char)pgp_length(packet, 1);
+ DBG(DBG_PARSING,
+ DBG_log("L3 - signature type: 0x%2x", sig_type)
+ )
+
+ /* creation date - 4 bytes */
+ created = (time_t)pgp_length(packet, 4);
+ DBG(DBG_PARSING,
+ DBG_log("L3 - created:");
+ DBG_log(" %T", &cert->created, TRUE)
+ )
+
+ /* key ID of signer - 8 bytes */
+ keyid.ptr = packet->ptr;
+ keyid.len = PGP_KEYID_SIZE;
+ DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid);
+
+ return TRUE;
+}
+
+/**
+ * Parses the version and validity of an OpenPGP public key packet
+ */
+static bool parse_pgp_pubkey_version_validity(chunk_t *packet, pgpcert_t *cert)
+{
+ cert->version = pgp_version(packet);
+
+ if (cert->version < 3 || cert->version > 4)
+ {
+ plog("OpenPGP packet version V%d not supported", cert->version);
+ return FALSE;
+ }
+
+ /* creation date - 4 bytes */
+ cert->created = (time_t)pgp_length(packet, 4);
+ DBG(DBG_PARSING,
+ DBG_log("L3 - created:");
+ DBG_log(" %T", &cert->created, TRUE)
+ )
+
+ if (cert->version == 3)
+ {
+ /* validity in days - 2 bytes */
+ cert->until = (time_t)pgp_length(packet, 2);
+
+ /* validity of 0 days means that the key never expires */
+ if (cert->until > 0)
+ {
+ cert->until = cert->created + 24*3600*cert->until;
+ }
+ DBG(DBG_PARSING,
+ DBG_log("L3 - until:");
+ DBG_log(" %T", &cert->until, TRUE);
+ )
+ }
+ return TRUE;
+}
+
+/**
+ * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 4880
+ */
+static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
+{
+ pgp_pubkey_alg_t pubkey_alg;
+ public_key_t *key;
+
+ if (!parse_pgp_pubkey_version_validity(packet, cert))
+ {
+ return FALSE;
+ }
+
+ /* public key algorithm - 1 byte */
+ pubkey_alg = pgp_length(packet, 1);
+ DBG(DBG_PARSING,
+ DBG_log("L3 - public key algorithm:");
+ DBG_log(" %N", pgp_pubkey_alg_names, pubkey_alg)
+ )
+
+ switch (pubkey_alg)
+ {
+ case PGP_PUBKEY_ALG_RSA:
+ case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, *packet,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return FALSE;
+ }
+ cert->public_key = key;
+
+ if (cert->version == 3)
+ {
+ cert->fingerprint = key->get_id(key, ID_KEY_ID);
+ if (cert->fingerprint == NULL)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ plog(" computation of V4 key ID not implemented yet");
+ return FALSE;
+ }
+ break;
+ default:
+ plog(" non RSA public keys not supported");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Parse OpenPGP secret key packet defined in section 5.5.3 of RFC 4880
+ */
+static bool parse_pgp_secretkey_packet(chunk_t *packet, private_key_t **key)
+{
+ pgp_pubkey_alg_t pubkey_alg;
+ pgpcert_t cert = pgpcert_empty;
+
+ if (!parse_pgp_pubkey_version_validity(packet, &cert))
+ {
+ return FALSE;
+ }
+
+ /* public key algorithm - 1 byte */
+ pubkey_alg = pgp_length(packet, 1);
+ DBG(DBG_PARSING,
+ DBG_log("L3 - public key algorithm:");
+ DBG_log(" %N", pgp_pubkey_alg_names, pubkey_alg)
+ )
+
+ switch (pubkey_alg)
+ {
+ case PGP_PUBKEY_ALG_RSA:
+ case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
+ *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, *packet,
+ BUILD_END);
+ break;
+ default:
+ plog(" non RSA private keys not supported");
+ return FALSE;
+ }
+ return (*key != NULL);
+}
+
+bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
+{
+ DBG(DBG_PARSING,
+ DBG_log("L0 - PGP file:")
+ )
+ DBG_cond_dump_chunk(DBG_RAW, "", blob);
+
+ if (cert != NULL)
+ {
+ /* parse a PGP certificate file */
+ cert->certificate = blob;
+ time(&cert->installed);
+ }
+ else if (key == NULL)
+ {
+ /* should not occur, nothing to parse */
+ return FALSE;
+ }
+
+ while (blob.len > 0)
+ {
+ chunk_t packet = chunk_empty;
+ u_char packet_tag = *blob.ptr;
+
+ DBG(DBG_PARSING,
+ DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag)
+ )
+
+ /* bit 7 must be set */
+ if (!(packet_tag & 0x80))
+ {
+ plog(" incorrect Packet Tag");
+ return FALSE;
+ }
+
+ /* bit 6 set defines new packet format */
+ if (packet_tag & 0x40)
+ {
+ plog(" new PGP packet format not supported");
+ return FALSE;
+ }
+ else
+ {
+ int packet_type = (packet_tag & 0x3C) >> 2;
+
+ packet.len = pgp_old_packet_length(&blob);
+ packet.ptr = blob.ptr;
+ blob.ptr += packet.len;
+ blob.len -= packet.len;
+ DBG(DBG_PARSING,
+ DBG_log(" %N (%d), old format, %u bytes",
+ pgp_packet_tag_names, packet_type,
+ packet_type, packet.len);
+ DBG_log("L2 - body:")
+ )
+ DBG_cond_dump_chunk(DBG_RAW, "", packet);
+
+ if (cert != NULL)
+ {
+ /* parse a PGP certificate */
+ switch (packet_type)
+ {
+ case PGP_PKT_PUBLIC_KEY:
+ if (!parse_pgp_pubkey_packet(&packet, cert))
+ {
+ return FALSE;
+ }
+ break;
+ case PGP_PKT_SIGNATURE:
+ if (!parse_pgp_signature_packet(&packet, cert))
+ {
+ return FALSE;
+ }
+ break;
+ case PGP_PKT_USER_ID:
+ DBG(DBG_PARSING,
+ DBG_log("L3 - user ID:");
+ DBG_log(" '%.*s'", (int)packet.len, packet.ptr)
+ )
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* parse a PGP private key file */
+ switch (packet_type)
+ {
+ case PGP_PKT_SECRET_KEY:
+ if (!parse_pgp_secretkey_packet(&packet, key))
+ {
+ return FALSE;
+ }
+ break;
+ case PGP_PKT_USER_ID:
+ DBG(DBG_PARSING,
+ DBG_log("L3 - user ID:");
+ DBG_log(" '%.*s'", (int)packet.len, packet.ptr)
+ )
+ break;
+ default:
+ break;
+ }
+
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Compare two OpenPGP certificates
+ */
+static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
+{
+ return a->certificate.len == b->certificate.len &&
+ memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
+}
+
+/**
+ * For each link pointing to the certificate increase the count by one
+ */
+void share_pgpcert(pgpcert_t *cert)
+{
+ if (cert != NULL)
+ {
+ cert->count++;
+ }
+}
+
+/**
+ * Select the OpenPGP keyid as ID
+ */
+void select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
+{
+ end_id->kind = ID_KEY_ID;
+ end_id->name = cert->fingerprint->get_encoding(cert->fingerprint);
+}
+
+/**
+ * Add an OpenPGP user/host certificate to the chained list
+ */
+pgpcert_t* add_pgpcert(pgpcert_t *cert)
+{
+ pgpcert_t *c = pgpcerts;
+
+ while (c != NULL)
+ {
+ if (same_pgpcert(c, cert)) /* already in chain, free cert */
+ {
+ free_pgpcert(cert);
+ return c;
+ }
+ c = c->next;
+ }
+
+ /* insert new cert at the root of the chain */
+ cert->next = pgpcerts;
+ pgpcerts = cert;
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log(" pgp cert inserted")
+ )
+ return cert;
+}
+
+/**
+ * Release of a certificate decreases the count by one.
+ * The certificate is freed when the counter reaches zero
+ */
+void release_pgpcert(pgpcert_t *cert)
+{
+ if (cert != NULL && --cert->count == 0)
+ {
+ pgpcert_t **pp = &pgpcerts;
+ while (*pp != cert)
+ {
+ pp = &(*pp)->next;
+ }
+ *pp = cert->next;
+ free_pgpcert(cert);
+ }
+}
+
+/**
+ * Free a PGP certificate
+ */
+void free_pgpcert(pgpcert_t *cert)
+{
+ if (cert != NULL)
+ {
+ DESTROY_IF(cert->public_key);
+ DESTROY_IF(cert->fingerprint);
+ free(cert->certificate.ptr);
+ free(cert);
+ }
+}
+
+/**
+ * List all PGP end certificates in a chained list
+ */
+void list_pgp_end_certs(bool utc)
+{
+ pgpcert_t *cert = pgpcerts;
+ time_t now;
+
+ /* determine the current time */
+ time(&now);
+
+ if (cert != NULL)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of PGP End certificates:");
+ whack_log(RC_COMMENT, " ");
+ }
+
+ while (cert != NULL)
+ {
+ public_key_t *key = cert->public_key;
+ cert_t c;
+
+ c.type = CERT_PGP;
+ c.u.pgp = cert;
+
+ whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc, cert->count);
+ whack_log(RC_COMMENT, " digest: %Y", cert->fingerprint);
+ whack_log(RC_COMMENT, " created: %T", &cert->created, utc);
+ whack_log(RC_COMMENT, " until: %T %s", &cert->until, utc,
+ check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
+ key_type_names, key->get_type(key),
+ key->get_keysize(key) * BITS_PER_BYTE,
+ has_private_key(c)? ", has private key" : "");
+ whack_log(RC_COMMENT, " keyid: %Y",
+ key->get_id(key, ID_PUBKEY_INFO_SHA1));
+ cert = cert->next;
+ }
+}
+
diff --git a/src/pluto/pgp.h b/src/pluto/pgpcert.h
index 514265086..727648391 100644
--- a/src/pluto/pgp.h
+++ b/src/pluto/pgpcert.h
@@ -1,5 +1,7 @@
/* Support of OpenPGP certificates
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,18 +12,19 @@
* 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: pgp.h 3252 2007-10-06 21:24:50Z andreas $
*/
-#ifndef _PGP_H
-#define _PGP_H
+#ifndef _PGPCERT_H
+#define _PGPCERT_H
+
+#include <crypto/hashers/hasher.h>
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
-#include "pkcs1.h"
/*
* Length of PGP V3 fingerprint
*/
-#define PGP_FINGERPRINT_SIZE MD5_DIGEST_SIZE
+#define PGP_FINGERPRINT_SIZE HASH_SIZE_MD5
typedef char fingerprint_t[PGP_FINGERPRINT_SIZE];
@@ -30,20 +33,19 @@ typedef char fingerprint_t[PGP_FINGERPRINT_SIZE];
typedef struct pgpcert pgpcert_t;
struct pgpcert {
- pgpcert_t *next;
- time_t installed;
- int count;
- chunk_t certificate;
- time_t created;
- time_t until;
- enum pubkey_alg pubkeyAlg;
- chunk_t modulus;
- chunk_t publicExponent;
- fingerprint_t fingerprint;
+ pgpcert_t *next;
+ int version;
+ time_t installed;
+ int count;
+ chunk_t certificate;
+ time_t created;
+ time_t until;
+ public_key_t *public_key;
+ identification_t *fingerprint;
};
-extern const pgpcert_t empty_pgpcert;
-extern bool parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key);
+extern const pgpcert_t pgpcert_empty;
+extern bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key);
extern void share_pgpcert(pgpcert_t *cert);
extern void select_pgpcert_id(pgpcert_t *cert, struct id *end_id);
extern pgpcert_t* add_pgpcert(pgpcert_t *cert);
@@ -51,4 +53,4 @@ extern void list_pgp_end_certs(bool utc);
extern void release_pgpcert(pgpcert_t *cert);
extern void free_pgpcert(pgpcert_t *cert);
-#endif /* _PGP_H */
+#endif /* _PGPCERT_H */
diff --git a/src/pluto/pkcs1.c b/src/pluto/pkcs1.c
deleted file mode 100644
index 49a06a8bc..000000000
--- a/src/pluto/pkcs1.c
+++ /dev/null
@@ -1,676 +0,0 @@
-/* Support of PKCS#1 private key data structures
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
- *
- * 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: pkcs1.c 3427 2008-01-27 20:17:15Z andreas $
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <freeswan.h>
-#include <libsha2/sha2.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "mp_defs.h"
-#include "asn1.h"
-#include <asn1/oid.h>
-#include "log.h"
-#include "pkcs1.h"
-#include "md2.h"
-#include "md5.h"
-#include "sha1.h"
-#include "rnd.h"
-
-const struct fld RSA_private_field[] =
-{
- { "Modulus", offsetof(RSA_private_key_t, pub.n) },
- { "PublicExponent", offsetof(RSA_private_key_t, pub.e) },
-
- { "PrivateExponent", offsetof(RSA_private_key_t, d) },
- { "Prime1", offsetof(RSA_private_key_t, p) },
- { "Prime2", offsetof(RSA_private_key_t, q) },
- { "Exponent1", offsetof(RSA_private_key_t, dP) },
- { "Exponent2", offsetof(RSA_private_key_t, dQ) },
- { "Coefficient", offsetof(RSA_private_key_t, qInv) },
-};
-
-/* ASN.1 definition of a PKCS#1 RSA private key */
-
-static const asn1Object_t privkeyObjects[] = {
- { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
- { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
- { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
- { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
- { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
- { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
- { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
- { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
- { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
- { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
- ASN1_LOOP }, /* 10 */
- { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
- { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
- { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
- { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
- { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
-};
-
-#define PKCS1_PRIV_KEY_VERSION 1
-#define PKCS1_PRIV_KEY_MODULUS 2
-#define PKCS1_PRIV_KEY_PUB_EXP 3
-#define PKCS1_PRIV_KEY_COEFF 9
-#define PKCS1_PRIV_KEY_ROOF 16
-
-
-/*
- * forms the FreeS/WAN keyid from the public exponent e and modulus n
- */
-void
-form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize)
-{
- /* eliminate leading zero bytes in modulus from ASN.1 coding */
- while (n.len > 1 && *n.ptr == 0x00)
- {
- n.ptr++; n.len--;
- }
-
- /* form the FreeS/WAN keyid */
- keyid[0] = '\0'; /* in case of splitkeytoid failure */
- splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF);
-
- /* return the RSA modulus size in octets */
- *keysize = n.len;
-}
-
-/*
- * initialize an RSA_public_key_t object
- */
-void
-init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n)
-{
- n_to_mpz(&rsa->e, e.ptr, e.len);
- n_to_mpz(&rsa->n, n.ptr, n.len);
-
- form_keyid(e, n, rsa->keyid, &rsa->k);
-}
-
-#ifdef DEBUG
-static void
-RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt)
-{
- const struct fld *p;
-
- DBG_log(" keyid: *%s", k->pub.keyid);
-
- for (p = RSA_private_field; p < &RSA_private_field[fieldcnt]; p++)
- {
- MP_INT *n = (MP_INT *) ((char *)k + p->offset);
- size_t sz = mpz_sizeinbase(n, 16);
- char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */
-
- passert(sz <= sizeof(buf));
- mpz_get_str(buf, 16, n);
-
- DBG_log(" %s: 0x%s", p->name, buf);
- }
-}
-
-/* debugging info that compromises security! */
-void
-RSA_show_private_key(RSA_private_key_t *k)
-{
- RSA_show_key_fields(k, elemsof(RSA_private_field));
-}
-
-void
-RSA_show_public_key(RSA_public_key_t *k)
-{
- /* Kludge: pretend that it is a private key, but only display the
- * first two fields (which are the public key).
- */
- passert(offsetof(RSA_private_key_t, pub) == 0);
- RSA_show_key_fields((RSA_private_key_t *)k, 2);
-}
-#endif
-
-err_t
-RSA_private_key_sanity(RSA_private_key_t *k)
-{
- /* note that the *last* error found is reported */
- err_t ugh = NULL;
- mpz_t t, u, q1;
-
-#ifdef DEBUG /* debugging info that compromises security */
- DBG(DBG_PRIVATE, RSA_show_private_key(k));
-#endif
-
- /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
- * We actually require more (for security).
- */
- if (k->pub.k < RSA_MIN_OCTETS)
- return RSA_MIN_OCTETS_UGH;
-
- /* we picked a max modulus size to simplify buffer allocation */
- if (k->pub.k > RSA_MAX_OCTETS)
- return RSA_MAX_OCTETS_UGH;
-
- mpz_init(t);
- mpz_init(u);
- mpz_init(q1);
-
- /* check that n == p * q */
- mpz_mul(u, &k->p, &k->q);
- if (mpz_cmp(u, &k->pub.n) != 0)
- ugh = "n != p * q";
-
- /* check that e divides neither p-1 nor q-1 */
- mpz_sub_ui(t, &k->p, 1);
- mpz_mod(t, t, &k->pub.e);
- if (mpz_cmp_ui(t, 0) == 0)
- ugh = "e divides p-1";
-
- mpz_sub_ui(t, &k->q, 1);
- mpz_mod(t, t, &k->pub.e);
- if (mpz_cmp_ui(t, 0) == 0)
- ugh = "e divides q-1";
-
- /* check that d is e^-1 (mod lcm(p-1, q-1)) */
- /* see PKCS#1v2, aka RFC 2437, for the "lcm" */
- mpz_sub_ui(q1, &k->q, 1);
- mpz_sub_ui(u, &k->p, 1);
- mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */
- mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */
- mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */
-
- mpz_mul(t, &k->d, &k->pub.e);
- mpz_mod(t, t, u);
- if (mpz_cmp_ui(t, 1) != 0)
- ugh = "(d * e) mod (lcm(p-1, q-1)) != 1";
-
- /* check that dP is d mod (p-1) */
- mpz_sub_ui(u, &k->p, 1);
- mpz_mod(t, &k->d, u);
- if (mpz_cmp(t, &k->dP) != 0)
- ugh = "dP is not congruent to d mod (p-1)";
-
- /* check that dQ is d mod (q-1) */
- mpz_sub_ui(u, &k->q, 1);
- mpz_mod(t, &k->d, u);
- if (mpz_cmp(t, &k->dQ) != 0)
- ugh = "dQ is not congruent to d mod (q-1)";
-
- /* check that qInv is (q^-1) mod p */
- mpz_mul(t, &k->qInv, &k->q);
- mpz_mod(t, t, &k->p);
- if (mpz_cmp_ui(t, 1) != 0)
- ugh = "qInv is not conguent ot (q^-1) mod p";
-
- mpz_clear(t);
- mpz_clear(u);
- mpz_clear(q1);
- return ugh;
-}
-
-/*
- * Check the equality of two RSA public keys
- */
-bool
-same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b)
-{
- return a == b
- || (a->k == b->k && mpz_cmp(&a->n, &b->n) == 0 && mpz_cmp(&a->e, &b->e) == 0);
-}
-
-/*
- * Parses a PKCS#1 private key
- */
-bool
-pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key)
-{
- err_t ugh = NULL;
- asn1_ctx_t ctx;
- chunk_t object, modulus, exp;
- u_int level;
- int objectID = 0;
-
- asn1_init(&ctx, blob, 0, FALSE, DBG_PRIVATE);
-
- while (objectID < PKCS1_PRIV_KEY_ROOF) {
-
- if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx))
- return FALSE;
-
- if (objectID == PKCS1_PRIV_KEY_VERSION)
- {
- if (object.len > 0 && *object.ptr != 0)
- {
- plog(" wrong PKCS#1 private key version");
- return FALSE;
- }
- }
- else if (objectID >= PKCS1_PRIV_KEY_MODULUS &&
- objectID <= PKCS1_PRIV_KEY_COEFF)
- {
- MP_INT *u = (MP_INT *) ((char *)key
- + RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset);
-
- n_to_mpz(u, object.ptr, object.len);
-
- if (objectID == PKCS1_PRIV_KEY_MODULUS)
- modulus = object;
- else if (objectID == PKCS1_PRIV_KEY_PUB_EXP)
- exp = object;
- }
- objectID++;
- }
- form_keyid(exp, modulus, key->pub.keyid, &key->pub.k);
- ugh = RSA_private_key_sanity(key);
- return (ugh == NULL);
-}
-
-/*
- * compute a digest over a binary blob
- */
-bool
-compute_digest(chunk_t tbs, int alg, chunk_t *digest)
-{
- switch (alg)
- {
- case OID_MD2:
- case OID_MD2_WITH_RSA:
- {
- MD2_CTX context;
-
- MD2Init(&context);
- MD2Update(&context, tbs.ptr, tbs.len);
- MD2Final(digest->ptr, &context);
- digest->len = MD2_DIGEST_SIZE;
- return TRUE;
- }
- case OID_MD5:
- case OID_MD5_WITH_RSA:
- {
- MD5_CTX context;
-
- MD5Init(&context);
- MD5Update(&context, tbs.ptr, tbs.len);
- MD5Final(digest->ptr, &context);
- digest->len = MD5_DIGEST_SIZE;
- return TRUE;
- }
- case OID_SHA1:
- case OID_SHA1_WITH_RSA:
- case OID_SHA1_WITH_RSA_OIW:
- {
- SHA1_CTX context;
-
- SHA1Init(&context);
- SHA1Update(&context, tbs.ptr, tbs.len);
- SHA1Final(digest->ptr, &context);
- digest->len = SHA1_DIGEST_SIZE;
- return TRUE;
- }
- case OID_SHA256:
- case OID_SHA256_WITH_RSA:
- {
- sha256_context context;
-
- sha256_init(&context);
- sha256_write(&context, tbs.ptr, tbs.len);
- sha256_final(&context);
- memcpy(digest->ptr, context.sha_out, SHA2_256_DIGEST_SIZE);
- digest->len = SHA2_256_DIGEST_SIZE;
- return TRUE;
- }
- case OID_SHA384:
- case OID_SHA384_WITH_RSA:
- {
- sha512_context context;
-
- sha384_init(&context);
- sha512_write(&context, tbs.ptr, tbs.len);
- sha512_final(&context);
- memcpy(digest->ptr, context.sha_out, SHA2_384_DIGEST_SIZE);
- digest->len = SHA2_384_DIGEST_SIZE;
- return TRUE;
- }
- case OID_SHA512:
- case OID_SHA512_WITH_RSA:
- {
- sha512_context context;
-
- sha512_init(&context);
- sha512_write(&context, tbs.ptr, tbs.len);
- sha512_final(&context);
- memcpy(digest->ptr, context.sha_out, SHA2_512_DIGEST_SIZE);
- digest->len = SHA2_512_DIGEST_SIZE;
- return TRUE;
- }
- default:
- digest->len = 0;
- return FALSE;
- }
-}
-
-/*
- * compute an RSA signature with PKCS#1 padding
- */
-void
-sign_hash(const RSA_private_key_t *k, const u_char *hash_val, size_t hash_len
- , u_char *sig_val, size_t sig_len)
-{
- chunk_t ch;
- mpz_t t1, t2;
- size_t padlen;
- u_char *p = sig_val;
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with RSA Key *%s", k->pub.keyid)
- )
- /* PKCS#1 v1.5 8.1 encryption-block formatting */
- *p++ = 0x00;
- *p++ = 0x01; /* BT (block type) 01 */
- padlen = sig_len - 3 - hash_len;
- memset(p, 0xFF, padlen);
- p += padlen;
- *p++ = 0x00;
- memcpy(p, hash_val, hash_len);
- passert(p + hash_len - sig_val == (ptrdiff_t)sig_len);
-
- /* PKCS#1 v1.5 8.2 octet-string-to-integer conversion */
- n_to_mpz(t1, sig_val, sig_len); /* (could skip leading 0x00) */
-
- /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n
- * Better described in PKCS#1 v2.0 5.1 RSADP.
- * There are two methods, depending on the form of the private key.
- * We use the one based on the Chinese Remainder Theorem.
- */
- mpz_init(t2);
-
- mpz_powm(t2, t1, &k->dP, &k->p); /* m1 = c^dP mod p */
-
- mpz_powm(t1, t1, &k->dQ, &k->q); /* m2 = c^dQ mod Q */
-
- mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
- mpz_mod(t2, t2, &k->p);
- mpz_mul(t2, t2, &k->qInv);
- mpz_mod(t2, t2, &k->p);
-
- mpz_mul(t2, t2, &k->q); /* m = m2 + h q */
- mpz_add(t1, t1, t2);
-
- /* PKCS#1 v1.5 8.4 integer-to-octet-string conversion */
- ch = mpz_to_n(t1, sig_len);
- memcpy(sig_val, ch.ptr, sig_len);
- pfree(ch.ptr);
-
- mpz_clear(t1);
- mpz_clear(t2);
-}
-
-/*
- * encrypt data with an RSA public key after padding
- */
-chunk_t
-RSA_encrypt(const RSA_public_key_t *key, chunk_t in)
-{
- u_char padded[RSA_MAX_OCTETS];
- u_char *pos = padded;
- int padding = key->k - in.len - 3;
- int i;
-
- if (padding < 8 || key->k > RSA_MAX_OCTETS)
- return empty_chunk;
-
- /* add padding according to PKCS#1 7.2.1 1.+2. */
- *pos++ = 0x00;
- *pos++ = 0x02;
-
- /* pad with pseudo random bytes unequal to zero */
- for (i = 0; i < padding; i++)
- {
- get_rnd_bytes(pos, padding);
- while (!*pos)
- {
- get_rnd_bytes(pos, 1);
- }
- pos++;
- }
-
- /* append the padding terminator */
- *pos++ = 0x00;
-
- /* now add the data */
- memcpy(pos, in.ptr, in.len);
- DBG(DBG_RAW,
- DBG_dump_chunk("data for rsa encryption:\n", in);
- DBG_dump("padded data for rsa encryption:\n", padded, key->k)
- )
-
- /* convert chunk to integer (PKCS#1 7.2.1 3.a) */
- {
- chunk_t out;
- mpz_t m, c;
-
- mpz_init(c);
- n_to_mpz(m, padded, key->k);
-
- /* encrypt(PKCS#1 7.2.1 3.b) */
- mpz_powm(c, m, &key->e, &key->n);
-
- /* convert integer back to a chunk (PKCS#1 7.2.1 3.c) */
- out = mpz_to_n(c, key->k);
- mpz_clear(c);
- mpz_clear(m);
-
- DBG(DBG_RAW,
- DBG_dump_chunk("rsa encrypted data:\n", out)
- )
- return out;
- }
-}
-
-/*
- * decrypt data with an RSA private key and remove padding
- */
-bool
-RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out)
-{
- chunk_t padded;
- u_char *pos;
- mpz_t t1, t2;
-
- n_to_mpz(t1, in.ptr,in.len);
-
- /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n
- * Better described in PKCS#1 v2.0 5.1 RSADP.
- * There are two methods, depending on the form of the private key.
- * We use the one based on the Chinese Remainder Theorem.
- */
- mpz_init(t2);
-
- mpz_powm(t2, t1, &key->dP, &key->p); /* m1 = c^dP mod p */
- mpz_powm(t1, t1, &key->dQ, &key->q); /* m2 = c^dQ mod Q */
-
- mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
- mpz_mod(t2, t2, &key->p);
- mpz_mul(t2, t2, &key->qInv);
- mpz_mod(t2, t2, &key->p);
-
- mpz_mul(t2, t2, &key->q); /* m = m2 + h q */
- mpz_add(t1, t1, t2);
-
- padded = mpz_to_n(t1, key->pub.k);
- mpz_clear(t1);
- mpz_clear(t2);
-
- DBG(DBG_PRIVATE,
- DBG_dump_chunk("rsa decrypted data with padding:\n", padded)
- )
- pos = padded.ptr;
-
- /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */
-
- /* check for hex pattern 00 02 in decrypted message */
- if ((*pos++ != 0x00) || (*(pos++) != 0x02))
- {
- plog("incorrect padding - probably wrong RSA key");
- freeanychunk(padded);
- return FALSE;
- }
- padded.len -= 2;
-
- /* the plaintext data starts after first 0x00 byte */
- while (padded.len-- > 0 && *pos++ != 0x00)
-
- if (padded.len == 0)
- {
- plog("no plaintext data");
- freeanychunk(padded);
- return FALSE;
- }
-
- clonetochunk(*out, pos, padded.len, "decrypted data");
- freeanychunk(padded);
- return TRUE;
-}
-
-/*
- * build signatureValue
- */
-chunk_t
-pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key
-, bool bit_string)
-{
-
- size_t siglen = key->pub.k;
-
- u_char digest_buf[MAX_DIGEST_LEN];
- chunk_t digest = { digest_buf, MAX_DIGEST_LEN };
- chunk_t digestInfo, alg_id, signatureValue;
- u_char *pos;
-
- switch (hash_alg)
- {
- case OID_MD5:
- case OID_MD5_WITH_RSA:
- alg_id = ASN1_md5_id;
- break;
- case OID_SHA1:
- case OID_SHA1_WITH_RSA:
- alg_id = ASN1_sha1_id;
- break;
- default:
- return empty_chunk;
- }
- compute_digest(tbs, hash_alg, &digest);
-
- /* according to PKCS#1 v2.1 digest must be packaged into
- * an ASN.1 structure for encryption
- */
- digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm"
- , alg_id
- , asn1_simple_object(ASN1_OCTET_STRING, digest));
-
- /* generate the RSA signature */
- if (bit_string)
- {
- pos = build_asn1_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen);
- *pos++ = 0x00;
- }
- else
- {
- pos = build_asn1_object(&signatureValue, ASN1_OCTET_STRING, siglen);
- }
- sign_hash(key, digestInfo.ptr, digestInfo.len, pos, siglen);
- pfree(digestInfo.ptr);
-
- return signatureValue;
-}
-
-/*
- * build a DER-encoded PKCS#1 private key object
- */
-chunk_t
-pkcs1_build_private_key(const RSA_private_key_t *key)
-{
- chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm"
- , ASN1_INTEGER_0
- , asn1_integer_from_mpz(&key->pub.n)
- , asn1_integer_from_mpz(&key->pub.e)
- , asn1_integer_from_mpz(&key->d)
- , asn1_integer_from_mpz(&key->p)
- , asn1_integer_from_mpz(&key->q)
- , asn1_integer_from_mpz(&key->dP)
- , asn1_integer_from_mpz(&key->dQ)
- , asn1_integer_from_mpz(&key->qInv));
-
- DBG(DBG_PRIVATE,
- DBG_dump_chunk("PKCS#1 encoded private key:", pkcs1)
- )
- return pkcs1;
-}
-
-/*
- * build a DER-encoded PKCS#1 public key object
- */
-chunk_t
-pkcs1_build_public_key(const RSA_public_key_t *rsa)
-{
- return asn1_wrap(ASN1_SEQUENCE, "mm"
- , asn1_integer_from_mpz(&rsa->n)
- , asn1_integer_from_mpz(&rsa->e));
-}
-
-/*
- * build a DER-encoded publicKeyInfo object
- */
-chunk_t
-pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa)
-{
- chunk_t publicKey;
- chunk_t rawKey = pkcs1_build_public_key(rsa);
-
- u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING
- , 1 + rawKey.len);
- *pos++ = 0x00;
- mv_chunk(&pos, rawKey);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_rsaEncryption_id
- , publicKey);
-}
-void
-free_RSA_public_content(RSA_public_key_t *rsa)
-{
- mpz_clear(&rsa->n);
- mpz_clear(&rsa->e);
-}
-
-void
-free_RSA_private_content(RSA_private_key_t *rsak)
-{
- free_RSA_public_content(&rsak->pub);
- mpz_clear(&rsak->d);
- mpz_clear(&rsak->p);
- mpz_clear(&rsak->q);
- mpz_clear(&rsak->dP);
- mpz_clear(&rsak->dQ);
- mpz_clear(&rsak->qInv);
-}
-
diff --git a/src/pluto/pkcs1.h b/src/pluto/pkcs1.h
deleted file mode 100644
index 16a6f02b9..000000000
--- a/src/pluto/pkcs1.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Support of PKCS#1 private key data structures
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
- *
- * 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: pkcs1.h 3252 2007-10-06 21:24:50Z andreas $
- */
-
-#ifndef _PKCS1_H
-#define _PKCS1_H
-
-#include <gmp.h> /* GNU Multi Precision library */
-
-#include "defs.h"
-
-typedef struct RSA_public_key RSA_public_key_t;
-
-struct RSA_public_key
-{
- char keyid[KEYID_BUF]; /* see ipsec_keyblobtoid(3) */
-
- /* length of modulus n in octets: [RSA_MIN_OCTETS, RSA_MAX_OCTETS] */
- unsigned k;
-
- /* public: */
- MP_INT
- n, /* modulus: p * q */
- e; /* exponent: relatively prime to (p-1) * (q-1) [probably small] */
-};
-
-typedef struct RSA_private_key RSA_private_key_t;
-
-struct RSA_private_key {
- struct RSA_public_key pub; /* must be at start for RSA_show_public_key */
-
- MP_INT
- d, /* private exponent: (e^-1) mod ((p-1) * (q-1)) */
- /* help for Chinese Remainder Theorem speedup: */
- p, /* first secret prime */
- q, /* second secret prime */
- dP, /* first factor's exponent: (e^-1) mod (p-1) == d mod (p-1) */
- dQ, /* second factor's exponent: (e^-1) mod (q-1) == d mod (q-1) */
- qInv; /* (q^-1) mod p */
-};
-
-struct fld {
- const char *name;
- size_t offset;
-};
-
-extern const struct fld RSA_private_field[];
-#define RSA_PRIVATE_FIELD_ELEMENTS 8
-
-extern void init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n);
-extern bool pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key);
-extern chunk_t pkcs1_build_private_key(const RSA_private_key_t *key);
-extern chunk_t pkcs1_build_public_key(const RSA_public_key_t *rsa);
-extern chunk_t pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa);
-extern chunk_t pkcs1_build_signature(chunk_t tbs, int hash_alg
- , const RSA_private_key_t *key, bool bit_string);
-extern bool compute_digest(chunk_t tbs, int alg, chunk_t *digest);
-extern void sign_hash(const RSA_private_key_t *k, const u_char *hash_val
- , size_t hash_len, u_char *sig_val, size_t sig_len);
-extern chunk_t RSA_encrypt(const RSA_public_key_t *key, chunk_t in);
-extern bool RSA_decrypt(const RSA_private_key_t *key, chunk_t in
- , chunk_t *out);
-extern bool same_RSA_public_key(const RSA_public_key_t *a
- , const RSA_public_key_t *b);
-extern void form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize);
-extern err_t RSA_private_key_sanity(RSA_private_key_t *k);
-#ifdef DEBUG
-extern void RSA_show_public_key(RSA_public_key_t *k);
-extern void RSA_show_private_key(RSA_private_key_t *k);
-#endif
-extern void free_RSA_public_content(RSA_public_key_t *rsa);
-extern void free_RSA_private_content(RSA_private_key_t *rsak);
-
-#endif /* _PKCS1_H */
diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c
index 60636f385..7248b042f 100644
--- a/src/pluto/pkcs7.c
+++ b/src/pluto/pkcs7.c
@@ -1,7 +1,8 @@
/* Support of PKCS#7 data structures
* Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil, Switzerland
*
* 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,564 +13,562 @@
* 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: pkcs7.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdlib.h>
#include <string.h>
-#include <libdes/des.h>
#include <freeswan.h>
+#include <library.h>
+#include <debug.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
+#include <crypto/rngs/rng.h>
+#include <crypto/crypters/crypter.h>
+
#include "constants.h"
#include "defs.h"
-#include "asn1.h"
-#include <asn1/oid.h>
-#include "log.h"
#include "x509.h"
#include "certs.h"
#include "pkcs7.h"
-#include "rnd.h"
const contentInfo_t empty_contentInfo = {
- OID_UNKNOWN , /* type */
- { NULL, 0 } /* content */
+ OID_UNKNOWN , /* type */
+ { NULL, 0 } /* content */
};
-/* ASN.1 definition of the PKCS#7 ContentInfo type */
-
+/**
+ * ASN.1 definition of the PKCS#7 ContentInfo type
+ */
static const asn1Object_t contentInfoObjects[] = {
- { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
- { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_BODY }, /* 2 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */
+ { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
+ { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 2 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
+#define PKCS7_INFO_TYPE 1
+#define PKCS7_INFO_CONTENT 2
-#define PKCS7_INFO_TYPE 1
-#define PKCS7_INFO_CONTENT 2
-#define PKCS7_INFO_ROOF 4
-
-/* ASN.1 definition of the PKCS#7 signedData type */
-
+/**
+ * ASN.1 definition of the PKCS#7 signedData type
+ */
static const asn1Object_t signedDataObjects[] = {
- { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
- { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
- { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
- { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
- { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
- { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_LOOP }, /* 6 */
- { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
- { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
- { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT |
- ASN1_LOOP }, /* 9 */
- { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
- { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
- { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
- { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
- { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
- { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
- { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
- { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
- { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_OBJ }, /* 19 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
- { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
- { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
- { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
- { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */
+ { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
+ { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
+ { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
+ { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 6 */
+ { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
+ { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_LOOP }, /* 9 */
+ { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
+ { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
+ { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
+ { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
+ { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
+ { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 19 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
+ { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
+ { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
+ { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
+#define PKCS7_DIGEST_ALG 3
+#define PKCS7_SIGNED_CONTENT_INFO 5
+#define PKCS7_SIGNED_CERT 7
+#define PKCS7_SIGNER_INFO 13
+#define PKCS7_SIGNED_ISSUER 16
+#define PKCS7_SIGNED_SERIAL_NUMBER 17
+#define PKCS7_DIGEST_ALGORITHM 18
+#define PKCS7_AUTH_ATTRIBUTES 19
+#define PKCS7_DIGEST_ENC_ALGORITHM 21
+#define PKCS7_ENCRYPTED_DIGEST 22
-#define PKCS7_DIGEST_ALG 3
-#define PKCS7_SIGNED_CONTENT_INFO 5
-#define PKCS7_SIGNED_CERT 7
-#define PKCS7_SIGNER_INFO 13
-#define PKCS7_SIGNED_ISSUER 16
-#define PKCS7_SIGNED_SERIAL_NUMBER 17
-#define PKCS7_DIGEST_ALGORITHM 18
-#define PKCS7_AUTH_ATTRIBUTES 19
-#define PKCS7_DIGEST_ENC_ALGORITHM 21
-#define PKCS7_ENCRYPTED_DIGEST 22
-#define PKCS7_SIGNED_ROOF 26
-
-/* ASN.1 definition of the PKCS#7 envelopedData type */
-
+/**
+ * ASN.1 definition of the PKCS#7 envelopedData type
+ */
static const asn1Object_t envelopedDataObjects[] = {
- { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
- { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
- { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
- { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
- { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
- { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
- { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
- { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
- { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
- { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
- { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
- { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
- { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */
+ { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
+ { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
+ { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
+ { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
+ { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
+ { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
+ { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
+ { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
+ { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
+#define PKCS7_ENVELOPED_VERSION 1
+#define PKCS7_RECIPIENT_INFO_VERSION 4
+#define PKCS7_ISSUER 6
+#define PKCS7_SERIAL_NUMBER 7
+#define PKCS7_ENCRYPTION_ALG 8
+#define PKCS7_ENCRYPTED_KEY 9
+#define PKCS7_CONTENT_TYPE 12
+#define PKCS7_CONTENT_ENC_ALGORITHM 13
+#define PKCS7_ENCRYPTED_CONTENT 14
+#define PKCS7_ENVELOPED_ROOF 15
-#define PKCS7_ENVELOPED_VERSION 1
-#define PKCS7_RECIPIENT_INFO_VERSION 4
-#define PKCS7_ISSUER 6
-#define PKCS7_SERIAL_NUMBER 7
-#define PKCS7_ENCRYPTION_ALG 8
-#define PKCS7_ENCRYPTED_KEY 9
-#define PKCS7_CONTENT_TYPE 12
-#define PKCS7_CONTENT_ENC_ALGORITHM 13
-#define PKCS7_ENCRYPTED_CONTENT 14
-#define PKCS7_ENVELOPED_ROOF 15
-
-/* PKCS7 contentInfo OIDs */
+/**
+ * PKCS7 contentInfo OIDs
+ */
static u_char ASN1_pkcs7_data_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01
};
static u_char ASN1_pkcs7_signed_data_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02
};
static u_char ASN1_pkcs7_enveloped_data_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03
};
static u_char ASN1_pkcs7_signed_enveloped_data_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04
};
static u_char ASN1_pkcs7_digested_data_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05
};
static char ASN1_pkcs7_encrypted_data_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06
};
static const chunk_t ASN1_pkcs7_data_oid =
- strchunk(ASN1_pkcs7_data_oid_str);
+ chunk_from_buf(ASN1_pkcs7_data_oid_str);
static const chunk_t ASN1_pkcs7_signed_data_oid =
- strchunk(ASN1_pkcs7_signed_data_oid_str);
+ chunk_from_buf(ASN1_pkcs7_signed_data_oid_str);
static const chunk_t ASN1_pkcs7_enveloped_data_oid =
- strchunk(ASN1_pkcs7_enveloped_data_oid_str);
+ chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str);
static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid =
- strchunk(ASN1_pkcs7_signed_enveloped_data_oid_str);
+ chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str);
static const chunk_t ASN1_pkcs7_digested_data_oid =
- strchunk(ASN1_pkcs7_digested_data_oid_str);
+ chunk_from_buf(ASN1_pkcs7_digested_data_oid_str);
static const chunk_t ASN1_pkcs7_encrypted_data_oid =
- strchunk(ASN1_pkcs7_encrypted_data_oid_str);
+ chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str);
-/* 3DES and DES encryption OIDs */
+/**
+ * 3DES and DES encryption OIDs
+ */
static u_char ASN1_3des_ede_cbc_oid_str[] = {
- 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
+ 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
};
static u_char ASN1_des_cbc_oid_str[] = {
- 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x07
+ 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x07
};
static const chunk_t ASN1_3des_ede_cbc_oid =
- strchunk(ASN1_3des_ede_cbc_oid_str);
+ chunk_from_buf(ASN1_3des_ede_cbc_oid_str);
static const chunk_t ASN1_des_cbc_oid =
- strchunk(ASN1_des_cbc_oid_str);
+ chunk_from_buf(ASN1_des_cbc_oid_str);
-/* PKCS#7 attribute type OIDs */
+/**
+ * PKCS#7 attribute type OIDs
+ */
static u_char ASN1_contentType_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
};
static u_char ASN1_messageDigest_oid_str[] = {
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
};
static const chunk_t ASN1_contentType_oid =
- strchunk(ASN1_contentType_oid_str);
+ chunk_from_buf(ASN1_contentType_oid_str);
static const chunk_t ASN1_messageDigest_oid =
- strchunk(ASN1_messageDigest_oid_str);
+ chunk_from_buf(ASN1_messageDigest_oid_str);
-/*
+/**
* Parse PKCS#7 ContentInfo object
*/
-bool
-pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
+bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ bool success = FALSE;
- while (objectID < PKCS7_INFO_ROOF)
- {
- if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx))
- return FALSE;
+ parser = asn1_parser_create(contentInfoObjects, blob);
+ parser->set_top_level(parser, level0);
- if (objectID == PKCS7_INFO_TYPE)
+ while (parser->iterate(parser, &objectID, &object))
{
- cInfo->type = known_oid(object);
- if (cInfo->type < OID_PKCS7_DATA
- || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
- {
- plog("unknown pkcs7 content type");
- return FALSE;
- }
- }
- else if (objectID == PKCS7_INFO_CONTENT)
- {
- cInfo->content = object;
+ if (objectID == PKCS7_INFO_TYPE)
+ {
+ cInfo->type = asn1_known_oid(object);
+ if (cInfo->type < OID_PKCS7_DATA
+ || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
+ {
+ DBG1("unknown pkcs7 content type");
+ goto end;
+ }
+ }
+ else if (objectID == PKCS7_INFO_CONTENT)
+ {
+ cInfo->content = object;
+ }
}
- objectID++;
- }
- return TRUE;
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ return success;
}
-/*
+/**
* Parse a PKCS#7 signedData object
*/
-bool
-pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
-, chunk_t *attributes, const x509cert_t *cacert)
+bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert,
+ chunk_t *attributes, const x509cert_t *cacert)
{
- u_char buf[BUF_LEN];
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int digest_alg = OID_UNKNOWN;
- int enc_alg = OID_UNKNOWN;
- int signerInfos = 0;
- int objectID = 0;
-
- contentInfo_t cInfo = empty_contentInfo;
- chunk_t encrypted_digest = empty_chunk;
-
- if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
- return FALSE;
-
- if (cInfo.type != OID_PKCS7_SIGNED_DATA)
- {
- plog("pkcs7 content type is not signedData");
- return FALSE;
- }
-
- asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW);
-
- while (objectID < PKCS7_SIGNED_ROOF)
- {
- if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx))
- return FALSE;
-
- switch (objectID)
- {
- case PKCS7_DIGEST_ALG:
- digest_alg = parse_algorithmIdentifier(object, level, NULL);
- break;
- case PKCS7_SIGNED_CONTENT_INFO:
- if (data != NULL)
- {
- pkcs7_parse_contentInfo(object, level, data);
- }
- break;
- case PKCS7_SIGNED_CERT:
- if (cert != NULL)
- {
- chunk_t cert_blob;
-
- x509cert_t *newcert = alloc_thing(x509cert_t
- , "pkcs7 wrapped x509cert");
-
- clonetochunk(cert_blob, object.ptr, object.len
- , "pkcs7 cert blob");
- *newcert = empty_x509cert;
-
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("parsing pkcs7-wrapped certificate")
- )
- if (parse_x509cert(cert_blob, level+1, newcert))
- {
- newcert->next = *cert;
- *cert = newcert;
- }
- else
- {
- free_x509cert(newcert);
- }
- }
- break;
- case PKCS7_SIGNER_INFO:
- signerInfos++;
- DBG(DBG_PARSING,
- DBG_log(" signer #%d", signerInfos)
- )
- break;
- case PKCS7_SIGNED_ISSUER:
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'",buf)
- )
- break;
- case PKCS7_AUTH_ATTRIBUTES:
- if (attributes != NULL)
- {
- *attributes = object;
- *attributes->ptr = ASN1_SET;
- }
- break;
- case PKCS7_DIGEST_ALGORITHM:
- digest_alg = parse_algorithmIdentifier(object, level, NULL);
- break;
- case PKCS7_DIGEST_ENC_ALGORITHM:
- enc_alg = parse_algorithmIdentifier(object, level, NULL);
- break;
- case PKCS7_ENCRYPTED_DIGEST:
- encrypted_digest = object;
- }
- objectID++;
- }
-
- /* check the signature only if a cacert is available */
- if (cacert != NULL)
- {
- if (signerInfos == 0)
+ u_char buf[BUF_LEN];
+ asn1_parser_t *parser;
+ chunk_t object;
+ int digest_alg = OID_UNKNOWN;
+ int enc_alg = OID_UNKNOWN;
+ int signerInfos = 0;
+ int objectID;
+ bool success = FALSE;
+
+ contentInfo_t cInfo = empty_contentInfo;
+ chunk_t encrypted_digest = chunk_empty;
+
+ if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
{
- plog("no signerInfo object found");
- return FALSE;
+ return FALSE;
}
- else if (signerInfos > 1)
+ if (cInfo.type != OID_PKCS7_SIGNED_DATA)
{
- plog("more than one signerInfo object found");
- return FALSE;
+ DBG1("pkcs7 content type is not signedData");
+ return FALSE;
}
- if (attributes->ptr == NULL)
+
+ parser = asn1_parser_create(signedDataObjects, blob);
+ parser->set_top_level(parser, 2);
+
+ while (parser->iterate(parser, &objectID, &object))
{
- plog("no authenticatedAttributes object found");
- return FALSE;
+ u_int level = parser->get_level(parser);
+
+ switch (objectID)
+ {
+ case PKCS7_DIGEST_ALG:
+ digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_SIGNED_CONTENT_INFO:
+ if (data != NULL)
+ {
+ pkcs7_parse_contentInfo(object, level, data);
+ }
+ break;
+ case PKCS7_SIGNED_CERT:
+ if (cert != NULL)
+ {
+ chunk_t cert_blob = chunk_clone(object);
+ x509cert_t *newcert = malloc_thing(x509cert_t);
+
+ *newcert = empty_x509cert;
+
+ DBG2(" parsing pkcs7-wrapped certificate");
+ if (parse_x509cert(cert_blob, level+1, newcert))
+ {
+ newcert->next = *cert;
+ *cert = newcert;
+ }
+ else
+ {
+ free_x509cert(newcert);
+ }
+ }
+ break;
+ case PKCS7_SIGNER_INFO:
+ signerInfos++;
+ DBG2(" signer #%d", signerInfos);
+ break;
+ case PKCS7_SIGNED_ISSUER:
+ dntoa(buf, BUF_LEN, object);
+ DBG2(" '%s'",buf);
+ break;
+ case PKCS7_AUTH_ATTRIBUTES:
+ if (attributes != NULL)
+ {
+ *attributes = object;
+ *attributes->ptr = ASN1_SET;
+ }
+ break;
+ case PKCS7_DIGEST_ALGORITHM:
+ digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_DIGEST_ENC_ALGORITHM:
+ enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_ENCRYPTED_DIGEST:
+ encrypted_digest = object;
+ }
}
- if (!check_signature(*attributes, encrypted_digest, digest_alg
- , enc_alg, cacert))
+ success = parser->success(parser);
+ parser->destroy(parser);
+ if (!success)
{
- plog("invalid signature");
- return FALSE;
+ return FALSE;
}
- else
+
+ /* check the signature only if a cacert is available */
+ if (cacert != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("signature is valid")
- )
+ public_key_t *key = cacert->public_key;
+ signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+
+ if (signerInfos == 0)
+ {
+ DBG1("no signerInfo object found");
+ return FALSE;
+ }
+ else if (signerInfos > 1)
+ {
+ DBG1("more than one signerInfo object found");
+ return FALSE;
+ }
+ if (attributes->ptr == NULL)
+ {
+ DBG1("no authenticatedAttributes object found");
+ return FALSE;
+ }
+ if (enc_alg != OID_RSA_ENCRYPTION)
+ {
+ DBG1("only RSA digest encryption supported");
+ return FALSE;
+ }
+
+ /* determine signature scheme */
+ scheme = signature_scheme_from_oid(digest_alg);
+
+ if (scheme == SIGN_UNKNOWN)
+ {
+ return FALSE;
+ }
+ if (key->verify(key, scheme, *attributes, encrypted_digest))
+ {
+ DBG2("signature is valid");
+ }
+ else
+ {
+ DBG1("invalid signature");
+ return FALSE;
+ }
}
- }
- return TRUE;
+ return TRUE;
}
-/*
+/**
* Parse a PKCS#7 envelopedData object
*/
-bool
-pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data
-, chunk_t serialNumber, const RSA_private_key_t *key)
+bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
+ chunk_t serialNumber,
+ private_key_t *key)
{
- asn1_ctx_t ctx;
- chunk_t object;
- chunk_t iv = empty_chunk;
- chunk_t symmetric_key = empty_chunk;
- chunk_t encrypted_content = empty_chunk;
-
- u_char buf[BUF_LEN];
- u_int level;
- u_int total_keys = 3;
- int enc_alg = OID_UNKNOWN;
- int content_enc_alg = OID_UNKNOWN;
- int objectID = 0;
-
- contentInfo_t cInfo = empty_contentInfo;
- *data = empty_chunk;
-
- if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
- goto failed;
-
- if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
- {
- plog("pkcs7 content type is not envelopedData");
- return FALSE;
- }
-
- asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW);
-
- while (objectID < PKCS7_ENVELOPED_ROOF)
- {
- if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx))
- goto failed;
-
- switch (objectID)
- {
- case PKCS7_ENVELOPED_VERSION:
- if (*object.ptr != 0)
+ asn1_parser_t *parser;
+ chunk_t object;
+ chunk_t iv = chunk_empty;
+ chunk_t symmetric_key = chunk_empty;
+ chunk_t encrypted_content = chunk_empty;
+
+ crypter_t *crypter = NULL;
+
+ u_char buf[BUF_LEN];
+ int enc_alg = OID_UNKNOWN;
+ int content_enc_alg = OID_UNKNOWN;
+ int objectID;
+ bool success = FALSE;
+
+ contentInfo_t cInfo = empty_contentInfo;
+ *data = chunk_empty;
+
+ if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
{
- plog("envelopedData version is not 0");
- goto failed;
- }
- break;
- case PKCS7_RECIPIENT_INFO_VERSION:
- if (*object.ptr != 0)
- {
- plog("recipient info version is not 0");
- goto failed;
- }
- break;
- case PKCS7_ISSUER:
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'", buf)
- )
- break;
- case PKCS7_SERIAL_NUMBER:
- if (!same_chunk(serialNumber, object))
- {
- plog("serial numbers do not match");
- goto failed;
- }
- break;
- case PKCS7_ENCRYPTION_ALG:
- enc_alg = parse_algorithmIdentifier(object, level, NULL);
- if (enc_alg != OID_RSA_ENCRYPTION)
- {
- plog("only rsa encryption supported");
- goto failed;
- }
- break;
- case PKCS7_ENCRYPTED_KEY:
- if (!RSA_decrypt(key, object, &symmetric_key))
- {
- plog("symmetric key could not be decrypted with rsa");
- goto failed;
- }
- DBG(DBG_PRIVATE,
- DBG_dump_chunk("symmetric key :", symmetric_key)
- )
- break;
- case PKCS7_CONTENT_TYPE:
- if (known_oid(object) != OID_PKCS7_DATA)
- {
- plog("encrypted content not of type pkcs7 data");
- goto failed;
- }
- break;
- case PKCS7_CONTENT_ENC_ALGORITHM:
- content_enc_alg = parse_algorithmIdentifier(object, level, &iv);
-
- switch (content_enc_alg)
- {
- case OID_DES_CBC:
- total_keys = 1;
- break;
- case OID_3DES_EDE_CBC:
- total_keys = 3;
- break;
- default:
- plog("Only DES and 3DES supported for symmetric encryption");
- goto failed;
- }
- if (symmetric_key.len != (total_keys * DES_CBC_BLOCK_SIZE))
- {
- plog("key length is not %d",(total_keys * DES_CBC_BLOCK_SIZE));
- goto failed;
- }
- if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
- {
- plog("IV could not be parsed");
goto failed;
- }
- if (iv.len != DES_CBC_BLOCK_SIZE)
- {
- plog("IV has wrong length");
+ }
+ if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
+ {
+ DBG1("pkcs7 content type is not envelopedData");
goto failed;
- }
- break;
- case PKCS7_ENCRYPTED_CONTENT:
- encrypted_content = object;
- break;
}
- objectID++;
- }
- /* decrypt the content */
- {
- u_int i;
- des_cblock des_key[3], des_iv;
- des_key_schedule key_s[3];
+ parser = asn1_parser_create(envelopedDataObjects, cInfo.content);
+ parser->set_top_level(parser, 2);
- memcpy((char *)des_key, symmetric_key.ptr, symmetric_key.len);
- memcpy((char *)des_iv, iv.ptr, iv.len);
-
- for (i = 0; i < total_keys; i++)
+ while (parser->iterate(parser, &objectID, &object))
{
- if (des_set_key(&des_key[i], key_s[i]))
- {
- plog("des key schedule failed");
- goto failed;
- }
- }
+ u_int level = parser->get_level(parser);
- data->len = encrypted_content.len;
- data->ptr = alloc_bytes(data->len, "decrypted data");
+ switch (objectID)
+ {
+ case PKCS7_ENVELOPED_VERSION:
+ if (*object.ptr != 0)
+ {
+ DBG1("envelopedData version is not 0");
+ goto end;
+ }
+ break;
+ case PKCS7_RECIPIENT_INFO_VERSION:
+ if (*object.ptr != 0)
+ {
+ DBG1("recipient info version is not 0");
+ goto end;
+ }
+ break;
+ case PKCS7_ISSUER:
+ dntoa(buf, BUF_LEN, object);
+ DBG2(" '%s'", buf);
+ break;
+ case PKCS7_SERIAL_NUMBER:
+ if (!chunk_equals(serialNumber, object))
+ {
+ DBG1("serial numbers do not match");
+ goto end;
+ }
+ break;
+ case PKCS7_ENCRYPTION_ALG:
+ enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ if (enc_alg != OID_RSA_ENCRYPTION)
+ {
+ DBG1("only rsa encryption supported");
+ goto end;
+ }
+ break;
+ case PKCS7_ENCRYPTED_KEY:
+ if (!key->decrypt(key, object, &symmetric_key))
+ {
+ DBG1("symmetric key could not be decrypted with rsa");
+ goto end;
+ }
+ DBG4("symmetric key %B", &symmetric_key);
+ break;
+ case PKCS7_CONTENT_TYPE:
+ if (asn1_known_oid(object) != OID_PKCS7_DATA)
+ {
+ DBG1("encrypted content not of type pkcs7 data");
+ goto end;
+ }
+ break;
+ case PKCS7_CONTENT_ENC_ALGORITHM:
+ content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv);
+
+ if (content_enc_alg == OID_UNKNOWN)
+ {
+ DBG1("unknown content encryption algorithm");
+ goto end;
+ }
+ if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
+ {
+ DBG1("IV could not be parsed");
+ goto end;
+ }
+ break;
+ case PKCS7_ENCRYPTED_CONTENT:
+ encrypted_content = object;
+ break;
+ }
+ }
+ success = parser->success(parser);
- switch (content_enc_alg)
+end:
+ parser->destroy(parser);
+ if (!success)
{
- case OID_DES_CBC:
- des_cbc_encrypt((des_cblock*)encrypted_content.ptr
- , (des_cblock*)data->ptr, data->len
- , key_s[0], &des_iv, DES_DECRYPT);
- break;
- case OID_3DES_EDE_CBC:
- des_ede3_cbc_encrypt( (des_cblock*)encrypted_content.ptr
- , (des_cblock*)data->ptr, data->len
- , key_s[0], key_s[1], key_s[2]
- , &des_iv, DES_DECRYPT);
+ goto failed;
}
- DBG(DBG_PRIVATE,
- DBG_dump_chunk("decrypted content with padding:\n", *data)
- )
- }
-
- /* remove the padding */
- {
- u_char *pos = data->ptr + data->len - 1;
- u_char pattern = *pos;
- size_t padding = pattern;
-
- if (padding > data->len)
+ success = FALSE;
+
+ /* decrypt the content */
{
- plog("padding greater than data length");
- goto failed;
+ encryption_algorithm_t alg;
+ size_t key_size;
+ crypter_t *crypter;
+
+ alg = encryption_algorithm_from_oid(content_enc_alg, &key_size);
+ if (alg == ENCR_UNDEFINED)
+ {
+ DBG1("unsupported content encryption algorithm");
+ goto failed;
+ }
+ crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
+ if (crypter == NULL)
+ {
+ DBG1("crypter %N not available", encryption_algorithm_names, alg);
+ goto failed;
+ }
+ if (symmetric_key.len != crypter->get_key_size(crypter))
+ {
+ DBG1("symmetric key length %d is wrong", symmetric_key.len);
+ goto failed;
+ }
+ if (iv.len != crypter->get_block_size(crypter))
+ {
+ DBG1("IV length %d is wrong", iv.len);
+ goto failed;
+ }
+ crypter->set_key(crypter, symmetric_key);
+ crypter->decrypt(crypter, encrypted_content, iv, data);
+ DBG4("decrypted content with padding: %B", data);
}
- data->len -= padding;
- while (padding-- > 0)
+ /* remove the padding */
{
- if (*pos-- != pattern)
- {
- plog("wrong padding pattern");
- goto failed;
- }
+ u_char *pos = data->ptr + data->len - 1;
+ u_char pattern = *pos;
+ size_t padding = pattern;
+
+ if (padding > data->len)
+ {
+ DBG1("padding greater than data length");
+ goto failed;
+ }
+ data->len -= padding;
+
+ while (padding-- > 0)
+ {
+ if (*pos-- != pattern)
+ {
+ DBG1("wrong padding pattern");
+ goto failed;
+ }
+ }
}
- }
- freeanychunk(symmetric_key);
- return TRUE;
+ success = TRUE;
failed:
- freeanychunk(symmetric_key);
- pfreeany(data->ptr);
- return FALSE;
+ DESTROY_IF(crypter);
+ chunk_clear(&symmetric_key);
+ if (!success)
+ {
+ free(data->ptr);
+ }
+ return success;
}
/**
@@ -577,12 +576,11 @@ failed:
*
* @return ASN.1 encoded contentType attribute
*/
-chunk_t
-pkcs7_contentType_attribute(void)
+chunk_t pkcs7_contentType_attribute(void)
{
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_contentType_oid
- , asn1_simple_object(ASN1_SET, ASN1_pkcs7_data_oid));
+ return asn1_wrap(ASN1_SEQUENCE, "cm"
+ , ASN1_contentType_oid
+ , asn1_simple_object(ASN1_SET, ASN1_pkcs7_data_oid));
}
/**
@@ -594,269 +592,228 @@ pkcs7_contentType_attribute(void)
* @return ASN.1 encoded messageDigest attribute
*
*/
-chunk_t
-pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
+chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
{
- u_char digest_buf[MAX_DIGEST_LEN];
- chunk_t digest = { digest_buf, MAX_DIGEST_LEN };
-
- compute_digest(content, digest_alg, &digest);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_messageDigest_oid
- , asn1_wrap(ASN1_SET, "m"
- , asn1_simple_object(ASN1_OCTET_STRING, digest)
- )
- );
+ chunk_t digest;
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+
+ hash_alg = hasher_algorithm_from_oid(digest_alg);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ hasher->allocate_hash(hasher, content, &digest);
+ hasher->destroy(hasher);
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ ASN1_messageDigest_oid,
+ asn1_wrap(ASN1_SET, "m",
+ asn1_wrap(ASN1_OCTET_STRING, "m", digest)
+ )
+ );
}
-/*
+
+/**
* build a DER-encoded contentInfo object
*/
-static chunk_t
-pkcs7_build_contentInfo(contentInfo_t *cInfo)
+static chunk_t pkcs7_build_contentInfo(contentInfo_t *cInfo)
{
- chunk_t content_type;
-
- /* select DER-encoded OID for pkcs7 contentInfo type */
- switch(cInfo->type)
- {
- case OID_PKCS7_DATA:
- content_type = ASN1_pkcs7_data_oid;
- break;
- case OID_PKCS7_SIGNED_DATA:
- content_type = ASN1_pkcs7_signed_data_oid;
- break;
- case OID_PKCS7_ENVELOPED_DATA:
- content_type = ASN1_pkcs7_enveloped_data_oid;
- break;
- case OID_PKCS7_SIGNED_ENVELOPED_DATA:
- content_type = ASN1_pkcs7_signed_enveloped_data_oid;
- break;
- case OID_PKCS7_DIGESTED_DATA:
- content_type = ASN1_pkcs7_digested_data_oid;
- break;
- case OID_PKCS7_ENCRYPTED_DATA:
- content_type = ASN1_pkcs7_encrypted_data_oid;
- break;
- case OID_UNKNOWN:
- default:
- fprintf(stderr, "invalid pkcs7 contentInfo type");
- return empty_chunk;
- }
-
- return (cInfo->content.ptr == NULL)
- ? asn1_simple_object(ASN1_SEQUENCE, content_type)
- : asn1_wrap(ASN1_SEQUENCE, "cm"
- , content_type
- , asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content)
- );
+ chunk_t content_type;
+
+ /* select DER-encoded OID for pkcs7 contentInfo type */
+ switch(cInfo->type)
+ {
+ case OID_PKCS7_DATA:
+ content_type = ASN1_pkcs7_data_oid;
+ break;
+ case OID_PKCS7_SIGNED_DATA:
+ content_type = ASN1_pkcs7_signed_data_oid;
+ break;
+ case OID_PKCS7_ENVELOPED_DATA:
+ content_type = ASN1_pkcs7_enveloped_data_oid;
+ break;
+ case OID_PKCS7_SIGNED_ENVELOPED_DATA:
+ content_type = ASN1_pkcs7_signed_enveloped_data_oid;
+ break;
+ case OID_PKCS7_DIGESTED_DATA:
+ content_type = ASN1_pkcs7_digested_data_oid;
+ break;
+ case OID_PKCS7_ENCRYPTED_DATA:
+ content_type = ASN1_pkcs7_encrypted_data_oid;
+ break;
+ case OID_UNKNOWN:
+ default:
+ DBG1("invalid pkcs7 contentInfo type");
+ return chunk_empty;
+ }
+
+ return (cInfo->content.ptr == NULL)
+ ? asn1_simple_object(ASN1_SEQUENCE, content_type)
+ : asn1_wrap(ASN1_SEQUENCE, "cm"
+ , content_type
+ , asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content)
+ );
}
-/*
+/**
* build issuerAndSerialNumber object
*/
-chunk_t
-pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert)
+chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert)
{
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , cert->issuer
- , asn1_simple_object(ASN1_INTEGER, cert->serialNumber));
+ return asn1_wrap(ASN1_SEQUENCE, "cm"
+ , cert->issuer
+ , asn1_integer("c", cert->serialNumber));
}
-/*
+/**
* create a signed pkcs7 contentInfo object
*/
-chunk_t
-pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert
-, int digest_alg, const RSA_private_key_t *key)
+chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
+ const x509cert_t *cert, int digest_alg,
+ private_key_t *key)
{
- contentInfo_t pkcs7Data, signedData;
- chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo;
-
- chunk_t digestAlgorithm = asn1_algorithmIdentifier(digest_alg);
-
- if (attributes.ptr != NULL)
- {
- encryptedDigest = pkcs1_build_signature(attributes, digest_alg
- , key, FALSE);
- clonetochunk(authenticatedAttributes, attributes.ptr, attributes.len
- , "authenticatedAttributes");
- *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
- }
- else
- {
- encryptedDigest = (data.ptr == NULL)? empty_chunk
- : pkcs1_build_signature(data, digest_alg, key, FALSE);
- authenticatedAttributes = empty_chunk;
- }
-
- signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm"
- , ASN1_INTEGER_1
- , pkcs7_build_issuerAndSerialNumber(cert)
- , digestAlgorithm
- , authenticatedAttributes
- , ASN1_rsaEncryption_id
- , encryptedDigest);
-
- pkcs7Data.type = OID_PKCS7_DATA;
- pkcs7Data.content = (data.ptr == NULL)? empty_chunk
- : asn1_simple_object(ASN1_OCTET_STRING, data);
-
- signedData.type = OID_PKCS7_SIGNED_DATA;
- signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
- , ASN1_INTEGER_1
- , asn1_simple_object(ASN1_SET, digestAlgorithm)
- , pkcs7_build_contentInfo(&pkcs7Data)
- , asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate)
- , asn1_wrap(ASN1_SET, "m", signerInfo));
-
- cInfo = pkcs7_build_contentInfo(&signedData);
- DBG(DBG_RAW,
- DBG_dump_chunk("signedData:\n", cInfo)
- )
-
- freeanychunk(pkcs7Data.content);
- freeanychunk(signedData.content);
- return cInfo;
+ contentInfo_t pkcs7Data, signedData;
+ chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo;
+
+ chunk_t digestAlgorithm = asn1_algorithmIdentifier(digest_alg);
+
+ if (attributes.ptr != NULL)
+ {
+ encryptedDigest = x509_build_signature(attributes, digest_alg, key,
+ FALSE);
+ authenticatedAttributes = chunk_clone(attributes);
+ *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ }
+ else
+ {
+ encryptedDigest = (data.ptr == NULL)? chunk_empty
+ : x509_build_signature(data, digest_alg, key, FALSE);
+ authenticatedAttributes = chunk_empty;
+ }
+
+ signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm"
+ , ASN1_INTEGER_1
+ , pkcs7_build_issuerAndSerialNumber(cert)
+ , digestAlgorithm
+ , authenticatedAttributes
+ , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
+ , encryptedDigest);
+
+ pkcs7Data.type = OID_PKCS7_DATA;
+ pkcs7Data.content = (data.ptr == NULL)? chunk_empty
+ : asn1_simple_object(ASN1_OCTET_STRING, data);
+
+ signedData.type = OID_PKCS7_SIGNED_DATA;
+ signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
+ , ASN1_INTEGER_1
+ , asn1_simple_object(ASN1_SET, digestAlgorithm)
+ , pkcs7_build_contentInfo(&pkcs7Data)
+ , asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate)
+ , asn1_wrap(ASN1_SET, "m", signerInfo));
+
+ cInfo = pkcs7_build_contentInfo(&signedData);
+ DBG3("signedData %B", &cInfo);
+
+ free(pkcs7Data.content.ptr);
+ free(signedData.content.ptr);
+ return cInfo;
}
-/*
+/**
* create a symmetrically encrypted pkcs7 contentInfo object
*/
-chunk_t
-pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int cipher)
+chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_alg)
{
- bool des_check_key_save;
- des_key_schedule ks[3];
- des_cblock key[3], des_iv, des_iv_buf;
-
- chunk_t iv = { (u_char *)des_iv_buf, DES_CBC_BLOCK_SIZE };
- chunk_t out;
- chunk_t cipher_oid;
-
- u_int total_keys, i;
- size_t padding = pad_up(data.len, DES_CBC_BLOCK_SIZE);
-
- RSA_public_key_t public_key;
-
- init_RSA_public_key(&public_key, cert->publicExponent
- , cert->modulus);
-
- if (padding == 0)
- padding += DES_CBC_BLOCK_SIZE;
-
- out.len = data.len + padding;
- out.ptr = alloc_bytes(out.len, "DES-encrypted output");
-
- DBG(DBG_CONTROL,
- DBG_log("padding %d bytes of data to multiple DES block size of %d bytes"
- , (int)data.len, (int)out.len)
- )
-
- /* copy data */
- memcpy(out.ptr, data.ptr, data.len);
- /* append padding */
- memset(out.ptr + data.len, padding, padding);
-
- DBG(DBG_RAW,
- DBG_dump_chunk("Padded unencrypted data:\n", out)
- )
-
- /* select OID and keylength for specified cipher */
- switch (cipher)
- {
- case OID_DES_CBC:
- total_keys = 1;
- cipher_oid = ASN1_des_cbc_oid;
- break;
- case OID_3DES_EDE_CBC:
- default:
- total_keys = 3;
- cipher_oid = ASN1_3des_ede_cbc_oid;
- }
- DBG(DBG_CONTROLMORE,
- DBG_log("pkcs7 encryption cipher: %s", oid_names[cipher].name)
- )
-
- /* generate a strong random key for DES/3DES */
- des_check_key_save = des_check_key;
- des_check_key = TRUE;
- for (i = 0; i < total_keys;i++)
- {
- for (;;)
+ encryption_algorithm_t alg;
+ size_t alg_key_size;
+ chunk_t symmetricKey, protectedKey, iv, in, out;
+ crypter_t *crypter;
+
+ alg = encryption_algorithm_from_oid(enc_alg, &alg_key_size);
+ crypter = lib->crypto->create_crypter(lib->crypto, alg,
+ alg_key_size/BITS_PER_BYTE);
+ if (crypter == NULL)
{
- get_rnd_bytes((char*)key[i], DES_CBC_BLOCK_SIZE);
- des_set_odd_parity(&key[i]);
- if (!des_set_key(&key[i], ks[i]))
- break;
- plog("weak DES key discarded - we try again");
+ DBG1("crypter for %N not available", encryption_algorithm_names, alg);
+ return chunk_empty;
+ }
+
+ /* generate a true random symmetric encryption key and a pseudo-random iv */
+ {
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
+ rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey);
+ DBG4("symmetric encryption key %B", &symmetricKey);
+ rng->destroy(rng);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ rng->allocate_bytes(rng, crypter->get_block_size(crypter), &iv);
+ DBG4("initialization vector: %B", &iv);
+ rng->destroy(rng);
+ }
+
+ /* pad the data to a multiple of the block size */
+ {
+ size_t block_size = crypter->get_block_size(crypter);
+ size_t padding = block_size - data.len % block_size;
+
+ in.len = data.len + padding;
+ in.ptr = malloc(in.len);
+
+ DBG2("padding %u bytes of data to multiple block size of %u bytes",
+ data.len, in.len);
+
+ /* copy data */
+ memcpy(in.ptr, data.ptr, data.len);
+ /* append padding */
+ memset(in.ptr + data.len, padding, padding);
+ }
+ DBG3("padded unencrypted data %B", &in);
+
+ /* symmetric encryption of data object */
+ crypter->set_key(crypter, symmetricKey);
+ crypter->encrypt(crypter, in, iv, &out);
+ crypter->destroy(crypter);
+ DBG3("encrypted data %B", &out);
+
+ cert->public_key->encrypt(cert->public_key, symmetricKey, &protectedKey);
+
+ /* build pkcs7 enveloped data object */
+ {
+
+ chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm"
+ , asn1_build_known_oid(enc_alg)
+ , asn1_simple_object(ASN1_OCTET_STRING, iv));
+
+ chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm"
+ , ASN1_pkcs7_data_oid
+ , contentEncryptionAlgorithm
+ , asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
+
+ chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
+ , protectedKey);
+
+ chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm"
+ , ASN1_INTEGER_0
+ , pkcs7_build_issuerAndSerialNumber(cert)
+ , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
+ , encryptedKey);
+
+ chunk_t cInfo;
+ contentInfo_t envelopedData;
+
+ envelopedData.type = OID_PKCS7_ENVELOPED_DATA;
+ envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm"
+ , ASN1_INTEGER_0
+ , asn1_wrap(ASN1_SET, "m", recipientInfo)
+ , encryptedContentInfo);
+
+ cInfo = pkcs7_build_contentInfo(&envelopedData);
+ DBG3("envelopedData %B", &cInfo);
+
+ free(envelopedData.content.ptr);
+ free(symmetricKey.ptr);
+ free(in.ptr);
+ free(iv.ptr);
+ return cInfo;
}
- DBG(DBG_PRIVATE,
- DBG_dump("DES key:", key[i], 8)
- )
- }
- des_check_key = des_check_key_save;
-
- /* generate an iv for DES/3DES CBC */
- get_rnd_bytes(des_iv, DES_CBC_BLOCK_SIZE);
- memcpy(iv.ptr, des_iv, DES_CBC_BLOCK_SIZE);
- DBG(DBG_RAW,
- DBG_dump_chunk("DES IV :", iv)
- )
-
- /* encryption using specified cipher */
- switch (cipher)
- {
- case OID_DES_CBC:
- des_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len
- , ks[0], &des_iv, DES_ENCRYPT);
- break;
- case OID_3DES_EDE_CBC:
- default:
- des_ede3_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len
- , ks[0], ks[1], ks[2], &des_iv, DES_ENCRYPT);
- }
- DBG(DBG_RAW,
- DBG_dump_chunk("Encrypted data:\n", out));
-
- /* build pkcs7 enveloped data object */
- {
- chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm"
- , cipher_oid
- , asn1_simple_object(ASN1_OCTET_STRING, iv));
-
- chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm"
- , ASN1_pkcs7_data_oid
- , contentEncryptionAlgorithm
- , asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
-
- chunk_t plainKey = { (u_char *)key, DES_CBC_BLOCK_SIZE * total_keys };
-
- chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
- , RSA_encrypt(&public_key, plainKey));
-
- chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm"
- , ASN1_INTEGER_0
- , pkcs7_build_issuerAndSerialNumber(cert)
- , ASN1_rsaEncryption_id
- , encryptedKey);
-
- chunk_t cInfo;
- contentInfo_t envelopedData;
-
- envelopedData.type = OID_PKCS7_ENVELOPED_DATA;
- envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm"
- , ASN1_INTEGER_0
- , asn1_wrap(ASN1_SET, "m", recipientInfo)
- , encryptedContentInfo);
-
- cInfo = pkcs7_build_contentInfo(&envelopedData);
- DBG(DBG_RAW,
- DBG_dump_chunk("envelopedData:\n", cInfo)
- )
-
- free_RSA_public_content(&public_key);
- freeanychunk(envelopedData.content);
- return cInfo;
- }
}
diff --git a/src/pluto/pkcs7.h b/src/pluto/pkcs7.h
index a577f8022..028822dfe 100644
--- a/src/pluto/pkcs7.h
+++ b/src/pluto/pkcs7.h
@@ -1,6 +1,7 @@
/* Support of PKCS#7 data structures
* Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -12,15 +13,14 @@
* 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: pkcs7.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _PKCS7_H
#define _PKCS7_H
+#include <crypto/crypters/crypter.h>
+#include <credentials/keys/private_key.h>
#include "defs.h"
-#include "pkcs1.h"
#include "x509.h"
/* Access structure for a PKCS#7 ContentInfo object */
@@ -28,24 +28,24 @@
typedef struct contentInfo contentInfo_t;
struct contentInfo {
- int type;
- chunk_t content;
+ int type;
+ chunk_t content;
};
extern const contentInfo_t empty_contentInfo;
-extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0
- , contentInfo_t *cInfo);
-extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data
- , x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert);
-extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data
- , chunk_t serialNumber, const RSA_private_key_t *key);
+extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
+ contentInfo_t *cInfo);
+extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
+ x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert);
+extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
+ chunk_t serialNumber, private_key_t *key);
extern chunk_t pkcs7_contentType_attribute(void);
extern chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg);
extern chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert);
-extern chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes
- ,const x509cert_t *cert, int digest_alg, const RSA_private_key_t *key);
-extern chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert
- , int cipher);
+extern chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
+ const x509cert_t *cert, int digest_alg, private_key_t *key);
+extern chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert,
+ int enc_alg);
#endif /* _PKCS7_H */
diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c
index a39934f1f..39367cafa 100644
--- a/src/pluto/plutomain.c
+++ b/src/pluto/plutomain.c
@@ -1,6 +1,7 @@
/* Pluto main program
* Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
+ * Copyright (C) 1998-2001 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,8 +12,6 @@
* 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: plutomain.c 4313 2008-08-29 09:24:14Z martin $
*/
#include <stdio.h>
@@ -27,7 +26,7 @@
#include <fcntl.h>
#include <getopt.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <sys/prctl.h>
#include <pwd.h>
@@ -39,6 +38,16 @@
#include <freeswan.h>
+#include <library.h>
+#include <debug.h>
+#include <utils/enumerator.h>
+#include <utils/optionsfrom.h>
+
+#ifdef INTEGRITY_TEST
+#include <fips/fips.h>
+#include <fips/fips_signature.h>
+#endif /* INTEGRITY_TEST */
+
#include <pfkeyv2.h>
#include <pfkey.h>
@@ -51,91 +60,88 @@
#include "connections.h"
#include "foodgroups.h"
#include "packet.h"
-#include "demux.h" /* needs packet.h */
+#include "demux.h" /* needs packet.h */
#include "server.h"
#include "kernel.h"
#include "log.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "rnd.h"
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "state.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "ocsp.h"
#include "crl.h"
#include "fetch.h"
#include "xauth.h"
-#include "sha1.h"
-#include "md5.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
+#include "crypto.h"
#include "nat_traversal.h"
#include "virtual.h"
+#include "timer.h"
+#include "vendor.h"
-static void
-usage(const char *mess)
+static void usage(const char *mess)
{
- if (mess != NULL && *mess != '\0')
- fprintf(stderr, "%s\n", mess);
- fprintf(stderr
- , "Usage: pluto"
- " [--help]"
- " [--version]"
- " [--optionsfrom <filename>]"
- " \\\n\t"
- "[--nofork]"
- " [--stderrlog]"
- " [--noklips]"
- " [--nocrsend]"
- " \\\n\t"
- "[--strictcrlpolicy]"
- " [--crlcheckinterval <interval>]"
- " [--cachecrls]"
- " [--uniqueids]"
- " \\\n\t"
- "[--interface <ifname>]"
- " [--ikeport <port-number>]"
- " \\\n\t"
- "[--ctlbase <path>]"
- " \\\n\t"
- "[--perpeerlogbase <path>] [--perpeerlog]"
- " \\\n\t"
- "[--secretsfile <secrets-file>]"
- " [--policygroupsdir <policygroups-dir>]"
- " \\\n\t"
- "[--adns <pathname>]"
- "[--pkcs11module <path>]"
- "[--pkcs11keepstate]"
- "[--pkcs11initargs <string>]"
+ if (mess != NULL && *mess != '\0')
+ fprintf(stderr, "%s\n", mess);
+ fprintf(stderr
+ , "Usage: pluto"
+ " [--help]"
+ " [--version]"
+ " [--optionsfrom <filename>]"
+ " \\\n\t"
+ "[--nofork]"
+ " [--stderrlog]"
+ " [--noklips]"
+ " [--nocrsend]"
+ " \\\n\t"
+ "[--strictcrlpolicy]"
+ " [--crlcheckinterval <interval>]"
+ " [--cachecrls]"
+ " [--uniqueids]"
+ " \\\n\t"
+ "[--interface <ifname>]"
+ " [--ikeport <port-number>]"
+ " \\\n\t"
+ "[--ctlbase <path>]"
+ " \\\n\t"
+ "[--perpeerlogbase <path>] [--perpeerlog]"
+ " \\\n\t"
+ "[--secretsfile <secrets-file>]"
+ " [--policygroupsdir <policygroups-dir>]"
+ " \\\n\t"
+ "[--adns <pathname>]"
+ "[--pkcs11module <path>]"
+ "[--pkcs11keepstate]"
+ "[--pkcs11initargs <string>]"
#ifdef DEBUG
- " \\\n\t"
- "[--debug-none]"
- " [--debug-all]"
- " \\\n\t"
- "[--debug-raw]"
- " [--debug-crypt]"
- " [--debug-parsing]"
- " [--debug-emitting]"
- " \\\n\t"
- "[--debug-control]"
- " [--debug-lifecycle]"
- " [--debug-klips]"
- " [--debug-dns]"
- " \\\n\t"
- "[--debug-oppo]"
- " [--debug-controlmore]"
- " [--debug-private]"
+ " \\\n\t"
+ "[--debug-none]"
+ " [--debug-all]"
+ " \\\n\t"
+ "[--debug-raw]"
+ " [--debug-crypt]"
+ " [--debug-parsing]"
+ " [--debug-emitting]"
+ " \\\n\t"
+ "[--debug-control]"
+ " [--debug-lifecycle]"
+ " [--debug-klips]"
+ " [--debug-dns]"
+ " \\\n\t"
+ "[--debug-oppo]"
+ " [--debug-controlmore]"
+ " [--debug-private]"
+ " [--debug-natt]"
#endif
- " [ --debug-natt]"
- " \\\n\t"
- "[--nat_traversal] [--keep_alive <delay_sec>]"
- " \\\n\t"
- "[--force_keepalive] [--disable_port_floating]"
- " \\\n\t"
- "[--virtual_private <network_list>]"
- "\n"
- "strongSwan %s\n"
- , ipsec_version_code());
- exit_pluto(mess == NULL? 0 : 1);
+ " \\\n\t"
+ "[--nat_traversal] [--keep_alive <delay_sec>]"
+ " \\\n\t"
+ "[--force_keepalive] [--disable_port_floating]"
+ " \\\n\t"
+ "[--virtual_private <network_list>]"
+ "\n"
+ "strongSwan "VERSION"\n");
+ exit_pluto(mess == NULL? 0 : 1);
}
@@ -150,53 +156,51 @@ static char pluto_lock[sizeof(ctl_addr.sun_path)] = DEFAULT_CTLBASE LOCK_SUFFIX;
static bool pluto_lock_created = FALSE;
/* create lockfile, or die in the attempt */
-static int
-create_lock(void)
+static int create_lock(void)
{
- int fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC
- , S_IRUSR | S_IRGRP | S_IROTH);
+ int fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC
+ , S_IRUSR | S_IRGRP | S_IROTH);
- if (fd < 0)
- {
- if (errno == EEXIST)
+ if (fd < 0)
{
- fprintf(stderr, "pluto: lock file \"%s\" already exists\n"
- , pluto_lock);
- exit_pluto(10);
+ if (errno == EEXIST)
+ {
+ fprintf(stderr, "pluto: lock file \"%s\" already exists\n"
+ , pluto_lock);
+ exit_pluto(10);
+ }
+ else
+ {
+ fprintf(stderr
+ , "pluto: unable to create lock file \"%s\" (%d %s)\n"
+ , pluto_lock, errno, strerror(errno));
+ exit_pluto(1);
+ }
}
- else
- {
- fprintf(stderr
- , "pluto: unable to create lock file \"%s\" (%d %s)\n"
- , pluto_lock, errno, strerror(errno));
- exit_pluto(1);
- }
- }
- pluto_lock_created = TRUE;
- return fd;
+ pluto_lock_created = TRUE;
+ return fd;
}
-static bool
-fill_lock(int lockfd, pid_t pid)
+static bool fill_lock(int lockfd, pid_t pid)
{
- char buf[30]; /* holds "<pid>\n" */
- int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid);
- bool ok = len > 0 && write(lockfd, buf, len) == len;
+ char buf[30]; /* holds "<pid>\n" */
+ int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid);
+ bool ok = len > 0 && write(lockfd, buf, len) == len;
- close(lockfd);
- return ok;
+ close(lockfd);
+ return ok;
}
-static void
-delete_lock(void)
+static void delete_lock(void)
{
- if (pluto_lock_created)
- {
- delete_ctl_socket();
- unlink(pluto_lock); /* is noting failure useful? */
- }
+ if (pluto_lock_created)
+ {
+ delete_ctl_socket();
+ unlink(pluto_lock); /* is noting failure useful? */
+ }
}
+
/* by default pluto sends certificate requests to its peers */
bool no_cr_send = FALSE;
@@ -223,459 +227,504 @@ bool pkcs11_proxy = FALSE;
*/
static const char *pkcs11_init_args = NULL;
-int
-main(int argc, char **argv)
+/* options read by optionsfrom */
+options_t *options;
+
+/**
+ * Log loaded plugins
+ */
+static void print_plugins()
+{
+ char buf[BUF_LEN], *plugin;
+ int len = 0;
+ enumerator_t *enumerator;
+
+ buf[0] = '\0';
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (len < BUF_LEN && enumerator->enumerate(enumerator, &plugin))
+ {
+ len += snprintf(&buf[len], BUF_LEN-len, "%s ", plugin);
+ }
+ enumerator->destroy(enumerator);
+ DBG1("loaded plugins: %s", buf);
+}
+
+int main(int argc, char **argv)
{
- bool fork_desired = TRUE;
- bool log_to_stderr_desired = FALSE;
- bool nat_traversal = FALSE;
- bool nat_t_spf = TRUE; /* support port floating */
- unsigned int keep_alive = 0;
- bool force_keepalive = FALSE;
- char *virtual_private = NULL;
- int lockfd;
+ bool fork_desired = TRUE;
+ bool log_to_stderr_desired = FALSE;
+ bool nat_traversal = FALSE;
+ bool nat_t_spf = TRUE; /* support port floating */
+ unsigned int keep_alive = 0;
+ bool force_keepalive = FALSE;
+ char *virtual_private = NULL;
+ int lockfd;
#ifdef CAPABILITIES
- cap_t caps;
- int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
+ cap_t caps;
+ int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
#endif /* CAPABILITIES */
- /* handle arguments */
- for (;;)
- {
-# define DBG_OFFSET 256
- static const struct option long_opts[] = {
- /* name, has_arg, flag, val */
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'v' },
- { "optionsfrom", required_argument, NULL, '+' },
- { "nofork", no_argument, NULL, 'd' },
- { "stderrlog", no_argument, NULL, 'e' },
- { "noklips", no_argument, NULL, 'n' },
- { "nocrsend", no_argument, NULL, 'c' },
- { "strictcrlpolicy", no_argument, NULL, 'r' },
- { "crlcheckinterval", required_argument, NULL, 'x'},
- { "cachecrls", no_argument, NULL, 'C' },
- { "uniqueids", no_argument, NULL, 'u' },
- { "interface", required_argument, NULL, 'i' },
- { "ikeport", required_argument, NULL, 'p' },
- { "ctlbase", required_argument, NULL, 'b' },
- { "secretsfile", required_argument, NULL, 's' },
- { "foodgroupsdir", required_argument, NULL, 'f' },
- { "perpeerlogbase", required_argument, NULL, 'P' },
- { "perpeerlog", no_argument, NULL, 'l' },
- { "policygroupsdir", required_argument, NULL, 'f' },
+ /* initialize library and optionsfrom */
+ library_init(STRONGSWAN_CONF);
+ options = options_create();
+
+ /* handle arguments */
+ for (;;)
+ {
+# define DBG_OFFSET 256
+ static const struct option long_opts[] = {
+ /* name, has_arg, flag, val */
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "optionsfrom", required_argument, NULL, '+' },
+ { "nofork", no_argument, NULL, 'd' },
+ { "stderrlog", no_argument, NULL, 'e' },
+ { "noklips", no_argument, NULL, 'n' },
+ { "nocrsend", no_argument, NULL, 'c' },
+ { "strictcrlpolicy", no_argument, NULL, 'r' },
+ { "crlcheckinterval", required_argument, NULL, 'x'},
+ { "cachecrls", no_argument, NULL, 'C' },
+ { "uniqueids", no_argument, NULL, 'u' },
+ { "interface", required_argument, NULL, 'i' },
+ { "ikeport", required_argument, NULL, 'p' },
+ { "ctlbase", required_argument, NULL, 'b' },
+ { "secretsfile", required_argument, NULL, 's' },
+ { "foodgroupsdir", required_argument, NULL, 'f' },
+ { "perpeerlogbase", required_argument, NULL, 'P' },
+ { "perpeerlog", no_argument, NULL, 'l' },
+ { "policygroupsdir", required_argument, NULL, 'f' },
#ifdef USE_LWRES
- { "lwdnsq", required_argument, NULL, 'a' },
+ { "lwdnsq", required_argument, NULL, 'a' },
#else /* !USE_LWRES */
- { "adns", required_argument, NULL, 'a' },
+ { "adns", required_argument, NULL, 'a' },
#endif /* !USE_LWRES */
- { "pkcs11module", required_argument, NULL, 'm' },
- { "pkcs11keepstate", no_argument, NULL, 'k' },
- { "pkcs11initargs", required_argument, NULL, 'z' },
- { "pkcs11proxy", no_argument, NULL, 'y' },
- { "nat_traversal", no_argument, NULL, '1' },
- { "keep_alive", required_argument, NULL, '2' },
- { "force_keepalive", no_argument, NULL, '3' },
- { "disable_port_floating", no_argument, NULL, '4' },
- { "debug-natt", no_argument, NULL, '5' },
- { "virtual_private", required_argument, NULL, '6' },
+ { "pkcs11module", required_argument, NULL, 'm' },
+ { "pkcs11keepstate", no_argument, NULL, 'k' },
+ { "pkcs11initargs", required_argument, NULL, 'z' },
+ { "pkcs11proxy", no_argument, NULL, 'y' },
+ { "nat_traversal", no_argument, NULL, '1' },
+ { "keep_alive", required_argument, NULL, '2' },
+ { "force_keepalive", no_argument, NULL, '3' },
+ { "disable_port_floating", no_argument, NULL, '4' },
+ { "debug-natt", no_argument, NULL, '5' },
+ { "virtual_private", required_argument, NULL, '6' },
#ifdef DEBUG
- { "debug-none", no_argument, NULL, 'N' },
- { "debug-all", no_argument, NULL, 'A' },
- { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
- { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
- { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
- { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
- { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
- { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
- { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET },
- { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
- { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
- { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
- { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
-
- { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
- { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
- { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
- { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
+ { "debug-none", no_argument, NULL, 'N' },
+ { "debug-all", no_argument, NULL, 'A' },
+ { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
+ { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
+ { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
+ { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
+ { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
+ { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
+ { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET },
+ { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
+ { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
+ { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
+ { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
+
+ { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
+ { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
+ { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
+ { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
#endif
- { 0,0,0,0 }
- };
- /* Note: we don't like the way short options get parsed
- * by getopt_long, so we simply pass an empty string as
- * the list. It could be "hvdenp:l:s:" "NARXPECK".
- */
- int c = getopt_long(argc, argv, "", long_opts, NULL);
-
- /* Note: "breaking" from case terminates loop */
- switch (c)
- {
- case EOF: /* end of flags */
- break;
-
- case 0: /* long option already handled */
- continue;
-
- case ':': /* diagnostic already printed by getopt_long */
- case '?': /* diagnostic already printed by getopt_long */
- usage("");
- break; /* not actually reached */
-
- case 'h': /* --help */
- usage(NULL);
- break; /* not actually reached */
-
- case 'v': /* --version */
- {
- const char **sp = ipsec_copyright_notice();
-
- printf("%s%s\n", ipsec_version_string(),
- compile_time_interop_options);
- for (; *sp != NULL; sp++)
- puts(*sp);
- }
- exit_pluto(0);
- break; /* not actually reached */
-
- case '+': /* --optionsfrom <filename> */
- optionsfrom(optarg, &argc, &argv, optind, stderr);
- /* does not return on error */
- continue;
-
- case 'd': /* --nofork*/
- fork_desired = FALSE;
- continue;
-
- case 'e': /* --stderrlog */
- log_to_stderr_desired = TRUE;
- continue;
-
- case 'n': /* --noklips */
- no_klips = TRUE;
- continue;
-
- case 'c': /* --nocrsend */
- no_cr_send = TRUE;
- continue;
-
- case 'r': /* --strictcrlpolicy */
- strict_crl_policy = TRUE;
- continue;
-
- case 'x': /* --crlcheckinterval <time>*/
- if (optarg == NULL || !isdigit(optarg[0]))
- usage("missing interval time");
-
- {
- char *endptr;
- long interval = strtol(optarg, &endptr, 0);
-
- if (*endptr != '\0' || endptr == optarg
- || interval <= 0)
- usage("<interval-time> must be a positive number");
- crl_check_interval = interval;
- }
- continue;
-
- case 'C': /* --cachecrls */
- cache_crls = TRUE;
- continue;
-
- case 'u': /* --uniqueids */
- uniqueIDs = TRUE;
- continue;
-
- case 'i': /* --interface <ifname> */
- if (!use_interface(optarg))
- usage("too many --interface specifications");
- continue;
-
- case 'p': /* --port <portnumber> */
- if (optarg == NULL || !isdigit(optarg[0]))
- usage("missing port number");
-
- {
- char *endptr;
- long port = strtol(optarg, &endptr, 0);
-
- if (*endptr != '\0' || endptr == optarg
- || port <= 0 || port > 0x10000)
- usage("<port-number> must be a number between 1 and 65535");
- pluto_port = port;
- }
- continue;
-
- case 'b': /* --ctlbase <path> */
- if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
- , "%s%s", optarg, CTL_SUFFIX) == -1)
- usage("<path>" CTL_SUFFIX " too long for sun_path");
- if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
- , "%s%s", optarg, INFO_SUFFIX) == -1)
- usage("<path>" INFO_SUFFIX " too long for sun_path");
- if (snprintf(pluto_lock, sizeof(pluto_lock)
- , "%s%s", optarg, LOCK_SUFFIX) == -1)
- usage("<path>" LOCK_SUFFIX " must fit");
- continue;
-
- case 's': /* --secretsfile <secrets-file> */
- shared_secrets_file = optarg;
- continue;
-
- case 'f': /* --policygroupsdir <policygroups-dir> */
- policygroups_dir = optarg;
- continue;
-
- case 'a': /* --adns <pathname> */
- pluto_adns_option = optarg;
- continue;
-
- case 'm': /* --pkcs11module <pathname> */
- pkcs11_module_path = optarg;
- continue;
-
- case 'k': /* --pkcs11keepstate */
- pkcs11_keep_state = TRUE;
- continue;
-
- case 'y': /* --pkcs11proxy */
- pkcs11_proxy = TRUE;
- continue;
-
- case 'z': /* --pkcs11initargs */
- pkcs11_init_args = optarg;
- continue;
+ { 0,0,0,0 }
+ };
+ /* Note: we don't like the way short options get parsed
+ * by getopt_long, so we simply pass an empty string as
+ * the list. It could be "hvdenp:l:s:" "NARXPECK".
+ */
+ int c = getopt_long(argc, argv, "", long_opts, NULL);
+
+ /* Note: "breaking" from case terminates loop */
+ switch (c)
+ {
+ case EOF: /* end of flags */
+ break;
+
+ case 0: /* long option already handled */
+ continue;
+
+ case ':': /* diagnostic already printed by getopt_long */
+ case '?': /* diagnostic already printed by getopt_long */
+ usage("");
+ break; /* not actually reached */
+
+ case 'h': /* --help */
+ usage(NULL);
+ break; /* not actually reached */
+
+ case 'v': /* --version */
+ {
+ const char **sp = ipsec_copyright_notice();
+
+ printf("strongSwan "VERSION"%s\n", compile_time_interop_options);
+ for (; *sp != NULL; sp++)
+ puts(*sp);
+ }
+ exit_pluto(0);
+ break; /* not actually reached */
+
+ case '+': /* --optionsfrom <filename> */
+ if (!options->from(options, optarg, &argc, &argv, optind))
+ {
+ exit_pluto(1);
+ }
+ continue;
+
+ case 'd': /* --nofork*/
+ fork_desired = FALSE;
+ continue;
+
+ case 'e': /* --stderrlog */
+ log_to_stderr_desired = TRUE;
+ continue;
+
+ case 'n': /* --noklips */
+ no_klips = TRUE;
+ continue;
+
+ case 'c': /* --nocrsend */
+ no_cr_send = TRUE;
+ continue;
+
+ case 'r': /* --strictcrlpolicy */
+ strict_crl_policy = TRUE;
+ continue;
+
+ case 'x': /* --crlcheckinterval <time>*/
+ if (optarg == NULL || !isdigit(optarg[0]))
+ usage("missing interval time");
+
+ {
+ char *endptr;
+ long interval = strtol(optarg, &endptr, 0);
+
+ if (*endptr != '\0' || endptr == optarg
+ || interval <= 0)
+ usage("<interval-time> must be a positive number");
+ crl_check_interval = interval;
+ }
+ continue;
+
+ case 'C': /* --cachecrls */
+ cache_crls = TRUE;
+ continue;
+
+ case 'u': /* --uniqueids */
+ uniqueIDs = TRUE;
+ continue;
+
+ case 'i': /* --interface <ifname> */
+ if (!use_interface(optarg))
+ usage("too many --interface specifications");
+ continue;
+
+ case 'p': /* --port <portnumber> */
+ if (optarg == NULL || !isdigit(optarg[0]))
+ usage("missing port number");
+
+ {
+ char *endptr;
+ long port = strtol(optarg, &endptr, 0);
+
+ if (*endptr != '\0' || endptr == optarg
+ || port <= 0 || port > 0x10000)
+ usage("<port-number> must be a number between 1 and 65535");
+ pluto_port = port;
+ }
+ continue;
+
+ case 'b': /* --ctlbase <path> */
+ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
+ , "%s%s", optarg, CTL_SUFFIX) == -1)
+ usage("<path>" CTL_SUFFIX " too long for sun_path");
+ if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
+ , "%s%s", optarg, INFO_SUFFIX) == -1)
+ usage("<path>" INFO_SUFFIX " too long for sun_path");
+ if (snprintf(pluto_lock, sizeof(pluto_lock)
+ , "%s%s", optarg, LOCK_SUFFIX) == -1)
+ usage("<path>" LOCK_SUFFIX " must fit");
+ continue;
+
+ case 's': /* --secretsfile <secrets-file> */
+ shared_secrets_file = optarg;
+ continue;
+
+ case 'f': /* --policygroupsdir <policygroups-dir> */
+ policygroups_dir = optarg;
+ continue;
+
+ case 'a': /* --adns <pathname> */
+ pluto_adns_option = optarg;
+ continue;
+
+ case 'm': /* --pkcs11module <pathname> */
+ pkcs11_module_path = optarg;
+ continue;
+
+ case 'k': /* --pkcs11keepstate */
+ pkcs11_keep_state = TRUE;
+ continue;
+
+ case 'y': /* --pkcs11proxy */
+ pkcs11_proxy = TRUE;
+ continue;
+
+ case 'z': /* --pkcs11initargs */
+ pkcs11_init_args = optarg;
+ continue;
#ifdef DEBUG
- case 'N': /* --debug-none */
- base_debugging = DBG_NONE;
- continue;
+ case 'N': /* --debug-none */
+ base_debugging = DBG_NONE;
+ continue;
- case 'A': /* --debug-all */
- base_debugging = DBG_ALL;
- continue;
+ case 'A': /* --debug-all */
+ base_debugging = DBG_ALL;
+ continue;
#endif
- case 'P': /* --perpeerlogbase */
- base_perpeer_logdir = optarg;
- continue;
-
- case 'l':
- log_to_perpeer = TRUE;
- continue;
-
- case '1': /* --nat_traversal */
- nat_traversal = TRUE;
- continue;
- case '2': /* --keep_alive */
- keep_alive = atoi(optarg);
- continue;
- case '3': /* --force_keepalive */
- force_keepalive = TRUE;
- continue;
- case '4': /* --disable_port_floating */
- nat_t_spf = FALSE;
- continue;
- case '5': /* --debug-nat_t */
- base_debugging |= DBG_NATT;
- continue;
- case '6': /* --virtual_private */
- virtual_private = optarg;
- continue;
-
- default:
+ case 'P': /* --perpeerlogbase */
+ base_perpeer_logdir = optarg;
+ continue;
+
+ case 'l':
+ log_to_perpeer = TRUE;
+ continue;
+
+ case '1': /* --nat_traversal */
+ nat_traversal = TRUE;
+ continue;
+ case '2': /* --keep_alive */
+ keep_alive = atoi(optarg);
+ continue;
+ case '3': /* --force_keepalive */
+ force_keepalive = TRUE;
+ continue;
+ case '4': /* --disable_port_floating */
+ nat_t_spf = FALSE;
+ continue;
+ case '5': /* --debug-nat_t */
+ base_debugging |= DBG_NATT;
+ continue;
+ case '6': /* --virtual_private */
+ virtual_private = optarg;
+ continue;
+
+ default:
#ifdef DEBUG
- if (c >= DBG_OFFSET)
- {
- base_debugging |= c - DBG_OFFSET;
- continue;
- }
-# undef DBG_OFFSET
+ if (c >= DBG_OFFSET)
+ {
+ base_debugging |= c - DBG_OFFSET;
+ continue;
+ }
+# undef DBG_OFFSET
#endif
- bad_case(c);
+ bad_case(c);
+ }
+ break;
}
- break;
- }
- if (optind != argc)
- usage("unexpected argument");
- reset_debugging();
- lockfd = create_lock();
+ if (optind != argc)
+ usage("unexpected argument");
+ reset_debugging();
+ lockfd = create_lock();
- /* select between logging methods */
+ /* select between logging methods */
- if (log_to_stderr_desired)
- log_to_syslog = FALSE;
- else
- log_to_stderr = FALSE;
+ if (log_to_stderr_desired)
+ {
+ log_to_syslog = FALSE;
+ }
+ else
+ {
+ log_to_stderr = FALSE;
+ }
- /* set the logging function of pfkey debugging */
+ /* set the logging function of pfkey debugging */
#ifdef DEBUG
- pfkey_debug_func = DBG_log;
+ pfkey_debug_func = DBG_log;
#else
- pfkey_debug_func = NULL;
+ pfkey_debug_func = NULL;
#endif
- /* create control socket.
- * We must create it before the parent process returns so that
- * there will be no race condition in using it. The easiest
- * place to do this is before the daemon fork.
- */
- {
- err_t ugh = init_ctl_socket();
-
- if (ugh != NULL)
+ /* create control socket.
+ * We must create it before the parent process returns so that
+ * there will be no race condition in using it. The easiest
+ * place to do this is before the daemon fork.
+ */
{
- fprintf(stderr, "pluto: %s", ugh);
- exit_pluto(1);
+ err_t ugh = init_ctl_socket();
+
+ if (ugh != NULL)
+ {
+ fprintf(stderr, "pluto: %s", ugh);
+ exit_pluto(1);
+ }
}
- }
- /* If not suppressed, do daemon fork */
+ /* If not suppressed, do daemon fork */
- if (fork_desired)
- {
+ if (fork_desired)
{
- pid_t pid = fork();
+ {
+ pid_t pid = fork();
+
+ if (pid < 0)
+ {
+ int e = errno;
+
+ fprintf(stderr, "pluto: fork failed (%d %s)\n",
+ errno, strerror(e));
+ exit_pluto(1);
+ }
+
+ if (pid != 0)
+ {
+ /* parent: die, after filling PID into lock file.
+ * must not use exit_pluto: lock would be removed!
+ */
+ exit(fill_lock(lockfd, pid)? 0 : 1);
+ }
+ }
+
+ if (setsid() < 0)
+ {
+ int e = errno;
+
+ fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
+ errno, strerror(e));
+ exit_pluto(1);
+ }
+ }
+ else
+ {
+ /* no daemon fork: we have to fill in lock file */
+ (void) fill_lock(lockfd, getpid());
+ fprintf(stdout, "Pluto initialized\n");
+ fflush(stdout);
+ }
- if (pid < 0)
- {
- int e = errno;
+ /* Close everything but ctl_fd and (if needed) stderr.
+ * There is some danger that a library that we don't know
+ * about is using some fd that we don't know about.
+ * I guess we'll soon find out.
+ */
+ {
+ int i;
+
+ for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */
+ {
+ if ((!log_to_stderr || i != 2) && i != ctl_fd)
+ close(i);
+ }
+
+ /* make sure that stdin, stdout, stderr are reserved */
+ if (open("/dev/null", O_RDONLY) != 0)
+ abort();
+ if (dup2(0, 1) != 1)
+ abort();
+ if (!log_to_stderr && dup2(0, 2) != 2)
+ abort();
+ }
- fprintf(stderr, "pluto: fork failed (%d %s)\n",
- errno, strerror(e));
- exit_pluto(1);
- }
+ init_constants();
+ init_log("pluto");
- if (pid != 0)
- {
- /* parent: die, after filling PID into lock file.
- * must not use exit_pluto: lock would be removed!
- */
- exit(fill_lock(lockfd, pid)? 0 : 1);
- }
- }
+ /* Note: some scripts may look for this exact message -- don't change
+ * ipsec barf was one, but it no longer does.
+ */
+ plog("Starting IKEv1 pluto daemon (strongSwan "VERSION")%s",
+ compile_time_interop_options);
- if (setsid() < 0)
- {
- int e = errno;
+ /* load plugins, further infrastructure may need it */
+ lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR,
+ lib->settings->get_str(lib->settings, "pluto.load", PLUGINS));
+ print_plugins();
- fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
- errno, strerror(e));
- exit_pluto(1);
+#ifdef INTEGRITY_TEST
+ DBG1("integrity test of libstrongswan code");
+ if (fips_verify_hmac_signature(hmac_key, hmac_signature))
+ {
+ DBG1(" integrity test passed");
}
- }
- else
- {
- /* no daemon fork: we have to fill in lock file */
- (void) fill_lock(lockfd, getpid());
- fprintf(stdout, "Pluto initialized\n");
- fflush(stdout);
- }
-
- /* Close everything but ctl_fd and (if needed) stderr.
- * There is some danger that a library that we don't know
- * about is using some fd that we don't know about.
- * I guess we'll soon find out.
- */
- {
- int i;
-
- for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */
+ else
{
- if ((!log_to_stderr || i != 2) && i != ctl_fd)
- close(i);
+ DBG1(" integrity test failed");
+ abort();
}
-
- /* make sure that stdin, stdout, stderr are reserved */
- if (open("/dev/null", O_RDONLY) != 0)
- abort();
- if (dup2(0, 1) != 1)
- abort();
- if (!log_to_stderr && dup2(0, 2) != 2)
- abort();
- }
-
- init_constants();
- init_log("pluto");
-
- /* Note: some scripts may look for this exact message -- don't change
- * ipsec barf was one, but it no longer does.
- */
- plog("Starting Pluto (strongSwan Version %s%s)"
- , ipsec_version_code()
- , compile_time_interop_options);
-
- init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
- init_virtual_ip(virtual_private);
- scx_init(pkcs11_module_path, pkcs11_init_args); /* load and initialize PKCS #11 module */
- xauth_init(); /* load and initialize XAUTH module */
- init_rnd_pool();
- init_secret();
- init_states();
- init_crypto();
- init_demux();
- init_kernel();
- init_adns();
- init_id();
- init_fetch();
-
- /* drop unneeded capabilities and change UID/GID */
-
- prctl(PR_SET_KEEPCAPS, 1);
-
+#endif /* INTEGRITY_TEST */
+
+ init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
+ init_virtual_ip(virtual_private);
+ scx_init(pkcs11_module_path, pkcs11_init_args);
+ xauth_init();
+ init_secret();
+ init_states();
+ init_crypto();
+ init_demux();
+ init_kernel();
+ init_adns();
+ init_id();
+ init_fetch();
+
+ /* drop unneeded capabilities and change UID/GID */
+ prctl(PR_SET_KEEPCAPS, 1);
+
#ifdef IPSEC_GROUP
- {
- struct group group, *grp;
- char buf[1024];
-
- if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
- grp == NULL || setgid(grp->gr_gid) != 0)
{
- plog("unable to change daemon group");
- abort();
+ struct group group, *grp;
+ char buf[1024];
+
+ if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
+ grp == NULL || setgid(grp->gr_gid) != 0)
+ {
+ plog("unable to change daemon group");
+ abort();
+ }
}
- }
#endif
#ifdef IPSEC_USER
- {
- struct passwd passwd, *pwp;
- char buf[1024];
-
- if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
- pwp == NULL || setuid(pwp->pw_uid) != 0)
{
- plog("unable to change daemon user");
- abort();
- }
- }
+ struct passwd passwd, *pwp;
+ char buf[1024];
+
+ if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
+ pwp == NULL || setuid(pwp->pw_uid) != 0)
+ {
+ plog("unable to change daemon user");
+ abort();
+ }
+ }
#endif
#ifdef CAPABILITIES
- caps = cap_init();
- cap_set_flag(caps, CAP_EFFECTIVE, 2, keep, CAP_SET);
- cap_set_flag(caps, CAP_INHERITABLE, 2, keep, CAP_SET);
- cap_set_flag(caps, CAP_PERMITTED, 2, keep, CAP_SET);
- if (cap_set_proc(caps) != 0)
- {
- plog("unable to drop daemon capabilities");
- abort();
- }
- cap_free(caps);
+ caps = cap_init();
+ cap_set_flag(caps, CAP_EFFECTIVE, 2, keep, CAP_SET);
+ cap_set_flag(caps, CAP_INHERITABLE, 2, keep, CAP_SET);
+ cap_set_flag(caps, CAP_PERMITTED, 2, keep, CAP_SET);
+ if (cap_set_proc(caps) != 0)
+ {
+ plog("unable to drop daemon capabilities");
+ abort();
+ }
+ cap_free(caps);
#endif /* CAPABILITIES */
- /* loading X.509 CA certificates */
- load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
- /* loading X.509 AA certificates */
- load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
- /* loading X.509 OCSP certificates */
- load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
- /* loading X.509 CRLs */
- load_crls();
- /* loading attribute certificates (experimental) */
- load_acerts();
-
- daily_log_event();
- call_server();
- return -1; /* Shouldn't ever reach this */
+ /* loading X.509 CA certificates */
+ load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
+ /* loading X.509 AA certificates */
+ load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
+ /* loading X.509 OCSP certificates */
+ load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
+ /* loading X.509 CRLs */
+ load_crls();
+ /* loading attribute certificates (experimental) */
+ load_acerts();
+
+ daily_log_event();
+ call_server();
+ return -1; /* Shouldn't ever reach this */
}
/* leave pluto, with status.
@@ -686,31 +735,33 @@ main(int argc, char **argv)
* 1 general discomfort
* 10 lock file exists
*/
-void
-exit_pluto(int status)
+void exit_pluto(int status)
{
- reset_globals(); /* needed because we may be called in odd state */
- free_preshared_secrets();
- free_remembered_public_keys();
- delete_every_connection();
- free_crl_fetch(); /* free chain of crl fetch requests */
- free_ocsp_fetch(); /* free chain of ocsp fetch requests */
- free_authcerts(); /* free chain of X.509 authority certificates */
- free_crls(); /* free chain of X.509 CRLs */
- free_acerts(); /* free chain of X.509 attribute certificates */
- free_ca_infos(); /* free chain of X.509 CA information records */
- free_ocsp(); /* free ocsp cache */
- free_ifaces();
- scx_finalize(); /* finalize and unload PKCS #11 module */
- xauth_finalize(); /* finalize and unload XAUTH module */
- stop_adns();
- free_md_pool();
- delete_lock();
-#ifdef LEAK_DETECTIVE
- report_leaks();
-#endif /* LEAK_DETECTIVE */
- close_log();
- exit(status);
+ reset_globals(); /* needed because we may be called in odd state */
+ free_preshared_secrets();
+ free_remembered_public_keys();
+ delete_every_connection();
+ free_crl_fetch(); /* free chain of crl fetch requests */
+ free_ocsp_fetch(); /* free chain of ocsp fetch requests */
+ free_authcerts(); /* free chain of X.509 authority certificates */
+ free_crls(); /* free chain of X.509 CRLs */
+ free_acerts(); /* free chain of X.509 attribute certificates */
+ free_ca_infos(); /* free chain of X.509 CA information records */
+ free_ocsp(); /* free ocsp cache */
+ free_ifaces();
+ scx_finalize(); /* finalize and unload PKCS #11 module */
+ xauth_finalize(); /* finalize and unload XAUTH module */
+ stop_adns();
+ free_md_pool();
+ free_crypto();
+ free_id(); /* free myids */
+ free_events(); /* free remaining events */
+ free_vendorid(); /* free all vendor id records */
+ delete_lock();
+ options->destroy(options);
+ library_deinit();
+ close_log();
+ exit(status);
}
/*
diff --git a/src/pluto/primegen.c b/src/pluto/primegen.c
deleted file mode 100644
index 159490345..000000000
--- a/src/pluto/primegen.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/* primegen.c - prime number generator
- * 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
- *
- * ***********************************************************************
- * The algorithm used to generate practically save primes is due to
- * Lim and Lee as described in the CRYPTO '97 proceedings (ISBN3540633847)
- * page 260.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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 <assert.h> */
-/* #include <config.h> */
-/* #include "util.h" */
-/* #include "mpi.h" */
-/* #include "cipher.h" */
-#endif /* !PLUTO */
-
-static int no_of_small_prime_numbers;
-static MPI gen_prime( unsigned nbits, int mode, int randomlevel );
-static int check_prime( MPI prime, MPI val_2 );
-static int is_prime( MPI n, unsigned steps, int *count );
-static void m_out_of_n( char *array, int m, int n );
-
-
-static void
-progress( int c )
-{
- fputc( c, stderr );
-}
-
-
-/****************
- * Generate a prime number (stored in secure memory)
- */
-MPI
-generate_secret_prime( unsigned nbits )
-{
- MPI prime;
-
- prime = gen_prime( nbits, 1, 2 );
- progress('\n');
- return prime;
-}
-
-MPI
-generate_public_prime( unsigned nbits )
-{
- MPI prime;
-
- prime = gen_prime( nbits, 0, 2 );
- progress('\n');
- return prime;
-}
-
-
-/****************
- * We do not need to use the strongest RNG because we gain no extra
- * security from it - The prime number is public and we could also
- * offer the factors for those who are willing to check that it is
- * indeed a strong prime.
- *
- * mode 0: Standard
- * 1: Make sure that at least one factor is of size qbits.
- */
-MPI
-generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
- MPI g, MPI **ret_factors )
-{
- int n; /* number of factors */
- int m; /* number of primes in pool */
- unsigned fbits; /* length of prime factors */
- MPI *factors; /* current factors */
- MPI *pool; /* pool of primes */
- MPI q; /* first prime factor (variable)*/
- MPI prime; /* prime test value */
- MPI q_factor; /* used for mode 1 */
- byte *perms = NULL;
- int i, j;
- int count1, count2;
- unsigned nprime;
- unsigned req_qbits = qbits; /* the requested q bits size */
- MPI val_2 = mpi_alloc_set_ui( 2 );
-
- /* find number of needed prime factors */
- for(n=1; (pbits - qbits - 1) / n >= qbits; n++ )
- ;
- n--;
- if( !n || (mode==1 && n < 2) )
- log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits );
- if( mode == 1 ) {
- n--;
- fbits = (pbits - 2*req_qbits -1) / n;
- qbits = pbits - req_qbits - n*fbits;
- }
- else {
- fbits = (pbits - req_qbits -1) / n;
- qbits = pbits - n*fbits;
- }
- if( DBG_CIPHER )
- log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
- pbits, req_qbits, qbits, fbits, n );
- prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB );
- q = gen_prime( qbits, 0, 1 );
- q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL;
-
- /* allocate an array to hold the factors + 2 for later usage */
-#ifdef PLUTO
- m_alloc_ptrs_clear(factors, n+2);
-#else
- factors = m_alloc_clear( (n+2) * sizeof *factors );
-#endif
-
- /* make a pool of 3n+5 primes (this is an arbitrary value) */
- m = n*3+5;
- if( mode == 1 )
- m += 5; /* need some more for DSA */
- if( m < 25 )
- m = 25;
-#ifdef PLUTO
- m_alloc_ptrs_clear(pool, m);
-#else
- pool = m_alloc_clear( m * sizeof *pool );
-#endif
-
- /* permutate over the pool of primes */
- count1=count2=0;
- do {
- next_try:
- if( !perms ) {
- /* allocate new primes */
- for(i=0; i < m; i++ ) {
- mpi_free(pool[i]);
- pool[i] = NULL;
- }
- /* init m_out_of_n() */
-#ifdef PLUTO
- perms = alloc_bytes( m, "perms" );
-#else
- perms = m_alloc_clear( m );
-#endif
- for(i=0; i < n; i++ ) {
- perms[i] = 1;
- pool[i] = gen_prime( fbits, 0, 1 );
- factors[i] = pool[i];
- }
- }
- else {
- m_out_of_n( perms, n, m );
- for(i=j=0; i < m && j < n ; i++ )
- if( perms[i] ) {
- if( !pool[i] )
- pool[i] = gen_prime( fbits, 0, 1 );
- factors[j++] = pool[i];
- }
- if( i == n ) {
- m_free(perms); perms = NULL;
- progress('!');
- goto next_try; /* allocate new primes */
- }
- }
-
- mpi_set( prime, q );
- mpi_mul_ui( prime, prime, 2 );
- if( mode == 1 )
- mpi_mul( prime, prime, q_factor );
- for(i=0; i < n; i++ )
- mpi_mul( prime, prime, factors[i] );
- mpi_add_ui( prime, prime, 1 );
- nprime = mpi_get_nbits(prime);
- if( nprime < pbits ) {
- if( ++count1 > 20 ) {
- count1 = 0;
- qbits++;
- progress('>');
- q = gen_prime( qbits, 0, 1 );
- goto next_try;
- }
- }
- else
- count1 = 0;
- if( nprime > pbits ) {
- if( ++count2 > 20 ) {
- count2 = 0;
- qbits--;
- progress('<');
- q = gen_prime( qbits, 0, 1 );
- goto next_try;
- }
- }
- else
- count2 = 0;
- } while( !(nprime == pbits && check_prime( prime, val_2 )) );
-
- if( DBG_CIPHER ) {
- progress('\n');
- log_mpidump( "prime : ", prime );
- log_mpidump( "factor q: ", q );
- if( mode == 1 )
- log_mpidump( "factor q0: ", q_factor );
- for(i=0; i < n; i++ )
- log_mpidump( "factor pi: ", factors[i] );
- log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
- if( mode == 1 )
- fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) );
- for(i=0; i < n; i++ )
- fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
- progress('\n');
- }
-
- if( ret_factors ) { /* caller wants the factors */
-#ifdef PLUTO
- m_alloc_ptrs_clear(*ret_factors, n+2);
-#else
- *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
-#endif
- if( mode == 1 ) {
- i = 0;
- (*ret_factors)[i++] = mpi_copy( q_factor );
- for(; i <= n; i++ )
- (*ret_factors)[i] = mpi_copy( factors[i] );
- }
- else {
- for(; i < n; i++ )
- (*ret_factors)[i] = mpi_copy( factors[i] );
- }
- }
-
- if( g ) { /* create a generator (start with 3)*/
- MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) );
- MPI b = mpi_alloc( mpi_get_nlimbs(prime) );
- MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) );
-
- if( mode == 1 )
- BUG(); /* not yet implemented */
- factors[n] = q;
- factors[n+1] = mpi_alloc_set_ui(2);
- mpi_sub_ui( pmin1, prime, 1 );
- mpi_set_ui(g,2);
- do {
- mpi_add_ui(g, g, 1);
- if( DBG_CIPHER ) {
-#ifdef PLUTO
- log_mpidump("checking g: ", g);
-#else
- log_debug("checking g: ");
- mpi_print( stderr, g, 1 );
-#endif
- }
- else
- progress('^');
- for(i=0; i < n+2; i++ ) {
- /*fputc('~', stderr);*/
- mpi_fdiv_q(tmp, pmin1, factors[i] );
- /* (no mpi_pow(), but it is okay to use this with mod prime) */
- mpi_powm(b, g, tmp, prime );
- if( !mpi_cmp_ui(b, 1) )
- break;
- }
- if( DBG_CIPHER )
- progress('\n');
- } while( i < n+2 );
- mpi_free(factors[n+1]);
- mpi_free(tmp);
- mpi_free(b);
- mpi_free(pmin1);
- }
- if( !DBG_CIPHER )
- progress('\n');
-
- m_free( factors ); /* (factors are shallow copies) */
- for(i=0; i < m; i++ )
- mpi_free( pool[i] );
- m_free( pool );
- m_free(perms);
- mpi_free(val_2);
- return prime;
-}
-
-
-
-static MPI
-gen_prime( unsigned nbits, int secret, int randomlevel )
-{
- unsigned nlimbs;
- MPI prime, ptest, pminus1, val_2, val_3, result;
- int i;
- unsigned x, step;
- unsigned count1, count2;
- int *mods;
-
- if( 0 && DBG_CIPHER )
- log_debug("generate a prime of %u bits ", nbits );
-
- if( !no_of_small_prime_numbers ) {
- for(i=0; small_prime_numbers[i]; i++ )
- no_of_small_prime_numbers++;
- }
- mods = m_alloc( no_of_small_prime_numbers * sizeof *mods );
- /* make nbits fit into MPI implementation */
- nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB;
- val_2 = mpi_alloc_set_ui( 2 );
- val_3 = mpi_alloc_set_ui( 3);
- prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs );
- result = mpi_alloc_like( prime );
- pminus1= mpi_alloc_like( prime );
- ptest = mpi_alloc_like( prime );
- count1 = count2 = 0;
- for(;;) { /* try forvever */
- int dotcount=0;
-
- /* generate a random number */
- { char *p = get_random_bits( nbits, randomlevel, secret );
- mpi_set_buffer( prime, p, (nbits+7)/8, 0 );
- m_free(p);
- }
-
- /* set high order bit to 1, set low order bit to 1 */
- mpi_set_highbit( prime, nbits-1 );
- mpi_set_bit( prime, 0 );
-
- /* calculate all remainders */
- for(i=0; (x = small_prime_numbers[i]); i++ )
- mods[i] = mpi_fdiv_r_ui(NULL, prime, x);
-
- /* now try some primes starting with prime */
- for(step=0; step < 20000; step += 2 ) {
- /* check against all the small primes we have in mods */
- count1++;
- for(i=0; (x = small_prime_numbers[i]); i++ ) {
- while( mods[i] + step >= x )
- mods[i] -= x;
- if( !(mods[i] + step) )
- break;
- }
- if( x )
- continue; /* found a multiple of an already known prime */
-
- mpi_add_ui( ptest, prime, step );
-
- /* do a faster Fermat test */
- count2++;
- mpi_sub_ui( pminus1, ptest, 1);
- mpi_powm( result, val_2, pminus1, ptest );
- if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */
- /* perform stronger tests */
- if( is_prime(ptest, 5, &count2 ) ) {
- if( !mpi_test_bit( ptest, nbits-1 ) ) {
- progress('\n');
- log_debug("overflow in prime generation\n");
- break; /* step loop, continue with a new prime */
- }
-
- mpi_free(val_2);
- mpi_free(val_3);
- mpi_free(result);
- mpi_free(pminus1);
- mpi_free(prime);
- m_free(mods);
- return ptest;
- }
- }
- if( ++dotcount == 10 ) {
- progress('.');
- dotcount = 0;
- }
- }
- progress(':'); /* restart with a new random value */
- }
-}
-
-/****************
- * Returns: true if this may be a prime
- */
-static int
-check_prime( MPI prime, MPI val_2 )
-{
- int i;
- unsigned x;
- int count=0;
-
- /* check against small primes */
- for(i=0; (x = small_prime_numbers[i]); i++ ) {
- if( mpi_divisible_ui( prime, x ) )
- return 0;
- }
-
- /* a quick fermat test */
- {
- MPI result = mpi_alloc_like( prime );
- MPI pminus1 = mpi_alloc_like( prime );
- mpi_sub_ui( pminus1, prime, 1);
- mpi_powm( result, val_2, pminus1, prime );
- mpi_free( pminus1 );
- if( mpi_cmp_ui( result, 1 ) ) { /* if composite */
- mpi_free( result );
- progress('.');
- return 0;
- }
- mpi_free( result );
- }
-
- /* perform stronger tests */
- if( is_prime(prime, 5, &count ) )
- return 1; /* is probably a prime */
- progress('.');
- return 0;
-}
-
-
-/****************
- * Return true if n is probably a prime
- */
-static int
-is_prime( MPI n, unsigned steps, int *count )
-{
- MPI x = mpi_alloc( mpi_get_nlimbs( n ) );
- MPI y = mpi_alloc( mpi_get_nlimbs( n ) );
- MPI z = mpi_alloc( mpi_get_nlimbs( n ) );
- MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) );
- MPI a2 = mpi_alloc_set_ui( 2 );
- MPI q;
- unsigned i, j, k;
- int rc = 0;
- unsigned nbits = mpi_get_nbits( n );
-
- mpi_sub_ui( nminus1, n, 1 );
-
- /* find q and k, so that n = 1 + 2^k * q */
- q = mpi_copy( nminus1 );
- k = mpi_trailing_zeros( q );
- mpi_tdiv_q_2exp(q, q, k);
-
- for(i=0 ; i < steps; i++ ) {
- ++*count;
- if( !i ) {
- mpi_set_ui( x, 2 );
- }
- else {
- /*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/
- { char *p = get_random_bits( nbits, 0, 0 );
- mpi_set_buffer( x, p, (nbits+7)/8, 0 );
- m_free(p);
- }
- /* make sure that the number is smaller than the prime
- * and keep the randomness of the high bit */
- if( mpi_test_bit( x, nbits-2 ) ) {
- mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */
- }
- else {
- mpi_set_highbit( x, nbits-2 );
- mpi_clear_bit( x, nbits-2 );
- }
- assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 );
- }
- mpi_powm( y, x, q, n);
- if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) {
- for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) {
- mpi_powm(y, y, a2, n);
- if( !mpi_cmp_ui( y, 1 ) )
- goto leave; /* not a prime */
- }
- if( mpi_cmp( y, nminus1 ) )
- goto leave; /* not a prime */
- }
- progress('+');
- }
- rc = 1; /* may be a prime */
-
- leave:
- mpi_free( x );
- mpi_free( y );
- mpi_free( z );
- mpi_free( nminus1 );
- mpi_free( q );
-
- return rc;
-}
-
-
-static void
-m_out_of_n( char *array, int m, int n )
-{
- int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0;
-
- if( !m || m >= n )
- return;
-
- if( m == 1 ) { /* special case */
- for(i=0; i < n; i++ )
- if( array[i] ) {
- array[i++] = 0;
- if( i >= n )
- i = 0;
- array[i] = 1;
- return;
- }
- BUG();
- }
-
- for(j=1; j < n; j++ ) {
- if( array[n-1] == array[n-j-1] )
- continue;
- j1 = j;
- break;
- }
-
- if( m & 1 ) { /* m is odd */
- if( array[n-1] ) {
- if( j1 & 1 ) {
- k1 = n - j1;
- k2 = k1+2;
- if( k2 > n )
- k2 = n;
- goto leave;
- }
- goto scan;
- }
- k2 = n - j1 - 1;
- if( k2 == 0 ) {
- k1 = i;
- k2 = n - j1;
- }
- else if( array[k2] && array[k2-1] )
- k1 = n;
- else
- k1 = k2 + 1;
- }
- else { /* m is even */
- if( !array[n-1] ) {
- k1 = n - j1;
- k2 = k1 + 1;
- goto leave;
- }
-
- if( !(j1 & 1) ) {
- k1 = n - j1;
- k2 = k1+2;
- if( k2 > n )
- k2 = n;
- goto leave;
- }
- scan:
- jp = n - j1 - 1;
- for(i=1; i <= jp; i++ ) {
- i1 = jp + 2 - i;
- if( array[i1-1] ) {
- if( array[i1-2] ) {
- k1 = i1 - 1;
- k2 = n - j1;
- }
- else {
- k1 = i1 - 1;
- k2 = n + 1 - j1;
- }
- goto leave;
- }
- }
- k1 = 1;
- k2 = n + 1 - m;
- }
- leave:
- array[k1-1] = !array[k1-1];
- array[k2-1] = !array[k2-1];
-}
-
diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c
index 00fed63ea..013deb446 100644
--- a/src/pluto/rcv_whack.c
+++ b/src/pluto/rcv_whack.c
@@ -11,8 +11,6 @@
* 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: rcv_whack.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -27,7 +25,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <fcntl.h>
@@ -42,17 +40,17 @@
#include "smartcard.h"
#include "connections.h"
#include "foodgroups.h"
-#include "whack.h" /* needs connections.h */
+#include "whack.h" /* needs connections.h */
#include "packet.h"
-#include "demux.h" /* needs packet.h */
+#include "demux.h" /* needs packet.h */
#include "state.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "kernel.h"
#include "rcv_whack.h"
#include "log.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "server.h"
#include "fetch.h"
#include "ocsp.h"
@@ -63,186 +61,186 @@
/* helper variables and function to decode strings from whack message */
static char *next_str
- , *str_roof;
+ , *str_roof;
static bool
unpack_str(char **p)
{
- char *end = memchr(next_str, '\0', str_roof - next_str);
-
- if (end == NULL)
- {
- return FALSE; /* fishy: no end found */
- }
- else
- {
- *p = next_str == end? NULL : next_str;
- next_str = end + 1;
- return TRUE;
- }
+ char *end = memchr(next_str, '\0', str_roof - next_str);
+
+ if (end == NULL)
+ {
+ return FALSE; /* fishy: no end found */
+ }
+ else
+ {
+ *p = next_str == end? NULL : next_str;
+ next_str = end + 1;
+ return TRUE;
+ }
}
/* bits loading keys from asynchronous DNS */
enum key_add_attempt {
- ka_TXT,
+ ka_TXT,
#ifdef USE_KEYRR
- ka_KEY,
+ ka_KEY,
#endif
- ka_roof /* largest value + 1 */
+ ka_roof /* largest value + 1 */
};
struct key_add_common {
- int refCount;
- char *diag[ka_roof];
- int whack_fd;
- bool success;
+ int refCount;
+ char *diag[ka_roof];
+ int whack_fd;
+ bool success;
};
struct key_add_continuation {
- struct adns_continuation ac; /* common prefix */
- struct key_add_common *common; /* common data */
- enum key_add_attempt lookingfor;
+ struct adns_continuation ac; /* common prefix */
+ struct key_add_common *common; /* common data */
+ enum key_add_attempt lookingfor;
};
static void
key_add_ugh(const struct id *keyid, err_t ugh)
{
- char name[BUF_LEN]; /* longer IDs will be truncated in message */
+ char name[BUF_LEN]; /* longer IDs will be truncated in message */
- (void)idtoa(keyid, name, sizeof(name));
- loglog(RC_NOKEY
- , "failure to fetch key for %s from DNS: %s", name, ugh);
+ (void)idtoa(keyid, name, sizeof(name));
+ loglog(RC_NOKEY
+ , "failure to fetch key for %s from DNS: %s", name, ugh);
}
/* last one out: turn out the lights */
static void
key_add_merge(struct key_add_common *oc, const struct id *keyid)
{
- if (oc->refCount == 0)
- {
- enum key_add_attempt kaa;
-
- /* if no success, print all diagnostics */
- if (!oc->success)
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
- key_add_ugh(keyid, oc->diag[kaa]);
+ if (oc->refCount == 0)
+ {
+ enum key_add_attempt kaa;
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
- pfreeany(oc->diag[kaa]);
+ /* if no success, print all diagnostics */
+ if (!oc->success)
+ for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ key_add_ugh(keyid, oc->diag[kaa]);
- close(oc->whack_fd);
- pfree(oc);
- }
+ for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ {
+ free(oc->diag[kaa]);
+ }
+ close(oc->whack_fd);
+ free(oc);
+ }
}
static void
key_add_continue(struct adns_continuation *ac, err_t ugh)
{
- struct key_add_continuation *kc = (void *) ac;
- struct key_add_common *oc = kc->common;
-
- passert(whack_log_fd == NULL_FD);
- whack_log_fd = oc->whack_fd;
-
- if (ugh != NULL)
- {
- oc->diag[kc->lookingfor] = clone_str(ugh, "key add error");
- }
- else
- {
- oc->success = TRUE;
- transfer_to_public_keys(kc->ac.gateways_from_dns
+ struct key_add_continuation *kc = (void *) ac;
+ struct key_add_common *oc = kc->common;
+
+ passert(whack_log_fd == NULL_FD);
+ whack_log_fd = oc->whack_fd;
+
+ if (ugh != NULL)
+ {
+ oc->diag[kc->lookingfor] = clone_str(ugh);
+ }
+ else
+ {
+ oc->success = TRUE;
+ transfer_to_public_keys(kc->ac.gateways_from_dns
#ifdef USE_KEYRR
- , &kc->ac.keys_from_dns
+ , &kc->ac.keys_from_dns
#endif /* USE_KEYRR */
- );
- }
+ );
+ }
- oc->refCount--;
- key_add_merge(oc, &ac->id);
- whack_log_fd = NULL_FD;
+ oc->refCount--;
+ key_add_merge(oc, &ac->id);
+ whack_log_fd = NULL_FD;
}
static void
key_add_request(const whack_message_t *msg)
{
- struct id keyid;
- err_t ugh = atoid(msg->keyid, &keyid, FALSE);
-
- if (ugh != NULL)
- {
- loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh);
- }
- else
- {
- if (!msg->whack_addkey)
- delete_public_keys(&keyid, msg->pubkey_alg
- , empty_chunk, empty_chunk);
-
- if (msg->keyval.len == 0)
- {
- struct key_add_common *oc
- = alloc_thing(struct key_add_common
- , "key add common things");
- enum key_add_attempt kaa;
-
- /* initialize state shared by queries */
- oc->refCount = 0;
- oc->whack_fd = dup_any(whack_log_fd);
- oc->success = FALSE;
-
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
- {
- struct key_add_continuation *kc
- = alloc_thing(struct key_add_continuation
- , "key add continuation");
-
- oc->diag[kaa] = NULL;
- oc->refCount++;
- kc->common = oc;
- kc->lookingfor = kaa;
- switch (kaa)
+ struct id keyid;
+ err_t ugh = atoid(msg->keyid, &keyid, FALSE);
+
+ if (ugh != NULL)
+ {
+ loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh);
+ }
+ else
+ {
+ if (!msg->whack_addkey)
+ delete_public_keys(&keyid, msg->pubkey_alg
+ , chunk_empty, chunk_empty);
+
+ if (msg->keyval.len == 0)
{
- case ka_TXT:
- ugh = start_adns_query(&keyid
- , &keyid /* same */
- , T_TXT
- , key_add_continue
- , &kc->ac);
- break;
+ struct key_add_common *oc = malloc_thing(struct key_add_common);
+ enum key_add_attempt kaa;
+
+ /* initialize state shared by queries */
+ oc->refCount = 0;
+ oc->whack_fd = dup_any(whack_log_fd);
+ oc->success = FALSE;
+
+ for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ {
+ struct key_add_continuation *kc;
+
+ oc->diag[kaa] = NULL;
+ oc->refCount++;
+ kc = malloc_thing(struct key_add_continuation);
+ kc->common = oc;
+ kc->lookingfor = kaa;
+
+ switch (kaa)
+ {
+ case ka_TXT:
+ ugh = start_adns_query(&keyid
+ , &keyid /* same */
+ , T_TXT
+ , key_add_continue
+ , &kc->ac);
+ break;
#ifdef USE_KEYRR
- case ka_KEY:
- ugh = start_adns_query(&keyid
- , NULL
- , T_KEY
- , key_add_continue
- , &kc->ac);
- break;
+ case ka_KEY:
+ ugh = start_adns_query(&keyid
+ , NULL
+ , T_KEY
+ , key_add_continue
+ , &kc->ac);
+ break;
#endif /* USE_KEYRR */
- default:
- bad_case(kaa); /* suppress gcc warning */
+ default:
+ bad_case(kaa); /* suppress gcc warning */
+ }
+ if (ugh != NULL)
+ {
+ oc->diag[kaa] = clone_str(ugh);
+ oc->refCount--;
+ }
+ }
+
+ /* Done launching queries.
+ * Handle total failure case.
+ */
+ key_add_merge(oc, &keyid);
}
- if (ugh != NULL)
+ else
{
- oc->diag[kaa] = clone_str(ugh, "early key add failure");
- oc->refCount--;
+ if (!add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
+ &pubkeys))
+ {
+ loglog(RC_LOG_SERIOUS, "failed to add public key");
+ }
}
- }
-
- /* Done launching queries.
- * Handle total failure case.
- */
- key_add_merge(oc, &keyid);
}
- else
- {
- ugh = add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg
- , &msg->keyval, &pubkeys);
- if (ugh != NULL)
- loglog(RC_LOG_SERIOUS, "%s", ugh);
- }
- }
}
/* Handle a kernel request. Supposedly, there's a message in
@@ -251,430 +249,431 @@ key_add_request(const whack_message_t *msg)
void
whack_handle(int whackctlfd)
{
- whack_message_t msg;
- struct sockaddr_un whackaddr;
- int whackaddrlen = sizeof(whackaddr);
- int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen);
- /* Note: actual value in n should fit in int. To print, cast to int. */
- ssize_t n;
-
- if (whackfd < 0)
- {
- log_errno((e, "accept() failed in whack_handle()"));
- return;
- }
- if (fcntl(whackfd, F_SETFD, FD_CLOEXEC) < 0)
- {
- log_errno((e, "failed to set CLOEXEC in whack_handle()"));
- close(whackfd);
- return;
- }
+ whack_message_t msg;
+ struct sockaddr_un whackaddr;
+ int whackaddrlen = sizeof(whackaddr);
+ int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen);
+ /* Note: actual value in n should fit in int. To print, cast to int. */
+ ssize_t n;
+
+ if (whackfd < 0)
+ {
+ log_errno((e, "accept() failed in whack_handle()"));
+ return;
+ }
+ if (fcntl(whackfd, F_SETFD, FD_CLOEXEC) < 0)
+ {
+ log_errno((e, "failed to set CLOEXEC in whack_handle()"));
+ close(whackfd);
+ return;
+ }
- n = read(whackfd, &msg, sizeof(msg));
+ n = read(whackfd, &msg, sizeof(msg));
- if (n == -1)
- {
- log_errno((e, "read() failed in whack_handle()"));
- close(whackfd);
- return;
- }
+ if (n == -1)
+ {
+ log_errno((e, "read() failed in whack_handle()"));
+ close(whackfd);
+ return;
+ }
- whack_log_fd = whackfd;
+ whack_log_fd = whackfd;
- /* sanity check message */
- {
- err_t ugh = NULL;
+ /* sanity check message */
+ {
+ err_t ugh = NULL;
- next_str = msg.string;
- str_roof = (char *)&msg + n;
+ next_str = msg.string;
+ str_roof = (char *)&msg + n;
- if ((size_t)n < offsetof(whack_message_t, whack_shutdown) + sizeof(msg.whack_shutdown))
+ if ((size_t)n < offsetof(whack_message_t, whack_shutdown) + sizeof(msg.whack_shutdown))
+ {
+ ugh = builddiag("ignoring runt message from whack: got %d bytes", (int)n);
+ }
+ else if (msg.magic != WHACK_MAGIC)
+ {
+ if (msg.magic == WHACK_BASIC_MAGIC)
+ {
+ /* Only shutdown command. Simpler inter-version compatability. */
+ if (msg.whack_shutdown)
+ {
+ plog("shutting down");
+ exit_pluto(0); /* delete lock and leave, with 0 status */
+ }
+ ugh = ""; /* bail early, but without complaint */
+ }
+ else
+ {
+ ugh = builddiag("ignoring message from whack with bad magic %d; should be %d; probably wrong version"
+ , msg.magic, WHACK_MAGIC);
+ }
+ }
+ else if (next_str > str_roof)
+ {
+ ugh = builddiag("ignoring truncated message from whack: got %d bytes; expected %u"
+ , (int) n, (unsigned) sizeof(msg));
+ }
+ else if (!unpack_str(&msg.name) /* string 1 */
+ || !unpack_str(&msg.left.id) /* string 2 */
+ || !unpack_str(&msg.left.cert) /* string 3 */
+ || !unpack_str(&msg.left.ca) /* string 4 */
+ || !unpack_str(&msg.left.groups) /* string 5 */
+ || !unpack_str(&msg.left.updown) /* string 6 */
+ || !unpack_str(&msg.left.virt) /* string 7 */
+ || !unpack_str(&msg.right.id) /* string 8 */
+ || !unpack_str(&msg.right.cert) /* string 9 */
+ || !unpack_str(&msg.right.ca) /* string 10 */
+ || !unpack_str(&msg.right.groups) /* string 11 */
+ || !unpack_str(&msg.right.updown) /* string 12 */
+ || !unpack_str(&msg.right.virt) /* string 13 */
+ || !unpack_str(&msg.keyid) /* string 14 */
+ || !unpack_str(&msg.myid) /* string 15 */
+ || !unpack_str(&msg.cacert) /* string 16 */
+ || !unpack_str(&msg.ldaphost) /* string 17 */
+ || !unpack_str(&msg.ldapbase) /* string 18 */
+ || !unpack_str(&msg.crluri) /* string 19 */
+ || !unpack_str(&msg.crluri2) /* string 20 */
+ || !unpack_str(&msg.ocspuri) /* string 21 */
+ || !unpack_str(&msg.ike) /* string 22 */
+ || !unpack_str(&msg.esp) /* string 23 */
+ || !unpack_str(&msg.sc_data) /* string 24 */
+ || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
+ {
+ ugh = "message from whack contains bad string";
+ }
+ else
+ {
+ msg.keyval.ptr = next_str; /* grab chunk */
+ }
+
+ if (ugh != NULL)
+ {
+ if (*ugh != '\0')
+ loglog(RC_BADWHACKMESSAGE, "%s", ugh);
+ whack_log_fd = NULL_FD;
+ close(whackfd);
+ return;
+ }
+ }
+
+ if (msg.whack_options)
{
- ugh = builddiag("ignoring runt message from whack: got %d bytes", (int)n);
+#ifdef DEBUG
+ if (msg.name == NULL)
+ {
+ /* we do a two-step so that if either old or new would
+ * cause the message to print, it will be printed.
+ */
+ cur_debugging |= msg.debugging;
+ DBG(DBG_CONTROL
+ , DBG_log("base debugging = %s"
+ , bitnamesof(debug_bit_names, msg.debugging)));
+ cur_debugging = base_debugging = msg.debugging;
+ }
+ else if (!msg.whack_connection)
+ {
+ struct connection *c = con_by_name(msg.name, TRUE);
+
+ if (c != NULL)
+ {
+ c->extra_debugging = msg.debugging;
+ DBG(DBG_CONTROL
+ , DBG_log("\"%s\" extra_debugging = %s"
+ , c->name
+ , bitnamesof(debug_bit_names, c->extra_debugging)));
+ }
+ }
+#endif
+ }
+
+ if (msg.whack_myid)
+ set_myid(MYID_SPECIFIED, msg.myid);
+
+ /* Deleting combined with adding a connection works as replace.
+ * To make this more useful, in only this combination,
+ * delete will silently ignore the lack of the connection.
+ */
+ if (msg.whack_delete)
+ {
+ if (msg.whack_ca)
+ find_ca_info_by_name(msg.name, TRUE);
+ else
+ delete_connections_by_name(msg.name, !msg.whack_connection);
}
- else if (msg.magic != WHACK_MAGIC)
+
+ if (msg.whack_deletestate)
{
- if (msg.magic == WHACK_BASIC_MAGIC)
- {
- /* Only shutdown command. Simpler inter-version compatability. */
- if (msg.whack_shutdown)
+ struct state *st = state_with_serialno(msg.whack_deletestateno);
+
+ if (st == NULL)
+ {
+ loglog(RC_UNKNOWN_NAME, "no state #%lu to delete"
+ , msg.whack_deletestateno);
+ }
+ else
{
- plog("shutting down");
- exit_pluto(0); /* delete lock and leave, with 0 status */
+ delete_state(st);
}
- ugh = ""; /* bail early, but without complaint */
- }
- else
- {
- ugh = builddiag("ignoring message from whack with bad magic %d; should be %d; probably wrong version"
- , msg.magic, WHACK_MAGIC);
- }
- }
- else if (next_str > str_roof)
- {
- ugh = builddiag("ignoring truncated message from whack: got %d bytes; expected %u"
- , (int) n, (unsigned) sizeof(msg));
- }
- else if (!unpack_str(&msg.name) /* string 1 */
- || !unpack_str(&msg.left.id) /* string 2 */
- || !unpack_str(&msg.left.cert) /* string 3 */
- || !unpack_str(&msg.left.ca) /* string 4 */
- || !unpack_str(&msg.left.groups) /* string 5 */
- || !unpack_str(&msg.left.updown) /* string 6 */
- || !unpack_str(&msg.left.virt) /* string 7 */
- || !unpack_str(&msg.right.id) /* string 8 */
- || !unpack_str(&msg.right.cert) /* string 9 */
- || !unpack_str(&msg.right.ca) /* string 10 */
- || !unpack_str(&msg.right.groups) /* string 11 */
- || !unpack_str(&msg.right.updown) /* string 12 */
- || !unpack_str(&msg.right.virt) /* string 13 */
- || !unpack_str(&msg.keyid) /* string 14 */
- || !unpack_str(&msg.myid) /* string 15 */
- || !unpack_str(&msg.cacert) /* string 16 */
- || !unpack_str(&msg.ldaphost) /* string 17 */
- || !unpack_str(&msg.ldapbase) /* string 18 */
- || !unpack_str(&msg.crluri) /* string 19 */
- || !unpack_str(&msg.crluri2) /* string 20 */
- || !unpack_str(&msg.ocspuri) /* string 21 */
- || !unpack_str(&msg.ike) /* string 22 */
- || !unpack_str(&msg.esp) /* string 23 */
- || !unpack_str(&msg.sc_data) /* string 24 */
- || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
- {
- ugh = "message from whack contains bad string";
}
- else
+
+ if (msg.whack_crash)
+ delete_states_by_peer(&msg.whack_crash_peer);
+
+ if (msg.whack_connection)
+ add_connection(&msg);
+
+ if (msg.whack_ca && msg.cacert != NULL)
+ add_ca_info(&msg);
+
+ /* process "listen" before any operation that could require it */
+ if (msg.whack_listen)
+ {
+ close_peerlog(); /* close any open per-peer logs */
+ plog("listening for IKE messages");
+ listening = TRUE;
+ daily_log_reset();
+ reset_adns_restart_count();
+ set_myFQDN();
+ find_ifaces();
+ load_preshared_secrets(NULL_FD);
+ load_groups();
+ }
+ if (msg.whack_unlisten)
{
- msg.keyval.ptr = next_str; /* grab chunk */
+ plog("no longer listening for IKE messages");
+ listening = FALSE;
}
- if (ugh != NULL)
+ if (msg.whack_reread & REREAD_SECRETS)
{
- if (*ugh != '\0')
- loglog(RC_BADWHACKMESSAGE, "%s", ugh);
- whack_log_fd = NULL_FD;
- close(whackfd);
- return;
+ load_preshared_secrets(whackfd);
}
- }
- if (msg.whack_options)
- {
-#ifdef DEBUG
- if (msg.name == NULL)
- {
- /* we do a two-step so that if either old or new would
- * cause the message to print, it will be printed.
- */
- cur_debugging |= msg.debugging;
- DBG(DBG_CONTROL
- , DBG_log("base debugging = %s"
- , bitnamesof(debug_bit_names, msg.debugging)));
- cur_debugging = base_debugging = msg.debugging;
- }
- else if (!msg.whack_connection)
- {
- struct connection *c = con_by_name(msg.name, TRUE);
-
- if (c != NULL)
- {
- c->extra_debugging = msg.debugging;
- DBG(DBG_CONTROL
- , DBG_log("\"%s\" extra_debugging = %s"
- , c->name
- , bitnamesof(debug_bit_names, c->extra_debugging)));
- }
+ if (msg.whack_reread & REREAD_CACERTS)
+ {
+ load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
}
-#endif
- }
-
- if (msg.whack_myid)
- set_myid(MYID_SPECIFIED, msg.myid);
-
- /* Deleting combined with adding a connection works as replace.
- * To make this more useful, in only this combination,
- * delete will silently ignore the lack of the connection.
- */
- if (msg.whack_delete)
- {
- if (msg.whack_ca)
- find_ca_info_by_name(msg.name, TRUE);
- else
- delete_connections_by_name(msg.name, !msg.whack_connection);
- }
- if (msg.whack_deletestate)
- {
- struct state *st = state_with_serialno(msg.whack_deletestateno);
+ if (msg.whack_reread & REREAD_AACERTS)
+ {
+ load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
+ }
- if (st == NULL)
+ if (msg.whack_reread & REREAD_OCSPCERTS)
{
- loglog(RC_UNKNOWN_NAME, "no state #%lu to delete"
- , msg.whack_deletestateno);
+ load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
}
- else
+
+ if (msg.whack_reread & REREAD_ACERTS)
{
- delete_state(st);
- }
- }
-
- if (msg.whack_crash)
- delete_states_by_peer(&msg.whack_crash_peer);
-
- if (msg.whack_connection)
- add_connection(&msg);
-
- if (msg.whack_ca && msg.cacert != NULL)
- add_ca_info(&msg);
-
- /* process "listen" before any operation that could require it */
- if (msg.whack_listen)
- {
- close_peerlog(); /* close any open per-peer logs */
- plog("listening for IKE messages");
- listening = TRUE;
- daily_log_reset();
- reset_adns_restart_count();
- set_myFQDN();
- find_ifaces();
- load_preshared_secrets(NULL_FD);
- load_groups();
- }
- if (msg.whack_unlisten)
- {
- plog("no longer listening for IKE messages");
- listening = FALSE;
- }
-
- if (msg.whack_reread & REREAD_SECRETS)
- {
- load_preshared_secrets(whackfd);
- }
-
- if (msg.whack_reread & REREAD_CACERTS)
- {
- load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
- }
-
- if (msg.whack_reread & REREAD_AACERTS)
- {
- load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
- }
-
- if (msg.whack_reread & REREAD_OCSPCERTS)
- {
- load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
- }
-
- if (msg.whack_reread & REREAD_ACERTS)
- {
- load_acerts();
- }
-
- if (msg.whack_reread & REREAD_CRLS)
- {
- load_crls();
- }
-
- if (msg.whack_purgeocsp)
- {
- free_ocsp_fetch();
- free_ocsp_cache();
- }
-
- if (msg.whack_list & LIST_ALGS)
- {
- ike_alg_list();
- kernel_alg_list();
- }
+ load_acerts();
+ }
+
+ if (msg.whack_reread & REREAD_CRLS)
+ {
+ load_crls();
+ }
+
+ if (msg.whack_purgeocsp)
+ {
+ free_ocsp_fetch();
+ free_ocsp_cache();
+ }
+
if (msg.whack_list & LIST_PUBKEYS)
- {
- list_public_keys(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CERTS)
- {
- list_certs(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CACERTS)
- {
- list_authcerts("CA", AUTH_CA, msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_AACERTS)
- {
- list_authcerts("AA", AUTH_AA, msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_OCSPCERTS)
- {
- list_authcerts("OCSP", AUTH_OCSP, msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_ACERTS)
- {
- list_acerts(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_GROUPS)
- {
- list_groups(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CAINFOS)
- {
- list_ca_infos(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CRLS)
- {
- list_crls(msg.whack_utc, strict_crl_policy);
- list_crl_fetch_requests(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_OCSP)
- {
- list_ocsp_cache(msg.whack_utc, strict_crl_policy);
- list_ocsp_fetch_requests(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CARDS)
- {
- scx_list(msg.whack_utc);
- }
-
- if (msg.whack_key)
- {
- /* add a public key */
- key_add_request(&msg);
- }
-
- if (msg.whack_route)
- {
- if (!listening)
- {
- whack_log(RC_DEAF, "need --listen before --route");
- }
- if (msg.name == NULL)
- {
- whack_log(RC_UNKNOWN_NAME
- , "whack --route requires a connection name");
+ {
+ list_public_keys(msg.whack_utc);
}
- else
+
+ if (msg.whack_list & LIST_CERTS)
{
- struct connection *c = con_by_name(msg.name, TRUE);
+ list_certs(msg.whack_utc);
+ }
- if (c != NULL && c->ikev1)
- {
- set_cur_connection(c);
- if (!oriented(*c))
- whack_log(RC_ORIENT
- , "we have no ipsecN interface for either end of this connection");
- else if (c->policy & POLICY_GROUP)
- route_group(c);
- else if (!trap_connection(c))
- whack_log(RC_ROUTE, "could not route");
- reset_cur_connection();
- }
+ if (msg.whack_list & LIST_CACERTS)
+ {
+ list_authcerts("CA", AUTH_CA, msg.whack_utc);
}
- }
- if (msg.whack_unroute)
- {
- if (msg.name == NULL)
+ if (msg.whack_list & LIST_AACERTS)
{
- whack_log(RC_UNKNOWN_NAME
- , "whack --unroute requires a connection name");
+ list_authcerts("AA", AUTH_AA, msg.whack_utc);
}
- else
+
+ if (msg.whack_list & LIST_OCSPCERTS)
{
- struct connection *c = con_by_name(msg.name, TRUE);
+ list_authcerts("OCSP", AUTH_OCSP, msg.whack_utc);
+ }
- if (c != NULL && c->ikev1)
- {
- struct spd_route *sr;
- int fail = 0;
+ if (msg.whack_list & LIST_ACERTS)
+ {
+ list_acerts(msg.whack_utc);
+ }
- set_cur_connection(c);
+ if (msg.whack_list & LIST_GROUPS)
+ {
+ list_groups(msg.whack_utc);
+ }
- for (sr = &c->spd; sr != NULL; sr = sr->next)
- {
- if (sr->routing >= RT_ROUTED_TUNNEL)
- fail++;
- }
- if (fail > 0)
- whack_log(RC_RTBUSY, "cannot unroute: route busy");
- else if (c->policy & POLICY_GROUP)
- unroute_group(c);
- else
- unroute_connection(c);
- reset_cur_connection();
- }
+ if (msg.whack_list & LIST_CAINFOS)
+ {
+ list_ca_infos(msg.whack_utc);
}
- }
- if (msg.whack_initiate)
- {
- if (!listening)
+ if (msg.whack_list & LIST_CRLS)
{
- whack_log(RC_DEAF, "need --listen before --initiate");
+ list_crls(msg.whack_utc, strict_crl_policy);
+ list_crl_fetch_requests(msg.whack_utc);
}
- else if (msg.name == NULL)
+
+ if (msg.whack_list & LIST_OCSP)
{
- whack_log(RC_UNKNOWN_NAME
- , "whack --initiate requires a connection name");
+ list_ocsp_cache(msg.whack_utc, strict_crl_policy);
+ list_ocsp_fetch_requests(msg.whack_utc);
}
- else
+
+ if (msg.whack_list & LIST_CARDS)
{
- initiate_connection(msg.name
- , msg.whack_async? NULL_FD : dup_any(whackfd));
+ scx_list(msg.whack_utc);
}
- }
- if (msg.whack_oppo_initiate)
- {
- if (!listening)
- whack_log(RC_DEAF, "need --listen before opportunistic initiation");
- else
- initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client, 0
- , FALSE
- , msg.whack_async? NULL_FD : dup_any(whackfd));
- }
+ if (msg.whack_list & LIST_ALGS)
+ {
+ ike_alg_list();
+ kernel_alg_list();
+ }
- if (msg.whack_terminate)
- {
- if (msg.name == NULL)
+ if (msg.whack_key)
{
- whack_log(RC_UNKNOWN_NAME
- , "whack --terminate requires a connection name");
+ /* add a public key */
+ key_add_request(&msg);
}
- else
+
+ if (msg.whack_route)
{
- terminate_connection(msg.name);
+ if (!listening)
+ {
+ whack_log(RC_DEAF, "need --listen before --route");
+ }
+ if (msg.name == NULL)
+ {
+ whack_log(RC_UNKNOWN_NAME
+ , "whack --route requires a connection name");
+ }
+ else
+ {
+ struct connection *c = con_by_name(msg.name, TRUE);
+
+ if (c != NULL && c->ikev1)
+ {
+ set_cur_connection(c);
+ if (!oriented(*c))
+ whack_log(RC_ORIENT
+ , "we have no ipsecN interface for either end of this connection");
+ else if (c->policy & POLICY_GROUP)
+ route_group(c);
+ else if (!trap_connection(c))
+ whack_log(RC_ROUTE, "could not route");
+ reset_cur_connection();
+ }
+ }
}
- }
- if (msg.whack_status)
- show_status(msg.whack_statusall, msg.name);
+ if (msg.whack_unroute)
+ {
+ if (msg.name == NULL)
+ {
+ whack_log(RC_UNKNOWN_NAME
+ , "whack --unroute requires a connection name");
+ }
+ else
+ {
+ struct connection *c = con_by_name(msg.name, TRUE);
+
+ if (c != NULL && c->ikev1)
+ {
+ struct spd_route *sr;
+ int fail = 0;
+
+ set_cur_connection(c);
+
+ for (sr = &c->spd; sr != NULL; sr = sr->next)
+ {
+ if (sr->routing >= RT_ROUTED_TUNNEL)
+ fail++;
+ }
+ if (fail > 0)
+ whack_log(RC_RTBUSY, "cannot unroute: route busy");
+ else if (c->policy & POLICY_GROUP)
+ unroute_group(c);
+ else
+ unroute_connection(c);
+ reset_cur_connection();
+ }
+ }
+ }
- if (msg.whack_shutdown)
- {
- plog("shutting down");
- exit_pluto(0); /* delete lock and leave, with 0 status */
- }
+ if (msg.whack_initiate)
+ {
+ if (!listening)
+ {
+ whack_log(RC_DEAF, "need --listen before --initiate");
+ }
+ else if (msg.name == NULL)
+ {
+ whack_log(RC_UNKNOWN_NAME
+ , "whack --initiate requires a connection name");
+ }
+ else
+ {
+ initiate_connection(msg.name
+ , msg.whack_async? NULL_FD : dup_any(whackfd));
+ }
+ }
- if (msg.whack_sc_op != SC_OP_NONE)
- {
- if (pkcs11_proxy)
- scx_op_via_whack(msg.sc_data, msg.inbase, msg.outbase
- , msg.whack_sc_op, msg.keyid, whackfd);
- else
- plog("pkcs11 access to smartcard not allowed (set pkcs11proxy=yes)");
- }
+ if (msg.whack_oppo_initiate)
+ {
+ if (!listening)
+ whack_log(RC_DEAF, "need --listen before opportunistic initiation");
+ else
+ initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client, 0
+ , FALSE
+ , msg.whack_async? NULL_FD : dup_any(whackfd));
+ }
+
+ if (msg.whack_terminate)
+ {
+ if (msg.name == NULL)
+ {
+ whack_log(RC_UNKNOWN_NAME
+ , "whack --terminate requires a connection name");
+ }
+ else
+ {
+ terminate_connection(msg.name);
+ }
+ }
+
+ if (msg.whack_status)
+ show_status(msg.whack_statusall, msg.name);
+
+ if (msg.whack_shutdown)
+ {
+ plog("shutting down");
+ exit_pluto(0); /* delete lock and leave, with 0 status */
+ }
- whack_log_fd = NULL_FD;
- close(whackfd);
+ if (msg.whack_sc_op != SC_OP_NONE)
+ {
+ if (pkcs11_proxy)
+ scx_op_via_whack(msg.sc_data, msg.inbase, msg.outbase
+ , msg.whack_sc_op, msg.keyid, whackfd);
+ else
+ plog("pkcs11 access to smartcard not allowed (set pkcs11proxy=yes)");
+ }
+
+ whack_log_fd = NULL_FD;
+ close(whackfd);
}
/*
diff --git a/src/pluto/rcv_whack.h b/src/pluto/rcv_whack.h
index e0582202f..66edaaf80 100644
--- a/src/pluto/rcv_whack.h
+++ b/src/pluto/rcv_whack.h
@@ -10,8 +10,6 @@
* 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: rcv_whack.h 3252 2007-10-06 21:24:50Z andreas $
*/
extern void whack_handle(int kernelfd);
diff --git a/src/pluto/rnd.c b/src/pluto/rnd.c
deleted file mode 100644
index 7941034d8..000000000
--- a/src/pluto/rnd.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* randomness machinery
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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: rnd.c 3252 2007-10-06 21:24:50Z andreas $
- */
-
-/* A true random number generator (we hope)
- *
- * Under LINUX ("linux" predefined), use /dev/urandom.
- * Under OpenBSD ("__OpenBSD__" predefined), use arc4random().
- * Otherwise use our own random number generator based on clock skew.
- * I (ADK) first heard of the idea from John Ioannidis, who heard it
- * from Matt Blaze and/or Jack Lacy.
- * ??? Why is mixing need for linux but not OpenBSD?
- */
-
-/* Pluto's uses of randomness:
- *
- * - Setting up the "secret_of_the_day". This changes every hour! 20
- * bytes a shot. It is used in building responder cookies.
- *
- * - generating initiator cookies (8 bytes, once per Phase 1 initiation).
- *
- * - 32 bytes per DH local secret. Once per Main Mode exchange and once
- * per Quick Mode Exchange with PFS. (Size is our choice, with
- * tradeoffs.)
- *
- * - 16 bytes per nonce we generate. Once per Main Mode exchange and
- * once per Quick Mode exchange. (Again, we choose the size.)
- *
- * - 4 bytes per SPI number that we generate. We choose the SPIs for all
- * inbound SPIs, one to three per IPSEC SA (one for AH (rare, probably)
- * one for ESP (almost always), and one for tunnel (very common)).
- * I don't actually know how the kernel would generate these numbers --
- * currently Pluto generates them; this isn't the way things will be
- * done in the future.
- *
- * - 4 bytes per Message ID we need to generate. One per Quick Mode
- * exchange. Eventually, one per informational exchange.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <fcntl.h>
-
-#include <freeswan.h>
-
-#include "sha1.h"
-#include "constants.h"
-#include "defs.h"
-#include "rnd.h"
-#include "log.h"
-#include "timer.h"
-
-#ifdef linux
-# define USE_DEV_RANDOM 1
-# define RANDOM_PATH DEV_URANDOM
-#else
-# ifdef __OpenBSD__
-# define USE_ARC4RANDOM
-# else
-# define USE_CLOCK_SLEW
-# endif
-#endif
-
-#ifdef USE_ARC4RANDOM
-
-#define get_rnd_byte() (arc4random() % 256)
-
-#else /**** start of large #else ****/
-
-#ifdef USE_DEV_RANDOM
-static int random_fd = NULL_FD;
-#endif
-
-#define RANDOM_POOL_SIZE SHA1_DIGEST_SIZE
-static u_char random_pool[RANDOM_POOL_SIZE];
-
-#ifdef USE_DEV_RANDOM
-
-/* Generate (what we hope is) a true random byte using /dev/urandom */
-static u_char
-generate_rnd_byte(void)
-{
- u_char c;
-
- if (read(random_fd, &c, sizeof(c)) == -1)
- exit_log_errno((e, "read() failed in get_rnd_byte()"));
-
- return c;
-}
-
-#else /* !USE_DEV_RANDOM */
-
-/* Generate (what we hope is) a true random byte using the clock skew trick.
- * Note: this code is not maintained! In particular, LINUX signal(2)
- * semantics changed with glibc2 (and not for the better). It isn't clear
- * that this code will work. We keep the code because someday it might
- * come in handy.
- */
-# error "This code is not maintained. Please define USE_DEV_RANDOM."
-
-static volatile sig_atomic_t i, j, k;
-
-/* timer signal handler */
-static void
-rnd_handler(int ignore_me UNUSED)
-{
- k <<= 1; /* Shift left by 1 */
- j++;
- k |= (i & 0x1); /* Get lsbit of counter */
-
- if (j != 8)
- signal(SIGVTALRM, rnd_handler);
-}
-
-static u_char
-generate_rnd_byte(void)
-{
- struct itimerval tmval, ntmval;
-
-# ifdef NEVER /* ??? */
-# ifdef linux
- int mask = siggetmask();
-
- mask |= SIGVTALRM;
- sigsetmask(mask);
-# endif
-# endif
-
- i = 0;
- j = 0;
-
- ntmval.it_interval.tv_sec = 0;
- ntmval.it_interval.tv_usec = 1;
- ntmval.it_value.tv_sec = 0;
- ntmval.it_value.tv_usec = 1;
- signal(SIGVTALRM, rnd_handler);
- setitimer(ITIMER_VIRTUAL, &ntmval, &tmval);
-
- while (j != 8)
- i++;
-
- setitimer(ITIMER_VIRTUAL, &tmval, &ntmval);
- signal(SIGVTALRM, SIG_IGN);
-
-# ifdef NEVER /* ??? */
-# ifdef linux
- mask ^= SIGVTALRM;
- sigsetmask(mask);
-# endif
-# endif
-
- return k;
-}
-
-#endif /* !USE_DEV_RANDOM */
-
-static void
-mix_pool(void)
-{
- SHA1_CTX ctx;
-
- SHA1Init(&ctx);
- SHA1Update(&ctx, random_pool, RANDOM_POOL_SIZE);
- SHA1Final(random_pool, &ctx);
-}
-
-/*
- * Get a single random byte.
- */
-static u_char
-get_rnd_byte(void)
-{
- random_pool[RANDOM_POOL_SIZE - 1] = generate_rnd_byte();
- random_pool[0] = generate_rnd_byte();
- mix_pool();
- return random_pool[0];
-}
-
-#endif /* !USE_ARC4RANDOM */ /**** end of large #else ****/
-
-void
-get_rnd_bytes(u_char *buffer, int length)
-{
- int i;
-
- for (i = 0; i < length; i++)
- buffer[i] = get_rnd_byte();
-}
-
-/*
- * Initialize the random pool.
- */
-void
-init_rnd_pool(void)
-{
-#ifndef USE_ARC4RANDOM
-# ifdef USE_DEV_RANDOM
- DBG(DBG_KLIPS, DBG_log("opening %s", RANDOM_PATH));
- random_fd = open(RANDOM_PATH, O_RDONLY);
- if (random_fd == -1)
- exit_log_errno((e, "open of %s failed in init_rnd_pool()", RANDOM_PATH));
- fcntl(random_fd, F_SETFD, FD_CLOEXEC);
-# endif
-
- get_rnd_bytes(random_pool, RANDOM_POOL_SIZE);
- mix_pool();
-#endif /* !USE_ARC4RANDOM */
-
- /* start of rand(3) on the right foot */
- {
- unsigned int seed;
-
- get_rnd_bytes((void *)&seed, sizeof(seed));
- srand(seed);
- }
-}
-
-u_char secret_of_the_day[SHA1_DIGEST_SIZE];
-
-#ifndef NO_PLUTO
-
-void
-init_secret(void)
-{
- /*
- * Generate the secret value for responder cookies, and
- * schedule an event for refresh.
- */
- get_rnd_bytes(secret_of_the_day, sizeof(secret_of_the_day));
- event_schedule(EVENT_REINIT_SECRET, EVENT_REINIT_SECRET_DELAY, NULL);
-}
-
-#endif /* NO_PLUTO */
diff --git a/src/pluto/rnd.h b/src/pluto/rnd.h
deleted file mode 100644
index e32b68b47..000000000
--- a/src/pluto/rnd.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* randomness machinery
- * Copyright (C) 1998, 1999 D. Hugh Redelmeier.
- *
- * 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: rnd.h 3252 2007-10-06 21:24:50Z andreas $
- */
-
-extern u_char secret_of_the_day[SHA1_DIGEST_SIZE];
-
-extern void get_rnd_bytes(u_char *buffer, int length);
-extern void init_rnd_pool(void);
-extern void init_secret(void);
diff --git a/src/pluto/server.c b/src/pluto/server.c
index b0e158503..21f65f4f8 100644
--- a/src/pluto/server.c
+++ b/src/pluto/server.c
@@ -11,8 +11,6 @@
* 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: server.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -27,7 +25,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#ifdef SOLARIS
-# include <sys/sockio.h> /* for Solaris 2.6: defines SIOCGIFCONF */
+# include <sys/sockio.h> /* for Solaris 2.6: defines SIOCGIFCONF */
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -38,7 +36,7 @@
#include <net/if.h>
#include <sys/ioctl.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <freeswan.h>
@@ -55,9 +53,9 @@
#include "demux.h" /* needs packet.h */
#include "rcv_whack.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "whack.h" /* for RC_LOG_SERIOUS */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
+#include "whack.h" /* for RC_LOG_SERIOUS */
#include <pfkeyv2.h>
#include <pfkey.h>
@@ -68,10 +66,10 @@
* Server main loop and socket initialization routines.
*/
-static const int on = TRUE; /* by-reference parameter; constant, we hope */
+static const int on = TRUE; /* by-reference parameter; constant, we hope */
/* control (whack) socket */
-int ctl_fd = NULL_FD; /* file descriptor of control (whack) socket */
+int ctl_fd = NULL_FD; /* file descriptor of control (whack) socket */
struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX };
/* info (showpolicy) socket */
@@ -86,121 +84,121 @@ struct sockaddr_un info_addr= { AF_UNIX, DEFAULT_CTLBASE INFO_SUFFIX };
err_t
init_ctl_socket(void)
{
- err_t failed = NULL;
-
- delete_ctl_socket(); /* preventative medicine */
- ctl_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (ctl_fd == -1)
- failed = "create";
- else if (fcntl(ctl_fd, F_SETFD, FD_CLOEXEC) == -1)
- failed = "fcntl FD+CLOEXEC";
- else if (setsockopt(ctl_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0)
- failed = "setsockopt";
- else
- {
- /* to keep control socket secure, use umask */
- mode_t ou = umask(~S_IRWXU);
-
- if (bind(ctl_fd, (struct sockaddr *)&ctl_addr
- , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
- failed = "bind";
- umask(ou);
- }
-
- /* 5 is a haphazardly chosen limit for the backlog.
- * Rumour has it that this is the max on BSD systems.
- */
- if (failed == NULL && listen(ctl_fd, 5) < 0)
- failed = "listen() on";
-
- return failed == NULL? NULL : builddiag("could not %s control socket: %d %s"
- , failed, errno, strerror(errno));
+ err_t failed = NULL;
+
+ delete_ctl_socket(); /* preventative medicine */
+ ctl_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (ctl_fd == -1)
+ failed = "create";
+ else if (fcntl(ctl_fd, F_SETFD, FD_CLOEXEC) == -1)
+ failed = "fcntl FD+CLOEXEC";
+ else if (setsockopt(ctl_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0)
+ failed = "setsockopt";
+ else
+ {
+ /* to keep control socket secure, use umask */
+ mode_t ou = umask(~S_IRWXU);
+
+ if (bind(ctl_fd, (struct sockaddr *)&ctl_addr
+ , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
+ failed = "bind";
+ umask(ou);
+ }
+
+ /* 5 is a haphazardly chosen limit for the backlog.
+ * Rumour has it that this is the max on BSD systems.
+ */
+ if (failed == NULL && listen(ctl_fd, 5) < 0)
+ failed = "listen() on";
+
+ return failed == NULL? NULL : builddiag("could not %s control socket: %d %s"
+ , failed, errno, strerror(errno));
}
void
delete_ctl_socket(void)
{
- /* Is noting failure useful? Not when used as preventative medicine. */
- unlink(ctl_addr.sun_path);
+ /* Is noting failure useful? Not when used as preventative medicine. */
+ unlink(ctl_addr.sun_path);
}
-bool listening = FALSE; /* should we pay attention to IKE messages? */
+bool listening = FALSE; /* should we pay attention to IKE messages? */
-struct iface *interfaces = NULL; /* public interfaces */
+struct iface *interfaces = NULL; /* public interfaces */
/* Initialize the interface sockets. */
static void
mark_ifaces_dead(void)
{
- struct iface *p;
+ struct iface *p;
- for (p = interfaces; p != NULL; p = p->next)
- p->change = IFN_DELETE;
+ for (p = interfaces; p != NULL; p = p->next)
+ p->change = IFN_DELETE;
}
static void
free_dead_ifaces(void)
{
- struct iface *p;
- bool some_dead = FALSE
- , some_new = FALSE;
+ struct iface *p;
+ bool some_dead = FALSE
+ , some_new = FALSE;
- for (p = interfaces; p != NULL; p = p->next)
- {
- if (p->change == IFN_DELETE)
- {
- plog("shutting down interface %s/%s %s"
- , p->vname, p->rname, ip_str(&p->addr));
- some_dead = TRUE;
- }
- else if (p->change == IFN_ADD)
+ for (p = interfaces; p != NULL; p = p->next)
{
- some_new = TRUE;
+ if (p->change == IFN_DELETE)
+ {
+ plog("shutting down interface %s/%s %s"
+ , p->vname, p->rname, ip_str(&p->addr));
+ some_dead = TRUE;
+ }
+ else if (p->change == IFN_ADD)
+ {
+ some_new = TRUE;
+ }
}
- }
-
- if (some_dead)
- {
- struct iface **pp;
- release_dead_interfaces();
- for (pp = &interfaces; (p = *pp) != NULL; )
+ if (some_dead)
{
- if (p->change == IFN_DELETE)
- {
- *pp = p->next; /* advance *pp */
- pfree(p->vname);
- pfree(p->rname);
- close(p->fd);
- pfree(p);
- }
- else
- {
- pp = &p->next; /* advance pp */
- }
+ struct iface **pp;
+
+ release_dead_interfaces();
+ for (pp = &interfaces; (p = *pp) != NULL; )
+ {
+ if (p->change == IFN_DELETE)
+ {
+ *pp = p->next; /* advance *pp */
+ free(p->vname);
+ free(p->rname);
+ close(p->fd);
+ free(p);
+ }
+ else
+ {
+ pp = &p->next; /* advance pp */
+ }
+ }
}
- }
-
- /* this must be done after the release_dead_interfaces
- * in case some to the newly unoriented connections can
- * become oriented here.
- */
- if (some_dead || some_new)
- check_orientations();
+
+ /* this must be done after the release_dead_interfaces
+ * in case some to the newly unoriented connections can
+ * become oriented here.
+ */
+ if (some_dead || some_new)
+ check_orientations();
}
void
free_ifaces(void)
{
- mark_ifaces_dead();
- free_dead_ifaces();
+ mark_ifaces_dead();
+ free_dead_ifaces();
}
struct raw_iface {
- ip_address addr;
- char name[IFNAMSIZ + 20]; /* what would be a safe size? */
- struct raw_iface *next;
+ ip_address addr;
+ char name[IFNAMSIZ + 20]; /* what would be a safe size? */
+ struct raw_iface *next;
};
/* Called to handle --interface <ifname>
@@ -212,15 +210,15 @@ static int pluto_ifn_roof = 0;
bool
use_interface(const char *rifn)
{
- if (pluto_ifn_roof >= (int)elemsof(pluto_ifn))
- {
- return FALSE;
- }
- else
- {
- pluto_ifn[pluto_ifn_roof++] = rifn;
- return TRUE;
- }
+ if (pluto_ifn_roof >= (int)countof(pluto_ifn))
+ {
+ return FALSE;
+ }
+ else
+ {
+ pluto_ifn[pluto_ifn_roof++] = rifn;
+ return TRUE;
+ }
}
#ifndef IPSECDEVPREFIX
@@ -230,538 +228,542 @@ use_interface(const char *rifn)
static struct raw_iface *
find_raw_ifaces4(void)
{
- int j; /* index into buf */
- struct ifconf ifconf;
- struct ifreq buf[300]; /* for list of interfaces -- arbitrary limit */
- struct raw_iface *rifaces = NULL;
- int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */
-
- /* get list of interfaces with assigned IPv4 addresses from system */
-
- if (master_sock == -1)
- exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));
-
- if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR
- , (const void *)&on, sizeof(on)) < 0)
- exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));
-
- /* bind the socket */
- {
- ip_address any;
-
- happy(anyaddr(AF_INET, &any));
- setportof(htons(pluto_port), &any);
- if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)
- exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
- }
-
- /* Get local interfaces. See netdevice(7). */
- ifconf.ifc_len = sizeof(buf);
- ifconf.ifc_buf = (void *) buf;
- zero(buf);
-
- if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
- exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
-
- /* Add an entry to rifaces for each interesting interface. */
- for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)
- {
- struct raw_iface ri;
- const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
- struct ifreq auxinfo;
-
- /* ignore all but AF_INET interfaces */
- if (rs->sin_family != AF_INET)
- continue; /* not interesting */
-
- /* build a NUL-terminated copy of the rname field */
- memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);
- ri.name[IFNAMSIZ] = '\0';
-
- /* ignore if our interface names were specified, and this isn't one */
- if (pluto_ifn_roof != 0)
+ int j; /* index into buf */
+ struct ifconf ifconf;
+ struct ifreq buf[300]; /* for list of interfaces -- arbitrary limit */
+ struct raw_iface *rifaces = NULL;
+ int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */
+
+ /* get list of interfaces with assigned IPv4 addresses from system */
+
+ if (master_sock == -1)
+ exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));
+
+ if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR
+ , (const void *)&on, sizeof(on)) < 0)
+ exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));
+
+ /* bind the socket */
{
- int i;
+ ip_address any;
- for (i = 0; i != pluto_ifn_roof; i++)
- if (streq(ri.name, pluto_ifn[i]))
- break;
- if (i == pluto_ifn_roof)
- continue; /* not found -- skip */
+ happy(anyaddr(AF_INET, &any));
+ setportof(htons(pluto_port), &any);
+ if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)
+ exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
}
- /* Find out stuff about this interface. See netdevice(7). */
- zero(&auxinfo); /* paranoia */
- memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);
- if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)
- exit_log_errno((e
- , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"
- , ri.name));
- if (!(auxinfo.ifr_flags & IFF_UP))
- continue; /* ignore an interface that isn't UP */
+ /* Get local interfaces. See netdevice(7). */
+ ifconf.ifc_len = sizeof(buf);
+ ifconf.ifc_buf = (void *) buf;
+ zero(buf);
- /* ignore unconfigured interfaces */
- if (rs->sin_addr.s_addr == 0)
- continue;
+ if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
+ exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
- happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr)
- , AF_INET, &ri.addr));
+ /* Add an entry to rifaces for each interesting interface. */
+ for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)
+ {
+ struct raw_iface ri;
+ const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
+ struct ifreq auxinfo;
- DBG(DBG_CONTROL, DBG_log("found %s with address %s"
- , ri.name, ip_str(&ri.addr)));
- ri.next = rifaces;
- rifaces = clone_thing(ri, "struct raw_iface");
- }
+ /* ignore all but AF_INET interfaces */
+ if (rs->sin_family != AF_INET)
+ continue; /* not interesting */
- close(master_sock);
+ /* build a NUL-terminated copy of the rname field */
+ memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);
+ ri.name[IFNAMSIZ] = '\0';
- return rifaces;
+ /* ignore if our interface names were specified, and this isn't one */
+ if (pluto_ifn_roof != 0)
+ {
+ int i;
+
+ for (i = 0; i != pluto_ifn_roof; i++)
+ if (streq(ri.name, pluto_ifn[i]))
+ break;
+ if (i == pluto_ifn_roof)
+ continue; /* not found -- skip */
+ }
+
+ /* Find out stuff about this interface. See netdevice(7). */
+ zero(&auxinfo); /* paranoia */
+ memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);
+ if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)
+ exit_log_errno((e
+ , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"
+ , ri.name));
+ if (!(auxinfo.ifr_flags & IFF_UP))
+ continue; /* ignore an interface that isn't UP */
+
+ /* ignore unconfigured interfaces */
+ if (rs->sin_addr.s_addr == 0)
+ continue;
+
+ happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr)
+ , AF_INET, &ri.addr));
+
+ DBG(DBG_CONTROL, DBG_log("found %s with address %s"
+ , ri.name, ip_str(&ri.addr)));
+ ri.next = rifaces;
+ rifaces = clone_thing(ri);
+ }
+
+ close(master_sock);
+
+ return rifaces;
}
static struct raw_iface *
find_raw_ifaces6(void)
{
- /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6).
- *
- * Documentation of format?
- * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info()
- * linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info()
- *
- * Sample from Gerhard's laptop:
- * 00000000000000000000000000000001 01 80 10 80 lo
- * 30490009000000000000000000010002 02 40 00 80 ipsec0
- * 30490009000000000000000000010002 07 40 00 80 eth0
- * fe80000000000000025004fffefd5484 02 0a 20 80 ipsec0
- * fe80000000000000025004fffefd5484 07 0a 20 80 eth0
- *
- * Each line contains:
- * - IPv6 address: 16 bytes, in hex, no punctuation
- * - ifindex: 1 byte, in hex
- * - prefix_len: 1 byte, in hex
- * - scope (e.g. global, link local): 1 byte, in hex
- * - flags: 1 byte, in hex
- * - device name: string, followed by '\n'
- */
- struct raw_iface *rifaces = NULL;
- static const char proc_name[] = "/proc/net/if_inet6";
- FILE *proc_sock = fopen(proc_name, "r");
-
- if (proc_sock == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name));
- }
- else
- {
- for (;;)
+ /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6).
+ *
+ * Documentation of format?
+ * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info()
+ * linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info()
+ *
+ * Sample from Gerhard's laptop:
+ * 00000000000000000000000000000001 01 80 10 80 lo
+ * 30490009000000000000000000010002 02 40 00 80 ipsec0
+ * 30490009000000000000000000010002 07 40 00 80 eth0
+ * fe80000000000000025004fffefd5484 02 0a 20 80 ipsec0
+ * fe80000000000000025004fffefd5484 07 0a 20 80 eth0
+ *
+ * Each line contains:
+ * - IPv6 address: 16 bytes, in hex, no punctuation
+ * - ifindex: 1 byte, in hex
+ * - prefix_len: 1 byte, in hex
+ * - scope (e.g. global, link local): 1 byte, in hex
+ * - flags: 1 byte, in hex
+ * - device name: string, followed by '\n'
+ */
+ struct raw_iface *rifaces = NULL;
+ static const char proc_name[] = "/proc/net/if_inet6";
+ FILE *proc_sock = fopen(proc_name, "r");
+
+ if (proc_sock == NULL)
{
- struct raw_iface ri;
- unsigned short xb[8]; /* IPv6 address as 8 16-bit chunks */
- char sb[8*5]; /* IPv6 address as string-with-colons */
- unsigned int if_idx; /* proc field, not used */
- unsigned int plen; /* proc field, not used */
- unsigned int scope; /* proc field, used to exclude link-local */
- unsigned int dad_status; /* proc field, not used */
- /* ??? I hate and distrust scanf -- DHR */
- int r = fscanf(proc_sock
- , "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx"
- " %02x %02x %02x %02x %20s\n"
- , xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7
- , &if_idx, &plen, &scope, &dad_status, ri.name);
-
- /* ??? we should diagnose any problems */
- if (r != 13)
- break;
-
- /* ignore addresses with link local scope.
- * From linux-2.4.9-13/include/net/ipv6.h:
- * IPV6_ADDR_LINKLOCAL 0x0020U
- * IPV6_ADDR_SCOPE_MASK 0x00f0U
- */
- if ((scope & 0x00f0U) == 0x0020U)
- continue;
-
- snprintf(sb, sizeof(sb)
- , "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
- , xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]);
-
- happy(ttoaddr(sb, 0, AF_INET6, &ri.addr));
-
- if (!isunspecaddr(&ri.addr))
- {
- DBG(DBG_CONTROL
- , DBG_log("found %s with address %s"
- , ri.name, sb));
- ri.next = rifaces;
- rifaces = clone_thing(ri, "struct raw_iface");
- }
+ DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name));
+ }
+ else
+ {
+ for (;;)
+ {
+ struct raw_iface ri;
+ unsigned short xb[8]; /* IPv6 address as 8 16-bit chunks */
+ char sb[8*5]; /* IPv6 address as string-with-colons */
+ unsigned int if_idx; /* proc field, not used */
+ unsigned int plen; /* proc field, not used */
+ unsigned int scope; /* proc field, used to exclude link-local */
+ unsigned int dad_status; /* proc field, not used */
+ /* ??? I hate and distrust scanf -- DHR */
+ int r = fscanf(proc_sock
+ , "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx"
+ " %02x %02x %02x %02x %20s\n"
+ , xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7
+ , &if_idx, &plen, &scope, &dad_status, ri.name);
+
+ /* ??? we should diagnose any problems */
+ if (r != 13)
+ break;
+
+ /* ignore addresses with link local scope.
+ * From linux-2.4.9-13/include/net/ipv6.h:
+ * IPV6_ADDR_LINKLOCAL 0x0020U
+ * IPV6_ADDR_SCOPE_MASK 0x00f0U
+ */
+ if ((scope & 0x00f0U) == 0x0020U)
+ continue;
+
+ snprintf(sb, sizeof(sb)
+ , "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+ , xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]);
+
+ happy(ttoaddr(sb, 0, AF_INET6, &ri.addr));
+
+ if (!isunspecaddr(&ri.addr))
+ {
+ DBG(DBG_CONTROL
+ , DBG_log("found %s with address %s"
+ , ri.name, sb));
+ ri.next = rifaces;
+ rifaces = clone_thing(ri);
+ }
+ }
+ fclose(proc_sock);
}
- fclose(proc_sock);
- }
- return rifaces;
+ return rifaces;
}
#if 1
static int
create_socket(struct raw_iface *ifp, const char *v_name, int port)
{
- int fd = socket(addrtypeof(&ifp->addr), SOCK_DGRAM, IPPROTO_UDP);
- int fcntl_flags;
+ int fd = socket(addrtypeof(&ifp->addr), SOCK_DGRAM, IPPROTO_UDP);
+ int fcntl_flags;
- if (fd < 0)
- {
- log_errno((e, "socket() in process_raw_ifaces()"));
- return -1;
- }
+ if (fd < 0)
+ {
+ log_errno((e, "socket() in process_raw_ifaces()"));
+ return -1;
+ }
#if 1
- /* Set socket Nonblocking */
- if ((fcntl_flags=fcntl(fd, F_GETFL)) >= 0) {
- if (!(fcntl_flags & O_NONBLOCK)) {
- fcntl_flags |= O_NONBLOCK;
- fcntl(fd, F_SETFL, fcntl_flags);
+ /* Set socket Nonblocking */
+ if ((fcntl_flags=fcntl(fd, F_GETFL)) >= 0) {
+ if (!(fcntl_flags & O_NONBLOCK)) {
+ fcntl_flags |= O_NONBLOCK;
+ fcntl(fd, F_SETFL, fcntl_flags);
+ }
}
- }
-#endif
-
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
- {
- log_errno((e, "fcntl(,, FD_CLOEXEC) in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR
- , (const void *)&on, sizeof(on)) < 0)
- {
- log_errno((e, "setsockopt SO_REUSEADDR in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-
- /* To improve error reporting. See ip(7). */
-#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
- if (setsockopt(fd, SOL_IP, IP_RECVERR
- , (const void *)&on, sizeof(on)) < 0)
- {
- log_errno((e, "setsockopt IP_RECVERR in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-#endif
-
- /* With IPv6, there is no fragmentation after
- * it leaves our interface. PMTU discovery
- * is mandatory but doesn't work well with IKE (why?).
- * So we must set the IPV6_USE_MIN_MTU option.
- * See draft-ietf-ipngwg-rfc2292bis-01.txt 11.1
- */
-#ifdef IPV6_USE_MIN_MTU /* YUCK: not always defined */
- if (addrtypeof(&ifp->addr) == AF_INET6
- && setsockopt(fd, SOL_SOCKET, IPV6_USE_MIN_MTU
- , (const void *)&on, sizeof(on)) < 0)
- {
- log_errno((e, "setsockopt IPV6_USE_MIN_MTU in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
#endif
-#if defined(linux) && defined(KERNEL26_SUPPORT)
- if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)
- {
- struct sadb_x_policy policy;
- int level, opt;
-
- policy.sadb_x_policy_len = sizeof(policy) / IPSEC_PFKEYv2_ALIGN;
- policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
- policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
- policy.sadb_x_policy_reserved = 0;
- policy.sadb_x_policy_id = 0;
- policy.sadb_x_policy_reserved2 = 0;
-
- if (addrtypeof(&ifp->addr) == AF_INET6)
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
{
- level = IPPROTO_IPV6;
- opt = IPV6_IPSEC_POLICY;
+ log_errno((e, "fcntl(,, FD_CLOEXEC) in process_raw_ifaces()"));
+ close(fd);
+ return -1;
}
- else
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR
+ , (const void *)&on, sizeof(on)) < 0)
{
- level = IPPROTO_IP;
- opt = IP_IPSEC_POLICY;
+ log_errno((e, "setsockopt SO_REUSEADDR in process_raw_ifaces()"));
+ close(fd);
+ return -1;
}
- if (setsockopt(fd, level, opt
- , &policy, sizeof(policy)) < 0)
+ /* To improve error reporting. See ip(7). */
+#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
+ if (setsockopt(fd, SOL_IP, IP_RECVERR
+ , (const void *)&on, sizeof(on)) < 0)
{
- log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));
- close(fd);
- return -1;
+ log_errno((e, "setsockopt IP_RECVERR in process_raw_ifaces()"));
+ close(fd);
+ return -1;
}
+#endif
- policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
+ /* With IPv6, there is no fragmentation after
+ * it leaves our interface. PMTU discovery
+ * is mandatory but doesn't work well with IKE (why?).
+ * So we must set the IPV6_USE_MIN_MTU option.
+ * See draft-ietf-ipngwg-rfc2292bis-01.txt 11.1
+ */
+#ifdef IPV6_USE_MIN_MTU /* YUCK: not always defined */
+ if (addrtypeof(&ifp->addr) == AF_INET6
+ && setsockopt(fd, SOL_SOCKET, IPV6_USE_MIN_MTU
+ , (const void *)&on, sizeof(on)) < 0)
+ {
+ log_errno((e, "setsockopt IPV6_USE_MIN_MTU in process_raw_ifaces()"));
+ close(fd);
+ return -1;
+ }
+#endif
- if (setsockopt(fd, level, opt
- , &policy, sizeof(policy)) < 0)
+#if defined(linux) && defined(KERNEL26_SUPPORT)
+ if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)
{
- log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));
- close(fd);
- return -1;
+ struct sadb_x_policy policy;
+ int level, opt;
+
+ policy.sadb_x_policy_len = sizeof(policy) / IPSEC_PFKEYv2_ALIGN;
+ policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
+ policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+ policy.sadb_x_policy_reserved = 0;
+ policy.sadb_x_policy_id = 0;
+ policy.sadb_x_policy_reserved2 = 0;
+
+ if (addrtypeof(&ifp->addr) == AF_INET6)
+ {
+ level = IPPROTO_IPV6;
+ opt = IPV6_IPSEC_POLICY;
+ }
+ else
+ {
+ level = IPPROTO_IP;
+ opt = IP_IPSEC_POLICY;
+ }
+
+ if (setsockopt(fd, level, opt
+ , &policy, sizeof(policy)) < 0)
+ {
+ log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));
+ close(fd);
+ return -1;
+ }
+
+ policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
+
+ if (setsockopt(fd, level, opt
+ , &policy, sizeof(policy)) < 0)
+ {
+ log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));
+ close(fd);
+ return -1;
+ }
}
- }
#endif
- setportof(htons(port), &ifp->addr);
- if (bind(fd, sockaddrof(&ifp->addr), sockaddrlenof(&ifp->addr)) < 0)
- {
- log_errno((e, "bind() for %s/%s %s:%u in process_raw_ifaces()"
- , ifp->name, v_name
- , ip_str(&ifp->addr), (unsigned) port));
- close(fd);
- return -1;
- }
- setportof(htons(pluto_port), &ifp->addr);
- return fd;
+ setportof(htons(port), &ifp->addr);
+ if (bind(fd, sockaddrof(&ifp->addr), sockaddrlenof(&ifp->addr)) < 0)
+ {
+ log_errno((e, "bind() for %s/%s %s:%u in process_raw_ifaces()"
+ , ifp->name, v_name
+ , ip_str(&ifp->addr), (unsigned) port));
+ close(fd);
+ return -1;
+ }
+ setportof(htons(pluto_port), &ifp->addr);
+ return fd;
}
#endif
static void
process_raw_ifaces(struct raw_iface *rifaces)
{
- struct raw_iface *ifp;
-
- /* Find all virtual/real interface pairs.
- * For each real interface...
- */
- for (ifp = rifaces; ifp != NULL; ifp = ifp->next)
- {
- struct raw_iface *v = NULL; /* matching ipsecX interface */
- struct raw_iface fake_v;
- bool after = FALSE; /* has vfp passed ifp on the list? */
- bool bad = FALSE;
- struct raw_iface *vfp;
-
- /* ignore if virtual (ipsec*) interface */
- if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0)
- continue;
-
- for (vfp = rifaces; vfp != NULL; vfp = vfp->next)
+ struct raw_iface *ifp;
+
+ /* Find all virtual/real interface pairs.
+ * For each real interface...
+ */
+ for (ifp = rifaces; ifp != NULL; ifp = ifp->next)
{
- if (vfp == ifp)
- {
- after = TRUE;
- }
- else if (sameaddr(&ifp->addr, &vfp->addr))
- {
- /* Different entries with matching IP addresses.
- * Many interesting cases.
- */
- if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0)
+ struct raw_iface *v = NULL; /* matching ipsecX interface */
+ struct raw_iface fake_v;
+ bool after = FALSE; /* has vfp passed ifp on the list? */
+ bool bad = FALSE;
+ struct raw_iface *vfp;
+
+ /* ignore if virtual (ipsec*) interface */
+ if (strneq(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1))
{
- if (v != NULL && !streq(v->name, vfp->name))
- {
- loglog(RC_LOG_SERIOUS
- , "ipsec interfaces %s and %s share same address %s"
- , v->name, vfp->name, ip_str(&ifp->addr));
- bad = TRUE;
- }
- else
- {
- v = vfp; /* current winner */
- }
+ continue;
}
- else
+
+ for (vfp = rifaces; vfp != NULL; vfp = vfp->next)
{
- /* ugh: a second real interface with the same IP address
- * "after" allows us to avoid double reporting.
- */
-#if defined(linux) && defined(KERNEL26_SUPPORT)
- if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)
- {
- if (after)
+ if (vfp == ifp)
{
- bad = TRUE;
- break;
+ after = TRUE;
}
- continue;
- }
+ else if (sameaddr(&ifp->addr, &vfp->addr))
+ {
+ /* Different entries with matching IP addresses.
+ * Many interesting cases.
+ */
+ if (strneq(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1))
+ {
+ if (v != NULL && !streq(v->name, vfp->name))
+ {
+ loglog(RC_LOG_SERIOUS
+ , "ipsec interfaces %s and %s share same address %s"
+ , v->name, vfp->name, ip_str(&ifp->addr));
+ bad = TRUE;
+ }
+ else
+ {
+ v = vfp; /* current winner */
+ }
+ }
+ else
+ {
+ /* ugh: a second real interface with the same IP address
+ * "after" allows us to avoid double reporting.
+ */
+#if defined(linux) && defined(KERNEL26_SUPPORT)
+ if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)
+ {
+ if (after)
+ {
+ bad = TRUE;
+ break;
+ }
+ continue;
+ }
#endif
- if (after)
- {
- loglog(RC_LOG_SERIOUS
- , "IP interfaces %s and %s share address %s!"
- , ifp->name, vfp->name, ip_str(&ifp->addr));
- }
- bad = TRUE;
+ if (after)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "IP interfaces %s and %s share address %s!"
+ , ifp->name, vfp->name, ip_str(&ifp->addr));
+ }
+ bad = TRUE;
+ }
+ }
}
- }
- }
- if (bad)
- continue;
+ if (bad)
+ continue;
#if defined(linux) && defined(KERNEL26_SUPPORT)
- if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)
- {
- v = ifp;
- goto add_entry;
- }
+ if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)
+ {
+ v = ifp;
+ goto add_entry;
+ }
#endif
- /* what if we didn't find a virtual interface? */
- if (v == NULL)
- {
- if (no_klips)
- {
- /* kludge for testing: invent a virtual device */
- static const char fvp[] = "virtual";
- fake_v = *ifp;
- passert(sizeof(fake_v.name) > sizeof(fvp));
- strcpy(fake_v.name, fvp);
- addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1
- , sizeof(fake_v.name) - (sizeof(fvp) - 1));
- v = &fake_v;
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored"
- , ifp->name, ip_str(&ifp->addr)));
- continue;
- }
- }
+ /* what if we didn't find a virtual interface? */
+ if (v == NULL)
+ {
+ if (no_klips)
+ {
+ /* kludge for testing: invent a virtual device */
+ static const char fvp[] = "virtual";
+ fake_v = *ifp;
+ passert(sizeof(fake_v.name) > sizeof(fvp));
+ strcpy(fake_v.name, fvp);
+ addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1
+ , sizeof(fake_v.name) - (sizeof(fvp) - 1));
+ v = &fake_v;
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored"
+ , ifp->name, ip_str(&ifp->addr)));
+ continue;
+ }
+ }
- /* We've got all we need; see if this is a new thing:
- * search old interfaces list.
- */
+ /* We've got all we need; see if this is a new thing:
+ * search old interfaces list.
+ */
#if defined(linux) && defined(KERNEL26_SUPPORT)
add_entry:
#endif
- {
- struct iface **p = &interfaces;
-
- for (;;)
- {
- struct iface *q = *p;
-
- /* search is over if at end of list */
- if (q == NULL)
{
- /* matches nothing -- create a new entry */
- int fd = create_socket(ifp, v->name, pluto_port);
-
- if (fd < 0)
- break;
-
- if (nat_traversal_support_non_ike
- && addrtypeof(&ifp->addr) == AF_INET)
- {
- nat_traversal_espinudp_socket(fd, ESPINUDP_WITH_NON_IKE);
- }
-
- q = alloc_thing(struct iface, "struct iface");
- q->rname = clone_str(ifp->name, "real device name");
- q->vname = clone_str(v->name, "virtual device name");
- q->addr = ifp->addr;
- q->fd = fd;
- q->next = interfaces;
- q->change = IFN_ADD;
- interfaces = q;
- plog("adding interface %s/%s %s:%d"
- , q->vname, q->rname, ip_str(&q->addr), pluto_port);
-
- if (nat_traversal_support_port_floating
- && addrtypeof(&ifp->addr) == AF_INET)
- {
- fd = create_socket(ifp, v->name, NAT_T_IKE_FLOAT_PORT);
- if (fd < 0)
- break;
- nat_traversal_espinudp_socket(fd,
- ESPINUDP_WITH_NON_ESP);
- q = alloc_thing(struct iface, "struct iface");
- q->rname = clone_str(ifp->name, "real device name");
- q->vname = clone_str(v->name, "virtual device name");
- q->addr = ifp->addr;
- setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->addr);
- q->fd = fd;
- q->next = interfaces;
- q->change = IFN_ADD;
- q->ike_float = TRUE;
- interfaces = q;
- plog("adding interface %s/%s %s:%d",
- q->vname, q->rname, ip_str(&q->addr), NAT_T_IKE_FLOAT_PORT);
- }
- break;
- }
+ struct iface **p = &interfaces;
- /* search over if matching old entry found */
- if (streq(q->rname, ifp->name)
- && streq(q->vname, v->name)
- && sameaddr(&q->addr, &ifp->addr))
- {
- /* matches -- rejuvinate old entry */
- q->change = IFN_KEEP;
-
- /* look for other interfaces to keep (due to NAT-T) */
- for (q = q->next ; q ; q = q->next)
- {
- if (streq(q->rname, ifp->name)
- && streq(q->vname, v->name)
- && sameaddr(&q->addr, &ifp->addr))
+ for (;;)
{
- q->change = IFN_KEEP;
- }
- }
- break;
+ struct iface *q = *p;
+
+ /* search is over if at end of list */
+ if (q == NULL)
+ {
+ /* matches nothing -- create a new entry */
+ int fd = create_socket(ifp, v->name, pluto_port);
+
+ if (fd < 0)
+ break;
+
+ if (nat_traversal_support_non_ike
+ && addrtypeof(&ifp->addr) == AF_INET)
+ {
+ nat_traversal_espinudp_socket(fd, ESPINUDP_WITH_NON_IKE);
+ }
+
+ q = malloc_thing(struct iface);
+ zero(q);
+ q->rname = clone_str(ifp->name);
+ q->vname = clone_str(v->name);
+ q->addr = ifp->addr;
+ q->fd = fd;
+ q->next = interfaces;
+ q->change = IFN_ADD;
+ interfaces = q;
+ plog("adding interface %s/%s %s:%d"
+ , q->vname, q->rname, ip_str(&q->addr), pluto_port);
+
+ if (nat_traversal_support_port_floating
+ && addrtypeof(&ifp->addr) == AF_INET)
+ {
+ fd = create_socket(ifp, v->name, NAT_T_IKE_FLOAT_PORT);
+ if (fd < 0)
+ break;
+ nat_traversal_espinudp_socket(fd,
+ ESPINUDP_WITH_NON_ESP);
+ q = malloc_thing(struct iface);
+ zero(q);
+ q->rname = clone_str(ifp->name);
+ q->vname = clone_str(v->name);
+ q->addr = ifp->addr;
+ setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->addr);
+ q->fd = fd;
+ q->next = interfaces;
+ q->change = IFN_ADD;
+ q->ike_float = TRUE;
+ interfaces = q;
+ plog("adding interface %s/%s %s:%d",
+ q->vname, q->rname, ip_str(&q->addr), NAT_T_IKE_FLOAT_PORT);
+ }
+ break;
+ }
+
+ /* search over if matching old entry found */
+ if (streq(q->rname, ifp->name)
+ && streq(q->vname, v->name)
+ && sameaddr(&q->addr, &ifp->addr))
+ {
+ /* matches -- rejuvinate old entry */
+ q->change = IFN_KEEP;
+
+ /* look for other interfaces to keep (due to NAT-T) */
+ for (q = q->next ; q ; q = q->next)
+ {
+ if (streq(q->rname, ifp->name)
+ && streq(q->vname, v->name)
+ && sameaddr(&q->addr, &ifp->addr))
+ {
+ q->change = IFN_KEEP;
+ }
+ }
+ break;
+ }
+
+ /* try again */
+ p = &q->next;
+ } /* for (;;) */
}
-
- /* try again */
- p = &q->next;
- } /* for (;;) */
}
- }
- /* delete the raw interfaces list */
- while (rifaces != NULL)
- {
- struct raw_iface *t = rifaces;
+ /* delete the raw interfaces list */
+ while (rifaces != NULL)
+ {
+ struct raw_iface *t = rifaces;
- rifaces = t->next;
- pfree(t);
- }
+ rifaces = t->next;
+ free(t);
+ }
}
void
find_ifaces(void)
{
- mark_ifaces_dead();
- process_raw_ifaces(find_raw_ifaces4());
- process_raw_ifaces(find_raw_ifaces6());
+ mark_ifaces_dead();
+ process_raw_ifaces(find_raw_ifaces4());
+ process_raw_ifaces(find_raw_ifaces6());
- free_dead_ifaces(); /* ditch remaining old entries */
+ free_dead_ifaces(); /* ditch remaining old entries */
- if (interfaces == NULL)
- loglog(RC_LOG_SERIOUS, "no public interfaces found");
+ if (interfaces == NULL)
+ loglog(RC_LOG_SERIOUS, "no public interfaces found");
}
void
show_ifaces_status(void)
{
- struct iface *p;
+ struct iface *p;
- for (p = interfaces; p != NULL; p = p->next)
- whack_log(RC_COMMENT, "interface %s/%s %s:%d"
- , p->vname, p->rname, ip_str(&p->addr), ntohs(portof(&p->addr)));
+ for (p = interfaces; p != NULL; p = p->next)
+ whack_log(RC_COMMENT, "interface %s/%s %s:%d"
+ , p->vname, p->rname, ip_str(&p->addr), ntohs(portof(&p->addr)));
}
void
show_debug_status(void)
{
#ifdef DEBUG
- whack_log(RC_COMMENT, "debug %s"
- , bitnamesof(debug_bit_names, cur_debugging));
+ whack_log(RC_COMMENT, "debug options: %s"
+ , bitnamesof(debug_bit_names, cur_debugging));
#endif
}
@@ -770,7 +772,7 @@ static volatile sig_atomic_t sighupflag = FALSE;
static void
huphandler(int sig UNUSED)
{
- sighupflag = TRUE;
+ sighupflag = TRUE;
}
static volatile sig_atomic_t sigtermflag = FALSE;
@@ -778,7 +780,7 @@ static volatile sig_atomic_t sigtermflag = FALSE;
static void
termhandler(int sig UNUSED)
{
- sigtermflag = TRUE;
+ sigtermflag = TRUE;
}
/* call_server listens for incoming ISAKMP packets and Whack messages,
@@ -787,206 +789,206 @@ termhandler(int sig UNUSED)
void
call_server(void)
{
- struct iface *ifp;
+ struct iface *ifp;
- /* catch SIGHUP and SIGTERM */
- {
- int r;
- struct sigaction act;
+ /* catch SIGHUP and SIGTERM */
+ {
+ int r;
+ struct sigaction act;
+
+ act.sa_handler = &huphandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0; /* no SA_ONESHOT, no SA_RESTART, no nothing */
+ r = sigaction(SIGHUP, &act, NULL);
+ passert(r == 0);
+
+ act.sa_handler = &termhandler;
+ r = sigaction(SIGTERM, &act, NULL);
+ passert(r == 0);
+ }
- act.sa_handler = &huphandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0; /* no SA_ONESHOT, no SA_RESTART, no nothing */
- r = sigaction(SIGHUP, &act, NULL);
- passert(r == 0);
+ for (;;)
+ {
+ fd_set readfds;
+ fd_set writefds;
+ int ndes;
- act.sa_handler = &termhandler;
- r = sigaction(SIGTERM, &act, NULL);
- passert(r == 0);
- }
+ /* wait for next interesting thing */
- for (;;)
- {
- fd_set readfds;
- fd_set writefds;
- int ndes;
+ for (;;)
+ {
+ long next_time = next_event(); /* time to any pending timer event */
+ int maxfd = ctl_fd;
- /* wait for next interesting thing */
+ if (sigtermflag)
+ exit_pluto(0);
- for (;;)
- {
- long next_time = next_event(); /* time to any pending timer event */
- int maxfd = ctl_fd;
-
- if (sigtermflag)
- exit_pluto(0);
-
- if (sighupflag)
- {
- /* Ignorant folks think poking any daemon with SIGHUP
- * is polite. We catch it and tell them otherwise.
- * There is one use: unsticking a hung recvfrom.
- * This sticking happens sometimes -- kernel bug?
- */
- sighupflag = FALSE;
- plog("Pluto ignores SIGHUP -- perhaps you want \"whack --listen\"");
- }
-
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_SET(ctl_fd, &readfds);
-
- /* the only write file-descriptor of interest */
- if (adns_qfd != NULL_FD && unsent_ADNS_queries)
- {
- if (maxfd < adns_qfd)
- maxfd = adns_qfd;
- FD_SET(adns_qfd, &writefds);
- }
-
- if (adns_afd != NULL_FD)
- {
- if (maxfd < adns_afd)
- maxfd = adns_afd;
- FD_SET(adns_afd, &readfds);
- }
+ if (sighupflag)
+ {
+ /* Ignorant folks think poking any daemon with SIGHUP
+ * is polite. We catch it and tell them otherwise.
+ * There is one use: unsticking a hung recvfrom.
+ * This sticking happens sometimes -- kernel bug?
+ */
+ sighupflag = FALSE;
+ plog("Pluto ignores SIGHUP -- perhaps you want \"whack --listen\"");
+ }
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_SET(ctl_fd, &readfds);
+
+ /* the only write file-descriptor of interest */
+ if (adns_qfd != NULL_FD && unsent_ADNS_queries)
+ {
+ if (maxfd < adns_qfd)
+ maxfd = adns_qfd;
+ FD_SET(adns_qfd, &writefds);
+ }
+
+ if (adns_afd != NULL_FD)
+ {
+ if (maxfd < adns_afd)
+ maxfd = adns_afd;
+ FD_SET(adns_afd, &readfds);
+ }
#ifdef KLIPS
- if (!no_klips)
- {
- int fd = *kernel_ops->async_fdp;
-
- if (kernel_ops->process_queue)
- kernel_ops->process_queue();
- if (maxfd < fd)
- maxfd = fd;
- passert(!FD_ISSET(fd, &readfds));
- FD_SET(fd, &readfds);
- }
+ if (!no_klips)
+ {
+ int fd = *kernel_ops->async_fdp;
+
+ if (kernel_ops->process_queue)
+ kernel_ops->process_queue();
+ if (maxfd < fd)
+ maxfd = fd;
+ passert(!FD_ISSET(fd, &readfds));
+ FD_SET(fd, &readfds);
+ }
#endif
- if (listening)
- {
- for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
- {
- if (maxfd < ifp->fd)
- maxfd = ifp->fd;
- passert(!FD_ISSET(ifp->fd, &readfds));
- FD_SET(ifp->fd, &readfds);
- }
- }
-
- if (next_time == -1)
- {
- /* select without timer */
-
- ndes = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
- }
- else if (next_time == 0)
- {
- /* timer without select: there is a timer event pending,
- * and it should fire now so don't bother to do the select.
- */
- ndes = 0; /* signify timer expiration */
- }
- else
- {
- /* select with timer */
+ if (listening)
+ {
+ for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
+ {
+ if (maxfd < ifp->fd)
+ maxfd = ifp->fd;
+ passert(!FD_ISSET(ifp->fd, &readfds));
+ FD_SET(ifp->fd, &readfds);
+ }
+ }
- struct timeval tm;
+ if (next_time == -1)
+ {
+ /* select without timer */
- tm.tv_sec = next_time;
- tm.tv_usec = 0;
- ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm);
- }
+ ndes = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
+ }
+ else if (next_time == 0)
+ {
+ /* timer without select: there is a timer event pending,
+ * and it should fire now so don't bother to do the select.
+ */
+ ndes = 0; /* signify timer expiration */
+ }
+ else
+ {
+ /* select with timer */
- if (ndes != -1)
- break; /* success */
+ struct timeval tm;
- if (errno != EINTR)
- exit_log_errno((e, "select() failed in call_server()"));
+ tm.tv_sec = next_time;
+ tm.tv_usec = 0;
+ ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm);
+ }
- /* retry if terminated by signal */
- }
+ if (ndes != -1)
+ break; /* success */
- /* figure out what is interesting */
+ if (errno != EINTR)
+ exit_log_errno((e, "select() failed in call_server()"));
- if (ndes == 0)
- {
- /* timer event */
+ /* retry if terminated by signal */
+ }
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*time to handle event"));
+ /* figure out what is interesting */
- handle_timer_event();
- passert(GLOBALS_ARE_RESET());
- }
- else
- {
- /* at least one file descriptor is ready */
-
- if (adns_qfd != NULL_FD && FD_ISSET(adns_qfd, &writefds))
- {
- passert(ndes > 0);
- send_unsent_ADNS_queries();
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
-
- if (adns_afd != NULL_FD && FD_ISSET(adns_afd, &readfds))
- {
- passert(ndes > 0);
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*received adns message"));
- handle_adns_answer();
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
+ if (ndes == 0)
+ {
+ /* timer event */
+
+ DBG(DBG_CONTROL,
+ DBG_log(BLANK_FORMAT);
+ DBG_log("*time to handle event"));
+
+ handle_timer_event();
+ passert(GLOBALS_ARE_RESET());
+ }
+ else
+ {
+ /* at least one file descriptor is ready */
+
+ if (adns_qfd != NULL_FD && FD_ISSET(adns_qfd, &writefds))
+ {
+ passert(ndes > 0);
+ send_unsent_ADNS_queries();
+ passert(GLOBALS_ARE_RESET());
+ ndes--;
+ }
+
+ if (adns_afd != NULL_FD && FD_ISSET(adns_afd, &readfds))
+ {
+ passert(ndes > 0);
+ DBG(DBG_CONTROL,
+ DBG_log(BLANK_FORMAT);
+ DBG_log("*received adns message"));
+ handle_adns_answer();
+ passert(GLOBALS_ARE_RESET());
+ ndes--;
+ }
#ifdef KLIPS
- if (!no_klips && FD_ISSET(*kernel_ops->async_fdp, &readfds))
- {
- passert(ndes > 0);
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*received kernel message"));
- kernel_ops->process_msg();
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
+ if (!no_klips && FD_ISSET(*kernel_ops->async_fdp, &readfds))
+ {
+ passert(ndes > 0);
+ DBG(DBG_CONTROL,
+ DBG_log(BLANK_FORMAT);
+ DBG_log("*received kernel message"));
+ kernel_ops->process_msg();
+ passert(GLOBALS_ARE_RESET());
+ ndes--;
+ }
#endif
- for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
- {
- if (FD_ISSET(ifp->fd, &readfds))
- {
- /* comm_handle will print DBG_CONTROL intro,
- * with more info than we have here.
- */
-
- passert(ndes > 0);
- comm_handle(ifp);
- passert(GLOBALS_ARE_RESET());
- ndes--;
+ for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
+ {
+ if (FD_ISSET(ifp->fd, &readfds))
+ {
+ /* comm_handle will print DBG_CONTROL intro,
+ * with more info than we have here.
+ */
+
+ passert(ndes > 0);
+ comm_handle(ifp);
+ passert(GLOBALS_ARE_RESET());
+ ndes--;
+ }
+ }
+
+ if (FD_ISSET(ctl_fd, &readfds))
+ {
+ passert(ndes > 0);
+ DBG(DBG_CONTROL,
+ DBG_log(BLANK_FORMAT);
+ DBG_log("*received whack message"));
+ whack_handle(ctl_fd);
+ passert(GLOBALS_ARE_RESET());
+ ndes--;
+ }
+
+ passert(ndes == 0);
}
- }
-
- if (FD_ISSET(ctl_fd, &readfds))
- {
- passert(ndes > 0);
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*received whack message"));
- whack_handle(ctl_fd);
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
-
- passert(ndes == 0);
}
- }
}
/*
diff --git a/src/pluto/server.h b/src/pluto/server.h
index d0d46a5f4..b8123f6dc 100644
--- a/src/pluto/server.h
+++ b/src/pluto/server.h
@@ -10,20 +10,18 @@
* 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: server.h 3252 2007-10-06 21:24:50Z andreas $
*/
-extern int ctl_fd; /* file descriptor of control (whack) socket */
-extern struct sockaddr_un ctl_addr; /* address of control (whack) socket */
+extern int ctl_fd; /* file descriptor of control (whack) socket */
+extern struct sockaddr_un ctl_addr; /* address of control (whack) socket */
-extern int info_fd; /* file descriptor of control (info) socket */
-extern struct sockaddr_un info_addr; /* address of control (info) socket */
+extern int info_fd; /* file descriptor of control (info) socket */
+extern struct sockaddr_un info_addr; /* address of control (info) socket */
extern err_t init_ctl_socket(void);
extern void delete_ctl_socket(void);
-extern bool listening; /* should we pay attention to IKE messages? */
+extern bool listening; /* should we pay attention to IKE messages? */
/* interface: a terminal point for IKE traffic, IPsec transport mode
@@ -35,16 +33,16 @@ extern bool listening; /* should we pay attention to IKE messages? */
* Note: the port for IKE is always implicitly UDP/pluto_port.
*/
struct iface {
- char *vname; /* virtual (ipsec) device name */
- char *rname; /* real device name */
- ip_address addr; /* interface IP address */
- int fd; /* file descriptor of socket for IKE UDP messages */
- struct iface *next;
- bool ike_float;
- enum { IFN_ADD, IFN_KEEP, IFN_DELETE } change;
+ char *vname; /* virtual (ipsec) device name */
+ char *rname; /* real device name */
+ ip_address addr; /* interface IP address */
+ int fd; /* file descriptor of socket for IKE UDP messages */
+ struct iface *next;
+ bool ike_float;
+ enum { IFN_ADD, IFN_KEEP, IFN_DELETE } change;
};
-extern struct iface *interfaces; /* public interfaces */
+extern struct iface *interfaces; /* public interfaces */
extern bool use_interface(const char *rifn);
extern void find_ifaces(void);
diff --git a/src/pluto/sha1.c b/src/pluto/sha1.c
deleted file mode 100644
index bbf062876..000000000
--- a/src/pluto/sha1.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
-SHA-1 in C
-By Steve Reid <steve@edmweb.com>
-100% Public Domain
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
-/* #define SHA1HANDSOFF * Copies data before messing with it. */
-
-#define SHA1HANDSOFF
-
-#include <string.h>
-#include <sys/types.h> /* for u_int*_t */
-#include <endian.h> /* sets BYTE_ORDER, LITTLE_ENDIAN, and BIG_ENDIAN */
-
-#include "sha1.h"
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
- |(rol(block->l[i],8)&0x00FF00FF))
-#elif BYTE_ORDER == BIG_ENDIAN
-#define blk0(i) block->l[i]
-#else
-#error "Endianness not defined!"
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
- ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
-{
-u_int32_t a, b, c, d, e;
-typedef union {
- unsigned char c[64];
- u_int32_t l[16];
-} CHAR64LONG16;
-#ifdef SHA1HANDSOFF
-CHAR64LONG16 block[1]; /* use array to appear as a pointer */
- memcpy(block, buffer, 64);
-#else
- /* The following had better never be used because it causes the
- * pointer-to-const buffer to be cast into a pointer to non-const.
- * And the result is written through. I threw a "const" in, hoping
- * this will cause a diagnostic.
- */
-CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
-#endif
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- /* Wipe variables */
- a = b = c = d = e = 0;
-#ifdef SHA1HANDSOFF
- memset(block, '\0', sizeof(block));
-#endif
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len)
-{
-u_int32_t i;
-u_int32_t j;
-
- j = context->count[0];
- if ((context->count[0] += len << 3) < j)
- context->count[1]++;
- context->count[1] += (len>>29);
- j = (j >> 3) & 63;
- if ((j + len) > 63) {
- memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64) {
- SHA1Transform(context->state, &data[i]);
- }
- j = 0;
- }
- else i = 0;
- memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
-{
-unsigned i;
-unsigned char finalcount[8];
-unsigned char c;
-
-#if 0 /* untested "improvement" by DHR */
- /* Convert context->count to a sequence of bytes
- * in finalcount. Second element first, but
- * big-endian order within element.
- * But we do it all backwards.
- */
- unsigned char *fcp = &finalcount[8];
-
- for (i = 0; i < 2; i++)
- {
- u_int32_t t = context->count[i];
- int j;
-
- for (j = 0; j < 4; t >>= 8, j++)
- *--fcp = (unsigned char) t
- }
-#else
- for (i = 0; i < 8; i++) {
- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
-#endif
- c = 0200;
- SHA1Update(context, &c, 1);
- while ((context->count[0] & 504) != 448) {
- c = 0000;
- SHA1Update(context, &c, 1);
- }
- SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
- for (i = 0; i < 20; i++) {
- digest[i] = (unsigned char)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- /* Wipe variables */
- memset(context, '\0', sizeof(*context));
- memset(&finalcount, '\0', sizeof(finalcount));
-}
diff --git a/src/pluto/sha1.h b/src/pluto/sha1.h
deleted file mode 100644
index 64b3d2f5d..000000000
--- a/src/pluto/sha1.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
-SHA-1 in C
-By Steve Reid <steve@edmweb.com>
-100% Public Domain
-*/
-
-typedef struct {
- u_int32_t state[5];
- u_int32_t count[2];
- unsigned char buffer[64];
-} SHA1_CTX;
-
-void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]);
-void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len);
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
diff --git a/src/pluto/smallprime.c b/src/pluto/smallprime.c
deleted file mode 100644
index 87497d096..000000000
--- a/src/pluto/smallprime.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* smallprime.c - List of small primes
- * 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 "gcryptfix.h"
-#else
-/* #include <config.h> */
-/* #include <stdio.h> */
-/* #include <stdlib.h> */
-/* #include "util.h" */
-/* #include "types.h" */
-#endif
-
-/* Note: 2 is not included because it can be tested more easily
- * by looking at bit 0. The last entry in this list is marked by a zero
- */
-ushort
-small_prime_numbers[] = {
- 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
- 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
- 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
- 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
- 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
- 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
- 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
- 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
- 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
- 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
- 587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
- 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
- 709, 719, 727, 733, 739, 743, 751, 757, 761, 769,
- 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
- 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
- 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
- 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
- 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
- 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
- 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
- 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277,
- 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307,
- 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
- 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
- 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
- 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
- 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
- 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
- 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
- 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,
- 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
- 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
- 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,
- 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
- 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111,
- 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161,
- 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243,
- 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
- 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
- 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411,
- 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473,
- 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
- 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633,
- 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
- 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729,
- 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
- 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851,
- 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917,
- 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
- 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061,
- 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137,
- 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209,
- 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
- 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
- 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391,
- 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467,
- 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533,
- 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583,
- 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
- 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
- 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779,
- 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
- 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917,
- 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
- 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049,
- 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111,
- 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
- 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243,
- 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
- 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391,
- 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
- 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519,
- 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597,
- 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
- 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
- 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799,
- 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
- 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951,
- 4957, 4967, 4969, 4973, 4987, 4993, 4999,
- 0
-};
-
-
diff --git a/src/pluto/smartcard.c b/src/pluto/smartcard.c
index 937c3f93a..7e4452d89 100644
--- a/src/pluto/smartcard.c
+++ b/src/pluto/smartcard.c
@@ -6,7 +6,7 @@
* Copyright (C) 2005 Michael Joosten
*
* Copyright (C) 2005 Andreas Steffen
- * Hochschule für Technik Rapperswil, Switzerland
+ * Hochschule fuer Technik Rapperswil, Switzerland
*
* 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
@@ -17,8 +17,6 @@
* 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: smartcard.c 3686 2008-03-28 11:48:14Z martin $
*/
#include <stdio.h>
@@ -30,7 +28,9 @@
#include <dlfcn.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <asn1/asn1.h>
+#include <credentials/keys/public_key.h>
#include "constants.h"
@@ -40,7 +40,6 @@
#endif
#include "defs.h"
-#include "mp_defs.h"
#include "log.h"
#include "x509.h"
#include "ca.h"
@@ -50,7 +49,7 @@
#include "whack.h"
#include "fetch.h"
-#define DEFAULT_BASE 16
+#define DEFAULT_BASE 16
/* chained list of smartcard records */
static smartcard_t *smartcards = NULL;
@@ -59,30 +58,30 @@ static smartcard_t *smartcards = NULL;
static int sc_number = 0;
const smartcard_t empty_sc = {
- NULL , /* next */
- 0 , /* last_load */
- { CERT_NONE, {NULL} }, /* last_cert */
- 0 , /* count */
- 0 , /* number */
- 999999 , /* slot */
- NULL , /* id */
- NULL , /* label */
- { NULL, 0 } , /* pin */
- FALSE , /* pinpad */
- FALSE , /* valid */
- FALSE , /* session_opened */
- FALSE , /* logged_in */
- TRUE , /* any_slot */
- 0L , /* session */
+ NULL , /* next */
+ 0 , /* last_load */
+ { CERT_NONE, {NULL} }, /* last_cert */
+ 0 , /* count */
+ 0 , /* number */
+ 999999 , /* slot */
+ NULL , /* id */
+ NULL , /* label */
+ { NULL, 0 } , /* pin */
+ FALSE , /* pinpad */
+ FALSE , /* valid */
+ FALSE , /* session_opened */
+ FALSE , /* logged_in */
+ TRUE , /* any_slot */
+ 0L , /* session */
};
-#ifdef SMARTCARD /* compile with smartcard support */
+#ifdef SMARTCARD /* compile with smartcard support */
-#define SCX_MAGIC 0xd00bed00
+#define SCX_MAGIC 0xd00bed00
struct scx_pkcs11_module {
- u_int _magic;
- void *handle;
+ u_int _magic;
+ void *handle;
};
typedef struct scx_pkcs11_module scx_pkcs11_module_t;
@@ -95,292 +94,292 @@ static CK_FUNCTION_LIST_PTR pkcs11_functions = NULL_PTR;
/* crytoki v2.11 - return values of PKCS #11 functions*/
static const char *const pkcs11_return_name[] = {
- "CKR_OK",
- "CKR_CANCEL",
- "CKR_HOST_MEMORY",
- "CKR_SLOT_ID_INVALID",
- "CKR_FLAGS_INVALID",
- "CKR_GENERAL_ERROR",
- "CKR_FUNCTION_FAILED",
- "CKR_ARGUMENTS_BAD",
- "CKR_NO_EVENT",
- "CKR_NEED_TO_CREATE_THREADS",
- "CKR_CANT_LOCK"
- };
+ "CKR_OK",
+ "CKR_CANCEL",
+ "CKR_HOST_MEMORY",
+ "CKR_SLOT_ID_INVALID",
+ "CKR_FLAGS_INVALID",
+ "CKR_GENERAL_ERROR",
+ "CKR_FUNCTION_FAILED",
+ "CKR_ARGUMENTS_BAD",
+ "CKR_NO_EVENT",
+ "CKR_NEED_TO_CREATE_THREADS",
+ "CKR_CANT_LOCK"
+ };
static const char *const pkcs11_return_name_10[] = {
- "CKR_ATTRIBUTE_READ_ONLY",
- "CKR_ATTRIBUTE_SENSITIVE",
- "CKR_ATTRIBUTE_TYPE_INVALID",
- "CKR_ATTRIBUTE_VALUE_INVALID"
- };
+ "CKR_ATTRIBUTE_READ_ONLY",
+ "CKR_ATTRIBUTE_SENSITIVE",
+ "CKR_ATTRIBUTE_TYPE_INVALID",
+ "CKR_ATTRIBUTE_VALUE_INVALID"
+ };
static const char *const pkcs11_return_name_20[] = {
- "CKR_DATA_INVALID",
- "CKR_DATA_LEN_RANGE"
- };
+ "CKR_DATA_INVALID",
+ "CKR_DATA_LEN_RANGE"
+ };
static const char *const pkcs11_return_name_30[] = {
- "CKR_DEVICE_ERROR",
- "CKR_DEVICE_MEMORY",
- "CKR_DEVICE_REMOVED"
- };
+ "CKR_DEVICE_ERROR",
+ "CKR_DEVICE_MEMORY",
+ "CKR_DEVICE_REMOVED"
+ };
static const char *const pkcs11_return_name_40[] = {
- "CKR_ENCRYPTED_DATA_INVALID",
- "CKR_ENCRYPTED_DATA_LEN_RANGE"
- };
+ "CKR_ENCRYPTED_DATA_INVALID",
+ "CKR_ENCRYPTED_DATA_LEN_RANGE"
+ };
static const char *const pkcs11_return_name_50[] = {
- "CKR_FUNCTION_CANCELED",
- "CKR_FUNCTION_NOT_PARALLEL",
- "CKR_0x52_UNDEFINED",
- "CKR_0x53_UNDEFINED",
- "CKR_FUNCTION_NOT_SUPPORTED"
- };
+ "CKR_FUNCTION_CANCELED",
+ "CKR_FUNCTION_NOT_PARALLEL",
+ "CKR_0x52_UNDEFINED",
+ "CKR_0x53_UNDEFINED",
+ "CKR_FUNCTION_NOT_SUPPORTED"
+ };
static const char *const pkcs11_return_name_60[] = {
- "CKR_KEY_HANDLE_INVALID",
- "CKR_KEY_SENSITIVE",
- "CKR_KEY_SIZE_RANGE",
- "CKR_KEY_TYPE_INCONSISTENT",
- "CKR_KEY_NOT_NEEDED",
- "CKR_KEY_CHANGED",
- "CKR_KEY_NEEDED",
- "CKR_KEY_INDIGESTIBLE",
- "CKR_KEY_FUNCTION_NOT_PERMITTED",
- "CKR_KEY_NOT_WRAPPABLE",
- "CKR_KEY_UNEXTRACTABLE"
- };
+ "CKR_KEY_HANDLE_INVALID",
+ "CKR_KEY_SENSITIVE",
+ "CKR_KEY_SIZE_RANGE",
+ "CKR_KEY_TYPE_INCONSISTENT",
+ "CKR_KEY_NOT_NEEDED",
+ "CKR_KEY_CHANGED",
+ "CKR_KEY_NEEDED",
+ "CKR_KEY_INDIGESTIBLE",
+ "CKR_KEY_FUNCTION_NOT_PERMITTED",
+ "CKR_KEY_NOT_WRAPPABLE",
+ "CKR_KEY_UNEXTRACTABLE"
+ };
static const char *const pkcs11_return_name_70[] = {
- "CKR_MECHANISM_INVALID",
- "CKR_MECHANISM_PARAM_INVALID"
- };
+ "CKR_MECHANISM_INVALID",
+ "CKR_MECHANISM_PARAM_INVALID"
+ };
static const char *const pkcs11_return_name_80[] = {
- "CKR_OBJECT_HANDLE_INVALID"
- };
+ "CKR_OBJECT_HANDLE_INVALID"
+ };
static const char *const pkcs11_return_name_90[] = {
- "CKR_OPERATION_ACTIVE",
- "CKR_OPERATION_NOT_INITIALIZED"
- };
+ "CKR_OPERATION_ACTIVE",
+ "CKR_OPERATION_NOT_INITIALIZED"
+ };
static const char *const pkcs11_return_name_A0[] = {
- "CKR_PIN_INCORRECT",
- "CKR_PIN_INVALID",
- "CKR_PIN_LEN_RANGE",
- "CKR_PIN_EXPIRED",
- "CKR_PIN_LOCKED"
- };
+ "CKR_PIN_INCORRECT",
+ "CKR_PIN_INVALID",
+ "CKR_PIN_LEN_RANGE",
+ "CKR_PIN_EXPIRED",
+ "CKR_PIN_LOCKED"
+ };
static const char *const pkcs11_return_name_B0[] = {
- "CKR_SESSION_CLOSED",
- "CKR_SESSION_COUNT",
- "CKR_0xB2_UNDEFINED",
- "CKR_SESSION_HANDLE_INVALID",
- "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
- "CKR_SESSION_READ_ONLY",
- "CKR_SESSION_EXISTS",
- "CKR_SESSION_READ_ONLY_EXISTS",
- "CKR_SESSION_READ_WRITE_SO_EXISTS"
- };
+ "CKR_SESSION_CLOSED",
+ "CKR_SESSION_COUNT",
+ "CKR_0xB2_UNDEFINED",
+ "CKR_SESSION_HANDLE_INVALID",
+ "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
+ "CKR_SESSION_READ_ONLY",
+ "CKR_SESSION_EXISTS",
+ "CKR_SESSION_READ_ONLY_EXISTS",
+ "CKR_SESSION_READ_WRITE_SO_EXISTS"
+ };
static const char *const pkcs11_return_name_C0[] = {
- "CKR_SIGNATURE_INVALID",
- "CKR_SIGNATURE_LEN_RANGE"
- };
+ "CKR_SIGNATURE_INVALID",
+ "CKR_SIGNATURE_LEN_RANGE"
+ };
static const char *const pkcs11_return_name_D0[] = {
- "CKR_TEMPLATE_INCOMPLETE",
- "CKR_TEMPLATE_INCONSISTENT"
- };
+ "CKR_TEMPLATE_INCOMPLETE",
+ "CKR_TEMPLATE_INCONSISTENT"
+ };
static const char *const pkcs11_return_name_E0[] = {
- "CKR_TOKEN_NOT_PRESENT",
- "CKR_TOKEN_NOT_RECOGNIZED",
- "CKR_TOKEN_WRITE_PROTECTED"
- };
+ "CKR_TOKEN_NOT_PRESENT",
+ "CKR_TOKEN_NOT_RECOGNIZED",
+ "CKR_TOKEN_WRITE_PROTECTED"
+ };
static const char *const pkcs11_return_name_F0[] = {
- "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
- "CKR_UNWRAPPING_KEY_SIZE_RANGE",
- "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"
- };
+ "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
+ "CKR_UNWRAPPING_KEY_SIZE_RANGE",
+ "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"
+ };
static const char *const pkcs11_return_name_100[] = {
- "CKR_USER_ALREADY_LOGGED_IN",
- "CKR_USER_NOT_LOGGED_IN",
- "CKR_USER_PIN_NOT_INITIALIZED",
- "CKR_USER_TYPE_INVALID",
- "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
- "CKR_USER_TOO_MANY_TYPES"
- };
+ "CKR_USER_ALREADY_LOGGED_IN",
+ "CKR_USER_NOT_LOGGED_IN",
+ "CKR_USER_PIN_NOT_INITIALIZED",
+ "CKR_USER_TYPE_INVALID",
+ "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
+ "CKR_USER_TOO_MANY_TYPES"
+ };
static const char *const pkcs11_return_name_110[] = {
- "CKR_WRAPPED_KEY_INVALID",
- "CKR_0x111_UNDEFINED",
- "CKR_WRAPPED_KEY_LEN_RANGE",
- "CKR_WRAPPING_KEY_HANDLE_INVALID",
- "CKR_WRAPPING_KEY_SIZE_RANGE",
- "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"
- };
+ "CKR_WRAPPED_KEY_INVALID",
+ "CKR_0x111_UNDEFINED",
+ "CKR_WRAPPED_KEY_LEN_RANGE",
+ "CKR_WRAPPING_KEY_HANDLE_INVALID",
+ "CKR_WRAPPING_KEY_SIZE_RANGE",
+ "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"
+ };
static const char *const pkcs11_return_name_120[] = {
- "CKR_RANDOM_SEED_NOT_SUPPORTED",
- "CKR_RANDOM_NO_RNG"
- };
+ "CKR_RANDOM_SEED_NOT_SUPPORTED",
+ "CKR_RANDOM_NO_RNG"
+ };
static const char *const pkcs11_return_name_130[] = {
- "CKR_DOMAIN_PARAMS_INVALID"
- };
+ "CKR_DOMAIN_PARAMS_INVALID"
+ };
static const char *const pkcs11_return_name_150[] = {
- "CKR_BUFFER_TOO_SMALL"
- };
+ "CKR_BUFFER_TOO_SMALL"
+ };
static const char *const pkcs11_return_name_160[] = {
- "CKR_SAVED_STATE_INVALID"
- };
+ "CKR_SAVED_STATE_INVALID"
+ };
static const char *const pkcs11_return_name_170[] = {
- "CKR_INFORMATION_SENSITIVE"
- };
+ "CKR_INFORMATION_SENSITIVE"
+ };
static const char *const pkcs11_return_name_180[] = {
- "CKR_STATE_UNSAVEABLE"
- };
+ "CKR_STATE_UNSAVEABLE"
+ };
static const char *const pkcs11_return_name_190[] = {
- "CKR_CRYPTOKI_NOT_INITIALIZED",
- "CKR_CRYPTOKI_ALREADY_INITIALIZED"
- };
+ "CKR_CRYPTOKI_NOT_INITIALIZED",
+ "CKR_CRYPTOKI_ALREADY_INITIALIZED"
+ };
static const char *const pkcs11_return_name_1A0[] = {
- "CKR_MUTEX_BAD",
- "CKR_MUTEX_NOT_LOCKED"
- };
+ "CKR_MUTEX_BAD",
+ "CKR_MUTEX_NOT_LOCKED"
+ };
static const char *const pkcs11_return_name_200[] = {
- "CKR_FUNCTION_REJECTED"
- };
+ "CKR_FUNCTION_REJECTED"
+ };
static const char *const pkcs11_return_name_vendor[] = {
- "CKR_VENDOR_DEFINED"
- };
+ "CKR_VENDOR_DEFINED"
+ };
static enum_names pkcs11_return_names_vendor =
- { CKR_VENDOR_DEFINED, CKR_VENDOR_DEFINED
- , pkcs11_return_name_vendor, NULL };
+ { CKR_VENDOR_DEFINED, CKR_VENDOR_DEFINED
+ , pkcs11_return_name_vendor, NULL };
static enum_names pkcs11_return_names_200 =
- { CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED
- , pkcs11_return_name_200, &pkcs11_return_names_vendor };
+ { CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED
+ , pkcs11_return_name_200, &pkcs11_return_names_vendor };
static enum_names pkcs11_return_names_1A0 =
- { CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED
- , pkcs11_return_name_1A0, &pkcs11_return_names_200 };
+ { CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED
+ , pkcs11_return_name_1A0, &pkcs11_return_names_200 };
static enum_names pkcs11_return_names_190 =
- { CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED
- , pkcs11_return_name_190, &pkcs11_return_names_1A0 };
+ { CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED
+ , pkcs11_return_name_190, &pkcs11_return_names_1A0 };
static enum_names pkcs11_return_names_180 =
- { CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE
- , pkcs11_return_name_180, &pkcs11_return_names_190 };
+ { CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE
+ , pkcs11_return_name_180, &pkcs11_return_names_190 };
static enum_names pkcs11_return_names_170 =
- { CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE
- , pkcs11_return_name_170, &pkcs11_return_names_180 };
+ { CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE
+ , pkcs11_return_name_170, &pkcs11_return_names_180 };
static enum_names pkcs11_return_names_160 =
- { CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID
- , pkcs11_return_name_160, &pkcs11_return_names_170 };
+ { CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID
+ , pkcs11_return_name_160, &pkcs11_return_names_170 };
static enum_names pkcs11_return_names_150 =
- { CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL
- , pkcs11_return_name_150, &pkcs11_return_names_160 };
+ { CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL
+ , pkcs11_return_name_150, &pkcs11_return_names_160 };
static enum_names pkcs11_return_names_130 =
- { CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID
- , pkcs11_return_name_130, &pkcs11_return_names_150 };
+ { CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID
+ , pkcs11_return_name_130, &pkcs11_return_names_150 };
static enum_names pkcs11_return_names_120 =
- { CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG
- , pkcs11_return_name_120, &pkcs11_return_names_130 };
+ { CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG
+ , pkcs11_return_name_120, &pkcs11_return_names_130 };
static enum_names pkcs11_return_names_110 =
- { CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
- , pkcs11_return_name_110, &pkcs11_return_names_120 };
+ { CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
+ , pkcs11_return_name_110, &pkcs11_return_names_120 };
static enum_names pkcs11_return_names_100 =
- { CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES
- , pkcs11_return_name_100, &pkcs11_return_names_110 };
+ { CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES
+ , pkcs11_return_name_100, &pkcs11_return_names_110 };
static enum_names pkcs11_return_names_F0 =
- { CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
- , pkcs11_return_name_F0, &pkcs11_return_names_100 };
+ { CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
+ , pkcs11_return_name_F0, &pkcs11_return_names_100 };
static enum_names pkcs11_return_names_E0 =
- { CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED
- , pkcs11_return_name_E0, &pkcs11_return_names_F0 };
+ { CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED
+ , pkcs11_return_name_E0, &pkcs11_return_names_F0 };
static enum_names pkcs11_return_names_D0 =
- { CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT
- , pkcs11_return_name_D0,&pkcs11_return_names_E0 };
+ { CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT
+ , pkcs11_return_name_D0,&pkcs11_return_names_E0 };
static enum_names pkcs11_return_names_C0 =
- { CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE
- , pkcs11_return_name_C0, &pkcs11_return_names_D0 };
+ { CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE
+ , pkcs11_return_name_C0, &pkcs11_return_names_D0 };
static enum_names pkcs11_return_names_B0 =
- { CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS
- , pkcs11_return_name_B0, &pkcs11_return_names_C0 };
+ { CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS
+ , pkcs11_return_name_B0, &pkcs11_return_names_C0 };
static enum_names pkcs11_return_names_A0 =
- { CKR_PIN_INCORRECT, CKR_PIN_LOCKED
- , pkcs11_return_name_A0, &pkcs11_return_names_B0 };
+ { CKR_PIN_INCORRECT, CKR_PIN_LOCKED
+ , pkcs11_return_name_A0, &pkcs11_return_names_B0 };
static enum_names pkcs11_return_names_90 =
- { CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED
- , pkcs11_return_name_90, &pkcs11_return_names_A0 };
+ { CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED
+ , pkcs11_return_name_90, &pkcs11_return_names_A0 };
static enum_names pkcs11_return_names_80 =
- { CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID
- , pkcs11_return_name_80, &pkcs11_return_names_90 };
+ { CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID
+ , pkcs11_return_name_80, &pkcs11_return_names_90 };
static enum_names pkcs11_return_names_70 =
- { CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID
- , pkcs11_return_name_70, &pkcs11_return_names_80 };
+ { CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID
+ , pkcs11_return_name_70, &pkcs11_return_names_80 };
static enum_names pkcs11_return_names_60 =
- { CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE
- , pkcs11_return_name_60, &pkcs11_return_names_70 };
+ { CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE
+ , pkcs11_return_name_60, &pkcs11_return_names_70 };
static enum_names pkcs11_return_names_50 =
- { CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED
- , pkcs11_return_name_50, &pkcs11_return_names_60 };
+ { CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED
+ , pkcs11_return_name_50, &pkcs11_return_names_60 };
static enum_names pkcs11_return_names_40 =
- { CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE
- , pkcs11_return_name_40, &pkcs11_return_names_50 };
+ { CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE
+ , pkcs11_return_name_40, &pkcs11_return_names_50 };
static enum_names pkcs11_return_names_30 =
- { CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED
- , pkcs11_return_name_30, &pkcs11_return_names_40 };
+ { CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED
+ , pkcs11_return_name_30, &pkcs11_return_names_40 };
static enum_names pkcs11_return_names_20 =
- { CKR_DATA_INVALID, CKR_DATA_LEN_RANGE
- , pkcs11_return_name_20, &pkcs11_return_names_30 };
+ { CKR_DATA_INVALID, CKR_DATA_LEN_RANGE
+ , pkcs11_return_name_20, &pkcs11_return_names_30 };
static enum_names pkcs11_return_names_10 =
- { CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID
- , pkcs11_return_name_10, &pkcs11_return_names_20};
+ { CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID
+ , pkcs11_return_name_10, &pkcs11_return_names_20};
static enum_names pkcs11_return_names =
- { CKR_OK, CKR_CANT_LOCK
- , pkcs11_return_name, &pkcs11_return_names_10};
+ { CKR_OK, CKR_CANT_LOCK
+ , pkcs11_return_name, &pkcs11_return_names_10};
/*
* Unload a PKCS#11 module.
@@ -390,49 +389,49 @@ static enum_names pkcs11_return_names =
static CK_RV
scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
{
- if (!mod || mod->_magic != SCX_MAGIC)
- return CKR_ARGUMENTS_BAD;
+ if (!mod || mod->_magic != SCX_MAGIC)
+ return CKR_ARGUMENTS_BAD;
- if (dlclose(mod->handle) < 0)
- return CKR_FUNCTION_FAILED;
+ if (dlclose(mod->handle) < 0)
+ return CKR_FUNCTION_FAILED;
- memset(mod, 0, sizeof(*mod));
- pfree(mod);
- return CKR_OK;
+ memset(mod, 0, sizeof(*mod));
+ free(mod);
+ return CKR_OK;
}
static scx_pkcs11_module_t*
scx_load_pkcs11_module(const char *name, CK_FUNCTION_LIST_PTR_PTR funcs)
{
- CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
- scx_pkcs11_module_t *mod;
- void *handle;
- int rv;
+ CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
+ scx_pkcs11_module_t *mod;
+ void *handle;
+ int rv;
- if (name == NULL || *name == '\0')
- return NULL;
+ if (name == NULL || *name == '\0')
+ return NULL;
- /* Try to load PKCS#11 library module*/
- handle = dlopen(name, RTLD_NOW);
- if (handle == NULL)
- return NULL;
+ /* Try to load PKCS#11 library module*/
+ handle = dlopen(name, RTLD_NOW);
+ if (handle == NULL)
+ return NULL;
- mod = alloc_thing(scx_pkcs11_module_t, "scx_pkcs11_module");
- mod->_magic = SCX_MAGIC;
- mod->handle = handle;
+ mod = malloc_thing(scx_pkcs11_module_t);
+ mod->_magic = SCX_MAGIC;
+ mod->handle = handle;
/* Get the list of function pointers */
- c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
- dlsym(mod->handle, "C_GetFunctionList");
- if (!c_get_function_list)
- goto failed;
+ c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
+ dlsym(mod->handle, "C_GetFunctionList");
+ if (!c_get_function_list)
+ goto failed;
- rv = c_get_function_list(funcs);
- if (rv == CKR_OK)
- return mod;
+ rv = c_get_function_list(funcs);
+ if (rv == CKR_OK)
+ return mod;
failed: scx_unload_pkcs11_module(mod);
- return NULL;
+ return NULL;
}
/*
@@ -442,78 +441,78 @@ static bool
scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
, smartcard_t *sc, cert_t *cert)
{
- size_t hex_len, label_len;
- u_char *hex_id = NULL;
- chunk_t blob;
- x509cert_t *x509cert;
-
- CK_ATTRIBUTE attr[] = {
- { CKA_ID, NULL_PTR, 0L },
- { CKA_LABEL, NULL_PTR, 0L },
- { CKA_VALUE, NULL_PTR, 0L }
- };
-
- /* initialize the return argument */
- *cert = empty_cert;
-
- /* get the length of the attributes first */
- CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
- if (rv != CKR_OK)
- {
- plog("couldn't read the attribute sizes: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- pfreeany(sc->label);
-
- hex_id = alloc_bytes(attr[0].ulValueLen, "hex id");
- hex_len = attr[0].ulValueLen;
- sc->label = alloc_bytes(attr[1].ulValueLen + 1, "sc label");
- label_len = attr[1].ulValueLen;
- blob.ptr = alloc_bytes(attr[2].ulValueLen, "x509cert blob");
- blob.len = attr[2].ulValueLen;
-
- attr[0].pValue = hex_id;
- attr[1].pValue = sc->label;
- attr[2].pValue = blob.ptr;
-
- /* now get the attributes */
- rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
- if (rv != CKR_OK)
- {
- plog("couldn't read the attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- pfree(hex_id);
- pfreeany(sc->label);
- pfree(blob.ptr);
- return FALSE;
- }
+ size_t hex_len, label_len;
+ u_char *hex_id = NULL;
+ chunk_t blob;
+ x509cert_t *x509cert;
+
+ CK_ATTRIBUTE attr[] = {
+ { CKA_ID, NULL_PTR, 0L },
+ { CKA_LABEL, NULL_PTR, 0L },
+ { CKA_VALUE, NULL_PTR, 0L }
+ };
+
+ /* initialize the return argument */
+ *cert = cert_empty;
+
+ /* get the length of the attributes first */
+ CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
+ if (rv != CKR_OK)
+ {
+ plog("couldn't read the attribute sizes: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+
+ free(sc->label);
+
+ hex_id = malloc(attr[0].ulValueLen);
+ hex_len = attr[0].ulValueLen;
+ sc->label = malloc(attr[1].ulValueLen + 1);
+ label_len = attr[1].ulValueLen;
+ blob.ptr = malloc(attr[2].ulValueLen);
+ blob.len = attr[2].ulValueLen;
+
+ attr[0].pValue = hex_id;
+ attr[1].pValue = sc->label;
+ attr[2].pValue = blob.ptr;
+
+ /* now get the attributes */
+ rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
+ if (rv != CKR_OK)
+ {
+ plog("couldn't read the attributes: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ free(hex_id);
+ free(sc->label);
+ free(blob.ptr);
+ return FALSE;
+ }
- pfreeany(sc->id);
+ free(sc->id);
- /* convert id from hex to ASCII */
- sc->id = alloc_bytes(2*hex_len + 1, " sc id");
- datatot(hex_id, hex_len, 16, sc->id, 2*hex_len + 1);
- pfree(hex_id);
+ /* convert id from hex to ASCII */
+ sc->id = malloc(2*hex_len + 1);
+ datatot(hex_id, hex_len, 16, sc->id, 2*hex_len + 1);
+ free(hex_id);
- /* safeguard in case the label is not null terminated */
- sc->label[label_len] = '\0';
+ /* safeguard in case the label is not null terminated */
+ sc->label[label_len] = '\0';
- /* parse the retrieved cert */
- x509cert = alloc_thing(x509cert_t, "x509cert");
- *x509cert = empty_x509cert;
- x509cert->smartcard = TRUE;
+ /* parse the retrieved cert */
+ x509cert = malloc_thing(x509cert_t);
+ *x509cert = empty_x509cert;
+ x509cert->smartcard = TRUE;
- if (!parse_x509cert(blob, 0, x509cert))
- {
- plog("failed to load cert from smartcard, error in X.509 certificate");
- free_x509cert(x509cert);
- return FALSE;
- }
- cert->type = CERT_X509_SIGNATURE;
- cert->u.x509 = x509cert;
- return TRUE;
+ if (!parse_x509cert(blob, 0, x509cert))
+ {
+ plog("failed to load cert from smartcard, error in X.509 certificate");
+ free_x509cert(x509cert);
+ return FALSE;
+ }
+ cert->type = CERT_X509_SIGNATURE;
+ cert->u.x509 = x509cert;
+ return TRUE;
}
/*
@@ -522,96 +521,96 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
static void
scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
- CK_RV rv;
- CK_OBJECT_CLASS class = CKO_CERTIFICATE;
- CK_ATTRIBUTE attr[] = {{ CKA_CLASS, &class, sizeof(class) }};
-
- rv = pkcs11_functions->C_FindObjectsInit(session, attr, 1);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return;
- }
-
- for (;;)
- {
- CK_OBJECT_HANDLE object;
- CK_ULONG obj_count = 0;
- err_t ugh;
- time_t valid_until;
- smartcard_t *sc;
- x509cert_t *cert;
+ CK_RV rv;
+ CK_OBJECT_CLASS class = CKO_CERTIFICATE;
+ CK_ATTRIBUTE attr[] = {{ CKA_CLASS, &class, sizeof(class) }};
- rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count);
+ rv = pkcs11_functions->C_FindObjectsInit(session, attr, 1);
if (rv != CKR_OK)
{
- plog("error in C_FindObjects: %s"
- , enum_show(&pkcs11_return_names, rv));
- break;
- }
-
- /* no objects left */
- if (obj_count == 0)
- break;
-
- /* create and initialize a new smartcard object */
- sc = alloc_thing(smartcard_t, "smartcard");
- *sc = empty_sc;
- sc->any_slot = FALSE;
- sc->slot = slot;
-
- if (!scx_find_cert_object(session, object, sc, &sc->last_cert))
- {
- scx_free(sc);
- continue;
+ plog("error in C_FindObjectsInit: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return;
}
- DBG(DBG_CONTROL,
- DBG_log("found cert in %s with id: %s, label: '%s'"
- , scx_print_slot(sc, ""), sc->id, sc->label)
- )
- /* check validity of certificate */
- cert = sc->last_cert.u.x509;
- valid_until = cert->notAfter;
- ugh = check_validity(cert, &valid_until);
- if (ugh != NULL)
- {
- plog(" %s", ugh);
- free_x509cert(cert);
- scx_free(sc);
- continue;
- }
- else
+ for (;;)
{
- DBG(DBG_CONTROL,
- DBG_log(" certificate is valid")
- )
+ CK_OBJECT_HANDLE object;
+ CK_ULONG obj_count = 0;
+ err_t ugh;
+ time_t valid_until;
+ smartcard_t *sc;
+ x509cert_t *cert;
+
+ rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_FindObjects: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ break;
+ }
+
+ /* no objects left */
+ if (obj_count == 0)
+ break;
+
+ /* create and initialize a new smartcard object */
+ sc = malloc_thing(smartcard_t);
+ *sc = empty_sc;
+ sc->any_slot = FALSE;
+ sc->slot = slot;
+
+ if (!scx_find_cert_object(session, object, sc, &sc->last_cert))
+ {
+ scx_free(sc);
+ continue;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("found cert in %s with id: %s, label: '%s'"
+ , scx_print_slot(sc, ""), sc->id, sc->label)
+ )
+
+ /* check validity of certificate */
+ cert = sc->last_cert.u.x509;
+ valid_until = cert->notAfter;
+ ugh = check_validity(cert, &valid_until);
+ if (ugh != NULL)
+ {
+ plog(" %s", ugh);
+ free_x509cert(cert);
+ scx_free(sc);
+ continue;
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log(" certificate is valid")
+ )
+ }
+
+ sc = scx_add(sc);
+
+ /* put end entity and ca certificates into different chains */
+ if (cert->isCA)
+ {
+ sc->last_cert.u.x509 = add_authcert(cert, AUTH_CA);
+ }
+ else
+ {
+ add_x509_public_key(cert, valid_until, DAL_LOCAL);
+ sc->last_cert.u.x509 = add_x509cert(cert);
+ }
+
+ share_cert(sc->last_cert);
+ time(&sc->last_load);
}
- sc = scx_add(sc);
-
- /* put end entity and ca certificates into different chains */
- if (cert->isCA)
- {
- sc->last_cert.u.x509 = add_authcert(cert, AUTH_CA);
- }
- else
+ rv = pkcs11_functions->C_FindObjectsFinal(session);
+ if (rv != CKR_OK)
{
- add_x509_public_key(cert, valid_until, DAL_LOCAL);
- sc->last_cert.u.x509 = add_x509cert(cert);
+ plog("error in C_FindObjectsFinal: %s"
+ , enum_show(&pkcs11_return_names, rv));
}
-
- share_cert(sc->last_cert);
- time(&sc->last_load);
- }
-
- rv = pkcs11_functions->C_FindObjectsFinal(session);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsFinal: %s"
- , enum_show(&pkcs11_return_names, rv));
- }
}
/*
@@ -620,74 +619,74 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
static void
scx_find_all_cert_objects(void)
{
- CK_RV rv;
- CK_SLOT_ID_PTR slots = NULL_PTR;
- CK_ULONG slot_count = 0;
- CK_ULONG i;
-
- if (!scx_initialized)
- {
- plog("pkcs11 module not initialized");
- return;
- }
-
- /* read size, always returns CKR_OK ! */
- rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
-
- /* allocate memory for the slots */
- slots = (CK_SLOT_ID *)alloc_bytes(slot_count * sizeof(CK_SLOT_ID), "slots");
-
- rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count);
- if (rv != CKR_OK)
- {
- plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names, rv));
- pfreeany(slots);
- return;
- }
-
- /* look in every slot for certificate objects */
- for (i = 0; i < slot_count; i++)
- {
- CK_SLOT_ID slot = slots[i];
- CK_SLOT_INFO info;
- CK_SESSION_HANDLE session;
-
- rv = pkcs11_functions->C_GetSlotInfo(slot, &info);
+ CK_RV rv;
+ CK_SLOT_ID_PTR slots = NULL_PTR;
+ CK_ULONG slot_count = 0;
+ CK_ULONG i;
- if (rv != CKR_OK)
+ if (!scx_initialized)
{
- plog("error in C_GetSlotInfo: %s"
- , enum_show(&pkcs11_return_names, rv));
- continue;
- }
-
- if (!(info.flags & CKF_TOKEN_PRESENT))
- {
- plog("no token present in slot %lu", slot);
- continue;
+ plog("pkcs11 module not initialized");
+ return;
}
- rv = pkcs11_functions->C_OpenSession(slot
- , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session);
+ /* read size, always returns CKR_OK ! */
+ rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
+
+ /* allocate memory for the slots */
+ slots = (CK_SLOT_ID *)malloc(slot_count * sizeof(CK_SLOT_ID));
+
+ rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count);
if (rv != CKR_OK)
{
- plog("failed to open a session on slot %lu: %s"
- , slot, enum_show(&pkcs11_return_names, rv));
- continue;
+ plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names, rv));
+ free(slots);
+ return;
}
- DBG(DBG_CONTROLMORE,
- DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot)
- )
- scx_find_cert_objects(slot, session);
- rv = pkcs11_functions->C_CloseSession(session);
- if (rv != CKR_OK)
+ /* look in every slot for certificate objects */
+ for (i = 0; i < slot_count; i++)
{
- plog("error in C_CloseSession: %s"
- , enum_show(&pkcs11_return_names, rv));
+ CK_SLOT_ID slot = slots[i];
+ CK_SLOT_INFO info;
+ CK_SESSION_HANDLE session;
+
+ rv = pkcs11_functions->C_GetSlotInfo(slot, &info);
+
+ if (rv != CKR_OK)
+ {
+ plog("error in C_GetSlotInfo: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ continue;
+ }
+
+ if (!(info.flags & CKF_TOKEN_PRESENT))
+ {
+ plog("no token present in slot %lu", slot);
+ continue;
+ }
+
+ rv = pkcs11_functions->C_OpenSession(slot
+ , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session);
+ if (rv != CKR_OK)
+ {
+ plog("failed to open a session on slot %lu: %s"
+ , slot, enum_show(&pkcs11_return_names, rv));
+ continue;
+ }
+ DBG(DBG_CONTROLMORE,
+ DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot)
+ )
+ scx_find_cert_objects(slot, session);
+
+ rv = pkcs11_functions->C_CloseSession(session);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_CloseSession: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ }
}
- }
- pfreeany(slots);
+ free(slots);
}
#endif
@@ -701,52 +700,52 @@ void
scx_init(const char* module, const char *init_args)
{
#ifdef SMARTCARD
- CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, };
- CK_RV rv;
+ CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, };
+ CK_RV rv;
- if (scx_initialized)
- {
- plog("weird - pkcs11 module seems already to be initialized");
- return;
- }
+ if (scx_initialized)
+ {
+ plog("weird - pkcs11 module seems already to be initialized");
+ return;
+ }
- if (module == NULL)
+ if (module == NULL)
#ifdef PKCS11_DEFAULT_LIB
- module = PKCS11_DEFAULT_LIB;
+ module = PKCS11_DEFAULT_LIB;
#else
- {
- plog("no pkcs11 module defined");
- return;
- }
+ {
+ plog("no pkcs11 module defined");
+ return;
+ }
#endif
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module '%s' loading...", module)
- )
- pkcs11_module = scx_load_pkcs11_module(module, &pkcs11_functions);
- if (pkcs11_module == NULL)
- {
- plog("failed to load pkcs11 module '%s'", module);
- return;
- }
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module initializing...")
- )
- rv = pkcs11_functions->C_Initialize(init_args ? &args : NULL);
- if (rv != CKR_OK)
- {
- plog("failed to initialize pkcs11 module: %s"
- , enum_show(&pkcs11_return_names, rv));
- return;
- }
-
- scx_initialized = TRUE;
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module loaded and initialized")
- )
-
- scx_find_all_cert_objects();
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 module '%s' loading...", module)
+ )
+ pkcs11_module = scx_load_pkcs11_module(module, &pkcs11_functions);
+ if (pkcs11_module == NULL)
+ {
+ plog("failed to load pkcs11 module '%s'", module);
+ return;
+ }
+
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 module initializing...")
+ )
+ rv = pkcs11_functions->C_Initialize(init_args ? &args : NULL);
+ if (rv != CKR_OK)
+ {
+ plog("failed to initialize pkcs11 module: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return;
+ }
+
+ scx_initialized = TRUE;
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 module loaded and initialized")
+ )
+
+ scx_find_all_cert_objects();
#endif
}
@@ -757,27 +756,27 @@ void
scx_finalize(void)
{
#ifdef SMARTCARD
- while (smartcards != NULL)
- {
- scx_release(smartcards);
- }
-
- if (pkcs11_functions != NULL_PTR)
- {
- pkcs11_functions->C_Finalize(NULL_PTR);
- pkcs11_functions = NULL_PTR;
- }
-
- if (pkcs11_module != NULL)
- {
- scx_unload_pkcs11_module(pkcs11_module);
- pkcs11_module = NULL;
- }
-
- scx_initialized = FALSE;
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module finalized and unloaded")
- )
+ while (smartcards != NULL)
+ {
+ scx_release(smartcards);
+ }
+
+ if (pkcs11_functions != NULL_PTR)
+ {
+ pkcs11_functions->C_Finalize(NULL_PTR);
+ pkcs11_functions = NULL_PTR;
+ }
+
+ if (pkcs11_module != NULL)
+ {
+ scx_unload_pkcs11_module(pkcs11_module);
+ pkcs11_module = NULL;
+ }
+
+ scx_initialized = FALSE;
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 module finalized and unloaded")
+ )
#endif
}
@@ -787,7 +786,7 @@ scx_finalize(void)
bool
scx_on_smartcard(const char *filename)
{
- return strncmp(filename, SCX_TOKEN, strlen(SCX_TOKEN)) == 0;
+ return strneq(filename, SCX_TOKEN, strlen(SCX_TOKEN));
}
#ifdef SMARTCARD
@@ -795,55 +794,55 @@ scx_on_smartcard(const char *filename)
* find a specific object on the smartcard
*/
static bool
-scx_pkcs11_find_object( CK_SESSION_HANDLE session,
- CK_OBJECT_HANDLE_PTR object,
- CK_OBJECT_CLASS class,
- const char* id)
+scx_pkcs11_find_object( CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR object,
+ CK_OBJECT_CLASS class,
+ const char* id)
{
- size_t len;
- char buf[BUF_LEN];
- CK_RV rv;
- CK_ULONG obj_count = 0;
- CK_ULONG attr_count = 1;
-
- CK_ATTRIBUTE attr[] = {
- { CKA_CLASS, &class, sizeof(class) },
- { CKA_ID, &buf, 0L }
- };
-
- if (id != NULL)
- {
- ttodata(id, strlen(id), 16, buf, BUF_LEN, &len);
- attr[1].ulValueLen = len;
- attr_count = 2;
- }
-
- /* get info for certificate with id */
- rv = pkcs11_functions->C_FindObjectsInit(session, attr, attr_count);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
+ size_t len;
+ char buf[BUF_LEN];
+ CK_RV rv;
+ CK_ULONG obj_count = 0;
+ CK_ULONG attr_count = 1;
- rv = pkcs11_functions->C_FindObjects(session, object, 1, &obj_count);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjects: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
+ CK_ATTRIBUTE attr[] = {
+ { CKA_CLASS, &class, sizeof(class) },
+ { CKA_ID, &buf, 0L }
+ };
- rv = pkcs11_functions->C_FindObjectsFinal(session);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsFinal: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
+ if (id != NULL)
+ {
+ ttodata(id, strlen(id), 16, buf, BUF_LEN, &len);
+ attr[1].ulValueLen = len;
+ attr_count = 2;
+ }
+
+ /* get info for certificate with id */
+ rv = pkcs11_functions->C_FindObjectsInit(session, attr, attr_count);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_FindObjectsInit: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_FindObjects(session, object, 1, &obj_count);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_FindObjects: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
- return (obj_count != 0);
+ rv = pkcs11_functions->C_FindObjectsFinal(session);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_FindObjectsFinal: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+
+ return (obj_count != 0);
}
/*
@@ -852,54 +851,54 @@ scx_pkcs11_find_object( CK_SESSION_HANDLE session,
static bool
scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
{
- CK_SESSION_HANDLE session;
- CK_OBJECT_HANDLE object;
- CK_SLOT_INFO info;
-
- CK_RV rv = pkcs11_functions->C_GetSlotInfo(slot, &info);
-
- if (rv != CKR_OK)
- {
- plog("error in C_GetSlotInfo: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- if (!(info.flags & CKF_TOKEN_PRESENT))
- {
- plog("no token present in slot %lu", slot);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_OpenSession(slot
- , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session);
- if (rv != CKR_OK)
- {
- plog("failed to open a session on slot %lu: %s"
- , slot, enum_show(&pkcs11_return_names, rv));
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE object;
+ CK_SLOT_INFO info;
+
+ CK_RV rv = pkcs11_functions->C_GetSlotInfo(slot, &info);
+
+ if (rv != CKR_OK)
+ {
+ plog("error in C_GetSlotInfo: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+
+ if (!(info.flags & CKF_TOKEN_PRESENT))
+ {
+ plog("no token present in slot %lu", slot);
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_OpenSession(slot
+ , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session);
+ if (rv != CKR_OK)
+ {
+ plog("failed to open a session on slot %lu: %s"
+ , slot, enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+ DBG(DBG_CONTROLMORE,
+ DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot)
+ )
+
+ /* check if there is a certificate on the card in the specified slot */
+ if (scx_pkcs11_find_object(session, &object, CKO_CERTIFICATE, sc->id))
+ {
+ sc->slot = slot;
+ sc->any_slot = FALSE;
+ sc->session = session;
+ sc->session_opened = TRUE;
+ return TRUE;
+ }
+
+ rv = pkcs11_functions->C_CloseSession(session);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_CloseSession: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ }
return FALSE;
- }
- DBG(DBG_CONTROLMORE,
- DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot)
- )
-
- /* check if there is a certificate on the card in the specified slot */
- if (scx_pkcs11_find_object(session, &object, CKO_CERTIFICATE, sc->id))
- {
- sc->slot = slot;
- sc->any_slot = FALSE;
- sc->session = session;
- sc->session_opened = TRUE;
- return TRUE;
- }
-
- rv = pkcs11_functions->C_CloseSession(session);
- if (rv != CKR_OK)
- {
- plog("error in C_CloseSession: %s"
- , enum_show(&pkcs11_return_names, rv));
- }
- return FALSE;
}
#endif
@@ -910,74 +909,74 @@ bool
scx_establish_context(smartcard_t *sc)
{
#ifdef SMARTCARD
- bool id_found = FALSE;
-
- if (!scx_initialized)
- {
- plog("pkcs11 module not initialized");
- return FALSE;
- }
+ bool id_found = FALSE;
- if (sc->session_opened)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld already open", sc->session)
- )
- return TRUE;
- }
-
- if (!sc->any_slot)
- id_found = scx_find_cert_id_in_slot(sc, sc->slot);
-
- if (!id_found)
- {
- CK_RV rv;
- CK_SLOT_ID slot;
- CK_SLOT_ID_PTR slots = NULL_PTR;
- CK_ULONG slot_count = 0;
- CK_ULONG i;
+ if (!scx_initialized)
+ {
+ plog("pkcs11 module not initialized");
+ return FALSE;
+ }
- /* read size, always returns CKR_OK ! */
- rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
+ if (sc->session_opened)
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 session #%ld already open", sc->session)
+ )
+ return TRUE;
+ }
- /* allocate memory for the slots */
- slots = (CK_SLOT_ID *)alloc_bytes(slot_count * sizeof(CK_SLOT_ID), "slots");
+ if (!sc->any_slot)
+ id_found = scx_find_cert_id_in_slot(sc, sc->slot);
- rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count);
- if (rv != CKR_OK)
+ if (!id_found)
{
- plog("error in C_GetSlotList: %s"
- , enum_show(&pkcs11_return_names, rv));
- pfreeany(slots);
- return FALSE;
- }
+ CK_RV rv;
+ CK_SLOT_ID slot;
+ CK_SLOT_ID_PTR slots = NULL_PTR;
+ CK_ULONG slot_count = 0;
+ CK_ULONG i;
+
+ /* read size, always returns CKR_OK ! */
+ rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
+
+ /* allocate memory for the slots */
+ slots = (CK_SLOT_ID *)malloc(slot_count * sizeof(CK_SLOT_ID));
+
+ rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_GetSlotList: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ free(slots);
+ return FALSE;
+ }
+
+ /* look in every slot for a certificate with a given object ID */
+ for (i = 0; i < slot_count; i++)
+ {
+ slot = slots[i];
+ id_found = scx_find_cert_id_in_slot(sc, slot);
+ if (id_found)
+ break;
+ }
+ free(slots);
+ }
- /* look in every slot for a certificate with a given object ID */
- for (i = 0; i < slot_count; i++)
+ if (id_found)
{
- slot = slots[i];
- id_found = scx_find_cert_id_in_slot(sc, slot);
- if (id_found)
- break;
- }
- pfreeany(slots)
- }
-
- if (id_found)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("found token with id %s in slot %lu", sc->id, sc->slot);
- DBG_log("pkcs11 session #%ld opened", sc->session)
- )
- }
- else
- {
- plog(" no certificate with id %s found on smartcard", sc->id);
- }
- return id_found;
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("found token with id %s in slot %lu", sc->id, sc->slot);
+ DBG_log("pkcs11 session #%ld opened", sc->session)
+ )
+ }
+ else
+ {
+ plog(" no certificate with id %s found on smartcard", sc->id);
+ }
+ return id_found;
#else
- plog("warning: SMARTCARD support is deactivated in pluto/Makefile!");
- return FALSE;
+ plog("warning: SMARTCARD support is deactivated in pluto/Makefile!");
+ return FALSE;
#endif
}
@@ -988,41 +987,41 @@ bool
scx_login(smartcard_t *sc)
{
#ifdef SMARTCARD
- CK_RV rv;
+ CK_RV rv;
+
+ if (sc->logged_in)
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 session #%ld login already done", sc->session)
+ )
+ return TRUE;
+ }
+
+ if (sc->pin.ptr == NULL)
+ {
+ plog("unable to log in without PIN!");
+ return FALSE;
+ }
+
+ if (!sc->session_opened)
+ {
+ plog("session not opened");
+ return FALSE;
+ }
- if (sc->logged_in)
- {
+ rv = pkcs11_functions->C_Login(sc->session, CKU_USER
+ , (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len);
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN)
+ {
+ plog("unable to login: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld login already done", sc->session)
+ DBG_log("pkcs11 session #%ld login successful", sc->session)
)
+ sc->logged_in = TRUE;
return TRUE;
- }
-
- if (sc->pin.ptr == NULL)
- {
- plog("unable to log in without PIN!");
- return FALSE;
- }
-
- if (!sc->session_opened)
- {
- plog("session not opened");
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Login(sc->session, CKU_USER
- , (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len);
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN)
- {
- plog("unable to login: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld login successful", sc->session)
- )
- sc->logged_in = TRUE;
- return TRUE;
#else
return FALSE;
#endif
@@ -1035,17 +1034,17 @@ scx_login(smartcard_t *sc)
static void
scx_logout(smartcard_t *sc)
{
- CK_RV rv;
-
- rv = pkcs11_functions->C_Logout(sc->session);
- if (rv != CKR_OK)
- plog("error in C_Logout: %s"
- , enum_show(&pkcs11_return_names, rv));
- else
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld logout", sc->session)
- )
- sc->logged_in = FALSE;
+ CK_RV rv;
+
+ rv = pkcs11_functions->C_Logout(sc->session);
+ if (rv != CKR_OK)
+ plog("error in C_Logout: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ else
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 session #%ld logout", sc->session)
+ )
+ sc->logged_in = FALSE;
}
#endif
@@ -1057,27 +1056,27 @@ void
scx_release_context(smartcard_t *sc)
{
#ifdef SMARTCARD
- CK_RV rv;
-
- if (!scx_initialized)
- return;
+ CK_RV rv;
- if (sc->session_opened)
- {
- if (sc->logged_in)
- scx_logout(sc);
+ if (!scx_initialized)
+ return;
- sc->session_opened = FALSE;
-
- rv = pkcs11_functions->C_CloseSession(sc->session);
- if (rv != CKR_OK)
- plog("error in C_CloseSession: %s"
- , enum_show(&pkcs11_return_names, rv));
- else
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld closed", sc->session)
- )
- }
+ if (sc->session_opened)
+ {
+ if (sc->logged_in)
+ scx_logout(sc);
+
+ sc->session_opened = FALSE;
+
+ rv = pkcs11_functions->C_CloseSession(sc->session);
+ if (rv != CKR_OK)
+ plog("error in C_CloseSession: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ else
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("pkcs11 session #%ld closed", sc->session)
+ )
+ }
#endif
}
@@ -1088,64 +1087,64 @@ bool
scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert
, bool *cached)
{
-#ifdef SMARTCARD /* compile with smartcard support */
- CK_OBJECT_HANDLE object;
+#ifdef SMARTCARD /* compile with smartcard support */
+ CK_OBJECT_HANDLE object;
- const char *number_slot_id = filename + strlen(SCX_TOKEN);
+ const char *number_slot_id = filename + strlen(SCX_TOKEN);
- smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id));
+ smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id));
- /* return the smartcard object */
- *scp = sc;
+ /* return the smartcard object */
+ *scp = sc;
- /* is there a cached smartcard certificate? */
- *cached = sc->last_cert.type != CERT_NONE
- && (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
+ /* is there a cached smartcard certificate? */
+ *cached = sc->last_cert.type != CERT_NONE
+ && (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
- if (*cached)
- {
- *cert = sc->last_cert;
- plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
- , sc->number
- , scx_print_slot(sc, "")
- , sc->id
- , sc->label);
- return TRUE;
- }
+ if (*cached)
+ {
+ *cert = sc->last_cert;
+ plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
+ , sc->number
+ , scx_print_slot(sc, "")
+ , sc->id
+ , sc->label);
+ return TRUE;
+ }
- if (!scx_establish_context(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
+ if (!scx_establish_context(sc))
+ {
+ scx_release_context(sc);
+ return FALSE;
+ }
- /* find the certificate object */
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
- {
- scx_release_context(sc);
- return FALSE;
- }
+ /* find the certificate object */
+ if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
+ {
+ scx_release_context(sc);
+ return FALSE;
+ }
- /* retrieve the certificate object */
- if (!scx_find_cert_object(sc->session, object, sc, cert))
- {
- scx_release_context(sc);
- return FALSE;
- }
+ /* retrieve the certificate object */
+ if (!scx_find_cert_object(sc->session, object, sc, cert))
+ {
+ scx_release_context(sc);
+ return FALSE;
+ }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
+ if (!pkcs11_keep_state)
+ scx_release_context(sc);
- plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
- , sc->number
- , scx_print_slot(sc, "")
- , sc->id
- , sc->label);
+ plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
+ , sc->number
+ , scx_print_slot(sc, "")
+ , sc->id
+ , sc->label);
- return TRUE;
+ return TRUE;
#else
- plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
- return FALSE;
+ plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
+ return FALSE;
#endif
}
@@ -1162,58 +1161,58 @@ scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert
smartcard_t*
scx_parse_number_slot_id(const char *number_slot_id)
{
- int len = strlen(number_slot_id);
- smartcard_t *sc = alloc_thing(smartcard_t, "smartcard");
-
- /* assign default values */
- *sc = empty_sc;
-
- if (len == 0) /* default: use certificate #1 */
- {
- sc->number = 1;
- }
- else if (*number_slot_id == '#') /* #number scheme */
- {
- err_t ugh;
- unsigned long ul;
-
- ugh = atoul(number_slot_id+1, len-1 , 10, &ul);
- if (ugh == NULL)
- sc->number = (int)ul;
- else
- plog("error parsing smartcard number: %s", ugh);
- }
- else /* slot:id scheme */
- {
- int slot_len = len;
- char *p = strchr(number_slot_id, ':');
-
- if (p != NULL)
- {
- int id_len = len - (p + 1 - number_slot_id);
- slot_len -= (1 + id_len);
-
- if (id_len > 0) /* we have an id */
- sc->id = p + 1;
- }
- if (slot_len > 0) /* we have a slot */
- {
- err_t ugh = NULL;
- unsigned long ul;
-
- ugh = atoul(number_slot_id, slot_len, 10, &ul);
- if (ugh == NULL)
- {
- sc->slot = ul;
- sc->any_slot = FALSE;
- }
- else
- plog("error parsing smartcard slot number: %s", ugh);
- }
- }
- /* unshare the id string */
- sc->id = clone_str(sc->id, "key id");
- return sc;
+ int len = strlen(number_slot_id);
+ smartcard_t *sc = malloc_thing(smartcard_t);
+
+ /* assign default values */
+ *sc = empty_sc;
+
+ if (len == 0) /* default: use certificate #1 */
+ {
+ sc->number = 1;
+ }
+ else if (*number_slot_id == '#') /* #number scheme */
+ {
+ err_t ugh;
+ unsigned long ul;
+
+ ugh = atoul(number_slot_id+1, len-1 , 10, &ul);
+ if (ugh == NULL)
+ sc->number = (int)ul;
+ else
+ plog("error parsing smartcard number: %s", ugh);
+ }
+ else /* slot:id scheme */
+ {
+ int slot_len = len;
+ char *p = strchr(number_slot_id, ':');
+
+ if (p != NULL)
+ {
+ int id_len = len - (p + 1 - number_slot_id);
+ slot_len -= (1 + id_len);
+
+ if (id_len > 0) /* we have an id */
+ sc->id = p + 1;
+ }
+ if (slot_len > 0) /* we have a slot */
+ {
+ err_t ugh = NULL;
+ unsigned long ul;
+
+ ugh = atoul(number_slot_id, slot_len, 10, &ul);
+ if (ugh == NULL)
+ {
+ sc->slot = ul;
+ sc->any_slot = FALSE;
+ }
+ else
+ plog("error parsing smartcard slot number: %s", ugh);
+ }
+ }
+ /* unshare the id string */
+ sc->id = clone_str(sc->id);
+ return sc;
}
/*
@@ -1223,49 +1222,49 @@ bool
scx_verify_pin(smartcard_t *sc)
{
#ifdef SMARTCARD
- CK_RV rv;
-
- if (!sc->pinpad)
- sc->valid = FALSE;
+ CK_RV rv;
+
+ if (!sc->pinpad)
+ sc->valid = FALSE;
- if (sc->pin.ptr == NULL)
- {
- plog("unable to verify without PIN");
- return FALSE;
- }
+ if (sc->pin.ptr == NULL)
+ {
+ plog("unable to verify without PIN");
+ return FALSE;
+ }
- /* establish context */
- if (!scx_establish_context(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
+ /* establish context */
+ if (!scx_establish_context(sc))
+ {
+ scx_release_context(sc);
+ return FALSE;
+ }
- rv = pkcs11_functions->C_Login(sc->session, CKU_USER,
- (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len);
- if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
- {
- sc->valid = TRUE;
- sc->logged_in = TRUE;
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log((rv == CKR_OK)
- ? "PIN code correct"
- : "already logged in, no PIN entry required");
- DBG_log("pkcs11 session #%ld login successful", sc->session)
- )
- }
- else
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("PIN code incorrect")
- )
- }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
+ rv = pkcs11_functions->C_Login(sc->session, CKU_USER,
+ (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len);
+ if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
+ {
+ sc->valid = TRUE;
+ sc->logged_in = TRUE;
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log((rv == CKR_OK)
+ ? "PIN code correct"
+ : "already logged in, no PIN entry required");
+ DBG_log("pkcs11 session #%ld login successful", sc->session)
+ )
+ }
+ else
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("PIN code incorrect")
+ )
+ }
+ if (!pkcs11_keep_state)
+ scx_release_context(sc);
#else
- sc->valid = FALSE;
+ sc->valid = FALSE;
#endif
- return sc->valid;
+ return sc->valid;
}
/*
@@ -1276,105 +1275,105 @@ scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
, u_char *out, size_t outlen)
{
#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ULONG siglen = (CK_ULONG)outlen;
- CK_BBOOL sign_flag, decrypt_flag;
- CK_ATTRIBUTE attr[] = {
- { CKA_SIGN, &sign_flag, sizeof(sign_flag) },
- { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) }
- };
-
- if (!sc->logged_in)
- return FALSE;
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
- {
- plog("unable to find private key with id '%s'", sc->id);
- return FALSE;
- }
+ CK_RV rv;
+ CK_OBJECT_HANDLE object;
+ CK_ULONG siglen = (CK_ULONG)outlen;
+ CK_BBOOL sign_flag, decrypt_flag;
+ CK_ATTRIBUTE attr[] = {
+ { CKA_SIGN, &sign_flag, sizeof(sign_flag) },
+ { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) }
+ };
+
+ if (!sc->logged_in)
+ return FALSE;
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2);
- if (rv != CKR_OK)
- {
- plog("couldn't read the private key attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("RSA key flags: sign = %s, decrypt = %s"
- , (sign_flag)? "true":"false"
- , (decrypt_flag)? "true":"false")
- )
-
- if (sign_flag)
- {
- CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
-
- rv = pkcs11_functions->C_SignInit(sc->session, &mech, object);
- if (rv != CKR_OK)
+ if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
{
- plog("error in C_SignInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
+ plog("unable to find private key with id '%s'", sc->id);
+ return FALSE;
}
- rv = pkcs11_functions->C_Sign(sc->session, (CK_BYTE_PTR)in, inlen
- , out, &siglen);
+ rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2);
if (rv != CKR_OK)
{
- plog("error in C_Sign: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- }
- else if (decrypt_flag)
- {
- CK_MECHANISM mech = { CKM_RSA_X_509, NULL_PTR, 0 };
- size_t padlen;
- u_char *p = out ;
-
- /* PKCS#1 v1.5 8.1 encryption-block formatting */
- *p++ = 0x00;
- *p++ = 0x01; /* BT (block type) 01 */
- padlen = outlen - 3 - inlen;
- memset(p, 0xFF, padlen);
- p += padlen;
- *p++ = 0x00;
- memcpy(p, in, inlen);
+ plog("couldn't read the private key attributes: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("RSA key flags: sign = %s, decrypt = %s"
+ , (sign_flag)? "true":"false"
+ , (decrypt_flag)? "true":"false")
+ )
- rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object);
- if (rv != CKR_OK)
+ if (sign_flag)
{
- plog("error in C_DecryptInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Decrypt(sc->session, out, outlen
- , out, &siglen);
- if (rv != CKR_OK)
- {
- plog("error in C_Decrypt: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- }
- else
- {
- plog("private key has neither sign nor decrypt flag set");
- return FALSE;
- }
+ CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
+
+ rv = pkcs11_functions->C_SignInit(sc->session, &mech, object);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_SignInit: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_Sign(sc->session, (CK_BYTE_PTR)in, inlen
+ , out, &siglen);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_Sign: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+ }
+ else if (decrypt_flag)
+ {
+ CK_MECHANISM mech = { CKM_RSA_X_509, NULL_PTR, 0 };
+ size_t padlen;
+ u_char *p = out ;
+
+ /* PKCS#1 v1.5 8.1 encryption-block formatting */
+ *p++ = 0x00;
+ *p++ = 0x01; /* BT (block type) 01 */
+ padlen = outlen - 3 - inlen;
+ memset(p, 0xFF, padlen);
+ p += padlen;
+ *p++ = 0x00;
+ memcpy(p, in, inlen);
+
+ rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_DecryptInit: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_Decrypt(sc->session, out, outlen
+ , out, &siglen);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_Decrypt: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
+ }
+ else
+ {
+ plog("private key has neither sign nor decrypt flag set");
+ return FALSE;
+ }
- if (siglen > (CK_ULONG)outlen)
- {
- plog("signature length (%lu) larger than allocated buffer (%d)"
- , siglen, (int)outlen);
- return FALSE;
- }
- return TRUE;
+ if (siglen > (CK_ULONG)outlen)
+ {
+ plog("signature length (%lu) larger than allocated buffer (%d)"
+ , siglen, (int)outlen);
+ return FALSE;
+ }
+ return TRUE;
#else
- return FALSE;
+ return FALSE;
#endif
}
@@ -1386,132 +1385,146 @@ scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
, u_char *out, size_t *outlen)
{
#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ULONG len = (CK_ULONG)(*outlen);
- CK_BBOOL encrypt_flag;
- CK_ATTRIBUTE attr[] = {
- { CKA_MODULUS, NULL_PTR, 0L },
- { CKA_PUBLIC_EXPONENT, NULL_PTR, 0L },
- { CKA_ENCRYPT, &encrypt_flag, sizeof(encrypt_flag) }
- };
- CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
-
- if (!scx_establish_context(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PUBLIC_KEY, sc->id))
- {
- plog("unable to find public key with id '%s'", sc->id);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 3);
- if (rv != CKR_OK)
- {
- plog("couldn't read the public key attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
+ CK_RV rv;
+ CK_OBJECT_HANDLE object;
+ CK_ULONG len = (CK_ULONG)(*outlen);
+ CK_BBOOL encrypt_flag;
+ CK_ATTRIBUTE attr[] = {
+ { CKA_MODULUS, NULL_PTR, 0L },
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0L },
+ { CKA_ENCRYPT, &encrypt_flag, sizeof(encrypt_flag) }
+ };
+ CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
+
+ if (!scx_establish_context(sc))
+ {
+ scx_release_context(sc);
+ return FALSE;
+ }
- if (!encrypt_flag)
- {
- plog("public key cannot be used for encryption");
- scx_release_context(sc);
- return FALSE;
- }
-
- /* there must be enough space left for the PKCS#1 v1.5 padding */
- if (inlen > attr[0].ulValueLen - 11)
- {
- plog("smartcard input data length (%d) exceeds maximum of %lu bytes"
- , (int)inlen, attr[0].ulValueLen - 11);
- if (!pkcs11_keep_state)
- scx_release_context(sc);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_EncryptInit(sc->session, &mech, object);
-
- if (rv != CKR_OK)
- {
- if (rv == CKR_FUNCTION_NOT_SUPPORTED)
- {
- RSA_public_key_t rsa;
- chunk_t plain_text = {(u_char*)in, inlen};
- chunk_t cipher_text;
-
- DBG(DBG_CONTROL,
- DBG_log("doing RSA encryption in software")
- )
- attr[0].pValue = alloc_bytes(attr[0].ulValueLen, "modulus");
- attr[1].pValue = alloc_bytes(attr[1].ulValueLen, "exponent");
-
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2);
- if (rv != CKR_OK)
- {
- plog("couldn't read modulus and public exponent: %s"
- , enum_show(&pkcs11_return_names, rv));
- pfree(attr[0].pValue);
- pfree(attr[1].pValue);
+ if (!scx_pkcs11_find_object(sc->session, &object, CKO_PUBLIC_KEY, sc->id))
+ {
+ plog("unable to find public key with id '%s'", sc->id);
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 3);
+ if (rv != CKR_OK)
+ {
+ plog("couldn't read the public key attributes: %s"
+ , enum_show(&pkcs11_return_names, rv));
scx_release_context(sc);
return FALSE;
- }
- rsa.k = attr[0].ulValueLen;
- n_to_mpz(&rsa.n, attr[0].pValue, attr[0].ulValueLen);
- n_to_mpz(&rsa.e, attr[1].pValue, attr[1].ulValueLen);
- pfree(attr[0].pValue);
- pfree(attr[1].pValue);
-
- cipher_text = RSA_encrypt(&rsa, plain_text);
- free_RSA_public_content(&rsa);
- if (cipher_text.ptr == NULL)
- {
- plog("smartcard input data length is too large");
- if (!pkcs11_keep_state)
- scx_release_context(sc);
- return FALSE;
- }
-
- memcpy(out, cipher_text.ptr, cipher_text.len);
- *outlen = cipher_text.len;
- freeanychunk(cipher_text);
- if (!pkcs11_keep_state)
+ }
+
+ if (!encrypt_flag)
+ {
+ plog("public key cannot be used for encryption");
scx_release_context(sc);
- return TRUE;
+ return FALSE;
}
- else
+
+ /* there must be enough space left for the PKCS#1 v1.5 padding */
+ if (inlen > attr[0].ulValueLen - 11)
{
- plog("error in C_EncryptInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
- }
-
- DBG(DBG_CONTROL,
- DBG_log("doing RSA encryption on smartcard")
- )
- rv = pkcs11_functions->C_Encrypt(sc->session, (u_char*)in, inlen
- , out, &len);
- if (rv != CKR_OK)
- {
- plog("error in C_Encrypt: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
+ plog("smartcard input data length (%d) exceeds maximum of %lu bytes"
+ , (int)inlen, attr[0].ulValueLen - 11);
+ if (!pkcs11_keep_state)
+ scx_release_context(sc);
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_EncryptInit(sc->session, &mech, object);
+
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_FUNCTION_NOT_SUPPORTED)
+ {
+ public_key_t *key;
+ chunk_t rsa_modulus, rsa_exponent, rsa_key, cipher_text;
+ chunk_t plain_text = {(u_char*)in, inlen};
+
+ DBG(DBG_CONTROL,
+ DBG_log("doing RSA encryption in software")
+ )
+ attr[0].pValue = malloc(attr[0].ulValueLen);
+ attr[1].pValue = malloc(attr[1].ulValueLen);
+
+ rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2);
+ if (rv != CKR_OK)
+ {
+ plog("couldn't read modulus and public exponent: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ free(attr[0].pValue);
+ free(attr[1].pValue);
+ scx_release_context(sc);
+ return FALSE;
+ }
+ rsa_modulus = chunk_create((u_char*) attr[0].pValue,
+ (size_t) attr[0].ulValueLen);
+ rsa_exponent = chunk_create((u_char*) attr[1].pValue,
+ (size_t) attr[1].ulValueLen);
+ rsa_key = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_integer("m", rsa_modulus),
+ asn1_integer("m", rsa_exponent));
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, rsa_key, BUILD_END);
+ free(rsa_key.ptr);
+ if (key == NULL)
+ {
+ return FALSE;
+ }
+ key->encrypt(key, plain_text, &cipher_text);
+ key->destroy(key);
+
+ if (cipher_text.ptr == NULL)
+ {
+ plog("smartcard input data length is too large");
+ if (!pkcs11_keep_state)
+ {
+ scx_release_context(sc);
+ }
+ return FALSE;
+ }
+
+ memcpy(out, cipher_text.ptr, cipher_text.len);
+ *outlen = cipher_text.len;
+ free(cipher_text.ptr);
+
+ if (!pkcs11_keep_state)
+ {
+ scx_release_context(sc);
+ }
+ return TRUE;
+ }
+ else
+ {
+ plog("error in C_EncryptInit: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ scx_release_context(sc);
+ return FALSE;
+ }
+ }
- *outlen = (size_t)len;
- return TRUE;
+ DBG(DBG_CONTROL,
+ DBG_log("doing RSA encryption on smartcard")
+ )
+ rv = pkcs11_functions->C_Encrypt(sc->session, (u_char*)in, inlen
+ , out, &len);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_Encrypt: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ scx_release_context(sc);
+ return FALSE;
+ }
+ if (!pkcs11_keep_state)
+ scx_release_context(sc);
+
+ *outlen = (size_t)len;
+ return TRUE;
#else
- return FALSE;
+ return FALSE;
#endif
}
/*
@@ -1522,70 +1535,70 @@ scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
, u_char *out, size_t *outlen)
{
#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ULONG len = (CK_ULONG)(*outlen);
- CK_BBOOL decrypt_flag;
- CK_ATTRIBUTE attr[] = {
- { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) }
- };
- CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
-
- if (!scx_establish_context(sc) || !scx_login(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
- {
- plog("unable to find private key with id '%s'", sc->id);
- return FALSE;
- }
+ CK_RV rv;
+ CK_OBJECT_HANDLE object;
+ CK_ULONG len = (CK_ULONG)(*outlen);
+ CK_BBOOL decrypt_flag;
+ CK_ATTRIBUTE attr[] = {
+ { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) }
+ };
+ CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
+
+ if (!scx_establish_context(sc) || !scx_login(sc))
+ {
+ scx_release_context(sc);
+ return FALSE;
+ }
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 1);
- if (rv != CKR_OK)
- {
- plog("couldn't read the private key attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
+ if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
+ {
+ plog("unable to find private key with id '%s'", sc->id);
+ return FALSE;
+ }
- if (!decrypt_flag)
- {
- plog("private key cannot be used for decryption");
- scx_release_context(sc);
- return FALSE;
- }
-
- DBG(DBG_CONTROL,
- DBG_log("doing RSA decryption on smartcard")
- )
- rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object);
- if (rv != CKR_OK)
- {
- plog("error in C_DecryptInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Decrypt(sc->session, (u_char*)in, inlen
- , out, &len);
- if (rv != CKR_OK)
- {
- plog("error in C_Decrypt: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
+ rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 1);
+ if (rv != CKR_OK)
+ {
+ plog("couldn't read the private key attributes: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
- *outlen = (size_t)len;
- return TRUE;
+ if (!decrypt_flag)
+ {
+ plog("private key cannot be used for decryption");
+ scx_release_context(sc);
+ return FALSE;
+ }
+
+ DBG(DBG_CONTROL,
+ DBG_log("doing RSA decryption on smartcard")
+ )
+ rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_DecryptInit: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ scx_release_context(sc);
+ return FALSE;
+ }
+
+ rv = pkcs11_functions->C_Decrypt(sc->session, (u_char*)in, inlen
+ , out, &len);
+ if (rv != CKR_OK)
+ {
+ plog("error in C_Decrypt: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ scx_release_context(sc);
+ return FALSE;
+ }
+ if (!pkcs11_keep_state)
+ scx_release_context(sc);
+
+ *outlen = (size_t)len;
+ return TRUE;
#else
- return FALSE;
+ return FALSE;
#endif
}
@@ -1597,92 +1610,92 @@ bool
scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
, const char* keyid, int whackfd)
{
- char inbuf[RSA_MAX_OCTETS];
- char outbuf[2*RSA_MAX_OCTETS + 1];
- size_t outlen = sizeof(inbuf);
- size_t inlen;
- smartcard_t *sc,*sc_new;
+ char inbuf[RSA_MAX_OCTETS];
+ char outbuf[2*RSA_MAX_OCTETS + 1];
+ size_t outlen = sizeof(inbuf);
+ size_t inlen;
+ smartcard_t *sc,*sc_new;
- const char *number_slot_id = "";
+ const char *number_slot_id = "";
- err_t ugh = ttodata(msg, 0, inbase, inbuf, sizeof(inbuf), &inlen);
+ err_t ugh = ttodata(msg, 0, inbase, inbuf, sizeof(inbuf), &inlen);
- /* no prefix - use default base */
- if (ugh != NULL && inbase == 0)
- ugh = ttodata(msg, 0, DEFAULT_BASE, inbuf, sizeof(inbuf), &inlen);
+ /* no prefix - use default base */
+ if (ugh != NULL && inbase == 0)
+ ugh = ttodata(msg, 0, DEFAULT_BASE, inbuf, sizeof(inbuf), &inlen);
- if (ugh != NULL)
- {
- plog("format error in smartcard input data: %s", ugh);
- return FALSE;
- }
-
- if (keyid != NULL)
- {
- number_slot_id = (strncmp(keyid, SCX_TOKEN, strlen(SCX_TOKEN)) == 0)
- ? keyid + strlen(SCX_TOKEN) : keyid;
- }
-
- sc_new = scx_parse_number_slot_id(number_slot_id);
- sc = scx_add(sc_new);
- if (sc == sc_new)
- scx_share(sc);
-
- DBG((op == SC_OP_ENCRYPT)? DBG_PRIVATE:DBG_RAW,
- DBG_dump("smartcard input data:\n", inbuf, inlen)
- )
-
- if (op == SC_OP_DECRYPT)
- {
- if (!sc->valid && whackfd != NULL_FD)
- scx_get_pin(sc, whackfd);
-
- if (!sc->valid)
- {
- loglog(RC_NOVALIDPIN, "cannot decrypt without valid PIN");
- return FALSE;
- }
- }
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("using RSA key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
- )
-
- switch (op)
- {
- case SC_OP_ENCRYPT:
- if (!scx_encrypt(sc, inbuf, inlen, inbuf, &outlen))
- return FALSE;
- break;
- case SC_OP_DECRYPT:
- if (!scx_decrypt(sc, inbuf, inlen, inbuf, &outlen))
- return FALSE;
- break;
- default:
- break;
- }
-
- DBG((op == SC_OP_DECRYPT)? DBG_PRIVATE:DBG_RAW,
- DBG_dump("smartcard output data:\n", inbuf, outlen)
- )
-
- if (outbase == 0) /* use default base */
- outbase = DEFAULT_BASE;
-
- if (outbase == 256) /* ascii plain text */
- whack_log(RC_COMMENT, "%.*s", (int)outlen, inbuf);
- else
- {
- outlen = datatot(inbuf, outlen, outbase, outbuf, sizeof(outbuf));
- if (outlen == 0)
- {
- plog("error in output format conversion");
- return FALSE;
- }
- whack_log(RC_COMMENT, "%s", outbuf);
- }
- return TRUE;
+ if (ugh != NULL)
+ {
+ plog("format error in smartcard input data: %s", ugh);
+ return FALSE;
+ }
+
+ if (keyid != NULL)
+ {
+ number_slot_id = (strneq(keyid, SCX_TOKEN, strlen(SCX_TOKEN)))
+ ? keyid + strlen(SCX_TOKEN) : keyid;
+ }
+
+ sc_new = scx_parse_number_slot_id(number_slot_id);
+ sc = scx_add(sc_new);
+ if (sc == sc_new)
+ scx_share(sc);
+
+ DBG((op == SC_OP_ENCRYPT)? DBG_PRIVATE:DBG_RAW,
+ DBG_dump("smartcard input data:\n", inbuf, inlen)
+ )
+
+ if (op == SC_OP_DECRYPT)
+ {
+ if (!sc->valid && whackfd != NULL_FD)
+ scx_get_pin(sc, whackfd);
+
+ if (!sc->valid)
+ {
+ loglog(RC_NOVALIDPIN, "cannot decrypt without valid PIN");
+ return FALSE;
+ }
+ }
+
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("using RSA key from smartcard (slot: %d, id: %s)"
+ , (int)sc->slot, sc->id)
+ )
+
+ switch (op)
+ {
+ case SC_OP_ENCRYPT:
+ if (!scx_encrypt(sc, inbuf, inlen, inbuf, &outlen))
+ return FALSE;
+ break;
+ case SC_OP_DECRYPT:
+ if (!scx_decrypt(sc, inbuf, inlen, inbuf, &outlen))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+
+ DBG((op == SC_OP_DECRYPT)? DBG_PRIVATE:DBG_RAW,
+ DBG_dump("smartcard output data:\n", inbuf, outlen)
+ )
+
+ if (outbase == 0) /* use default base */
+ outbase = DEFAULT_BASE;
+
+ if (outbase == 256) /* ascii plain text */
+ whack_log(RC_COMMENT, "%.*s", (int)outlen, inbuf);
+ else
+ {
+ outlen = datatot(inbuf, outlen, outbase, outbuf, sizeof(outbuf));
+ if (outlen == 0)
+ {
+ plog("error in output format conversion");
+ return FALSE;
+ }
+ whack_log(RC_COMMENT, "%s", outbuf);
+ }
+ return TRUE;
}
/*
@@ -1692,32 +1705,32 @@ size_t
scx_get_keylength(smartcard_t *sc)
{
#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ATTRIBUTE attr[] = {{ CKA_MODULUS, NULL_PTR, 0}};
+ CK_RV rv;
+ CK_OBJECT_HANDLE object;
+ CK_ATTRIBUTE attr[] = {{ CKA_MODULUS, NULL_PTR, 0}};
- if (!sc->logged_in)
- return FALSE;
+ if (!sc->logged_in)
+ return FALSE;
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
- {
- plog("unable to find private key with id '%s'", sc->id);
- return FALSE;
- }
-
- /* get the length of the private key */
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object
- , (CK_ATTRIBUTE_PTR)&attr, 1);
- if (rv != CKR_OK)
- {
- plog("failed to get key length: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
+ if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
+ {
+ plog("unable to find private key with id '%s'", sc->id);
+ return FALSE;
+ }
+
+ /* get the length of the private key */
+ rv = pkcs11_functions->C_GetAttributeValue(sc->session, object
+ , (CK_ATTRIBUTE_PTR)&attr, 1);
+ if (rv != CKR_OK)
+ {
+ plog("failed to get key length: %s"
+ , enum_show(&pkcs11_return_names, rv));
+ return FALSE;
+ }
- return attr[0].ulValueLen; /*Return key length in bytes */
+ return attr[0].ulValueLen; /*Return key length in bytes */
#else
- return 0;
+ return 0;
#endif
}
@@ -1728,54 +1741,55 @@ bool
scx_get_pin(smartcard_t *sc, int whackfd)
{
#ifdef SMARTCARD
- char pin[BUF_LEN];
- int i, n;
+ char pin[BUF_LEN];
+ int i, n;
- whack_log(RC_ENTERSECRET, "need PIN for #%d (%s, id: %s, label: '%s')"
- , sc->number, scx_print_slot(sc, ""), sc->id, sc->label);
+ whack_log(RC_ENTERSECRET, "need PIN for #%d (%s, id: %s, label: '%s')"
+ , sc->number, scx_print_slot(sc, ""), sc->id, sc->label);
- for (i = 0; i < SCX_MAX_PIN_TRIALS; i++)
- {
- if (i > 0)
- whack_log(RC_ENTERSECRET, "invalid PIN, please try again");
-
- n = read(whackfd, pin, BUF_LEN);
-
- if (n == -1)
+ for (i = 0; i < SCX_MAX_PIN_TRIALS; i++)
{
- whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
- return FALSE;
+ if (i > 0)
+ whack_log(RC_ENTERSECRET, "invalid PIN, please try again");
+
+ n = read(whackfd, pin, BUF_LEN);
+
+ if (n == -1)
+ {
+ whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
+ return FALSE;
+ }
+
+ if (strlen(pin) == 0)
+ {
+ whack_log(RC_LOG_SERIOUS, "no PIN entered, aborted");
+ return FALSE;
+ }
+
+ sc->pin.ptr = pin;
+ sc->pin.len = strlen(pin);
+
+ /* verify the pin */
+ if (scx_verify_pin(sc))
+ {
+ sc->pin = chunk_create(pin, strlen(pin));
+ sc->pin = chunk_clone(sc->pin);
+ break;
+ }
+
+ /* wrong pin - we try another round */
+ sc->pin = chunk_empty;
}
- if (strlen(pin) == 0)
- {
- whack_log(RC_LOG_SERIOUS, "no PIN entered, aborted");
- return FALSE;
- }
-
- sc->pin.ptr = pin;
- sc->pin.len = strlen(pin);
-
- /* verify the pin */
- if (scx_verify_pin(sc))
- {
- clonetochunk(sc->pin, pin, strlen(pin), "pin");
- break;
- }
-
- /* wrong pin - we try another round */
- sc->pin = empty_chunk;
- }
-
- if (sc->valid)
- whack_log(RC_SUCCESS, "valid PIN");
- else
- whack_log(RC_LOG_SERIOUS, "invalid PIN, too many trials");
+ if (sc->valid)
+ whack_log(RC_SUCCESS, "valid PIN");
+ else
+ whack_log(RC_LOG_SERIOUS, "invalid PIN, too many trials");
#else
- sc->valid = FALSE;
- whack_log(RC_LOG_SERIOUS, "SMARTCARD support is deactivated in pluto/Makefile!");
+ sc->valid = FALSE;
+ whack_log(RC_LOG_SERIOUS, "SMARTCARD support is deactivated in pluto/Makefile!");
#endif
- return sc->valid;
+ return sc->valid;
}
@@ -1785,13 +1799,13 @@ scx_get_pin(smartcard_t *sc, int whackfd)
void
scx_free_pin(chunk_t *pin)
{
- if (pin->ptr != NULL)
- {
- /* clear pin field in memory */
- memset(pin->ptr, '\0', pin->len);
- pfree(pin->ptr);
- *pin = empty_chunk;
- }
+ if (pin->ptr != NULL)
+ {
+ /* clear pin field in memory */
+ memset(pin->ptr, '\0', pin->len);
+ free(pin->ptr);
+ *pin = chunk_empty;
+ }
}
/*
@@ -1800,14 +1814,14 @@ scx_free_pin(chunk_t *pin)
void
scx_free(smartcard_t *sc)
{
- if (sc != NULL)
- {
- scx_release_context(sc);
- pfreeany(sc->id);
- pfreeany(sc->label);
- scx_free_pin(&sc->pin);
- pfree(sc);
- }
+ if (sc != NULL)
+ {
+ scx_release_context(sc);
+ free(sc->id);
+ free(sc->label);
+ scx_free_pin(&sc->pin);
+ free(sc);
+ }
}
/* release of a smartcard record decreases the count by one
@@ -1816,15 +1830,15 @@ scx_free(smartcard_t *sc)
void
scx_release(smartcard_t *sc)
{
- if (sc != NULL && --sc->count == 0)
- {
- smartcard_t **pp = &smartcards;
- while (*pp != sc)
- pp = &(*pp)->next;
- *pp = sc->next;
- release_cert(sc->last_cert);
- scx_free(sc);
- }
+ if (sc != NULL && --sc->count == 0)
+ {
+ smartcard_t **pp = &smartcards;
+ while (*pp != sc)
+ pp = &(*pp)->next;
+ *pp = sc->next;
+ release_cert(sc->last_cert);
+ scx_free(sc);
+ }
}
/*
@@ -1833,17 +1847,17 @@ scx_release(smartcard_t *sc)
static bool
scx_same(smartcard_t *a, smartcard_t *b)
{
- if (a->number && b->number)
- {
- /* same number */
- return a->number == b->number;
- }
- else
- {
- /* same id and/or same slot */
- return (!a->id || (b->id && streq(a->id, b->id)))
- && (a->any_slot || b->any_slot || a->slot == b->slot);
- }
+ if (a->number && b->number)
+ {
+ /* same number */
+ return a->number == b->number;
+ }
+ else
+ {
+ /* same id and/or same slot */
+ return (!a->id || (b->id && streq(a->id, b->id)))
+ && (a->any_slot || b->any_slot || a->slot == b->slot);
+ }
}
/* for each link pointing to the smartcard record
@@ -1852,8 +1866,8 @@ scx_same(smartcard_t *a, smartcard_t *b)
void
scx_share(smartcard_t *sc)
{
- if (sc != NULL)
- sc->count++;
+ if (sc != NULL)
+ sc->count++;
}
/*
@@ -1862,28 +1876,28 @@ scx_share(smartcard_t *sc)
smartcard_t*
scx_add(smartcard_t *smartcard)
{
- smartcard_t *sc = smartcards;
- smartcard_t **psc = &smartcards;
-
- while (sc != NULL)
- {
- if (scx_same(smartcard, sc)) /* already in chain, free smartcard record */
- {
- scx_free(smartcard);
- return sc;
- }
- psc = &sc->next;
- sc = sc->next;
- }
-
- /* insert new smartcard record at the end of the chain */
- *psc = smartcard;
- smartcard->number = ++sc_number;
- smartcard->count = 1;
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" smartcard #%d added", sc_number)
- )
- return smartcard;
+ smartcard_t *sc = smartcards;
+ smartcard_t **psc = &smartcards;
+
+ while (sc != NULL)
+ {
+ if (scx_same(smartcard, sc)) /* already in chain, free smartcard record */
+ {
+ scx_free(smartcard);
+ return sc;
+ }
+ psc = &sc->next;
+ sc = sc->next;
+ }
+
+ /* insert new smartcard record at the end of the chain */
+ *psc = smartcard;
+ smartcard->number = ++sc_number;
+ smartcard->count = 1;
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log(" smartcard #%d added", sc_number)
+ )
+ return smartcard;
}
/*
@@ -1892,15 +1906,15 @@ scx_add(smartcard_t *smartcard)
smartcard_t*
scx_get(x509cert_t *cert)
{
- smartcard_t *sc = smartcards;
-
- while (sc != NULL)
- {
- if (sc->last_cert.u.x509 == cert)
- return sc;
- sc = sc->next;
- }
- return NULL;
+ smartcard_t *sc = smartcards;
+
+ while (sc != NULL)
+ {
+ if (sc->last_cert.u.x509 == cert)
+ return sc;
+ sc = sc->next;
+ }
+ return NULL;
}
/*
@@ -1909,13 +1923,13 @@ scx_get(x509cert_t *cert)
char *
scx_print_slot(smartcard_t *sc, const char *whitespace)
{
- char *buf = temporary_cyclic_buffer();
+ char *buf = temporary_cyclic_buffer();
- if (sc->any_slot)
- snprintf(buf, BUF_LEN, "any slot");
- else
- snprintf(buf, BUF_LEN, "slot: %s%lu", whitespace, sc->slot);
- return buf;
+ if (sc->any_slot)
+ snprintf(buf, BUF_LEN, "any slot");
+ else
+ snprintf(buf, BUF_LEN, "slot: %s%lu", whitespace, sc->slot);
+ return buf;
}
/*
@@ -1924,39 +1938,39 @@ scx_print_slot(smartcard_t *sc, const char *whitespace)
void
scx_list(bool utc)
{
- smartcard_t *sc = smartcards;
-
- if (sc != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of Smartcard Objects:");
- whack_log(RC_COMMENT, " ");
- }
-
- while (sc != NULL)
- {
- whack_log(RC_COMMENT, "%s, #%d, count: %d"
- , timetoa(&sc->last_load, utc)
- , sc->number
- , sc->count);
- whack_log(RC_COMMENT, " %s, session %s, logged %s, has %s"
- , scx_print_slot(sc, " ")
- , sc->session_opened? "opened" : "closed"
- , sc->logged_in? "in" : "out"
- , sc->pinpad? "pin pad"
- : ((sc->pin.ptr == NULL)? "no pin"
- : sc->valid? "valid pin" : "invalid pin"));
- if (sc->id != NULL)
- whack_log(RC_COMMENT, " id: %s", sc->id);
- if (sc->label != NULL)
- whack_log(RC_COMMENT, " label: '%s'", sc->label);
- if (sc->last_cert.type == CERT_X509_SIGNATURE)
- {
- char buf[BUF_LEN];
-
- dntoa(buf, BUF_LEN, sc->last_cert.u.x509->subject);
- whack_log(RC_COMMENT, " subject: '%s'", buf);
- }
- sc = sc->next;
- }
+ smartcard_t *sc = smartcards;
+
+ if (sc != NULL)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of Smartcard Objects:");
+ whack_log(RC_COMMENT, " ");
+ }
+
+ while (sc != NULL)
+ {
+ whack_log(RC_COMMENT, "%T, #%d, count: %d"
+ , &sc->last_load, utc
+ , sc->number
+ , sc->count);
+ whack_log(RC_COMMENT, " %s, session %s, logged %s, has %s"
+ , scx_print_slot(sc, " ")
+ , sc->session_opened? "opened" : "closed"
+ , sc->logged_in? "in" : "out"
+ , sc->pinpad? "pin pad"
+ : ((sc->pin.ptr == NULL)? "no pin"
+ : sc->valid? "valid pin" : "invalid pin"));
+ if (sc->id != NULL)
+ whack_log(RC_COMMENT, " id: %s", sc->id);
+ if (sc->label != NULL)
+ whack_log(RC_COMMENT, " label: '%s'", sc->label);
+ if (sc->last_cert.type == CERT_X509_SIGNATURE)
+ {
+ char buf[BUF_LEN];
+
+ dntoa(buf, BUF_LEN, sc->last_cert.u.x509->subject);
+ whack_log(RC_COMMENT, " subject: '%s'", buf);
+ }
+ sc = sc->next;
+ }
}
diff --git a/src/pluto/smartcard.h b/src/pluto/smartcard.h
index 69510171c..60a0fccfc 100644
--- a/src/pluto/smartcard.h
+++ b/src/pluto/smartcard.h
@@ -12,8 +12,6 @@
* 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: smartcard.h 4709 2008-11-27 10:20:25Z martin $
*/
#ifndef _SMARTCARD_H
@@ -21,19 +19,19 @@
#include "certs.h"
-#define SCX_TOKEN "%smartcard"
-#define SCX_CERT_CACHE_INTERVAL 60 /* seconds */
-#define SCX_MAX_PIN_TRIALS 3
+#define SCX_TOKEN "%smartcard"
+#define SCX_CERT_CACHE_INTERVAL 60 /* seconds */
+#define SCX_MAX_PIN_TRIALS 3
/* smartcard operations, update copy in whack.h */
#ifndef SC_OP_T
#define SC_OP_T
typedef enum {
- SC_OP_NONE = 0,
- SC_OP_ENCRYPT = 1,
- SC_OP_DECRYPT = 2,
- SC_OP_SIGN = 3,
+ SC_OP_NONE = 0,
+ SC_OP_ENCRYPT = 1,
+ SC_OP_DECRYPT = 2,
+ SC_OP_SIGN = 3,
} sc_op_t;
#endif /* SC_OP_T */
@@ -42,21 +40,21 @@ typedef enum {
typedef struct smartcard smartcard_t;
struct smartcard {
- smartcard_t *next;
- time_t last_load;
- cert_t last_cert;
- int count;
- int number;
- unsigned long slot;
- char *id;
- char *label;
- chunk_t pin;
- bool pinpad;
- bool valid;
- bool session_opened;
- bool logged_in;
- bool any_slot;
- long session;
+ smartcard_t *next;
+ time_t last_load;
+ cert_t last_cert;
+ int count;
+ int number;
+ unsigned long slot;
+ char *id;
+ char *label;
+ chunk_t pin;
+ bool pinpad;
+ bool valid;
+ bool session_opened;
+ bool logged_in;
+ bool any_slot;
+ long session;
};
extern const smartcard_t empty_sc;
@@ -78,17 +76,17 @@ extern bool scx_establish_context(smartcard_t *sc);
extern bool scx_login(smartcard_t *sc);
extern bool scx_on_smartcard(const char *filename);
extern bool scx_load_cert(const char *filename, smartcard_t **scp
- , cert_t *cert, bool *cached);
+ , cert_t *cert, bool *cached);
extern bool scx_verify_pin(smartcard_t *sc);
extern void scx_share(smartcard_t *sc);
extern bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
- , u_char *out, size_t outlen);
+ , u_char *out, size_t outlen);
extern bool scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
- , u_char *out, size_t *outlen);
+ , u_char *out, size_t *outlen);
extern bool scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
- , u_char *out, size_t *outlen);
+ , u_char *out, size_t *outlen);
extern bool scx_op_via_whack(const char* msg, int inbase, int outbase
- , sc_op_t op, const char *keyid, int whackfd);
+ , sc_op_t op, const char *keyid, int whackfd);
extern bool scx_get_pin(smartcard_t *sc, int whackfd);
extern size_t scx_get_keylength(smartcard_t *sc);
extern smartcard_t* scx_add(smartcard_t *sc);
diff --git a/src/pluto/spdb.c b/src/pluto/spdb.c
index 9d1bf8843..b8f4a3c23 100644
--- a/src/pluto/spdb.c
+++ b/src/pluto/spdb.c
@@ -10,8 +10,6 @@
* 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: spdb.c 3845 2008-04-18 17:00:30Z andreas $
*/
#include <stdio.h>
@@ -23,7 +21,6 @@
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "constants.h"
#include "defs.h"
@@ -36,16 +33,14 @@
#include "log.h"
#include "spdb.h"
#include "whack.h"
-#include "sha1.h"
-#include "md5.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
+#include "crypto.h"
#include "alg_info.h"
#include "kernel_alg.h"
#include "ike_alg.h"
#include "db_ops.h"
#include "nat_traversal.h"
-#define AD(x) x, elemsof(x) /* Array Description */
+#define AD(x) x, countof(x) /* Array Description */
#define AD_NULL NULL, 0
/**************** Oakely (main mode) SA database ****************/
@@ -53,7 +48,7 @@
/* array of proposals to be conjoined (can only be one for Oakley) */
static struct db_prop oakley_pc[] =
- { { PROTO_ISAKMP, AD_NULL } };
+ { { PROTO_ISAKMP, AD_NULL } };
/* array of proposal conjuncts (can only be one) */
@@ -67,131 +62,131 @@ struct db_sa oakley_sadb = { AD(oakley_props) };
/* arrays of attributes for transforms */
static struct db_attr espsha1_attr[] = {
- { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
- };
+ { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
+ };
static struct db_attr ah_HMAC_SHA1_attr[] = {
- { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
- };
+ { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
+ };
/* arrays of transforms, each in in preference order */
static struct db_trans espa_trans[] = {
- { ESP_3DES, AD(espsha1_attr) },
- };
+ { ESP_3DES, AD(espsha1_attr) },
+ };
static struct db_trans esp_trans[] = {
- { ESP_3DES, AD_NULL },
- };
+ { ESP_3DES, AD_NULL },
+ };
#ifdef SUPPORT_ESP_NULL
static struct db_trans espnull_trans[] = {
- { ESP_NULL, AD(espsha1_attr) },
- };
+ { ESP_NULL, AD(espsha1_attr) },
+ };
#endif /* SUPPORT_ESP_NULL */
static struct db_trans ah_trans[] = {
- { AH_SHA, AD(ah_HMAC_SHA1_attr) },
- };
+ { AH_SHA, AD(ah_HMAC_SHA1_attr) },
+ };
static struct db_trans ipcomp_trans[] = {
- { IPCOMP_DEFLATE, AD_NULL },
- };
+ { IPCOMP_DEFLATE, AD_NULL },
+ };
/* arrays of proposals to be conjoined */
static struct db_prop ah_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- };
+ { PROTO_IPSEC_AH, AD(ah_trans) },
+ };
#ifdef SUPPORT_ESP_NULL
static struct db_prop espnull_pc[] = {
- { PROTO_IPSEC_ESP, AD(espnull_trans) },
- };
+ { PROTO_IPSEC_ESP, AD(espnull_trans) },
+ };
#endif /* SUPPORT_ESP_NULL */
static struct db_prop esp_pc[] = {
- { PROTO_IPSEC_ESP, AD(espa_trans) },
- };
+ { PROTO_IPSEC_ESP, AD(espa_trans) },
+ };
static struct db_prop ah_esp_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- { PROTO_IPSEC_ESP, AD(esp_trans) },
- };
+ { PROTO_IPSEC_AH, AD(ah_trans) },
+ { PROTO_IPSEC_ESP, AD(esp_trans) },
+ };
static struct db_prop compress_pc[] = {
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
+ { PROTO_IPCOMP, AD(ipcomp_trans) },
+ };
static struct db_prop ah_compress_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
+ { PROTO_IPSEC_AH, AD(ah_trans) },
+ { PROTO_IPCOMP, AD(ipcomp_trans) },
+ };
#ifdef SUPPORT_ESP_NULL
static struct db_prop espnull_compress_pc[] = {
- { PROTO_IPSEC_ESP, AD(espnull_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
+ { PROTO_IPSEC_ESP, AD(espnull_trans) },
+ { PROTO_IPCOMP, AD(ipcomp_trans) },
+ };
#endif /* SUPPORT_ESP_NULL */
static struct db_prop esp_compress_pc[] = {
- { PROTO_IPSEC_ESP, AD(espa_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
+ { PROTO_IPSEC_ESP, AD(espa_trans) },
+ { PROTO_IPCOMP, AD(ipcomp_trans) },
+ };
static struct db_prop ah_esp_compress_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- { PROTO_IPSEC_ESP, AD(esp_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
+ { PROTO_IPSEC_AH, AD(ah_trans) },
+ { PROTO_IPSEC_ESP, AD(esp_trans) },
+ { PROTO_IPCOMP, AD(ipcomp_trans) },
+ };
/* arrays of proposal alternatives (each element is a conjunction) */
static struct db_prop_conj ah_props[] = {
- { AD(ah_pc) },
+ { AD(ah_pc) },
#ifdef SUPPORT_ESP_NULL
- { AD(espnull_pc) }
+ { AD(espnull_pc) }
#endif
- };
+ };
static struct db_prop_conj esp_props[] =
- { { AD(esp_pc) } };
+ { { AD(esp_pc) } };
static struct db_prop_conj ah_esp_props[] =
- { { AD(ah_esp_pc) } };
+ { { AD(ah_esp_pc) } };
static struct db_prop_conj compress_props[] = {
- { AD(compress_pc) },
- };
+ { AD(compress_pc) },
+ };
static struct db_prop_conj ah_compress_props[] = {
- { AD(ah_compress_pc) },
+ { AD(ah_compress_pc) },
#ifdef SUPPORT_ESP_NULL
- { AD(espnull_compress_pc) }
+ { AD(espnull_compress_pc) }
#endif
- };
+ };
static struct db_prop_conj esp_compress_props[] =
- { { AD(esp_compress_pc) } };
+ { { AD(esp_compress_pc) } };
static struct db_prop_conj ah_esp_compress_props[] =
- { { AD(ah_esp_compress_pc) } };
+ { { AD(ah_esp_compress_pc) } };
/* The IPsec sadb is subscripted by a bitset (subset of policy)
* with members from { POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS }
* shifted right by POLICY_IPSEC_SHIFT.
*/
struct db_sa ipsec_sadb[1 << 3] = {
- { AD_NULL }, /* none */
- { AD(esp_props) }, /* POLICY_ENCRYPT */
- { AD(ah_props) }, /* POLICY_AUTHENTICATE */
- { AD(ah_esp_props) }, /* POLICY_ENCRYPT+POLICY_AUTHENTICATE */
- { AD(compress_props) }, /* POLICY_COMPRESS */
- { AD(esp_compress_props) }, /* POLICY_ENCRYPT+POLICY_COMPRESS */
- { AD(ah_compress_props) }, /* POLICY_AUTHENTICATE+POLICY_COMPRESS */
- { AD(ah_esp_compress_props) }, /* POLICY_ENCRYPT+POLICY_AUTHENTICATE+POLICY_COMPRESS */
- };
+ { AD_NULL }, /* none */
+ { AD(esp_props) }, /* POLICY_ENCRYPT */
+ { AD(ah_props) }, /* POLICY_AUTHENTICATE */
+ { AD(ah_esp_props) }, /* POLICY_ENCRYPT+POLICY_AUTHENTICATE */
+ { AD(compress_props) }, /* POLICY_COMPRESS */
+ { AD(esp_compress_props) }, /* POLICY_ENCRYPT+POLICY_COMPRESS */
+ { AD(ah_compress_props) }, /* POLICY_AUTHENTICATE+POLICY_COMPRESS */
+ { AD(ah_esp_compress_props) }, /* POLICY_ENCRYPT+POLICY_AUTHENTICATE+POLICY_COMPRESS */
+ };
#undef AD
#undef AD_NULL
@@ -204,41 +199,41 @@ out_attr(int type
, enum_names **attr_val_descs USED_BY_DEBUG
, pb_stream *pbs)
{
- struct isakmp_attribute attr;
-
- if (val >> 16 == 0)
- {
- /* short value: use TV form */
- attr.isaat_af_type = type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = val;
- if (!out_struct(&attr, attr_desc, pbs, NULL))
- return FALSE;
- }
- else
- {
- /* This is a real fudge! Since we rarely use long attributes
- * and since this is the only place where we can cause an
- * ISAKMP message length to be other than a multiple of 4 octets,
- * we force the length of the value to be a multiple of 4 octets.
- * Furthermore, we only handle values up to 4 octets in length.
- * Voila: a fixed format!
- */
- pb_stream val_pbs;
- u_int32_t nval = htonl(val);
-
- attr.isaat_af_type = type | ISAKMP_ATTR_AF_TLV;
- if (!out_struct(&attr, attr_desc, pbs, &val_pbs)
- || !out_raw(&nval, sizeof(nval), &val_pbs, "long attribute value"))
- return FALSE;
- close_output_pbs(&val_pbs);
- }
- DBG(DBG_EMITTING,
- enum_names *d = attr_val_descs[type];
-
- if (d != NULL)
- DBG_log(" [%lu is %s]"
- , val, enum_show(d, val)));
- return TRUE;
+ struct isakmp_attribute attr;
+
+ if (val >> 16 == 0)
+ {
+ /* short value: use TV form */
+ attr.isaat_af_type = type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = val;
+ if (!out_struct(&attr, attr_desc, pbs, NULL))
+ return FALSE;
+ }
+ else
+ {
+ /* This is a real fudge! Since we rarely use long attributes
+ * and since this is the only place where we can cause an
+ * ISAKMP message length to be other than a multiple of 4 octets,
+ * we force the length of the value to be a multiple of 4 octets.
+ * Furthermore, we only handle values up to 4 octets in length.
+ * Voila: a fixed format!
+ */
+ pb_stream val_pbs;
+ u_int32_t nval = htonl(val);
+
+ attr.isaat_af_type = type | ISAKMP_ATTR_AF_TLV;
+ if (!out_struct(&attr, attr_desc, pbs, &val_pbs)
+ || !out_raw(&nval, sizeof(nval), &val_pbs, "long attribute value"))
+ return FALSE;
+ close_output_pbs(&val_pbs);
+ }
+ DBG(DBG_EMITTING,
+ enum_names *d = attr_val_descs[type];
+
+ if (d != NULL)
+ DBG_log(" [%lu is %s]"
+ , val, enum_show(d, val)));
+ return TRUE;
}
#define return_on(var, val) do { var=val;goto return_out; } while(0);
/* Output an SA, as described by a db_sa.
@@ -251,336 +246,336 @@ out_sa(pb_stream *outs
, bool oakley_mode
, u_int8_t np)
{
- pb_stream sa_pbs;
- int pcn;
- bool ret = FALSE;
- bool ah_spi_generated = FALSE
- , esp_spi_generated = FALSE
- , ipcomp_cpi_generated = FALSE;
+ pb_stream sa_pbs;
+ int pcn;
+ bool ret = FALSE;
+ bool ah_spi_generated = FALSE
+ , esp_spi_generated = FALSE
+ , ipcomp_cpi_generated = FALSE;
#if !defined NO_KERNEL_ALG || !defined NO_IKE_ALG
- struct db_context *db_ctx = NULL;
+ struct db_context *db_ctx = NULL;
#endif
- /* SA header out */
- {
- struct isakmp_sa sa;
-
- sa.isasa_np = np;
- st->st_doi = sa.isasa_doi = ISAKMP_DOI_IPSEC; /* all we know */
- if (!out_struct(&sa, &isakmp_sa_desc, outs, &sa_pbs))
- return_on(ret, FALSE);
- }
-
- /* within SA: situation out */
- st->st_situation = SIT_IDENTITY_ONLY;
- if (!out_struct(&st->st_situation, &ipsec_sit_desc, &sa_pbs, NULL))
- return_on(ret, FALSE);
-
- /* within SA: Proposal Payloads
- *
- * Multiple Proposals with the same number are simultaneous
- * (conjuncts) and must deal with different protocols (AH or ESP).
- * Proposals with different numbers are alternatives (disjuncts),
- * in preference order.
- * Proposal numbers must be monotonic.
- * See RFC 2408 "ISAKMP" 4.2
- */
-
- for (pcn = 0; pcn != sadb->prop_conj_cnt; pcn++)
- {
- struct db_prop_conj *pc = &sadb->prop_conjs[pcn];
- int pn;
-
- for (pn = 0; pn != pc->prop_cnt; pn++)
+ /* SA header out */
{
- struct db_prop *p = &pc->props[pn];
- pb_stream proposal_pbs;
- struct isakmp_proposal proposal;
- struct_desc *trans_desc = NULL;
- struct_desc *attr_desc = NULL;
- enum_names **attr_val_descs = NULL;
- int tn;
- bool tunnel_mode;
-
- tunnel_mode = (pn == pc->prop_cnt-1)
- && (st->st_policy & POLICY_TUNNEL);
-
- /* Proposal header */
- proposal.isap_np = pcn == sadb->prop_conj_cnt-1 && pn == pc->prop_cnt-1
- ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_P;
- proposal.isap_proposal = pcn;
- proposal.isap_protoid = p->protoid;
- proposal.isap_spisize = oakley_mode ? 0
- : p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
- : IPSEC_DOI_SPI_SIZE;
-
- /* In quick mode ONLY, create proposal for runtime kernel algos.
- * Replace ESP proposals with runtime created one
- */
- if (!oakley_mode && p->protoid == PROTO_IPSEC_ESP)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- if (st->st_connection->alg_info_esp)
- {
- static char buf[256]="";
-
- alg_info_snprint(buf, sizeof (buf),
- (struct alg_info *)st->st_connection->alg_info_esp);
- DBG_log(buf);
- }
- )
- db_ctx = kernel_alg_db_new(st->st_connection->alg_info_esp, st->st_policy);
- p = db_prop_get(db_ctx);
-
- if (!p || p->trans_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS,
- "empty IPSEC SA proposal to send "
- "(no kernel algorithms for esp selection)");
- return_on(ret, FALSE);
- }
- }
-
- if (oakley_mode && p->protoid == PROTO_ISAKMP)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- if (st->st_connection->alg_info_ike)
- {
- static char buf[256]="";
-
- alg_info_snprint(buf, sizeof (buf),
- (struct alg_info *)st->st_connection->alg_info_ike);
- DBG_log(buf);
- }
- )
- db_ctx = ike_alg_db_new(st->st_connection->alg_info_ike, st->st_policy);
- p = db_prop_get(db_ctx);
-
- if (!p || p->trans_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS,
- "empty ISAKMP SA proposal to send "
- "(no algorithms for ike selection?)");
- return_on(ret, FALSE);
- }
- }
-
- proposal.isap_notrans = p->trans_cnt;
- if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
- return_on(ret, FALSE);
+ struct isakmp_sa sa;
- /* Per-protocols stuff:
- * Set trans_desc.
- * Set attr_desc.
- * Set attr_val_descs.
- * If not oakley_mode, emit SPI.
- * We allocate SPIs on demand.
- * All ESPs in an SA will share a single SPI.
- * All AHs in an SAwill share a single SPI.
- * AHs' SPI will be distinct from ESPs'.
- * This latter is needed because KLIPS doesn't
- * use the protocol when looking up a (dest, protocol, spi).
- * ??? If multiple ESPs are composed, how should their SPIs
- * be allocated?
- */
- {
- ipsec_spi_t *spi_ptr = NULL;
- int proto = 0;
- bool *spi_generated = NULL;
-
- switch (p->protoid)
- {
- case PROTO_ISAKMP:
- passert(oakley_mode);
- trans_desc = &isakmp_isakmp_transform_desc;
- attr_desc = &isakmp_oakley_attribute_desc;
- attr_val_descs = oakley_attr_val_descs;
- /* no SPI needed */
- break;
- case PROTO_IPSEC_AH:
- passert(!oakley_mode);
- trans_desc = &isakmp_ah_transform_desc;
- attr_desc = &isakmp_ipsec_attribute_desc;
- attr_val_descs = ipsec_attr_val_descs;
- spi_ptr = &st->st_ah.our_spi;
- spi_generated = &ah_spi_generated;
- proto = IPPROTO_AH;
- break;
- case PROTO_IPSEC_ESP:
- passert(!oakley_mode);
- trans_desc = &isakmp_esp_transform_desc;
- attr_desc = &isakmp_ipsec_attribute_desc;
- attr_val_descs = ipsec_attr_val_descs;
- spi_ptr = &st->st_esp.our_spi;
- spi_generated = &esp_spi_generated;
- proto = IPPROTO_ESP;
- break;
- case PROTO_IPCOMP:
- passert(!oakley_mode);
- trans_desc = &isakmp_ipcomp_transform_desc;
- attr_desc = &isakmp_ipsec_attribute_desc;
- attr_val_descs = ipsec_attr_val_descs;
-
- /* a CPI isn't quite the same as an SPI
- * so we use specialized code to emit it.
- */
- if (!ipcomp_cpi_generated)
- {
- st->st_ipcomp.our_spi = get_my_cpi(
- &st->st_connection->spd, tunnel_mode);
- if (st->st_ipcomp.our_spi == 0)
- return_on(ret, FALSE); /* problem generating CPI */
-
- ipcomp_cpi_generated = TRUE;
- }
- /* CPI is stored in network low order end of an
- * ipsec_spi_t. So we start a couple of bytes in.
- */
- if (!out_raw((u_char *)&st->st_ipcomp.our_spi
- + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
- , IPCOMP_CPI_SIZE
- , &proposal_pbs, "CPI"))
- return_on(ret, FALSE);
- break;
- default:
- bad_case(p->protoid);
- }
- if (spi_ptr != NULL)
- {
- if (!*spi_generated)
- {
- *spi_ptr = get_ipsec_spi(0
- , proto
- , &st->st_connection->spd
- , tunnel_mode);
- if (*spi_ptr == 0)
- return FALSE;
- *spi_generated = TRUE;
- }
- if (!out_raw((u_char *)spi_ptr, IPSEC_DOI_SPI_SIZE
- , &proposal_pbs, "SPI"))
+ sa.isasa_np = np;
+ st->st_doi = sa.isasa_doi = ISAKMP_DOI_IPSEC; /* all we know */
+ if (!out_struct(&sa, &isakmp_sa_desc, outs, &sa_pbs))
return_on(ret, FALSE);
- }
- }
+ }
- /* within proposal: Transform Payloads */
- for (tn = 0; tn != p->trans_cnt; tn++)
- {
- struct db_trans *t = &p->trans[tn];
- pb_stream trans_pbs;
- struct isakmp_transform trans;
- int an;
+ /* within SA: situation out */
+ st->st_situation = SIT_IDENTITY_ONLY;
+ if (!out_struct(&st->st_situation, &ipsec_sit_desc, &sa_pbs, NULL))
+ return_on(ret, FALSE);
- trans.isat_np = (tn == p->trans_cnt - 1)
- ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_T;
- trans.isat_transnum = tn;
- trans.isat_transid = t->transid;
- if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs))
- return_on(ret, FALSE);
+ /* within SA: Proposal Payloads
+ *
+ * Multiple Proposals with the same number are simultaneous
+ * (conjuncts) and must deal with different protocols (AH or ESP).
+ * Proposals with different numbers are alternatives (disjuncts),
+ * in preference order.
+ * Proposal numbers must be monotonic.
+ * See RFC 2408 "ISAKMP" 4.2
+ */
- /* Within tranform: Attributes. */
+ for (pcn = 0; pcn != sadb->prop_conj_cnt; pcn++)
+ {
+ struct db_prop_conj *pc = &sadb->prop_conjs[pcn];
+ int pn;
- /* For Phase 2 / Quick Mode, GROUP_DESCRIPTION is
- * automatically generated because it must be the same
- * in every transform. Except IPCOMP.
- */
- if (p->protoid != PROTO_IPCOMP
- && st->st_pfs_group != NULL)
+ for (pn = 0; pn != pc->prop_cnt; pn++)
{
- passert(!oakley_mode);
- passert(st->st_pfs_group != &unset_group);
- out_attr(GROUP_DESCRIPTION, st->st_pfs_group->group
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
+ struct db_prop *p = &pc->props[pn];
+ pb_stream proposal_pbs;
+ struct isakmp_proposal proposal;
+ struct_desc *trans_desc = NULL;
+ struct_desc *attr_desc = NULL;
+ enum_names **attr_val_descs = NULL;
+ int tn;
+ bool tunnel_mode;
+
+ tunnel_mode = (pn == pc->prop_cnt-1)
+ && (st->st_policy & POLICY_TUNNEL);
+
+ /* Proposal header */
+ proposal.isap_np = pcn == sadb->prop_conj_cnt-1 && pn == pc->prop_cnt-1
+ ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_P;
+ proposal.isap_proposal = pcn;
+ proposal.isap_protoid = p->protoid;
+ proposal.isap_spisize = oakley_mode ? 0
+ : p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
+ : IPSEC_DOI_SPI_SIZE;
+
+ /* In quick mode ONLY, create proposal for runtime kernel algos.
+ * Replace ESP proposals with runtime created one
+ */
+ if (!oakley_mode && p->protoid == PROTO_IPSEC_ESP)
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ if (st->st_connection->alg_info_esp)
+ {
+ static char buf[BUF_LEN]="";
+
+ alg_info_snprint(buf, sizeof (buf),
+ (struct alg_info *)st->st_connection->alg_info_esp);
+ DBG_log("esp proposal: %s", buf);
+ }
+ )
+ db_ctx = kernel_alg_db_new(st->st_connection->alg_info_esp, st->st_policy);
+ p = db_prop_get(db_ctx);
+
+ if (!p || p->trans_cnt == 0)
+ {
+ loglog(RC_LOG_SERIOUS,
+ "empty IPSEC SA proposal to send "
+ "(no kernel algorithms for esp selection)");
+ return_on(ret, FALSE);
+ }
+ }
- /* automatically generate duration
- * and, for Phase 2 / Quick Mode, encapsulation.
- */
- if (oakley_mode)
- {
- out_attr(OAKLEY_LIFE_TYPE, OAKLEY_LIFE_SECONDS
- , attr_desc, attr_val_descs
- , &trans_pbs);
- out_attr(OAKLEY_LIFE_DURATION
- , st->st_connection->sa_ike_life_seconds
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
- else
- {
- /* RFC 2407 (IPSEC DOI) 4.5 specifies that
- * the default is "unspecified (host-dependent)".
- * This makes little sense, so we always specify it.
- *
- * Unlike other IPSEC transforms, IPCOMP defaults
- * to Transport Mode, so we can exploit the default
- * (draft-shacham-ippcp-rfc2393bis-05.txt 4.1).
- */
- if (p->protoid != PROTO_IPCOMP
- || st->st_policy & POLICY_TUNNEL)
- {
-#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- if ((st->nat_traversal & NAT_T_DETECTED)
- && !(st->st_policy & POLICY_TUNNEL))
+ if (oakley_mode && p->protoid == PROTO_ISAKMP)
{
- /* Inform user that we will not respect policy and only
- * propose Tunnel Mode
- */
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
- "Transport Mode not allowed due to security concerns -- "
- "using Tunnel mode");
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ if (st->st_connection->alg_info_ike)
+ {
+ static char buf[BUF_LEN]="";
+
+ alg_info_snprint(buf, sizeof (buf),
+ (struct alg_info *)st->st_connection->alg_info_ike);
+ DBG_log("ike proposal: %s", buf);
+ }
+ )
+ db_ctx = ike_alg_db_new(st->st_connection, st->st_policy);
+ p = db_prop_get(db_ctx);
+
+ if (!p || p->trans_cnt == 0)
+ {
+ loglog(RC_LOG_SERIOUS,
+ "empty ISAKMP SA proposal to send "
+ "(no algorithms for ike selection?)");
+ return_on(ret, FALSE);
+ }
}
+
+ proposal.isap_notrans = p->trans_cnt;
+ if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
+ return_on(ret, FALSE);
+
+ /* Per-protocols stuff:
+ * Set trans_desc.
+ * Set attr_desc.
+ * Set attr_val_descs.
+ * If not oakley_mode, emit SPI.
+ * We allocate SPIs on demand.
+ * All ESPs in an SA will share a single SPI.
+ * All AHs in an SAwill share a single SPI.
+ * AHs' SPI will be distinct from ESPs'.
+ * This latter is needed because KLIPS doesn't
+ * use the protocol when looking up a (dest, protocol, spi).
+ * ??? If multiple ESPs are composed, how should their SPIs
+ * be allocated?
+ */
+ {
+ ipsec_spi_t *spi_ptr = NULL;
+ int proto = 0;
+ bool *spi_generated = NULL;
+
+ switch (p->protoid)
+ {
+ case PROTO_ISAKMP:
+ passert(oakley_mode);
+ trans_desc = &isakmp_isakmp_transform_desc;
+ attr_desc = &isakmp_oakley_attribute_desc;
+ attr_val_descs = oakley_attr_val_descs;
+ /* no SPI needed */
+ break;
+ case PROTO_IPSEC_AH:
+ passert(!oakley_mode);
+ trans_desc = &isakmp_ah_transform_desc;
+ attr_desc = &isakmp_ipsec_attribute_desc;
+ attr_val_descs = ipsec_attr_val_descs;
+ spi_ptr = &st->st_ah.our_spi;
+ spi_generated = &ah_spi_generated;
+ proto = IPPROTO_AH;
+ break;
+ case PROTO_IPSEC_ESP:
+ passert(!oakley_mode);
+ trans_desc = &isakmp_esp_transform_desc;
+ attr_desc = &isakmp_ipsec_attribute_desc;
+ attr_val_descs = ipsec_attr_val_descs;
+ spi_ptr = &st->st_esp.our_spi;
+ spi_generated = &esp_spi_generated;
+ proto = IPPROTO_ESP;
+ break;
+ case PROTO_IPCOMP:
+ passert(!oakley_mode);
+ trans_desc = &isakmp_ipcomp_transform_desc;
+ attr_desc = &isakmp_ipsec_attribute_desc;
+ attr_val_descs = ipsec_attr_val_descs;
+
+ /* a CPI isn't quite the same as an SPI
+ * so we use specialized code to emit it.
+ */
+ if (!ipcomp_cpi_generated)
+ {
+ st->st_ipcomp.our_spi = get_my_cpi(
+ &st->st_connection->spd, tunnel_mode);
+ if (st->st_ipcomp.our_spi == 0)
+ return_on(ret, FALSE); /* problem generating CPI */
+
+ ipcomp_cpi_generated = TRUE;
+ }
+ /* CPI is stored in network low order end of an
+ * ipsec_spi_t. So we start a couple of bytes in.
+ */
+ if (!out_raw((u_char *)&st->st_ipcomp.our_spi
+ + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
+ , IPCOMP_CPI_SIZE
+ , &proposal_pbs, "CPI"))
+ return_on(ret, FALSE);
+ break;
+ default:
+ bad_case(p->protoid);
+ }
+ if (spi_ptr != NULL)
+ {
+ if (!*spi_generated)
+ {
+ *spi_ptr = get_ipsec_spi(0
+ , proto
+ , &st->st_connection->spd
+ , tunnel_mode);
+ if (*spi_ptr == 0)
+ return FALSE;
+ *spi_generated = TRUE;
+ }
+ if (!out_raw((u_char *)spi_ptr, IPSEC_DOI_SPI_SIZE
+ , &proposal_pbs, "SPI"))
+ return_on(ret, FALSE);
+ }
+ }
+
+ /* within proposal: Transform Payloads */
+ for (tn = 0; tn != p->trans_cnt; tn++)
+ {
+ struct db_trans *t = &p->trans[tn];
+ pb_stream trans_pbs;
+ struct isakmp_transform trans;
+ int an;
+
+ trans.isat_np = (tn == p->trans_cnt - 1)
+ ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_T;
+ trans.isat_transnum = tn;
+ trans.isat_transid = t->transid;
+ if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs))
+ return_on(ret, FALSE);
+
+ /* Within tranform: Attributes. */
+
+ /* For Phase 2 / Quick Mode, GROUP_DESCRIPTION is
+ * automatically generated because it must be the same
+ * in every transform. Except IPCOMP.
+ */
+ if (p->protoid != PROTO_IPCOMP
+ && st->st_pfs_group != NULL)
+ {
+ passert(!oakley_mode);
+ passert(st->st_pfs_group != &unset_group);
+ out_attr(GROUP_DESCRIPTION, st->st_pfs_group->algo_id
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ }
+
+ /* automatically generate duration
+ * and, for Phase 2 / Quick Mode, encapsulation.
+ */
+ if (oakley_mode)
+ {
+ out_attr(OAKLEY_LIFE_TYPE, OAKLEY_LIFE_SECONDS
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ out_attr(OAKLEY_LIFE_DURATION
+ , st->st_connection->sa_ike_life_seconds
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ }
+ else
+ {
+ /* RFC 2407 (IPSEC DOI) 4.5 specifies that
+ * the default is "unspecified (host-dependent)".
+ * This makes little sense, so we always specify it.
+ *
+ * Unlike other IPSEC transforms, IPCOMP defaults
+ * to Transport Mode, so we can exploit the default
+ * (draft-shacham-ippcp-rfc2393bis-05.txt 4.1).
+ */
+ if (p->protoid != PROTO_IPCOMP
+ || st->st_policy & POLICY_TUNNEL)
+ {
+#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
+ if ((st->nat_traversal & NAT_T_DETECTED)
+ && !(st->st_policy & POLICY_TUNNEL))
+ {
+ /* Inform user that we will not respect policy and only
+ * propose Tunnel Mode
+ */
+ loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
+ "Transport Mode not allowed due to security concerns -- "
+ "using Tunnel mode");
+ }
#endif
- out_attr(ENCAPSULATION_MODE
+ out_attr(ENCAPSULATION_MODE
#ifdef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- , NAT_T_ENCAPSULATION_MODE(st, st->st_policy)
+ , NAT_T_ENCAPSULATION_MODE(st, st->st_policy)
#else
- /* If NAT-T is detected, use UDP_TUNNEL as long as Transport
- * Mode has security concerns.
- *
- * User has been informed of that
- */
- , NAT_T_ENCAPSULATION_MODE(st, POLICY_TUNNEL)
+ /* If NAT-T is detected, use UDP_TUNNEL as long as Transport
+ * Mode has security concerns.
+ *
+ * User has been informed of that
+ */
+ , NAT_T_ENCAPSULATION_MODE(st, POLICY_TUNNEL)
#endif
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
- out_attr(SA_LIFE_TYPE, SA_LIFE_TYPE_SECONDS
- , attr_desc, attr_val_descs
- , &trans_pbs);
- out_attr(SA_LIFE_DURATION
- , st->st_connection->sa_ipsec_life_seconds
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
-
- /* spit out attributes from table */
- for (an = 0; an != t->attr_cnt; an++)
- {
- struct db_attr *a = &t->attrs[an];
-
- out_attr(a->type, a->val
- , attr_desc, attr_val_descs
- , &trans_pbs);
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ }
+ out_attr(SA_LIFE_TYPE, SA_LIFE_TYPE_SECONDS
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ out_attr(SA_LIFE_DURATION
+ , st->st_connection->sa_ipsec_life_seconds
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ }
+
+ /* spit out attributes from table */
+ for (an = 0; an != t->attr_cnt; an++)
+ {
+ struct db_attr *a = &t->attrs[an];
+
+ out_attr(a->type, a->val
+ , attr_desc, attr_val_descs
+ , &trans_pbs);
+ }
+
+ close_output_pbs(&trans_pbs);
+ }
+ close_output_pbs(&proposal_pbs);
}
-
- close_output_pbs(&trans_pbs);
- }
- close_output_pbs(&proposal_pbs);
+ /* end of a conjunction of proposals */
}
- /* end of a conjunction of proposals */
- }
- close_output_pbs(&sa_pbs);
- ret = TRUE;
+ close_output_pbs(&sa_pbs);
+ ret = TRUE;
return_out:
#if !defined NO_KERNEL_ALG || !defined NO_IKE_ALG
- if (db_ctx)
- db_destroy(db_ctx);
+ if (db_ctx)
+ db_destroy(db_ctx);
#endif
- return ret;
+ return ret;
}
/* Handle long form of duration attribute.
@@ -590,27 +585,27 @@ return_out:
static u_int32_t
decode_long_duration(pb_stream *pbs)
{
- u_int32_t val = 0;
-
- /* ignore leading zeros */
- while (pbs_left(pbs) != 0 && *pbs->cur == '\0')
- pbs->cur++;
-
- if (pbs_left(pbs) > sizeof(val))
- {
- /* "clamp" too large value to max representable value */
- val -= 1; /* portable way to get to maximum value */
- DBG(DBG_PARSING, DBG_log(" too large duration clamped to: %lu"
- , (unsigned long)val));
- }
- else
- {
- /* decode number */
- while (pbs_left(pbs) != 0)
- val = (val << BITS_PER_BYTE) | *pbs->cur++;
- DBG(DBG_PARSING, DBG_log(" long duration: %lu", (unsigned long)val));
- }
- return val;
+ u_int32_t val = 0;
+
+ /* ignore leading zeros */
+ while (pbs_left(pbs) != 0 && *pbs->cur == '\0')
+ pbs->cur++;
+
+ if (pbs_left(pbs) > sizeof(val))
+ {
+ /* "clamp" too large value to max representable value */
+ val -= 1; /* portable way to get to maximum value */
+ DBG(DBG_PARSING, DBG_log(" too large duration clamped to: %lu"
+ , (unsigned long)val));
+ }
+ else
+ {
+ /* decode number */
+ while (pbs_left(pbs) != 0)
+ val = (val << BITS_PER_BYTE) | *pbs->cur++;
+ DBG(DBG_PARSING, DBG_log(" long duration: %lu", (unsigned long)val));
+ }
+ return val;
}
/* Preparse the body of an ISAKMP SA Payload and
@@ -621,99 +616,99 @@ decode_long_duration(pb_stream *pbs)
*/
notification_t
preparse_isakmp_sa_body(const struct isakmp_sa *sa
- , pb_stream *sa_pbs
- , u_int32_t *ipsecdoisit
- , pb_stream *proposal_pbs
- , struct isakmp_proposal *proposal)
+ , pb_stream *sa_pbs
+ , u_int32_t *ipsecdoisit
+ , pb_stream *proposal_pbs
+ , struct isakmp_proposal *proposal)
{
- /* DOI */
- if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
- {
- loglog(RC_LOG_SERIOUS, "Unknown/unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
- /* XXX Could send notification back */
- return DOI_NOT_SUPPORTED;
- }
-
- /* Situation */
- if (!in_struct(ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
- return SITUATION_NOT_SUPPORTED;
-
- if (*ipsecdoisit != SIT_IDENTITY_ONLY)
- {
- loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"
- , bitnamesof(sit_bit_names, *ipsecdoisit));
- /* XXX Could send notification back */
- return SITUATION_NOT_SUPPORTED;
- }
-
- /* The rules for ISAKMP SAs are scattered.
- * RFC 2409 "IKE" section 5 says that there
- * can only be one SA, and it can have only one proposal in it.
- * There may well be multiple transforms.
- */
- if (!in_struct(proposal, &isakmp_proposal_desc, sa_pbs, proposal_pbs))
- return PAYLOAD_MALFORMED;
-
- if (proposal->isap_np != ISAKMP_NEXT_NONE)
- {
- loglog(RC_LOG_SERIOUS, "Proposal Payload must be alone in Oakley SA; found %s following Proposal"
- , enum_show(&payload_names, proposal->isap_np));
- return PAYLOAD_MALFORMED;
- }
-
- if (proposal->isap_protoid != PROTO_ISAKMP)
- {
- loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) found in Oakley Proposal"
- , enum_show(&protocol_names, proposal->isap_protoid));
- return INVALID_PROTOCOL_ID;
- }
-
- /* Just what should we accept for the SPI field?
- * The RFC is sort of contradictory. We will ignore the SPI
- * as long as it is of the proper size.
- *
- * From RFC2408 2.4 Identifying Security Associations:
- * During phase 1 negotiations, the initiator and responder cookies
- * determine the ISAKMP SA. Therefore, the SPI field in the Proposal
- * payload is redundant and MAY be set to 0 or it MAY contain the
- * transmitting entity's cookie.
- *
- * From RFC2408 3.5 Proposal Payload:
- * o SPI Size (1 octet) - Length in octets of the SPI as defined by
- * the Protocol-Id. In the case of ISAKMP, the Initiator and
- * Responder cookie pair from the ISAKMP Header is the ISAKMP SPI,
- * therefore, the SPI Size is irrelevant and MAY be from zero (0) to
- * sixteen (16). If the SPI Size is non-zero, the content of the
- * SPI field MUST be ignored. If the SPI Size is not a multiple of
- * 4 octets it will have some impact on the SPI field and the
- * alignment of all payloads in the message. The Domain of
- * Interpretation (DOI) will dictate the SPI Size for other
- * protocols.
- */
- if (proposal->isap_spisize == 0)
- {
- /* empty (0) SPI -- fine */
- }
- else if (proposal->isap_spisize <= MAX_ISAKMP_SPI_SIZE)
- {
- u_char junk_spi[MAX_ISAKMP_SPI_SIZE];
-
- if (!in_raw(junk_spi, proposal->isap_spisize, proposal_pbs, "Oakley SPI"))
- return PAYLOAD_MALFORMED;
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "invalid SPI size (%u) in Oakley Proposal"
- , (unsigned)proposal->isap_spisize);
- return INVALID_SPI;
- }
- return NOTHING_WRONG;
+ /* DOI */
+ if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
+ {
+ loglog(RC_LOG_SERIOUS, "Unknown/unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
+ /* XXX Could send notification back */
+ return DOI_NOT_SUPPORTED;
+ }
+
+ /* Situation */
+ if (!in_struct(ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
+ return SITUATION_NOT_SUPPORTED;
+
+ if (*ipsecdoisit != SIT_IDENTITY_ONLY)
+ {
+ loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"
+ , bitnamesof(sit_bit_names, *ipsecdoisit));
+ /* XXX Could send notification back */
+ return SITUATION_NOT_SUPPORTED;
+ }
+
+ /* The rules for ISAKMP SAs are scattered.
+ * RFC 2409 "IKE" section 5 says that there
+ * can only be one SA, and it can have only one proposal in it.
+ * There may well be multiple transforms.
+ */
+ if (!in_struct(proposal, &isakmp_proposal_desc, sa_pbs, proposal_pbs))
+ return PAYLOAD_MALFORMED;
+
+ if (proposal->isap_np != ISAKMP_NEXT_NONE)
+ {
+ loglog(RC_LOG_SERIOUS, "Proposal Payload must be alone in Oakley SA; found %s following Proposal"
+ , enum_show(&payload_names, proposal->isap_np));
+ return PAYLOAD_MALFORMED;
+ }
+
+ if (proposal->isap_protoid != PROTO_ISAKMP)
+ {
+ loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) found in Oakley Proposal"
+ , enum_show(&protocol_names, proposal->isap_protoid));
+ return INVALID_PROTOCOL_ID;
+ }
+
+ /* Just what should we accept for the SPI field?
+ * The RFC is sort of contradictory. We will ignore the SPI
+ * as long as it is of the proper size.
+ *
+ * From RFC2408 2.4 Identifying Security Associations:
+ * During phase 1 negotiations, the initiator and responder cookies
+ * determine the ISAKMP SA. Therefore, the SPI field in the Proposal
+ * payload is redundant and MAY be set to 0 or it MAY contain the
+ * transmitting entity's cookie.
+ *
+ * From RFC2408 3.5 Proposal Payload:
+ * o SPI Size (1 octet) - Length in octets of the SPI as defined by
+ * the Protocol-Id. In the case of ISAKMP, the Initiator and
+ * Responder cookie pair from the ISAKMP Header is the ISAKMP SPI,
+ * therefore, the SPI Size is irrelevant and MAY be from zero (0) to
+ * sixteen (16). If the SPI Size is non-zero, the content of the
+ * SPI field MUST be ignored. If the SPI Size is not a multiple of
+ * 4 octets it will have some impact on the SPI field and the
+ * alignment of all payloads in the message. The Domain of
+ * Interpretation (DOI) will dictate the SPI Size for other
+ * protocols.
+ */
+ if (proposal->isap_spisize == 0)
+ {
+ /* empty (0) SPI -- fine */
+ }
+ else if (proposal->isap_spisize <= MAX_ISAKMP_SPI_SIZE)
+ {
+ u_char junk_spi[MAX_ISAKMP_SPI_SIZE];
+
+ if (!in_raw(junk_spi, proposal->isap_spisize, proposal_pbs, "Oakley SPI"))
+ return PAYLOAD_MALFORMED;
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "invalid SPI size (%u) in Oakley Proposal"
+ , (unsigned)proposal->isap_spisize);
+ return INVALID_SPI;
+ }
+ return NOTHING_WRONG;
}
static struct {
- u_int8_t *start;
- u_int8_t *cur;
- u_int8_t *roof;
+ u_int8_t *start;
+ u_int8_t *cur;
+ u_int8_t *roof;
} backup;
/*
@@ -722,9 +717,9 @@ static struct {
void
backup_pbs(pb_stream *pbs)
{
- backup.start = pbs->start;
- backup.cur = pbs->cur;
- backup.roof = pbs->roof;
+ backup.start = pbs->start;
+ backup.cur = pbs->cur;
+ backup.roof = pbs->roof;
}
/*
@@ -733,9 +728,9 @@ backup_pbs(pb_stream *pbs)
void
restore_pbs(pb_stream *pbs)
{
- pbs->start = backup.start;
- pbs->cur = backup.cur;
- pbs->roof = backup.roof;
+ pbs->start = backup.start;
+ pbs->cur = backup.cur;
+ pbs->roof = backup.roof;
}
/*
@@ -743,90 +738,93 @@ restore_pbs(pb_stream *pbs)
*/
notification_t
parse_isakmp_policy(pb_stream *proposal_pbs
- , u_int notrans
- , lset_t *policy)
+ , u_int notrans
+ , lset_t *policy)
{
- int last_transnum = -1;
+ int last_transnum = -1;
- *policy = LEMPTY;
+ *policy = LEMPTY;
- while (notrans--)
- {
- pb_stream trans_pbs;
- u_char *attr_start;
- size_t attr_len;
- struct isakmp_transform trans;
+ while (notrans--)
+ {
+ pb_stream trans_pbs;
+ u_char *attr_start;
+ size_t attr_len;
+ struct isakmp_transform trans;
- if (!in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs))
- return BAD_PROPOSAL_SYNTAX;
+ if (!in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs))
+ return BAD_PROPOSAL_SYNTAX;
- if (trans.isat_transnum <= last_transnum)
- {
- /* picky, picky, picky */
- loglog(RC_LOG_SERIOUS, "Transform Numbers are not monotonically increasing"
- " in Oakley Proposal");
- return BAD_PROPOSAL_SYNTAX;
- }
- last_transnum = trans.isat_transnum;
+ if (trans.isat_transnum <= last_transnum)
+ {
+ /* picky, picky, picky */
+ loglog(RC_LOG_SERIOUS, "Transform Numbers are not monotonically increasing"
+ " in Oakley Proposal");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ last_transnum = trans.isat_transnum;
- if (trans.isat_transid != KEY_IKE)
- {
- loglog(RC_LOG_SERIOUS, "expected KEY_IKE but found %s in Oakley Transform"
- , enum_show(&isakmp_transformid_names, trans.isat_transid));
- return INVALID_TRANSFORM_ID;
- }
+ if (trans.isat_transid != KEY_IKE)
+ {
+ loglog(RC_LOG_SERIOUS, "expected KEY_IKE but found %s in Oakley Transform"
+ , enum_show(&isakmp_transformid_names, trans.isat_transid));
+ return INVALID_TRANSFORM_ID;
+ }
- attr_start = trans_pbs.cur;
- attr_len = pbs_left(&trans_pbs);
+ attr_start = trans_pbs.cur;
+ attr_len = pbs_left(&trans_pbs);
- /* preprocess authentication attributes only */
- while (pbs_left(&trans_pbs) != 0)
- {
- struct isakmp_attribute a;
- pb_stream attr_pbs;
+ /* preprocess authentication attributes only */
+ while (pbs_left(&trans_pbs) != 0)
+ {
+ struct isakmp_attribute a;
+ pb_stream attr_pbs;
- if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
- return BAD_PROPOSAL_SYNTAX;
+ if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
+ return BAD_PROPOSAL_SYNTAX;
- passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
+ passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
- switch (a.isaat_af_type)
- {
- case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
- switch (a.isaat_lv)
- {
- case OAKLEY_PRESHARED_KEY:
- *policy |= POLICY_PSK;
- break;
- case OAKLEY_RSA_SIG:
- *policy |= POLICY_RSASIG;
- break;
- case XAUTHInitPreShared:
- *policy |= POLICY_XAUTH_SERVER;
- /* fall through */
- case XAUTHRespPreShared:
- *policy |= POLICY_XAUTH_PSK;
- break;
- case XAUTHInitRSA:
- *policy |= POLICY_XAUTH_SERVER;
- /* fall through */
- case XAUTHRespRSA:
- *policy |= POLICY_XAUTH_RSASIG;
- break;
- default:
- break;
+ switch (a.isaat_af_type)
+ {
+ case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
+ switch (a.isaat_lv)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ *policy |= POLICY_PSK;
+ break;
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ *policy |= POLICY_PUBKEY;
+ break;
+ case XAUTHInitPreShared:
+ *policy |= POLICY_XAUTH_SERVER;
+ /* fall through */
+ case XAUTHRespPreShared:
+ *policy |= POLICY_XAUTH_PSK;
+ break;
+ case XAUTHInitRSA:
+ *policy |= POLICY_XAUTH_SERVER;
+ /* fall through */
+ case XAUTHRespRSA:
+ *policy |= POLICY_XAUTH_RSASIG;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
}
- break;
- default:
- break;
- }
}
- }
- DBG(DBG_CONTROL|DBG_PARSING,
- DBG_log("preparse_isakmp_policy: peer requests %s authentication"
- , prettypolicy(*policy))
- )
- return NOTHING_WRONG;
+ DBG(DBG_CONTROL|DBG_PARSING,
+ DBG_log("preparse_isakmp_policy: peer requests %s authentication"
+ , prettypolicy(*policy))
+ )
+ return NOTHING_WRONG;
}
/*
@@ -835,22 +833,22 @@ parse_isakmp_policy(pb_stream *proposal_pbs
static err_t
find_preshared_key(struct state* st)
{
- err_t ugh = NULL;
- struct connection *c = st->st_connection;
+ err_t ugh = NULL;
+ struct connection *c = st->st_connection;
- if (get_preshared_secret(c) == NULL)
- {
- char my_id[BUF_LEN], his_id[BUF_LEN];
+ if (get_preshared_secret(c) == NULL)
+ {
+ char my_id[BUF_LEN], his_id[BUF_LEN];
- idtoa(&c->spd.this.id, my_id, sizeof(my_id));
- if (his_id_was_instantiated(c))
- strcpy(his_id, "%any");
- else
- idtoa(&c->spd.that.id, his_id, sizeof(his_id));
- ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
- , my_id, his_id);
- }
- return ugh;
+ idtoa(&c->spd.this.id, my_id, sizeof(my_id));
+ if (his_id_was_instantiated(c))
+ strcpy(his_id, "%any");
+ else
+ idtoa(&c->spd.that.id, his_id, sizeof(his_id));
+ ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
+ , my_id, his_id);
+ }
+ return ugh;
}
/* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode).
@@ -864,429 +862,432 @@ find_preshared_key(struct state* st)
*/
notification_t
parse_isakmp_sa_body(u_int32_t ipsecdoisit
- , pb_stream *proposal_pbs
- , struct isakmp_proposal *proposal
- , pb_stream *r_sa_pbs
- , struct state *st
- , bool initiator)
+ , pb_stream *proposal_pbs
+ , struct isakmp_proposal *proposal
+ , pb_stream *r_sa_pbs
+ , struct state *st
+ , bool initiator)
{
- struct connection *c = st->st_connection;
- unsigned no_trans_left;
-
- /* for each transform payload... */
- no_trans_left = proposal->isap_notrans;
-
- for (;;)
- {
- pb_stream trans_pbs;
- u_char *attr_start;
- size_t attr_len;
- struct isakmp_transform trans;
- lset_t seen_attrs = 0;
- lset_t seen_durations = 0;
- u_int16_t life_type = 0;
- struct oakley_trans_attrs ta;
- err_t ugh = NULL; /* set to diagnostic when problem detected */
+ struct connection *c = st->st_connection;
+ unsigned no_trans_left;
- /* initialize only optional field in ta */
- ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; /* When this SA expires (seconds) */
+ /* for each transform payload... */
+ no_trans_left = proposal->isap_notrans;
- if (no_trans_left == 0)
+ for (;;)
{
- loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
- return BAD_PROPOSAL_SYNTAX;
- }
-
- in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs);
- attr_start = trans_pbs.cur;
- attr_len = pbs_left(&trans_pbs);
-
- /* process all the attributes that make up the transform */
+ pb_stream trans_pbs;
+ u_char *attr_start;
+ size_t attr_len;
+ struct isakmp_transform trans;
+ lset_t seen_attrs = 0;
+ lset_t seen_durations = 0;
+ u_int16_t life_type = 0;
+ struct oakley_trans_attrs ta;
+ err_t ugh = NULL; /* set to diagnostic when problem detected */
- while (pbs_left(&trans_pbs) != 0)
- {
- struct isakmp_attribute a;
- pb_stream attr_pbs;
- u_int32_t val; /* room for larger values */
+ /* initialize only optional field in ta */
+ ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; /* When this SA expires (seconds) */
- if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
- return BAD_PROPOSAL_SYNTAX;
+ if (no_trans_left == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
+ return BAD_PROPOSAL_SYNTAX;
+ }
- passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
+ in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs);
+ attr_start = trans_pbs.cur;
+ attr_len = pbs_left(&trans_pbs);
- if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
- {
- loglog(RC_LOG_SERIOUS, "repeated %s attribute in Oakley Transform %u"
- , enum_show(&oakley_attr_names, a.isaat_af_type)
- , trans.isat_transnum);
- return BAD_PROPOSAL_SYNTAX;
- }
+ /* process all the attributes that make up the transform */
- seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
+ while (pbs_left(&trans_pbs) != 0)
+ {
+ struct isakmp_attribute a;
+ pb_stream attr_pbs;
+ u_int32_t val; /* room for larger values */
- val = a.isaat_lv;
+ if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
+ return BAD_PROPOSAL_SYNTAX;
- DBG(DBG_PARSING,
- {
- enum_names *vdesc = oakley_attr_val_descs
- [a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];
+ passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
- if (vdesc != NULL)
- {
- const char *nm = enum_name(vdesc, val);
+ if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
+ {
+ loglog(RC_LOG_SERIOUS, "repeated %s attribute in Oakley Transform %u"
+ , enum_show(&oakley_attr_names, a.isaat_af_type)
+ , trans.isat_transnum);
+ return BAD_PROPOSAL_SYNTAX;
+ }
- if (nm != NULL)
- DBG_log(" [%u is %s]", (unsigned)val, nm);
- }
- });
+ seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
- switch (a.isaat_af_type)
- {
- case OAKLEY_ENCRYPTION_ALGORITHM | ISAKMP_ATTR_AF_TV:
- if (ike_alg_enc_present(val))
- {
- ta.encrypt = val;
- ta.encrypter = ike_alg_get_encrypter(val);
- ta.enckeylen = ta.encrypter->keydeflen;
- }
- else
- {
- ugh = builddiag("%s is not supported"
- , enum_show(&oakley_enc_names, val));
- }
- break;
+ val = a.isaat_lv;
- case OAKLEY_HASH_ALGORITHM | ISAKMP_ATTR_AF_TV:
- if (ike_alg_hash_present(val))
- {
- ta.hash = val;
- ta.hasher = ike_alg_get_hasher(val);
- }
- else
- {
- ugh = builddiag("%s is not supported"
- , enum_show(&oakley_hash_names, val));
- }
- break;
+ DBG(DBG_PARSING,
+ {
+ enum_names *vdesc = oakley_attr_val_descs
+ [a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];
- case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
- {
- /* check that authentication method is acceptable */
- lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK;
+ if (vdesc != NULL)
+ {
+ const char *nm = enum_name(vdesc, val);
- /* is the initiator the XAUTH client? */
- bool xauth_init = ( initiator && (st->st_policy & POLICY_XAUTH_SERVER) == LEMPTY)
- || (!initiator && (st->st_policy & POLICY_XAUTH_SERVER) != LEMPTY);
+ if (nm != NULL)
+ DBG_log(" [%u is %s]", (unsigned)val, nm);
+ }
+ });
- switch (val)
- {
- case OAKLEY_PRESHARED_KEY:
- if ((iap & POLICY_PSK) == LEMPTY)
- {
- ugh = "policy does not allow OAKLEY_PRESHARED_KEY authentication";
- }
- else
- {
- ugh = find_preshared_key(st);
- ta.auth = OAKLEY_PRESHARED_KEY;
- }
- break;
- case XAUTHInitPreShared:
- if ((iap & POLICY_XAUTH_PSK) == LEMPTY || !xauth_init)
- {
- ugh = "policy does not allow XAUTHInitPreShared authentication";
- }
- else
- {
- ugh = find_preshared_key(st);
- ta.auth = XAUTHInitPreShared;
- }
- break;
- case XAUTHRespPreShared:
- if ((iap & POLICY_XAUTH_PSK) == LEMPTY || xauth_init)
- {
- ugh = "policy does not allow XAUTHRespPreShared authentication";
- }
- else
- {
- ugh = find_preshared_key(st);
- ta.auth = XAUTHRespPreShared;
- }
- break;
- case OAKLEY_RSA_SIG:
- /* Accept if policy specifies RSASIG or is default */
- if ((iap & POLICY_RSASIG) == LEMPTY)
- {
- ugh = "policy does not allow OAKLEY_RSA_SIG authentication";
- }
- else
- {
- ta.auth = OAKLEY_RSA_SIG;
- }
- break;
- case XAUTHInitRSA:
- if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || !xauth_init)
+ switch (a.isaat_af_type)
{
- ugh = "policy does not allow XAUTHInitRSA authentication";
- }
- else
- {
- ta.auth = XAUTHInitRSA;
- }
- break;
- case XAUTHRespRSA:
- if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || xauth_init)
- {
- ugh = "policy does not allow XAUTHRespRSA authentication";
+ case OAKLEY_ENCRYPTION_ALGORITHM | ISAKMP_ATTR_AF_TV:
+ if (ike_alg_get_crypter(val))
+ {
+ ta.encrypt = val;
+ ta.encrypter = ike_alg_get_crypter(val);
+ ta.enckeylen = ta.encrypter->keydeflen;
+ }
+ else
+ {
+ ugh = builddiag("%s is not supported"
+ , enum_show(&oakley_enc_names, val));
+ }
+ break;
+
+ case OAKLEY_HASH_ALGORITHM | ISAKMP_ATTR_AF_TV:
+ if (ike_alg_get_hasher(val))
+ {
+ ta.hash = val;
+ ta.hasher = ike_alg_get_hasher(val);
+ }
+ else
+ {
+ ugh = builddiag("%s is not supported"
+ , enum_show(&oakley_hash_names, val));
+ }
+ break;
+
+ case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
+ {
+ /* check that authentication method is acceptable */
+ lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK;
+
+ /* is the initiator the XAUTH client? */
+ bool xauth_init = ( initiator && (st->st_policy & POLICY_XAUTH_SERVER) == LEMPTY)
+ || (!initiator && (st->st_policy & POLICY_XAUTH_SERVER) != LEMPTY);
+
+ switch (val)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ if ((iap & POLICY_PSK) == LEMPTY)
+ {
+ ugh = "policy does not allow pre-shared key authentication";
+ }
+ else
+ {
+ ugh = find_preshared_key(st);
+ ta.auth = OAKLEY_PRESHARED_KEY;
+ }
+ break;
+ case XAUTHInitPreShared:
+ if ((iap & POLICY_XAUTH_PSK) == LEMPTY || !xauth_init)
+ {
+ ugh = "policy does not allow XAUTHInitPreShared authentication";
+ }
+ else
+ {
+ ugh = find_preshared_key(st);
+ ta.auth = XAUTHInitPreShared;
+ }
+ break;
+ case XAUTHRespPreShared:
+ if ((iap & POLICY_XAUTH_PSK) == LEMPTY || xauth_init)
+ {
+ ugh = "policy does not allow XAUTHRespPreShared authentication";
+ }
+ else
+ {
+ ugh = find_preshared_key(st);
+ ta.auth = XAUTHRespPreShared;
+ }
+ break;
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ if ((iap & POLICY_PUBKEY) == LEMPTY)
+ {
+ ugh = "policy does not allow public key authentication";
+ }
+ else
+ {
+ ta.auth = val;
+ }
+ break;
+ case XAUTHInitRSA:
+ if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || !xauth_init)
+ {
+ ugh = "policy does not allow XAUTHInitRSA authentication";
+ }
+ else
+ {
+ ta.auth = XAUTHInitRSA;
+ }
+ break;
+ case XAUTHRespRSA:
+ if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || xauth_init)
+ {
+ ugh = "policy does not allow XAUTHRespRSA authentication";
+ }
+ else
+ {
+ ta.auth = XAUTHRespRSA;
+ }
+ break;
+ default:
+ ugh = builddiag("Pluto does not support %s authentication"
+ , enum_show(&oakley_auth_names, val));
+ break;
+ }
+ }
+ break;
+
+ case OAKLEY_GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
+ ta.group = ike_alg_get_dh_group(val);
+ if (ta.group == NULL)
+ {
+ ugh = builddiag("%s is not supported"
+ , enum_show(&oakley_group_names, val));
+ }
+ break;
+
+ case OAKLEY_LIFE_TYPE | ISAKMP_ATTR_AF_TV:
+ switch (val)
+ {
+ case OAKLEY_LIFE_SECONDS:
+ case OAKLEY_LIFE_KILOBYTES:
+ if (LHAS(seen_durations, val))
+ {
+ loglog(RC_LOG_SERIOUS
+ , "attribute OAKLEY_LIFE_TYPE value %s repeated"
+ , enum_show(&oakley_lifetime_names, val));
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ seen_durations |= LELEM(val);
+ life_type = val;
+ break;
+ default:
+ ugh = builddiag("unknown value %s"
+ , enum_show(&oakley_lifetime_names, val));
+ break;
+ }
+ break;
+
+ case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
+ val = decode_long_duration(&attr_pbs);
+ /* fall through */
+ case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
+ if (!LHAS(seen_attrs, OAKLEY_LIFE_TYPE))
+ {
+ ugh = "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute";
+ break;
+ }
+ seen_attrs &= ~(LELEM(OAKLEY_LIFE_DURATION) | LELEM(OAKLEY_LIFE_TYPE));
+
+ switch (life_type)
+ {
+ case OAKLEY_LIFE_SECONDS:
+ if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM)
+ {
+#ifdef CISCO_QUIRKS
+ plog("peer requested %lu seconds"
+ " which exceeds our limit %d seconds"
+ , (long) val
+ , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
+ plog("lifetime reduced to %d seconds "
+ "(todo: IPSEC_RESPONDER_LIFETIME notification)"
+ , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
+ val = OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM;
+#else
+ ugh = builddiag("peer requested %lu seconds"
+ " which exceeds our limit %d seconds"
+ , (long) val
+ , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
+#endif
+ }
+ ta.life_seconds = val;
+ break;
+ case OAKLEY_LIFE_KILOBYTES:
+ ta.life_kilobytes = val;
+ break;
+ default:
+ bad_case(life_type);
+ }
+ break;
+
+ case OAKLEY_KEY_LENGTH | ISAKMP_ATTR_AF_TV:
+ if ((seen_attrs & LELEM(OAKLEY_ENCRYPTION_ALGORITHM)) == 0)
+ {
+ ugh = "OAKLEY_KEY_LENGTH attribute not preceded by "
+ "OAKLEY_ENCRYPTION_ALGORITHM attribute";
+ break;
+ }
+ if (ta.encrypter == NULL)
+ {
+ ugh = "NULL encrypter with seen OAKLEY_ENCRYPTION_ALGORITHM";
+ break;
+ }
+ /*
+ * check if this keylen is compatible with specified algorithm
+ */
+ if (val
+ && (val < ta.encrypter->keyminlen || val > ta.encrypter->keymaxlen))
+ {
+ ugh = "peer proposed key length not valid for "
+ "encryption algorithm specified";
+ }
+ ta.enckeylen = val;
+ break;
+#if 0 /* not yet supported */
+ case OAKLEY_GROUP_TYPE | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_PRF | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_FIELD_SIZE | ISAKMP_ATTR_AF_TV:
+
+ case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TLV:
+ case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TLV:
+ case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TLV:
+ case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TLV:
+ case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TLV:
+ case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TV:
+ case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TLV:
+#endif
+ default:
+ /* fix compiler warning */
+ memset(&ta, 0, sizeof(ta));
+ ugh = "unsupported OAKLEY attribute";
+ break;
}
- else
+
+ if (ugh != NULL)
{
- ta.auth = XAUTHRespRSA;
+ loglog(RC_LOG_SERIOUS, "%s. Attribute %s"
+ , ugh, enum_show(&oakley_attr_names, a.isaat_af_type));
+ break;
}
- break;
- default:
- ugh = builddiag("Pluto does not support %s authentication"
- , enum_show(&oakley_auth_names, val));
- break;
- }
}
- break;
- case OAKLEY_GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
- ta.group = lookup_group(val);
- if (ta.group == NULL)
+ /*
+ * ML: at last check for allowed transforms in alg_info_ike
+ * (ALG_INFO_F_STRICT flag)
+ */
+ if (ugh == NULL)
{
- ugh = "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported";
+ if (!ike_alg_ok_final(ta.encrypt, ta.enckeylen, ta.hash,
+ ta.group ? ta.group->algo_id : -1, c->alg_info_ike))
+ {
+ ugh = "OAKLEY proposal refused";
+ }
}
- break;
- case OAKLEY_LIFE_TYPE | ISAKMP_ATTR_AF_TV:
- switch (val)
+ if (ugh == NULL)
{
- case OAKLEY_LIFE_SECONDS:
- case OAKLEY_LIFE_KILOBYTES:
- if (LHAS(seen_durations, val))
- {
- loglog(RC_LOG_SERIOUS
- , "attribute OAKLEY_LIFE_TYPE value %s repeated"
- , enum_show(&oakley_lifetime_names, val));
- return BAD_PROPOSAL_SYNTAX;
- }
- seen_durations |= LELEM(val);
- life_type = val;
- break;
- default:
- ugh = builddiag("unknown value %s"
- , enum_show(&oakley_lifetime_names, val));
- break;
- }
- break;
+ /* a little more checking is in order */
+ {
+ lset_t missing
+ = ~seen_attrs
+ & (LELEM(OAKLEY_ENCRYPTION_ALGORITHM)
+ | LELEM(OAKLEY_HASH_ALGORITHM)
+ | LELEM(OAKLEY_AUTHENTICATION_METHOD)
+ | LELEM(OAKLEY_GROUP_DESCRIPTION));
+
+ if (missing)
+ {
+ loglog(RC_LOG_SERIOUS, "missing mandatory attribute(s) %s in Oakley Transform %u"
+ , bitnamesof(oakley_attr_bit_names, missing)
+ , trans.isat_transnum);
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ }
+ /* We must have liked this transform.
+ * Lets finish early and leave.
+ */
- case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
- val = decode_long_duration(&attr_pbs);
- /* fall through */
- case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
- if (!LHAS(seen_attrs, OAKLEY_LIFE_TYPE))
- {
- ugh = "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute";
- break;
- }
- seen_attrs &= ~(LELEM(OAKLEY_LIFE_DURATION) | LELEM(OAKLEY_LIFE_TYPE));
+ DBG(DBG_PARSING | DBG_CRYPT
+ , DBG_log("Oakley Transform %u accepted", trans.isat_transnum));
- switch (life_type)
- {
- case OAKLEY_LIFE_SECONDS:
- if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM)
- {
-#ifdef CISCO_QUIRKS
- plog("peer requested %lu seconds"
- " which exceeds our limit %d seconds"
- , (long) val
- , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
- plog("lifetime reduced to %d seconds "
- "(todo: IPSEC_RESPONDER_LIFETIME notification)"
- , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
- val = OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM;
-#else
- ugh = builddiag("peer requested %lu seconds"
- " which exceeds our limit %d seconds"
- , (long) val
- , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
-#endif
- }
- ta.life_seconds = val;
- break;
- case OAKLEY_LIFE_KILOBYTES:
- ta.life_kilobytes = val;
- break;
- default:
- bad_case(life_type);
- }
- break;
-
- case OAKLEY_KEY_LENGTH | ISAKMP_ATTR_AF_TV:
- if ((seen_attrs & LELEM(OAKLEY_ENCRYPTION_ALGORITHM)) == 0)
- {
- ugh = "OAKLEY_KEY_LENGTH attribute not preceded by "
- "OAKLEY_ENCRYPTION_ALGORITHM attribute";
- break;
- }
- if (ta.encrypter == NULL)
- {
- ugh = "NULL encrypter with seen OAKLEY_ENCRYPTION_ALGORITHM";
- break;
- }
- /*
- * check if this keylen is compatible with specified algorithm
- */
- if (val
- && (val < ta.encrypter->keyminlen || val > ta.encrypter->keymaxlen))
- {
- ugh = "peer proposed key length not valid for "
- "encryption algorithm specified";
- }
- ta.enckeylen = val;
- break;
-#if 0 /* not yet supported */
- case OAKLEY_GROUP_TYPE | ISAKMP_ATTR_AF_TV:
- case OAKLEY_PRF | ISAKMP_ATTR_AF_TV:
- case OAKLEY_FIELD_SIZE | ISAKMP_ATTR_AF_TV:
-
- case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TLV:
-#endif
- default:
- /* fix compiler warning */
- memset(&ta, 0, sizeof(ta));
- ugh = "unsupported OAKLEY attribute";
- break;
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s. Attribute %s"
- , ugh, enum_show(&oakley_attr_names, a.isaat_af_type));
- break;
- }
- }
+ 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;
- /*
- * ML: at last check for allowed transforms in alg_info_ike
- * (ALG_INFO_F_STRICT flag)
- */
- if (ugh == NULL)
- {
- if (!ike_alg_ok_final(ta.encrypt, ta.enckeylen, ta.hash,
- ta.group ? ta.group->group : -1, c->alg_info_ike))
- {
- ugh = "OAKLEY proposal refused";
- }
- }
+ /* Situation */
+ if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
+ impossible();
- if (ugh == NULL)
- {
- /* a little more checking is in order */
- {
- lset_t missing
- = ~seen_attrs
- & (LELEM(OAKLEY_ENCRYPTION_ALGORITHM)
- | LELEM(OAKLEY_HASH_ALGORITHM)
- | LELEM(OAKLEY_AUTHENTICATION_METHOD)
- | LELEM(OAKLEY_GROUP_DESCRIPTION));
-
- if (missing)
- {
- loglog(RC_LOG_SERIOUS, "missing mandatory attribute(s) %s in Oakley Transform %u"
- , bitnamesof(oakley_attr_bit_names, missing)
- , trans.isat_transnum);
- return BAD_PROPOSAL_SYNTAX;
- }
- }
- /* We must have liked this transform.
- * Lets finish early and leave.
- */
-
- 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))
- impossible();
-
- /* Proposal */
+ /* Proposal */
#ifdef EMIT_ISAKMP_SPI
- r_proposal.isap_spisize = COOKIE_SIZE;
+ r_proposal.isap_spisize = COOKIE_SIZE;
#else
- r_proposal.isap_spisize = 0;
+ 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))
- impossible();
+ r_proposal.isap_notrans = 1;
+ if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
+ impossible();
- /* SPI */
+ /* SPI */
#ifdef EMIT_ISAKMP_SPI
- if (!out_raw(my_cookie, COOKIE_SIZE, &r_proposal_pbs, "SPI"))
- impossible();
- r_proposal.isap_spisize = COOKIE_SIZE;
+ if (!out_raw(my_cookie, COOKIE_SIZE, &r_proposal_pbs, "SPI"))
+ impossible();
+ r_proposal.isap_spisize = COOKIE_SIZE;
#else
- /* none (0) */
+ /* 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))
- impossible();
-
- if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes"))
- impossible();
- close_output_pbs(&r_trans_pbs);
- close_output_pbs(&r_proposal_pbs);
- close_output_pbs(r_sa_pbs);
- }
-
- /* copy over the results */
- st->st_oakley = ta;
- return NOTHING_WRONG;
- }
+ /* Transform */
+ r_trans.isat_np = ISAKMP_NEXT_NONE;
+ if (!out_struct(&r_trans, &isakmp_isakmp_transform_desc, &r_proposal_pbs, &r_trans_pbs))
+ impossible();
- /* on to next transform */
- no_trans_left--;
+ if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes"))
+ impossible();
+ close_output_pbs(&r_trans_pbs);
+ close_output_pbs(&r_proposal_pbs);
+ close_output_pbs(r_sa_pbs);
+ }
- if (trans.isat_np == ISAKMP_NEXT_NONE)
- {
- if (no_trans_left != 0)
- {
- loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
- return BAD_PROPOSAL_SYNTAX;
- }
- break;
- }
- if (trans.isat_np != ISAKMP_NEXT_T)
- {
- loglog(RC_LOG_SERIOUS, "unexpected %s payload in Oakley Proposal"
- , enum_show(&payload_names, proposal->isap_np));
- return BAD_PROPOSAL_SYNTAX;
+ /* copy over the results */
+ st->st_oakley = ta;
+ return NOTHING_WRONG;
+ }
+
+ /* on to next transform */
+ no_trans_left--;
+
+ if (trans.isat_np == ISAKMP_NEXT_NONE)
+ {
+ if (no_trans_left != 0)
+ {
+ loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ break;
+ }
+ if (trans.isat_np != ISAKMP_NEXT_T)
+ {
+ loglog(RC_LOG_SERIOUS, "unexpected %s payload in Oakley Proposal"
+ , enum_show(&payload_names, proposal->isap_np));
+ return BAD_PROPOSAL_SYNTAX;
+ }
}
- }
- loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform");
- return NO_PROPOSAL_CHOSEN;
+ loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform");
+ return NO_PROPOSAL_CHOSEN;
}
/* Parse the body of an IPsec SA Payload (i.e. Phase 2 / Quick Mode).
@@ -1315,14 +1316,14 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
*/
static const struct ipsec_trans_attrs null_ipsec_trans_attrs = {
- 0, /* transid (NULL, for now) */
- 0, /* spi */
- SA_LIFE_DURATION_DEFAULT, /* life_seconds */
- SA_LIFE_DURATION_K_DEFAULT, /* life_kilobytes */
- ENCAPSULATION_MODE_UNSPECIFIED, /* encapsulation */
- AUTH_ALGORITHM_NONE, /* auth */
- 0, /* key_len */
- 0, /* key_rounds */
+ 0, /* transid (NULL, for now) */
+ 0, /* spi */
+ SA_LIFE_DURATION_DEFAULT, /* life_seconds */
+ SA_LIFE_DURATION_K_DEFAULT, /* life_kilobytes */
+ ENCAPSULATION_MODE_UNSPECIFIED, /* encapsulation */
+ AUTH_ALGORITHM_NONE, /* auth */
+ 0, /* key_len */
+ 0, /* key_rounds */
};
static bool
@@ -1331,988 +1332,988 @@ parse_ipsec_transform(struct isakmp_transform *trans
, pb_stream *prop_pbs
, pb_stream *trans_pbs
, struct_desc *trans_desc
-, int previous_transnum /* or -1 if none */
+, int previous_transnum /* or -1 if none */
, bool selection
, bool is_last
, bool is_ipcomp
-, struct state *st) /* current state object */
+, struct state *st) /* current state object */
{
- lset_t seen_attrs = 0;
- lset_t seen_durations = 0;
- u_int16_t life_type = 0;
- const struct oakley_group_desc *pfs_group = NULL;
-
- if (!in_struct(trans, trans_desc, prop_pbs, trans_pbs))
- return FALSE;
-
- if (trans->isat_transnum <= previous_transnum)
- {
- loglog(RC_LOG_SERIOUS, "Transform Numbers in Proposal are not monotonically increasing");
- return FALSE;
- }
-
- switch (trans->isat_np)
- {
- case ISAKMP_NEXT_T:
- if (is_last)
- {
- loglog(RC_LOG_SERIOUS, "Proposal Payload has more Transforms than specified");
- return FALSE;
- }
- break;
- case ISAKMP_NEXT_NONE:
- if (!is_last)
- {
- loglog(RC_LOG_SERIOUS, "Proposal Payload has fewer Transforms than specified");
- return FALSE;
- }
- break;
- default:
- loglog(RC_LOG_SERIOUS, "expecting Transform Payload, but found %s in Proposal"
- , enum_show(&payload_names, trans->isat_np));
- return FALSE;
- }
-
- *attrs = null_ipsec_trans_attrs;
- attrs->transid = trans->isat_transid;
-
- while (pbs_left(trans_pbs) != 0)
- {
- struct isakmp_attribute a;
- pb_stream attr_pbs;
- enum_names *vdesc;
- u_int32_t val; /* room for larger value */
- bool ipcomp_inappropriate = is_ipcomp; /* will get reset if OK */
-
- if (!in_struct(&a, &isakmp_ipsec_attribute_desc, trans_pbs, &attr_pbs))
- return FALSE;
-
- passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
-
- if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
- {
- loglog(RC_LOG_SERIOUS, "repeated %s attribute in IPsec Transform %u"
- , enum_show(&ipsec_attr_names, a.isaat_af_type)
- , trans->isat_transnum);
- return FALSE;
- }
-
- seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
+ lset_t seen_attrs = 0;
+ lset_t seen_durations = 0;
+ u_int16_t life_type = 0;
+ const struct dh_desc *pfs_group = NULL;
- val = a.isaat_lv;
+ if (!in_struct(trans, trans_desc, prop_pbs, trans_pbs))
+ return FALSE;
- vdesc = ipsec_attr_val_descs[a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];
- if (vdesc != NULL)
+ if (trans->isat_transnum <= previous_transnum)
{
- if (enum_name(vdesc, val) == NULL)
- {
- loglog(RC_LOG_SERIOUS, "invalid value %u for attribute %s in IPsec Transform"
- , (unsigned)val, enum_show(&ipsec_attr_names, a.isaat_af_type));
+ loglog(RC_LOG_SERIOUS, "Transform Numbers in Proposal are not monotonically increasing");
return FALSE;
- }
- DBG(DBG_PARSING
- , if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- DBG_log(" [%u is %s]"
- , (unsigned)val, enum_show(vdesc, val)));
}
- switch (a.isaat_af_type)
+ switch (trans->isat_np)
{
- case SA_LIFE_TYPE | ISAKMP_ATTR_AF_TV:
- ipcomp_inappropriate = FALSE;
- if (LHAS(seen_durations, val))
- {
- loglog(RC_LOG_SERIOUS, "attribute SA_LIFE_TYPE value %s repeated in message"
- , enum_show(&sa_lifetime_names, val));
- return FALSE;
- }
- seen_durations |= LELEM(val);
- life_type = val;
- break;
- case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
- val = decode_long_duration(&attr_pbs);
- /* fall through */
- case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
- ipcomp_inappropriate = FALSE;
- if (!LHAS(seen_attrs, SA_LIFE_DURATION))
- {
- loglog(RC_LOG_SERIOUS, "SA_LIFE_DURATION IPsec attribute not preceded by SA_LIFE_TYPE attribute");
- return FALSE;
- }
- seen_attrs &= ~(LELEM(SA_LIFE_DURATION) | LELEM(SA_LIFE_TYPE));
-
- switch (life_type)
- {
- case SA_LIFE_TYPE_SECONDS:
- /* silently limit duration to our maximum */
- attrs->life_seconds = val <= SA_LIFE_DURATION_MAXIMUM
- ? val : SA_LIFE_DURATION_MAXIMUM;
+ case ISAKMP_NEXT_T:
+ if (is_last)
+ {
+ loglog(RC_LOG_SERIOUS, "Proposal Payload has more Transforms than specified");
+ return FALSE;
+ }
break;
- case SA_LIFE_TYPE_KBYTES:
- attrs->life_kilobytes = val;
+ case ISAKMP_NEXT_NONE:
+ if (!is_last)
+ {
+ loglog(RC_LOG_SERIOUS, "Proposal Payload has fewer Transforms than specified");
+ return FALSE;
+ }
break;
- default:
- bad_case(life_type);
- }
- break;
- case GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
- if (is_ipcomp)
+ default:
+ loglog(RC_LOG_SERIOUS, "expecting Transform Payload, but found %s in Proposal"
+ , enum_show(&payload_names, trans->isat_np));
+ return FALSE;
+ }
+
+ *attrs = null_ipsec_trans_attrs;
+ attrs->transid = trans->isat_transid;
+
+ while (pbs_left(trans_pbs) != 0)
+ {
+ struct isakmp_attribute a;
+ pb_stream attr_pbs;
+ enum_names *vdesc;
+ u_int32_t val; /* room for larger value */
+ bool ipcomp_inappropriate = is_ipcomp; /* will get reset if OK */
+
+ if (!in_struct(&a, &isakmp_ipsec_attribute_desc, trans_pbs, &attr_pbs))
+ return FALSE;
+
+ passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
+
+ if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
{
- /* Accept reluctantly. Should not happen, according to
- * draft-shacham-ippcp-rfc2393bis-05.txt 4.1.
- */
- ipcomp_inappropriate = FALSE;
- loglog(RC_COMMENT
- , "IPCA (IPcomp SA) contains GROUP_DESCRIPTION."
- " Ignoring inapproprate attribute.");
+ loglog(RC_LOG_SERIOUS, "repeated %s attribute in IPsec Transform %u"
+ , enum_show(&ipsec_attr_names, a.isaat_af_type)
+ , trans->isat_transnum);
+ return FALSE;
}
- pfs_group = lookup_group(val);
- if (pfs_group == NULL)
+
+ seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
+
+ val = a.isaat_lv;
+
+ vdesc = ipsec_attr_val_descs[a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];
+ if (vdesc != NULL)
{
- loglog(RC_LOG_SERIOUS, "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported for PFS");
- return FALSE;
+ if (enum_name(vdesc, val) == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "invalid value %u for attribute %s in IPsec Transform"
+ , (unsigned)val, enum_show(&ipsec_attr_names, a.isaat_af_type));
+ return FALSE;
+ }
+ DBG(DBG_PARSING
+ , if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+ DBG_log(" [%u is %s]"
+ , (unsigned)val, enum_show(vdesc, val)));
}
- break;
- case ENCAPSULATION_MODE | ISAKMP_ATTR_AF_TV:
- ipcomp_inappropriate = FALSE;
- switch (val)
+
+ switch (a.isaat_af_type)
{
- case ENCAPSULATION_MODE_TUNNEL:
- case ENCAPSULATION_MODE_TRANSPORT:
- if (st->nat_traversal & NAT_T_DETECTED)
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used if NAT-Traversal is not detected"
- , enum_name(&enc_mode_names, val));
- /*
- * Accept it anyway because SSH-Sentinel does not
- * use UDP_TUNNEL or UDP_TRANSPORT for the diagnostic.
- *
- * remove when SSH-Sentinel is fixed
- */
+ case SA_LIFE_TYPE | ISAKMP_ATTR_AF_TV:
+ ipcomp_inappropriate = FALSE;
+ if (LHAS(seen_durations, val))
+ {
+ loglog(RC_LOG_SERIOUS, "attribute SA_LIFE_TYPE value %s repeated in message"
+ , enum_show(&sa_lifetime_names, val));
+ return FALSE;
+ }
+ seen_durations |= LELEM(val);
+ life_type = val;
+ break;
+ case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
+ val = decode_long_duration(&attr_pbs);
+ /* fall through */
+ case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
+ ipcomp_inappropriate = FALSE;
+ if (!LHAS(seen_attrs, SA_LIFE_DURATION))
+ {
+ loglog(RC_LOG_SERIOUS, "SA_LIFE_DURATION IPsec attribute not preceded by SA_LIFE_TYPE attribute");
+ return FALSE;
+ }
+ seen_attrs &= ~(LELEM(SA_LIFE_DURATION) | LELEM(SA_LIFE_TYPE));
+
+ switch (life_type)
+ {
+ case SA_LIFE_TYPE_SECONDS:
+ /* silently limit duration to our maximum */
+ attrs->life_seconds = val <= SA_LIFE_DURATION_MAXIMUM
+ ? val : SA_LIFE_DURATION_MAXIMUM;
+ break;
+ case SA_LIFE_TYPE_KBYTES:
+ attrs->life_kilobytes = val;
+ break;
+ default:
+ bad_case(life_type);
+ }
+ break;
+ case GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
+ if (is_ipcomp)
+ {
+ /* Accept reluctantly. Should not happen, according to
+ * draft-shacham-ippcp-rfc2393bis-05.txt 4.1.
+ */
+ ipcomp_inappropriate = FALSE;
+ loglog(RC_COMMENT
+ , "IPCA (IPcomp SA) contains GROUP_DESCRIPTION."
+ " Ignoring inapproprate attribute.");
+ }
+ pfs_group = ike_alg_get_dh_group(val);
+ if (pfs_group == NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported for PFS");
+ return FALSE;
+ }
+ break;
+ case ENCAPSULATION_MODE | ISAKMP_ATTR_AF_TV:
+ ipcomp_inappropriate = FALSE;
+ switch (val)
+ {
+ case ENCAPSULATION_MODE_TUNNEL:
+ case ENCAPSULATION_MODE_TRANSPORT:
+ if (st->nat_traversal & NAT_T_DETECTED)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "%s must only be used if NAT-Traversal is not detected"
+ , enum_name(&enc_mode_names, val));
+ /*
+ * Accept it anyway because SSH-Sentinel does not
+ * use UDP_TUNNEL or UDP_TRANSPORT for the diagnostic.
+ *
+ * remove when SSH-Sentinel is fixed
+ */
#ifdef I_DONT_CARE_OF_SSH_SENTINEL
- return FALSE;
+ return FALSE;
#endif
- }
- attrs->encapsulation = val;
- break;
- case ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS:
+ }
+ attrs->encapsulation = val;
+ break;
+ case ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS:
#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- loglog(RC_LOG_SERIOUS
- , "NAT-Traversal: Transport mode disabled due to security concerns");
- return FALSE;
+ loglog(RC_LOG_SERIOUS
+ , "NAT-Traversal: Transport mode disabled due to security concerns");
+ return FALSE;
#endif
- case ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS:
- if (st->nat_traversal & NAT_T_WITH_RFC_VALUES)
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used with old IETF drafts"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- else if (st->nat_traversal & NAT_T_DETECTED)
- {
- attrs->encapsulation = val
- - ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS
- + ENCAPSULATION_MODE_TUNNEL;
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used if NAT-Traversal is detected"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- break;
- case ENCAPSULATION_MODE_UDP_TRANSPORT_RFC:
+ case ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS:
+ if (st->nat_traversal & NAT_T_WITH_RFC_VALUES)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "%s must only be used with old IETF drafts"
+ , enum_name(&enc_mode_names, val));
+ return FALSE;
+ }
+ else if (st->nat_traversal & NAT_T_DETECTED)
+ {
+ attrs->encapsulation = val
+ - ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS
+ + ENCAPSULATION_MODE_TUNNEL;
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS
+ , "%s must only be used if NAT-Traversal is detected"
+ , enum_name(&enc_mode_names, val));
+ return FALSE;
+ }
+ break;
+ case ENCAPSULATION_MODE_UDP_TRANSPORT_RFC:
#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- loglog(RC_LOG_SERIOUS
- , "NAT-Traversal: Transport mode disabled due "
- "to security concerns");
- return FALSE;
+ loglog(RC_LOG_SERIOUS
+ , "NAT-Traversal: Transport mode disabled due "
+ "to security concerns");
+ return FALSE;
#endif
- case ENCAPSULATION_MODE_UDP_TUNNEL_RFC:
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_RFC_VALUES))
- {
- attrs->encapsulation = val
- - ENCAPSULATION_MODE_UDP_TUNNEL_RFC
- + ENCAPSULATION_MODE_TUNNEL;
- }
- else if (st->nat_traversal & NAT_T_DETECTED)
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used with NAT-T RFC"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used if NAT-Traversal is detected"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- break;
- default:
- loglog(RC_LOG_SERIOUS
- , "unknown ENCAPSULATION_MODE %d in IPSec SA", val);
- return FALSE;
- }
- break;
- case AUTH_ALGORITHM | ISAKMP_ATTR_AF_TV:
- attrs->auth = val;
- break;
- case KEY_LENGTH | ISAKMP_ATTR_AF_TV:
- attrs->key_len = val;
- break;
- case KEY_ROUNDS | ISAKMP_ATTR_AF_TV:
- attrs->key_rounds = val;
- break;
+ case ENCAPSULATION_MODE_UDP_TUNNEL_RFC:
+ if ((st->nat_traversal & NAT_T_DETECTED)
+ && (st->nat_traversal & NAT_T_WITH_RFC_VALUES))
+ {
+ attrs->encapsulation = val
+ - ENCAPSULATION_MODE_UDP_TUNNEL_RFC
+ + ENCAPSULATION_MODE_TUNNEL;
+ }
+ else if (st->nat_traversal & NAT_T_DETECTED)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "%s must only be used with NAT-T RFC"
+ , enum_name(&enc_mode_names, val));
+ return FALSE;
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS
+ , "%s must only be used if NAT-Traversal is detected"
+ , enum_name(&enc_mode_names, val));
+ return FALSE;
+ }
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS
+ , "unknown ENCAPSULATION_MODE %d in IPSec SA", val);
+ return FALSE;
+ }
+ break;
+ case AUTH_ALGORITHM | ISAKMP_ATTR_AF_TV:
+ attrs->auth = val;
+ break;
+ case KEY_LENGTH | ISAKMP_ATTR_AF_TV:
+ attrs->key_len = val;
+ break;
+ case KEY_ROUNDS | ISAKMP_ATTR_AF_TV:
+ attrs->key_rounds = val;
+ break;
#if 0 /* not yet implemented */
- case COMPRESS_DICT_SIZE | ISAKMP_ATTR_AF_TV:
- break;
- case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TV:
- break;
-
- case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
- break;
- case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TLV:
- break;
+ case COMPRESS_DICT_SIZE | ISAKMP_ATTR_AF_TV:
+ break;
+ case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TV:
+ break;
+
+ case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
+ break;
+ case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TLV:
+ break;
#endif
- default:
- loglog(RC_LOG_SERIOUS, "unsupported IPsec attribute %s"
- , enum_show(&ipsec_attr_names, a.isaat_af_type));
- return FALSE;
- }
- if (ipcomp_inappropriate)
- {
- loglog(RC_LOG_SERIOUS, "IPsec attribute %s inappropriate for IPCOMP"
- , enum_show(&ipsec_attr_names, a.isaat_af_type));
- return FALSE;
+ default:
+ loglog(RC_LOG_SERIOUS, "unsupported IPsec attribute %s"
+ , enum_show(&ipsec_attr_names, a.isaat_af_type));
+ return FALSE;
+ }
+ if (ipcomp_inappropriate)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec attribute %s inappropriate for IPCOMP"
+ , enum_show(&ipsec_attr_names, a.isaat_af_type));
+ return FALSE;
+ }
}
- }
-
- /* Although an IPCOMP SA (IPCA) ought not to have a pfs_group,
- * if it does, demand that it be consistent.
- * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1.
- */
- if (!is_ipcomp || pfs_group != NULL)
- {
- if (st->st_pfs_group == &unset_group)
- st->st_pfs_group = pfs_group;
-
- if (st->st_pfs_group != pfs_group)
+
+ /* Although an IPCOMP SA (IPCA) ought not to have a pfs_group,
+ * if it does, demand that it be consistent.
+ * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1.
+ */
+ if (!is_ipcomp || pfs_group != NULL)
{
- loglog(RC_LOG_SERIOUS, "GROUP_DESCRIPTION inconsistent with that of %s in IPsec SA"
- , selection? "the Proposal" : "a previous Transform");
- return FALSE;
- }
- }
+ if (st->st_pfs_group == &unset_group)
+ st->st_pfs_group = pfs_group;
- if (LHAS(seen_attrs, SA_LIFE_DURATION))
- {
- loglog(RC_LOG_SERIOUS, "SA_LIFE_TYPE IPsec attribute not followed by SA_LIFE_DURATION attribute in message");
- return FALSE;
- }
+ if (st->st_pfs_group != pfs_group)
+ {
+ loglog(RC_LOG_SERIOUS, "GROUP_DESCRIPTION inconsistent with that of %s in IPsec SA"
+ , selection? "the Proposal" : "a previous Transform");
+ return FALSE;
+ }
+ }
- if (!LHAS(seen_attrs, ENCAPSULATION_MODE))
- {
- if (is_ipcomp)
+ if (LHAS(seen_attrs, SA_LIFE_DURATION))
{
- /* draft-shacham-ippcp-rfc2393bis-05.txt 4.1:
- * "If the Encapsulation Mode is unspecified,
- * the default value of Transport Mode is assumed."
- * This contradicts/overrides the DOI (quuoted below).
- */
- attrs->encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ loglog(RC_LOG_SERIOUS, "SA_LIFE_TYPE IPsec attribute not followed by SA_LIFE_DURATION attribute in message");
+ return FALSE;
}
- else
+
+ if (!LHAS(seen_attrs, ENCAPSULATION_MODE))
{
- /* ??? Technically, RFC 2407 (IPSEC DOI) 4.5 specifies that
- * the default is "unspecified (host-dependent)".
- * This makes little sense, so we demand that it be specified.
- */
- loglog(RC_LOG_SERIOUS, "IPsec Transform must specify ENCAPSULATION_MODE");
- return FALSE;
+ if (is_ipcomp)
+ {
+ /* draft-shacham-ippcp-rfc2393bis-05.txt 4.1:
+ * "If the Encapsulation Mode is unspecified,
+ * the default value of Transport Mode is assumed."
+ * This contradicts/overrides the DOI (quuoted below).
+ */
+ attrs->encapsulation = ENCAPSULATION_MODE_TRANSPORT;
+ }
+ else
+ {
+ /* ??? Technically, RFC 2407 (IPSEC DOI) 4.5 specifies that
+ * the default is "unspecified (host-dependent)".
+ * This makes little sense, so we demand that it be specified.
+ */
+ loglog(RC_LOG_SERIOUS, "IPsec Transform must specify ENCAPSULATION_MODE");
+ return FALSE;
+ }
}
- }
- /* ??? should check for key_len and/or key_rounds if required */
+ /* ??? should check for key_len and/or key_rounds if required */
- return TRUE;
+ return TRUE;
}
static void
echo_proposal(
- struct isakmp_proposal r_proposal, /* proposal to emit */
- struct isakmp_transform r_trans, /* winning transformation within it */
- u_int8_t np, /* Next Payload for proposal */
- pb_stream *r_sa_pbs, /* SA PBS into which to emit */
- struct ipsec_proto_info *pi, /* info about this protocol instance */
- struct_desc *trans_desc, /* descriptor for this transformation */
- pb_stream *trans_pbs, /* PBS for incoming transform */
- struct spd_route *sr, /* host details for the association */
- bool tunnel_mode) /* true for inner most tunnel SA */
+ struct isakmp_proposal r_proposal, /* proposal to emit */
+ struct isakmp_transform r_trans, /* winning transformation within it */
+ u_int8_t np, /* Next Payload for proposal */
+ pb_stream *r_sa_pbs, /* SA PBS into which to emit */
+ struct ipsec_proto_info *pi, /* info about this protocol instance */
+ struct_desc *trans_desc, /* descriptor for this transformation */
+ pb_stream *trans_pbs, /* PBS for incoming transform */
+ struct spd_route *sr, /* host details for the association */
+ bool tunnel_mode) /* true for inner most tunnel SA */
{
- pb_stream r_proposal_pbs;
- pb_stream r_trans_pbs;
-
- /* Proposal */
- r_proposal.isap_np = np;
- r_proposal.isap_notrans = 1;
- if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
- impossible();
-
- /* allocate and emit our CPI/SPI */
- if (r_proposal.isap_protoid == PROTO_IPCOMP)
- {
- /* CPI is stored in network low order end of an
- * ipsec_spi_t. So we start a couple of bytes in.
- * Note: we may fail to generate a satisfactory CPI,
- * but we'll ignore that.
- */
- pi->our_spi = get_my_cpi(sr, tunnel_mode);
- out_raw((u_char *) &pi->our_spi
- + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
- , IPCOMP_CPI_SIZE
- , &r_proposal_pbs, "CPI");
- }
- else
- {
- pi->our_spi = get_ipsec_spi(pi->attrs.spi
- , r_proposal.isap_protoid == PROTO_IPSEC_AH ?
- IPPROTO_AH : IPPROTO_ESP
- , sr
- , tunnel_mode);
- /* XXX should check for errors */
- out_raw((u_char *) &pi->our_spi, IPSEC_DOI_SPI_SIZE
- , &r_proposal_pbs, "SPI");
- }
-
- /* Transform */
- r_trans.isat_np = ISAKMP_NEXT_NONE;
- if (!out_struct(&r_trans, trans_desc, &r_proposal_pbs, &r_trans_pbs))
- impossible();
-
- /* Transform Attributes: pure echo */
- trans_pbs->cur = trans_pbs->start + sizeof(struct isakmp_transform);
- if (!out_raw(trans_pbs->cur, pbs_left(trans_pbs)
- , &r_trans_pbs, "attributes"))
- impossible();
-
- close_output_pbs(&r_trans_pbs);
- close_output_pbs(&r_proposal_pbs);
-}
+ pb_stream r_proposal_pbs;
+ pb_stream r_trans_pbs;
-notification_t
-parse_ipsec_sa_body(
- pb_stream *sa_pbs, /* body of input SA Payload */
- const struct isakmp_sa *sa, /* header of input SA Payload */
- pb_stream *r_sa_pbs, /* if non-NULL, where to emit body of winning SA */
- bool selection, /* if this SA is a selection, only one transform may appear */
- struct state *st) /* current state object */
-{
- const struct connection *c = st->st_connection;
- u_int32_t ipsecdoisit;
- pb_stream next_proposal_pbs;
-
- struct isakmp_proposal next_proposal;
- ipsec_spi_t next_spi;
-
- bool next_full = TRUE;
-
- /* DOI */
- if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
- {
- loglog(RC_LOG_SERIOUS, "Unknown or unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
- /* XXX Could send notification back */
- return DOI_NOT_SUPPORTED;
- }
-
- /* Situation */
- if (!in_struct(&ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
- return SITUATION_NOT_SUPPORTED;
-
- if (ipsecdoisit != SIT_IDENTITY_ONLY)
- {
- loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"
- , bitnamesof(sit_bit_names, ipsecdoisit));
- /* XXX Could send notification back */
- return SITUATION_NOT_SUPPORTED;
- }
-
- /* The rules for IPsec SAs are scattered.
- * RFC 2408 "ISAKMP" section 4.2 gives some info.
- * There may be multiple proposals. Those with identical proposal
- * numbers must be considered as conjuncts. Those with different
- * numbers are disjuncts.
- * Each proposal may have several transforms, each considered
- * an alternative.
- * Each transform may have several attributes, all applying.
- *
- * To handle the way proposals are combined, we need to do a
- * look-ahead.
- */
-
- if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
- return BAD_PROPOSAL_SYNTAX;
-
- /* for each conjunction of proposals... */
- while (next_full)
- {
- int propno = next_proposal.isap_proposal;
- pb_stream ah_prop_pbs, esp_prop_pbs, ipcomp_prop_pbs;
- struct isakmp_proposal ah_proposal = {0, 0, 0, 0, 0, 0, 0};
- struct isakmp_proposal esp_proposal = {0, 0, 0, 0, 0, 0, 0};
- struct isakmp_proposal ipcomp_proposal = {0, 0, 0, 0, 0, 0, 0};
- ipsec_spi_t ah_spi = 0;
- ipsec_spi_t esp_spi = 0;
- ipsec_spi_t ipcomp_cpi = 0;
- bool ah_seen = FALSE;
- bool esp_seen = FALSE;
- bool ipcomp_seen = FALSE;
- bool tunnel_mode = FALSE;
- int inner_proto = 0;
- u_int16_t well_known_cpi = 0;
-
- pb_stream ah_trans_pbs, esp_trans_pbs, ipcomp_trans_pbs;
- struct isakmp_transform ah_trans, esp_trans, ipcomp_trans;
- struct ipsec_trans_attrs ah_attrs, esp_attrs, ipcomp_attrs;
-
- /* for each proposal in the conjunction */
- do {
-
- if (next_proposal.isap_protoid == PROTO_IPCOMP)
- {
- /* IPCOMP CPI */
- if (next_proposal.isap_spisize == IPSEC_DOI_SPI_SIZE)
- {
- /* This code is to accommodate those peculiar
- * implementations that send a CPI in the bottom of an
- * SPI-sized field.
- * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1
- */
- u_int8_t filler[IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE];
-
- if (!in_raw(filler, sizeof(filler)
- , &next_proposal_pbs, "CPI filler")
- || !all_zero(filler, sizeof(filler)))
- return INVALID_SPI;
- }
- else if (next_proposal.isap_spisize != IPCOMP_CPI_SIZE)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper CPI size (%u)"
- , next_proposal.isap_spisize);
- return INVALID_SPI;
- }
+ /* Proposal */
+ r_proposal.isap_np = np;
+ r_proposal.isap_notrans = 1;
+ if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
+ impossible();
- /* We store CPI in the low order of a network order
+ /* allocate and emit our CPI/SPI */
+ if (r_proposal.isap_protoid == PROTO_IPCOMP)
+ {
+ /* CPI is stored in network low order end of an
* ipsec_spi_t. So we start a couple of bytes in.
+ * Note: we may fail to generate a satisfactory CPI,
+ * but we'll ignore that.
*/
- zero(&next_spi);
- if (!in_raw((u_char *)&next_spi
- + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
- , IPCOMP_CPI_SIZE, &next_proposal_pbs, "CPI"))
- return INVALID_SPI;
-
- /* If sanity ruled, CPIs would have to be such that
- * the SAID (the triple (CPI, IPCOM, destination IP))
- * would be unique, just like for SPIs. But there is a
- * perversion where CPIs can be well-known and consequently
- * the triple is not unique. We hide this fact from
- * ourselves by fudging the top 16 bits to make
- * the property true internally!
- */
- switch (ntohl(next_spi))
- {
- case IPCOMP_DEFLATE:
- well_known_cpi = ntohl(next_spi);
- next_spi = uniquify_his_cpi(next_spi, st);
- if (next_spi == 0)
- {
- loglog(RC_LOG_SERIOUS
- , "IPsec Proposal contains well-known CPI that I cannot uniquify");
- return INVALID_SPI;
- }
- break;
- default:
- if (ntohl(next_spi) < IPCOMP_FIRST_NEGOTIATED
- || ntohl(next_spi) > IPCOMP_LAST_NEGOTIATED)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal contains CPI from non-negotiated range (0x%lx)"
- , (unsigned long) ntohl(next_spi));
- return INVALID_SPI;
- }
- break;
- }
- }
- else
- {
- /* AH or ESP SPI */
- if (next_proposal.isap_spisize != IPSEC_DOI_SPI_SIZE)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper SPI size (%u)"
- , next_proposal.isap_spisize);
- return INVALID_SPI;
- }
-
- if (!in_raw((u_char *)&next_spi, sizeof(next_spi), &next_proposal_pbs, "SPI"))
- return INVALID_SPI;
+ pi->our_spi = get_my_cpi(sr, tunnel_mode);
+ out_raw((u_char *) &pi->our_spi
+ + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
+ , IPCOMP_CPI_SIZE
+ , &r_proposal_pbs, "CPI");
+ }
+ else
+ {
+ pi->our_spi = get_ipsec_spi(pi->attrs.spi
+ , r_proposal.isap_protoid == PROTO_IPSEC_AH ?
+ IPPROTO_AH : IPPROTO_ESP
+ , sr
+ , tunnel_mode);
+ /* XXX should check for errors */
+ out_raw((u_char *) &pi->our_spi, IPSEC_DOI_SPI_SIZE
+ , &r_proposal_pbs, "SPI");
+ }
- /* SPI value 0 is invalid and values 1-255 are reserved to IANA.
- * RFC 2402 (ESP) 2.4, RFC 2406 (AH) 2.1
- * IPCOMP???
- */
- if (ntohl(next_spi) < IPSEC_DOI_SPI_MIN)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal contains invalid SPI (0x%lx)"
- , (unsigned long) ntohl(next_spi));
- return INVALID_SPI;
- }
- }
+ /* Transform */
+ r_trans.isat_np = ISAKMP_NEXT_NONE;
+ if (!out_struct(&r_trans, trans_desc, &r_proposal_pbs, &r_trans_pbs))
+ impossible();
- if (next_proposal.isap_notrans == 0)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal contains no Transforms");
- return BAD_PROPOSAL_SYNTAX;
- }
+ /* Transform Attributes: pure echo */
+ trans_pbs->cur = trans_pbs->start + sizeof(struct isakmp_transform);
+ if (!out_raw(trans_pbs->cur, pbs_left(trans_pbs)
+ , &r_trans_pbs, "attributes"))
+ impossible();
- switch (next_proposal.isap_protoid)
- {
- case PROTO_IPSEC_AH:
- if (ah_seen)
- {
- loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous AH Proposals");
- return BAD_PROPOSAL_SYNTAX;
- }
- ah_seen = TRUE;
- ah_prop_pbs = next_proposal_pbs;
- ah_proposal = next_proposal;
- ah_spi = next_spi;
- break;
+ close_output_pbs(&r_trans_pbs);
+ close_output_pbs(&r_proposal_pbs);
+}
- case PROTO_IPSEC_ESP:
- if (esp_seen)
- {
- loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous ESP Proposals");
- return BAD_PROPOSAL_SYNTAX;
- }
- esp_seen = TRUE;
- esp_prop_pbs = next_proposal_pbs;
- esp_proposal = next_proposal;
- esp_spi = next_spi;
- break;
+notification_t
+parse_ipsec_sa_body(
+ pb_stream *sa_pbs, /* body of input SA Payload */
+ const struct isakmp_sa *sa, /* header of input SA Payload */
+ pb_stream *r_sa_pbs, /* if non-NULL, where to emit body of winning SA */
+ bool selection, /* if this SA is a selection, only one transform may appear */
+ struct state *st) /* current state object */
+{
+ const struct connection *c = st->st_connection;
+ u_int32_t ipsecdoisit;
+ pb_stream next_proposal_pbs;
- case PROTO_IPCOMP:
- if (ipcomp_seen)
- {
- loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous IPCOMP Proposals");
- return BAD_PROPOSAL_SYNTAX;
- }
- ipcomp_seen = TRUE;
- ipcomp_prop_pbs = next_proposal_pbs;
- ipcomp_proposal = next_proposal;
- ipcomp_cpi = next_spi;
- break;
-
- default:
- loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) in IPsec Proposal"
- , enum_show(&protocol_names, next_proposal.isap_protoid));
- return INVALID_PROTOCOL_ID;
- }
-
- /* refill next_proposal */
- if (next_proposal.isap_np == ISAKMP_NEXT_NONE)
- {
- next_full = FALSE;
- break;
- }
- else if (next_proposal.isap_np != ISAKMP_NEXT_P)
- {
- loglog(RC_LOG_SERIOUS, "unexpected in Proposal: %s"
- , enum_show(&payload_names, next_proposal.isap_np));
- return BAD_PROPOSAL_SYNTAX;
- }
+ struct isakmp_proposal next_proposal;
+ ipsec_spi_t next_spi;
- if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
- return BAD_PROPOSAL_SYNTAX;
- } while (next_proposal.isap_proposal == propno);
-
- /* Now that we have all conjuncts, we should try
- * the Cartesian product of eachs tranforms!
- * At the moment, we take short-cuts on account of
- * our rudimentary hard-wired policy.
- * For now, we find an acceptable AH (if any)
- * and then an acceptable ESP. The only interaction
- * is that the ESP acceptance can know whether there
- * was an acceptable AH and hence not require an AUTH.
- */
+ bool next_full = TRUE;
- if (ah_seen)
+ /* DOI */
+ if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
{
- int previous_transnum = -1;
- int tn;
-
- for (tn = 0; tn != ah_proposal.isap_notrans; tn++)
- {
- int ok_transid = 0;
- bool ok_auth = FALSE;
-
- if (!parse_ipsec_transform(&ah_trans
- , &ah_attrs
- , &ah_prop_pbs
- , &ah_trans_pbs
- , &isakmp_ah_transform_desc
- , previous_transnum
- , selection
- , tn == ah_proposal.isap_notrans - 1
- , FALSE
- , st))
- return BAD_PROPOSAL_SYNTAX;
-
- previous_transnum = ah_trans.isat_transnum;
-
- /* we must understand ah_attrs.transid
- * COMBINED with ah_attrs.auth.
- * See RFC 2407 "IPsec DOI" section 4.4.3
- * The following combinations are legal,
- * but we don't implement all of them:
- * It seems as if each auth algorithm
- * only applies to one ah transid.
- * AH_MD5, AUTH_ALGORITHM_HMAC_MD5
- * AH_MD5, AUTH_ALGORITHM_KPDK (unimplemented)
- * AH_SHA, AUTH_ALGORITHM_HMAC_SHA1
- * AH_DES, AUTH_ALGORITHM_DES_MAC (unimplemented)
- */
- switch (ah_attrs.auth)
- {
- case AUTH_ALGORITHM_NONE:
- loglog(RC_LOG_SERIOUS, "AUTH_ALGORITHM attribute missing in AH Transform");
- return BAD_PROPOSAL_SYNTAX;
+ loglog(RC_LOG_SERIOUS, "Unknown or unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
+ /* XXX Could send notification back */
+ return DOI_NOT_SUPPORTED;
+ }
- case AUTH_ALGORITHM_HMAC_MD5:
- ok_auth = TRUE;
- /* fall through */
- case AUTH_ALGORITHM_KPDK:
- ok_transid = AH_MD5;
- break;
+ /* Situation */
+ if (!in_struct(&ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
+ return SITUATION_NOT_SUPPORTED;
- case AUTH_ALGORITHM_HMAC_SHA1:
- ok_auth = TRUE;
- ok_transid = AH_SHA;
- break;
-
- case AUTH_ALGORITHM_DES_MAC:
- ok_transid = AH_DES;
- break;
- }
- if (ah_attrs.transid != ok_transid)
- {
- loglog(RC_LOG_SERIOUS, "%s attribute inappropriate in %s Transform"
- , enum_name(&auth_alg_names, ah_attrs.auth)
- , enum_show(&ah_transformid_names, ah_attrs.transid));
- return BAD_PROPOSAL_SYNTAX;
- }
- if (!ok_auth)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("%s attribute unsupported"
- " in %s Transform from %s"
- , enum_name(&auth_alg_names, ah_attrs.auth)
- , enum_show(&ah_transformid_names, ah_attrs.transid)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- break; /* we seem to be happy */
- }
- if (tn == ah_proposal.isap_notrans)
- continue; /* we didn't find a nice one */
- ah_attrs.spi = ah_spi;
- inner_proto = IPPROTO_AH;
- if (ah_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- tunnel_mode = TRUE;
+ if (ipsecdoisit != SIT_IDENTITY_ONLY)
+ {
+ loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"
+ , bitnamesof(sit_bit_names, ipsecdoisit));
+ /* XXX Could send notification back */
+ return SITUATION_NOT_SUPPORTED;
}
- if (esp_seen)
+ /* The rules for IPsec SAs are scattered.
+ * RFC 2408 "ISAKMP" section 4.2 gives some info.
+ * There may be multiple proposals. Those with identical proposal
+ * numbers must be considered as conjuncts. Those with different
+ * numbers are disjuncts.
+ * Each proposal may have several transforms, each considered
+ * an alternative.
+ * Each transform may have several attributes, all applying.
+ *
+ * To handle the way proposals are combined, we need to do a
+ * look-ahead.
+ */
+
+ if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
+ return BAD_PROPOSAL_SYNTAX;
+
+ /* for each conjunction of proposals... */
+ while (next_full)
{
- int previous_transnum = -1;
- int tn;
-
- for (tn = 0; tn != esp_proposal.isap_notrans; tn++)
- {
- if (!parse_ipsec_transform(&esp_trans
- , &esp_attrs
- , &esp_prop_pbs
- , &esp_trans_pbs
- , &isakmp_esp_transform_desc
- , previous_transnum
- , selection
- , tn == esp_proposal.isap_notrans - 1
- , FALSE
- , st))
- return BAD_PROPOSAL_SYNTAX;
-
- previous_transnum = esp_trans.isat_transnum;
-
- /* set default key length for AES encryption */
- if (!esp_attrs.key_len && esp_attrs.transid == ESP_AES)
- {
- esp_attrs.key_len = 128; /* bits */
- }
+ int propno = next_proposal.isap_proposal;
+ pb_stream ah_prop_pbs, esp_prop_pbs, ipcomp_prop_pbs;
+ struct isakmp_proposal ah_proposal = {0, 0, 0, 0, 0, 0, 0};
+ struct isakmp_proposal esp_proposal = {0, 0, 0, 0, 0, 0, 0};
+ struct isakmp_proposal ipcomp_proposal = {0, 0, 0, 0, 0, 0, 0};
+ ipsec_spi_t ah_spi = 0;
+ ipsec_spi_t esp_spi = 0;
+ ipsec_spi_t ipcomp_cpi = 0;
+ bool ah_seen = FALSE;
+ bool esp_seen = FALSE;
+ bool ipcomp_seen = FALSE;
+ bool tunnel_mode = FALSE;
+ int inner_proto = 0;
+ u_int16_t well_known_cpi = 0;
+
+ pb_stream ah_trans_pbs, esp_trans_pbs, ipcomp_trans_pbs;
+ struct isakmp_transform ah_trans, esp_trans, ipcomp_trans;
+ struct ipsec_trans_attrs ah_attrs, esp_attrs, ipcomp_attrs;
+
+ /* for each proposal in the conjunction */
+ do {
+
+ if (next_proposal.isap_protoid == PROTO_IPCOMP)
+ {
+ /* IPCOMP CPI */
+ if (next_proposal.isap_spisize == IPSEC_DOI_SPI_SIZE)
+ {
+ /* This code is to accommodate those peculiar
+ * implementations that send a CPI in the bottom of an
+ * SPI-sized field.
+ * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1
+ */
+ u_int8_t filler[IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE];
+
+ if (!in_raw(filler, sizeof(filler)
+ , &next_proposal_pbs, "CPI filler")
+ || !all_zero(filler, sizeof(filler)))
+ return INVALID_SPI;
+ }
+ else if (next_proposal.isap_spisize != IPCOMP_CPI_SIZE)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper CPI size (%u)"
+ , next_proposal.isap_spisize);
+ return INVALID_SPI;
+ }
+
+ /* We store CPI in the low order of a network order
+ * ipsec_spi_t. So we start a couple of bytes in.
+ */
+ zero(&next_spi);
+ if (!in_raw((u_char *)&next_spi
+ + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
+ , IPCOMP_CPI_SIZE, &next_proposal_pbs, "CPI"))
+ return INVALID_SPI;
+
+ /* If sanity ruled, CPIs would have to be such that
+ * the SAID (the triple (CPI, IPCOM, destination IP))
+ * would be unique, just like for SPIs. But there is a
+ * perversion where CPIs can be well-known and consequently
+ * the triple is not unique. We hide this fact from
+ * ourselves by fudging the top 16 bits to make
+ * the property true internally!
+ */
+ switch (ntohl(next_spi))
+ {
+ case IPCOMP_DEFLATE:
+ well_known_cpi = ntohl(next_spi);
+ next_spi = uniquify_his_cpi(next_spi, st);
+ if (next_spi == 0)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "IPsec Proposal contains well-known CPI that I cannot uniquify");
+ return INVALID_SPI;
+ }
+ break;
+ default:
+ if (ntohl(next_spi) < IPCOMP_FIRST_NEGOTIATED
+ || ntohl(next_spi) > IPCOMP_LAST_NEGOTIATED)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec Proposal contains CPI from non-negotiated range (0x%lx)"
+ , (unsigned long) ntohl(next_spi));
+ return INVALID_SPI;
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* AH or ESP SPI */
+ if (next_proposal.isap_spisize != IPSEC_DOI_SPI_SIZE)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper SPI size (%u)"
+ , next_proposal.isap_spisize);
+ return INVALID_SPI;
+ }
+
+ if (!in_raw((u_char *)&next_spi, sizeof(next_spi), &next_proposal_pbs, "SPI"))
+ return INVALID_SPI;
+
+ /* SPI value 0 is invalid and values 1-255 are reserved to IANA.
+ * RFC 2402 (ESP) 2.4, RFC 2406 (AH) 2.1
+ * IPCOMP???
+ */
+ if (ntohl(next_spi) < IPSEC_DOI_SPI_MIN)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec Proposal contains invalid SPI (0x%lx)"
+ , (unsigned long) ntohl(next_spi));
+ return INVALID_SPI;
+ }
+ }
- if (!kernel_alg_esp_enc_ok(esp_attrs.transid, esp_attrs.key_len
- ,c->alg_info_esp))
- {
- switch (esp_attrs.transid)
- {
- case ESP_3DES:
- break;
-#ifdef SUPPORT_ESP_NULL /* should be about as secure as AH-only */
- case ESP_NULL:
- if (esp_attrs.auth == AUTH_ALGORITHM_NONE)
+ if (next_proposal.isap_notrans == 0)
{
- loglog(RC_LOG_SERIOUS, "ESP_NULL requires auth algorithm");
- return BAD_PROPOSAL_SYNTAX;
+ loglog(RC_LOG_SERIOUS, "IPsec Proposal contains no Transforms");
+ return BAD_PROPOSAL_SYNTAX;
}
- if (st->st_policy & POLICY_ENCRYPT)
+
+ switch (next_proposal.isap_protoid)
{
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("ESP_NULL Transform Proposal from %s"
- " does not satisfy POLICY_ENCRYPT"
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
+ case PROTO_IPSEC_AH:
+ if (ah_seen)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous AH Proposals");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ ah_seen = TRUE;
+ ah_prop_pbs = next_proposal_pbs;
+ ah_proposal = next_proposal;
+ ah_spi = next_spi;
+ break;
+
+ case PROTO_IPSEC_ESP:
+ if (esp_seen)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous ESP Proposals");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ esp_seen = TRUE;
+ esp_prop_pbs = next_proposal_pbs;
+ esp_proposal = next_proposal;
+ esp_spi = next_spi;
+ break;
+
+ case PROTO_IPCOMP:
+ if (ipcomp_seen)
+ {
+ loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous IPCOMP Proposals");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ ipcomp_seen = TRUE;
+ ipcomp_prop_pbs = next_proposal_pbs;
+ ipcomp_proposal = next_proposal;
+ ipcomp_cpi = next_spi;
+ break;
+
+ default:
+ loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) in IPsec Proposal"
+ , enum_show(&protocol_names, next_proposal.isap_protoid));
+ return INVALID_PROTOCOL_ID;
}
- break;
-#endif
- default:
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("unsupported ESP Transform %s from %s"
- , enum_show(&esp_transformid_names, esp_attrs.transid)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- }
- if (!kernel_alg_esp_auth_ok(esp_attrs.auth, c->alg_info_esp))
- {
- switch (esp_attrs.auth)
- {
- case AUTH_ALGORITHM_NONE:
- if (!ah_seen)
+ /* refill next_proposal */
+ if (next_proposal.isap_np == ISAKMP_NEXT_NONE)
{
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("ESP from %s must either have AUTH or be combined with AH"
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
+ next_full = FALSE;
+ break;
+ }
+ else if (next_proposal.isap_np != ISAKMP_NEXT_P)
+ {
+ loglog(RC_LOG_SERIOUS, "unexpected in Proposal: %s"
+ , enum_show(&payload_names, next_proposal.isap_np));
+ return BAD_PROPOSAL_SYNTAX;
}
- break;
- case AUTH_ALGORITHM_HMAC_MD5:
- case AUTH_ALGORITHM_HMAC_SHA1:
- break;
- default:
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("unsupported ESP auth alg %s from %s"
- , enum_show(&auth_alg_names, esp_attrs.auth)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- }
- /* A last check for allowed transforms in alg_info_esp
- * (ALG_INFO_F_STRICT flag)
+ if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
+ return BAD_PROPOSAL_SYNTAX;
+ } while (next_proposal.isap_proposal == propno);
+
+ /* Now that we have all conjuncts, we should try
+ * the Cartesian product of eachs tranforms!
+ * At the moment, we take short-cuts on account of
+ * our rudimentary hard-wired policy.
+ * For now, we find an acceptable AH (if any)
+ * and then an acceptable ESP. The only interaction
+ * is that the ESP acceptance can know whether there
+ * was an acceptable AH and hence not require an AUTH.
*/
- if (!kernel_alg_esp_ok_final(esp_attrs.transid, esp_attrs.key_len
- ,esp_attrs.auth, c->alg_info_esp))
- {
- continue;
- }
- if (ah_seen && ah_attrs.encapsulation != esp_attrs.encapsulation)
+ if (ah_seen)
{
- /* ??? This should be an error, but is it? */
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("AH and ESP transforms disagree about encapsulation; TUNNEL presumed"));
+ int previous_transnum = -1;
+ int tn;
+
+ for (tn = 0; tn != ah_proposal.isap_notrans; tn++)
+ {
+ int ok_transid = 0;
+ bool ok_auth = FALSE;
+
+ if (!parse_ipsec_transform(&ah_trans
+ , &ah_attrs
+ , &ah_prop_pbs
+ , &ah_trans_pbs
+ , &isakmp_ah_transform_desc
+ , previous_transnum
+ , selection
+ , tn == ah_proposal.isap_notrans - 1
+ , FALSE
+ , st))
+ return BAD_PROPOSAL_SYNTAX;
+
+ previous_transnum = ah_trans.isat_transnum;
+
+ /* we must understand ah_attrs.transid
+ * COMBINED with ah_attrs.auth.
+ * See RFC 2407 "IPsec DOI" section 4.4.3
+ * The following combinations are legal,
+ * but we don't implement all of them:
+ * It seems as if each auth algorithm
+ * only applies to one ah transid.
+ * AH_MD5, AUTH_ALGORITHM_HMAC_MD5
+ * AH_MD5, AUTH_ALGORITHM_KPDK (unimplemented)
+ * AH_SHA, AUTH_ALGORITHM_HMAC_SHA1
+ * AH_DES, AUTH_ALGORITHM_DES_MAC (unimplemented)
+ */
+ switch (ah_attrs.auth)
+ {
+ case AUTH_ALGORITHM_NONE:
+ loglog(RC_LOG_SERIOUS, "AUTH_ALGORITHM attribute missing in AH Transform");
+ return BAD_PROPOSAL_SYNTAX;
+
+ case AUTH_ALGORITHM_HMAC_MD5:
+ ok_auth = TRUE;
+ /* fall through */
+ case AUTH_ALGORITHM_KPDK:
+ ok_transid = AH_MD5;
+ break;
+
+ case AUTH_ALGORITHM_HMAC_SHA1:
+ ok_auth = TRUE;
+ ok_transid = AH_SHA;
+ break;
+
+ case AUTH_ALGORITHM_DES_MAC:
+ ok_transid = AH_DES;
+ break;
+ }
+ if (ah_attrs.transid != ok_transid)
+ {
+ loglog(RC_LOG_SERIOUS, "%s attribute inappropriate in %s Transform"
+ , enum_name(&auth_alg_names, ah_attrs.auth)
+ , enum_show(&ah_transformid_names, ah_attrs.transid));
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ if (!ok_auth)
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("%s attribute unsupported"
+ " in %s Transform from %s"
+ , enum_name(&auth_alg_names, ah_attrs.auth)
+ , enum_show(&ah_transformid_names, ah_attrs.transid)
+ , ip_str(&c->spd.that.host_addr)));
+ continue; /* try another */
+ }
+ break; /* we seem to be happy */
+ }
+ if (tn == ah_proposal.isap_notrans)
+ continue; /* we didn't find a nice one */
+ ah_attrs.spi = ah_spi;
+ inner_proto = IPPROTO_AH;
+ if (ah_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ tunnel_mode = TRUE;
}
- break; /* we seem to be happy */
- }
- if (tn == esp_proposal.isap_notrans)
- continue; /* we didn't find a nice one */
-
- esp_attrs.spi = esp_spi;
- inner_proto = IPPROTO_ESP;
- if (esp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- tunnel_mode = TRUE;
- }
- else if (st->st_policy & POLICY_ENCRYPT)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("policy for \"%s\" requires encryption but ESP not in Proposal from %s"
- , c->name, ip_str(&c->spd.that.host_addr)));
- continue; /* we needed encryption, but didn't find ESP */
- }
- else if ((st->st_policy & POLICY_AUTHENTICATE) && !ah_seen)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("policy for \"%s\" requires authentication"
- " but none in Proposal from %s"
- , c->name, ip_str(&c->spd.that.host_addr)));
- continue; /* we need authentication, but we found neither ESP nor AH */
- }
+ if (esp_seen)
+ {
+ int previous_transnum = -1;
+ int tn;
- if (ipcomp_seen)
- {
- int previous_transnum = -1;
- int tn;
-
-#ifdef NEVER /* we think IPcomp is working now */
- /**** FUDGE TO PREVENT UNREQUESTED IPCOMP:
- **** NEEDED BECAUSE OUR IPCOMP IS EXPERIMENTAL (UNSTABLE).
- ****/
- if (!(st->st_policy & POLICY_COMPRESS))
- {
- plog("compression proposed by %s, but policy for \"%s\" forbids it"
- , ip_str(&c->spd.that.host_addr), c->name);
- continue; /* unwanted compression proposal */
- }
+ for (tn = 0; tn != esp_proposal.isap_notrans; tn++)
+ {
+ if (!parse_ipsec_transform(&esp_trans
+ , &esp_attrs
+ , &esp_prop_pbs
+ , &esp_trans_pbs
+ , &isakmp_esp_transform_desc
+ , previous_transnum
+ , selection
+ , tn == esp_proposal.isap_notrans - 1
+ , FALSE
+ , st))
+ return BAD_PROPOSAL_SYNTAX;
+
+ previous_transnum = esp_trans.isat_transnum;
+
+ /* set default key length for AES encryption */
+ if (!esp_attrs.key_len && esp_attrs.transid == ESP_AES)
+ {
+ esp_attrs.key_len = 128; /* bits */
+ }
+
+ if (!kernel_alg_esp_enc_ok(esp_attrs.transid, esp_attrs.key_len
+ ,c->alg_info_esp))
+ {
+ switch (esp_attrs.transid)
+ {
+ case ESP_3DES:
+ break;
+#ifdef SUPPORT_ESP_NULL /* should be about as secure as AH-only */
+ case ESP_NULL:
+ if (esp_attrs.auth == AUTH_ALGORITHM_NONE)
+ {
+ loglog(RC_LOG_SERIOUS, "ESP_NULL requires auth algorithm");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+ if (st->st_policy & POLICY_ENCRYPT)
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("ESP_NULL Transform Proposal from %s"
+ " does not satisfy POLICY_ENCRYPT"
+ , ip_str(&c->spd.that.host_addr)));
+ continue; /* try another */
+ }
+ break;
#endif
- if (!can_do_IPcomp)
- {
- plog("compression proposed by %s, but KLIPS is not configured with IPCOMP"
- , ip_str(&c->spd.that.host_addr));
- continue;
- }
-
- if (well_known_cpi != 0 && !ah_seen && !esp_seen)
- {
- plog("illegal proposal: bare IPCOMP used with well-known CPI");
- return BAD_PROPOSAL_SYNTAX;
- }
-
- for (tn = 0; tn != ipcomp_proposal.isap_notrans; tn++)
- {
- if (!parse_ipsec_transform(&ipcomp_trans
- , &ipcomp_attrs
- , &ipcomp_prop_pbs
- , &ipcomp_trans_pbs
- , &isakmp_ipcomp_transform_desc
- , previous_transnum
- , selection
- , tn == ipcomp_proposal.isap_notrans - 1
- , TRUE
- , st))
- return BAD_PROPOSAL_SYNTAX;
-
- previous_transnum = ipcomp_trans.isat_transnum;
-
- if (well_known_cpi != 0 && ipcomp_attrs.transid != well_known_cpi)
- {
- plog("illegal proposal: IPCOMP well-known CPI disagrees with transform");
- return BAD_PROPOSAL_SYNTAX;
+ default:
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("unsupported ESP Transform %s from %s"
+ , enum_show(&esp_transformid_names, esp_attrs.transid)
+ , ip_str(&c->spd.that.host_addr)));
+ continue; /* try another */
+ }
+ }
+
+ if (!kernel_alg_esp_auth_ok(esp_attrs.auth, c->alg_info_esp))
+ {
+ switch (esp_attrs.auth)
+ {
+ case AUTH_ALGORITHM_NONE:
+ if (!ah_seen)
+ {
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("ESP from %s must either have AUTH or be combined with AH"
+ , ip_str(&c->spd.that.host_addr)));
+ continue; /* try another */
+ }
+ break;
+ case AUTH_ALGORITHM_HMAC_MD5:
+ case AUTH_ALGORITHM_HMAC_SHA1:
+ break;
+ default:
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("unsupported ESP auth alg %s from %s"
+ , enum_show(&auth_alg_names, esp_attrs.auth)
+ , ip_str(&c->spd.that.host_addr)));
+ continue; /* try another */
+ }
+ }
+
+ /* A last check for allowed transforms in alg_info_esp
+ * (ALG_INFO_F_STRICT flag)
+ */
+ if (!kernel_alg_esp_ok_final(esp_attrs.transid, esp_attrs.key_len
+ ,esp_attrs.auth, c->alg_info_esp))
+ {
+ continue;
+ }
+
+ if (ah_seen && ah_attrs.encapsulation != esp_attrs.encapsulation)
+ {
+ /* ??? This should be an error, but is it? */
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("AH and ESP transforms disagree about encapsulation; TUNNEL presumed"));
+ }
+
+ break; /* we seem to be happy */
+ }
+ if (tn == esp_proposal.isap_notrans)
+ continue; /* we didn't find a nice one */
+
+ esp_attrs.spi = esp_spi;
+ inner_proto = IPPROTO_ESP;
+ if (esp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ tunnel_mode = TRUE;
}
-
- switch (ipcomp_attrs.transid)
+ else if (st->st_policy & POLICY_ENCRYPT)
{
- case IPCOMP_DEFLATE: /* all we can handle! */
- break;
-
- default:
DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("unsupported IPCOMP Transform %s from %s"
- , enum_show(&ipcomp_transformid_names, ipcomp_attrs.transid)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
+ , DBG_log("policy for \"%s\" requires encryption but ESP not in Proposal from %s"
+ , c->name, ip_str(&c->spd.that.host_addr)));
+ continue; /* we needed encryption, but didn't find ESP */
}
-
- if (ah_seen && ah_attrs.encapsulation != ipcomp_attrs.encapsulation)
- {
- /* ??? This should be an error, but is it? */
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("AH and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
- } else if (esp_seen && esp_attrs.encapsulation != ipcomp_attrs.encapsulation)
+ else if ((st->st_policy & POLICY_AUTHENTICATE) && !ah_seen)
{
- /* ??? This should be an error, but is it? */
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("ESP and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("policy for \"%s\" requires authentication"
+ " but none in Proposal from %s"
+ , c->name, ip_str(&c->spd.that.host_addr)));
+ continue; /* we need authentication, but we found neither ESP nor AH */
}
- break; /* we seem to be happy */
- }
- if (tn == ipcomp_proposal.isap_notrans)
- continue; /* we didn't find a nice one */
- ipcomp_attrs.spi = ipcomp_cpi;
- inner_proto = IPPROTO_COMP;
- if (ipcomp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- tunnel_mode = TRUE;
- }
+ if (ipcomp_seen)
+ {
+ int previous_transnum = -1;
+ int tn;
+
+#ifdef NEVER /* we think IPcomp is working now */
+ /**** FUDGE TO PREVENT UNREQUESTED IPCOMP:
+ **** NEEDED BECAUSE OUR IPCOMP IS EXPERIMENTAL (UNSTABLE).
+ ****/
+ if (!(st->st_policy & POLICY_COMPRESS))
+ {
+ plog("compression proposed by %s, but policy for \"%s\" forbids it"
+ , ip_str(&c->spd.that.host_addr), c->name);
+ continue; /* unwanted compression proposal */
+ }
+#endif
+ if (!can_do_IPcomp)
+ {
+ plog("compression proposed by %s, but KLIPS is not configured with IPCOMP"
+ , ip_str(&c->spd.that.host_addr));
+ continue;
+ }
- /* Eureka: we liked what we saw -- accept it. */
+ if (well_known_cpi != 0 && !ah_seen && !esp_seen)
+ {
+ plog("illegal proposal: bare IPCOMP used with well-known CPI");
+ return BAD_PROPOSAL_SYNTAX;
+ }
- if (r_sa_pbs != NULL)
- {
- /* emit what we've accepted */
+ for (tn = 0; tn != ipcomp_proposal.isap_notrans; tn++)
+ {
+ if (!parse_ipsec_transform(&ipcomp_trans
+ , &ipcomp_attrs
+ , &ipcomp_prop_pbs
+ , &ipcomp_trans_pbs
+ , &isakmp_ipcomp_transform_desc
+ , previous_transnum
+ , selection
+ , tn == ipcomp_proposal.isap_notrans - 1
+ , TRUE
+ , st))
+ return BAD_PROPOSAL_SYNTAX;
+
+ previous_transnum = ipcomp_trans.isat_transnum;
+
+ if (well_known_cpi != 0 && ipcomp_attrs.transid != well_known_cpi)
+ {
+ plog("illegal proposal: IPCOMP well-known CPI disagrees with transform");
+ return BAD_PROPOSAL_SYNTAX;
+ }
+
+ switch (ipcomp_attrs.transid)
+ {
+ case IPCOMP_DEFLATE: /* all we can handle! */
+ break;
+
+ default:
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("unsupported IPCOMP Transform %s from %s"
+ , enum_show(&ipcomp_transformid_names, ipcomp_attrs.transid)
+ , ip_str(&c->spd.that.host_addr)));
+ continue; /* try another */
+ }
+
+ if (ah_seen && ah_attrs.encapsulation != ipcomp_attrs.encapsulation)
+ {
+ /* ??? This should be an error, but is it? */
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("AH and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
+ } else if (esp_seen && esp_attrs.encapsulation != ipcomp_attrs.encapsulation)
+ {
+ /* ??? This should be an error, but is it? */
+ DBG(DBG_CONTROL | DBG_CRYPT
+ , DBG_log("ESP and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
+ }
+
+ break; /* we seem to be happy */
+ }
+ if (tn == ipcomp_proposal.isap_notrans)
+ continue; /* we didn't find a nice one */
+ ipcomp_attrs.spi = ipcomp_cpi;
+ inner_proto = IPPROTO_COMP;
+ if (ipcomp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ tunnel_mode = TRUE;
+ }
- /* Situation */
- if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
- impossible();
+ /* Eureka: we liked what we saw -- accept it. */
- /* AH proposal */
- if (ah_seen)
- echo_proposal(ah_proposal
- , ah_trans
- , esp_seen || ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
- , r_sa_pbs
- , &st->st_ah
- , &isakmp_ah_transform_desc
- , &ah_trans_pbs
- , &st->st_connection->spd
- , tunnel_mode && inner_proto == IPPROTO_AH);
-
- /* ESP proposal */
- if (esp_seen)
- echo_proposal(esp_proposal
- , esp_trans
- , ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
- , r_sa_pbs
- , &st->st_esp
- , &isakmp_esp_transform_desc
- , &esp_trans_pbs
- , &st->st_connection->spd
- , tunnel_mode && inner_proto == IPPROTO_ESP);
-
- /* IPCOMP proposal */
- if (ipcomp_seen)
- echo_proposal(ipcomp_proposal
- , ipcomp_trans
- , ISAKMP_NEXT_NONE
- , r_sa_pbs
- , &st->st_ipcomp
- , &isakmp_ipcomp_transform_desc
- , &ipcomp_trans_pbs
- , &st->st_connection->spd
- , tunnel_mode && inner_proto == IPPROTO_COMP);
-
- close_output_pbs(r_sa_pbs);
- }
+ if (r_sa_pbs != NULL)
+ {
+ /* emit what we've accepted */
+
+ /* Situation */
+ if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
+ impossible();
+
+ /* AH proposal */
+ if (ah_seen)
+ echo_proposal(ah_proposal
+ , ah_trans
+ , esp_seen || ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
+ , r_sa_pbs
+ , &st->st_ah
+ , &isakmp_ah_transform_desc
+ , &ah_trans_pbs
+ , &st->st_connection->spd
+ , tunnel_mode && inner_proto == IPPROTO_AH);
+
+ /* ESP proposal */
+ if (esp_seen)
+ echo_proposal(esp_proposal
+ , esp_trans
+ , ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
+ , r_sa_pbs
+ , &st->st_esp
+ , &isakmp_esp_transform_desc
+ , &esp_trans_pbs
+ , &st->st_connection->spd
+ , tunnel_mode && inner_proto == IPPROTO_ESP);
+
+ /* IPCOMP proposal */
+ if (ipcomp_seen)
+ echo_proposal(ipcomp_proposal
+ , ipcomp_trans
+ , ISAKMP_NEXT_NONE
+ , r_sa_pbs
+ , &st->st_ipcomp
+ , &isakmp_ipcomp_transform_desc
+ , &ipcomp_trans_pbs
+ , &st->st_connection->spd
+ , tunnel_mode && inner_proto == IPPROTO_COMP);
+
+ close_output_pbs(r_sa_pbs);
+ }
- /* save decoded version of winning SA in state */
+ /* save decoded version of winning SA in state */
- st->st_ah.present = ah_seen;
- if (ah_seen)
- st->st_ah.attrs = ah_attrs;
+ st->st_ah.present = ah_seen;
+ if (ah_seen)
+ st->st_ah.attrs = ah_attrs;
- st->st_esp.present = esp_seen;
- if (esp_seen)
- st->st_esp.attrs = esp_attrs;
+ st->st_esp.present = esp_seen;
+ if (esp_seen)
+ st->st_esp.attrs = esp_attrs;
- st->st_ipcomp.present = ipcomp_seen;
- if (ipcomp_seen)
- st->st_ipcomp.attrs = ipcomp_attrs;
+ st->st_ipcomp.present = ipcomp_seen;
+ if (ipcomp_seen)
+ st->st_ipcomp.attrs = ipcomp_attrs;
- return NOTHING_WRONG;
- }
+ return NOTHING_WRONG;
+ }
- loglog(RC_LOG_SERIOUS, "no acceptable Proposal in IPsec SA");
- return NO_PROPOSAL_CHOSEN;
+ loglog(RC_LOG_SERIOUS, "no acceptable Proposal in IPsec SA");
+ return NO_PROPOSAL_CHOSEN;
}
diff --git a/src/pluto/spdb.h b/src/pluto/spdb.h
index b098e247a..221cc00bb 100644
--- a/src/pluto/spdb.h
+++ b/src/pluto/spdb.h
@@ -10,8 +10,6 @@
* 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: spdb.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _SPDB_H
@@ -25,39 +23,39 @@
* Note: only "basic" values are represented so far.
*/
struct db_attr {
- u_int16_t type; /* ISAKMP_ATTR_AF_TV is implied; 0 for end */
- u_int16_t val;
+ u_int16_t type; /* ISAKMP_ATTR_AF_TV is implied; 0 for end */
+ u_int16_t val;
};
/* transform */
struct db_trans {
- u_int8_t transid; /* Transform-Id */
- struct db_attr *attrs; /* array */
- int attr_cnt; /* number of elements */
+ u_int8_t transid; /* Transform-Id */
+ struct db_attr *attrs; /* array */
+ int attr_cnt; /* number of elements */
};
/* proposal */
struct db_prop {
- u_int8_t protoid; /* Protocol-Id */
- struct db_trans *trans; /* array (disjunction) */
- int trans_cnt; /* number of elements */
- /* SPI size and value isn't part of DB */
+ u_int8_t protoid; /* Protocol-Id */
+ struct db_trans *trans; /* array (disjunction) */
+ int trans_cnt; /* number of elements */
+ /* SPI size and value isn't part of DB */
};
/* conjunction of proposals */
struct db_prop_conj {
- struct db_prop *props; /* array */
- int prop_cnt; /* number of elements */
+ struct db_prop *props; /* array */
+ int prop_cnt; /* number of elements */
};
/* security association */
struct db_sa {
- struct db_prop_conj *prop_conjs; /* array */
- int prop_conj_cnt; /* number of elements */
- /* Hardwired for now;
- * DOI: ISAKMP_DOI_IPSEC
- * Situation: SIT_IDENTITY_ONLY
- */
+ struct db_prop_conj *prop_conjs; /* array */
+ int prop_conj_cnt; /* number of elements */
+ /* Hardwired for now;
+ * DOI: ISAKMP_DOI_IPSEC
+ * Situation: SIT_IDENTITY_ONLY
+ */
};
/* The oakley sadb */
@@ -72,38 +70,38 @@ extern struct db_sa ipsec_sadb[1 << 3];
struct state;
extern bool out_sa(
- pb_stream *outs,
- struct db_sa *sadb,
- struct state *st,
- bool oakley_mode,
- u_int8_t np);
+ pb_stream *outs,
+ struct db_sa *sadb,
+ struct state *st,
+ bool oakley_mode,
+ u_int8_t np);
extern notification_t preparse_isakmp_sa_body(
- const struct isakmp_sa *sa, /* header of input SA Payload */
- pb_stream *sa_pbs, /* body of input SA Payload */
- u_int32_t *ipsecdoisit, /* IPsec DOI SIT bitset */
- pb_stream *proposal_pbs, /* body of proposal Payload */
- struct isakmp_proposal *proposal);
+ const struct isakmp_sa *sa, /* header of input SA Payload */
+ pb_stream *sa_pbs, /* body of input SA Payload */
+ u_int32_t *ipsecdoisit, /* IPsec DOI SIT bitset */
+ pb_stream *proposal_pbs, /* body of proposal Payload */
+ struct isakmp_proposal *proposal);
extern notification_t parse_isakmp_policy(
- pb_stream *proposal_pbs, /* body of proposal Payload */
- u_int notrans, /* number of transforms */
- lset_t *policy); /* RSA, PSK or XAUTH policy */
+ pb_stream *proposal_pbs, /* body of proposal Payload */
+ u_int notrans, /* number of transforms */
+ lset_t *policy); /* RSA, PSK or XAUTH policy */
extern notification_t parse_isakmp_sa_body(
- u_int32_t ipsecdoisit, /* IPsec DOI SIT bitset */
- pb_stream *proposal_pbs, /* body of proposal Payload */
- struct isakmp_proposal *proposal,
- pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
- struct state *st, /* current state object */
- bool initiator); /* is caller initiator? */
+ u_int32_t ipsecdoisit, /* IPsec DOI SIT bitset */
+ pb_stream *proposal_pbs, /* body of proposal Payload */
+ struct isakmp_proposal *proposal,
+ pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
+ struct state *st, /* current state object */
+ bool initiator); /* is caller initiator? */
extern notification_t parse_ipsec_sa_body(
- pb_stream *sa_pbs, /* body of input SA Payload */
- const struct isakmp_sa *sa, /* header of input SA Payload */
- pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
- bool selection, /* if this SA is a selection, only one tranform can appear */
- struct state *st); /* current state object */
+ pb_stream *sa_pbs, /* body of input SA Payload */
+ const struct isakmp_sa *sa, /* header of input SA Payload */
+ pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
+ bool selection, /* if this SA is a selection, only one tranform can appear */
+ struct state *st); /* current state object */
extern void backup_pbs(pb_stream *pbs);
extern void restore_pbs(pb_stream *pbs);
diff --git a/src/pluto/state.c b/src/pluto/state.c
index 5372e86f5..6ce0d50e5 100644
--- a/src/pluto/state.c
+++ b/src/pluto/state.c
@@ -11,8 +11,6 @@
* 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: state.c 4924 2009-03-10 21:13:18Z andreas $
*/
#include <stdio.h>
@@ -28,29 +26,28 @@
#include <freeswan.h>
+#include <library.h>
+#include <crypto/rngs/rng.h>
+
#include "constants.h"
#include "defs.h"
#include "connections.h"
#include "state.h"
#include "kernel.h"
#include "log.h"
-#include "packet.h" /* so we can calculate sizeof(struct isakmp_hdr) */
-#include "keys.h" /* for free_public_key */
-#include "rnd.h"
+#include "packet.h" /* so we can calculate sizeof(struct isakmp_hdr) */
+#include "keys.h" /* for free_public_key */
#include "timer.h"
#include "whack.h"
-#include "demux.h" /* needs packet.h */
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-
-#include "sha1.h"
-#include "md5.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
+#include "demux.h" /* needs packet.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "crypto.h"
/*
* Global variables: had to go somewhere, might as well be this file.
*/
-u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
+u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
/*
* This file has the functions that handle the
@@ -79,51 +76,53 @@ u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
struct msgid_list
{
- msgid_t msgid; /* network order */
- struct msgid_list *next;
+ msgid_t msgid; /* network order */
+ struct msgid_list *next;
};
-bool
-reserve_msgid(struct state *isakmp_sa, msgid_t msgid)
+bool reserve_msgid(struct state *isakmp_sa, msgid_t msgid)
{
- struct msgid_list *p;
+ struct msgid_list *p;
- passert(msgid != MAINMODE_MSGID);
- passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
+ passert(msgid != MAINMODE_MSGID);
+ passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
- for (p = isakmp_sa->st_used_msgids; p != NULL; p = p->next)
- if (p->msgid == msgid)
- return FALSE;
+ for (p = isakmp_sa->st_used_msgids; p != NULL; p = p->next)
+ if (p->msgid == msgid)
+ return FALSE;
- p = alloc_thing(struct msgid_list, "msgid");
- p->msgid = msgid;
- p->next = isakmp_sa->st_used_msgids;
- isakmp_sa->st_used_msgids = p;
- return TRUE;
+ p = malloc_thing(struct msgid_list);
+ p->msgid = msgid;
+ p->next = isakmp_sa->st_used_msgids;
+ isakmp_sa->st_used_msgids = p;
+ return TRUE;
}
-msgid_t
-generate_msgid(struct state *isakmp_sa)
+msgid_t generate_msgid(struct state *isakmp_sa)
{
- int timeout = 100; /* only try so hard for unique msgid */
- msgid_t msgid;
+ int timeout = 100; /* only try so hard for unique msgid */
+ msgid_t msgid;
+ rng_t *rng;
- passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
+ passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- for (;;)
- {
- get_rnd_bytes((void *) &msgid, sizeof(msgid));
- if (msgid != 0 && reserve_msgid(isakmp_sa, msgid))
- break;
-
- if (--timeout == 0)
+ for (;;)
{
- plog("gave up looking for unique msgid; using 0x%08lx"
- , (unsigned long) msgid);
- break;
+ rng->get_bytes(rng, sizeof(msgid), (void *) &msgid);
+ if (msgid != 0 && reserve_msgid(isakmp_sa, msgid))
+ {
+ break;
+ }
+ if (--timeout == 0)
+ {
+ plog("gave up looking for unique msgid; using 0x%08lx"
+ , (unsigned long) msgid);
+ break;
+ }
}
- }
- return msgid;
+ rng->destroy(rng);
+ return msgid;
}
@@ -133,63 +132,61 @@ generate_msgid(struct state *isakmp_sa)
static struct state *statetable[STATE_TABLE_SIZE];
-static struct state **
-state_hash(const u_char *icookie, const u_char *rcookie, const ip_address *peer)
+static struct state **state_hash(const u_char *icookie, const u_char *rcookie,
+ const ip_address *peer)
{
- u_int i = 0, j;
- const unsigned char *byte_ptr;
- size_t length = addrbytesptr(peer, &byte_ptr);
+ u_int i = 0, j;
+ const unsigned char *byte_ptr;
+ size_t length = addrbytesptr(peer, &byte_ptr);
- DBG(DBG_RAW | DBG_CONTROL,
- DBG_dump("ICOOKIE:", icookie, COOKIE_SIZE);
- DBG_dump("RCOOKIE:", rcookie, COOKIE_SIZE);
- DBG_dump("peer:", byte_ptr, length));
+ DBG(DBG_RAW | DBG_CONTROL,
+ DBG_dump("ICOOKIE:", icookie, COOKIE_SIZE);
+ DBG_dump("RCOOKIE:", rcookie, COOKIE_SIZE);
+ DBG_dump("peer:", byte_ptr, length));
- /* XXX the following hash is pretty pathetic */
+ /* XXX the following hash is pretty pathetic */
- for (j = 0; j < COOKIE_SIZE; j++)
- i = i * 407 + icookie[j] + rcookie[j];
+ for (j = 0; j < COOKIE_SIZE; j++)
+ i = i * 407 + icookie[j] + rcookie[j];
- for (j = 0; j < length; j++)
- i = i * 613 + byte_ptr[j];
+ for (j = 0; j < length; j++)
+ i = i * 613 + byte_ptr[j];
- i = i % STATE_TABLE_SIZE;
+ i = i % STATE_TABLE_SIZE;
- DBG(DBG_CONTROL, DBG_log("state hash entry %d", i));
+ DBG(DBG_CONTROL, DBG_log("state hash entry %d", i));
- return &statetable[i];
+ return &statetable[i];
}
/* Get a state object.
* Caller must schedule an event for this object so that it doesn't leak.
* Caller must insert_state().
*/
-struct state *
-new_state(void)
+struct state *new_state(void)
{
- static const struct state blank_state; /* initialized all to zero & NULL */
- static so_serial_t next_so = SOS_FIRST;
- struct state *st;
-
- st = clone_thing(blank_state, "struct state in new_state()");
- st->st_serialno = next_so++;
- passert(next_so > SOS_FIRST); /* overflow can't happen! */
- st->st_whack_sock = NULL_FD;
- DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p",
- st->st_serialno, (void *) st));
- return st;
+ static const struct state blank_state; /* initialized all to zero & NULL */
+ static so_serial_t next_so = SOS_FIRST;
+ struct state *st;
+
+ st = clone_thing(blank_state);
+ st->st_serialno = next_so++;
+ passert(next_so > SOS_FIRST); /* overflow can't happen! */
+ st->st_whack_sock = NULL_FD;
+ DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p",
+ st->st_serialno, (void *) st));
+ return st;
}
/*
* Initialize the state table (and mask*).
*/
-void
-init_states(void)
+void init_states(void)
{
- int i;
+ int i;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- statetable[i] = (struct state *) NULL;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ statetable[i] = (struct state *) NULL;
}
/* Find the state object with this serial number.
@@ -199,627 +196,619 @@ init_states(void)
* If this turns out to be a significant CPU hog, it could be
* improved to use a hash table rather than sequential seartch.
*/
-struct state *
-state_with_serialno(so_serial_t sn)
+struct state *state_with_serialno(so_serial_t sn)
{
- if (sn >= SOS_FIRST)
- {
- struct state *st;
- int i;
+ if (sn >= SOS_FIRST)
+ {
+ struct state *st;
+ int i;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_serialno == sn)
- return st;
- }
- return NULL;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ if (st->st_serialno == sn)
+ return st;
+ }
+ return NULL;
}
/* Insert a state object in the hash table. The object is inserted
* at the begining of list.
* Needs cookies, connection, and msgid.
*/
-void
-insert_state(struct state *st)
+void insert_state(struct state *st)
{
- struct state **p = state_hash(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr);
-
- passert(st->st_hashchain_prev == NULL && st->st_hashchain_next == NULL);
-
- if (*p != NULL)
- {
- passert((*p)->st_hashchain_prev == NULL);
- (*p)->st_hashchain_prev = st;
- }
- st->st_hashchain_next = *p;
- *p = st;
-
- /* Ensure that somebody is in charge of killing this state:
- * if no event is scheduled for it, schedule one to discard the state.
- * If nothing goes wrong, this event will be replaced by
- * a more appropriate one.
- */
- if (st->st_event == NULL)
- event_schedule(EVENT_SO_DISCARD, 0, st);
+ struct state **p = state_hash(st->st_icookie, st->st_rcookie
+ , &st->st_connection->spd.that.host_addr);
+
+ passert(st->st_hashchain_prev == NULL && st->st_hashchain_next == NULL);
+
+ if (*p != NULL)
+ {
+ passert((*p)->st_hashchain_prev == NULL);
+ (*p)->st_hashchain_prev = st;
+ }
+ st->st_hashchain_next = *p;
+ *p = st;
+
+ /* Ensure that somebody is in charge of killing this state:
+ * if no event is scheduled for it, schedule one to discard the state.
+ * If nothing goes wrong, this event will be replaced by
+ * a more appropriate one.
+ */
+ if (st->st_event == NULL)
+ event_schedule(EVENT_SO_DISCARD, 0, st);
}
/* unlink a state object from the hash table, but don't free it
*/
-void
-unhash_state(struct state *st)
+void unhash_state(struct state *st)
{
- /* unlink from forward chain */
- struct state **p = st->st_hashchain_prev == NULL
- ? state_hash(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr)
- : &st->st_hashchain_prev->st_hashchain_next;
-
- /* unlink from forward chain */
- passert(*p == st);
- *p = st->st_hashchain_next;
-
- /* unlink from backward chain */
- if (st->st_hashchain_next != NULL)
- {
- passert(st->st_hashchain_next->st_hashchain_prev == st);
- st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev;
- }
-
- st->st_hashchain_next = st->st_hashchain_prev = NULL;
+ /* unlink from forward chain */
+ struct state **p = st->st_hashchain_prev == NULL
+ ? state_hash(st->st_icookie, st->st_rcookie
+ , &st->st_connection->spd.that.host_addr)
+ : &st->st_hashchain_prev->st_hashchain_next;
+
+ /* unlink from forward chain */
+ passert(*p == st);
+ *p = st->st_hashchain_next;
+
+ /* unlink from backward chain */
+ if (st->st_hashchain_next != NULL)
+ {
+ passert(st->st_hashchain_next->st_hashchain_prev == st);
+ st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev;
+ }
+
+ st->st_hashchain_next = st->st_hashchain_prev = NULL;
}
/* Free the Whack socket file descriptor.
* This has the side effect of telling Whack that we're done.
*/
-void
-release_whack(struct state *st)
+void release_whack(struct state *st)
{
- close_any(st->st_whack_sock);
+ close_any(st->st_whack_sock);
}
-/* delete a state object */
-void
-delete_state(struct state *st)
+/**
+ * Delete a state object
+ */
+void delete_state(struct state *st)
{
- struct connection *const c = st->st_connection;
- struct state *old_cur_state = cur_state == st? NULL : cur_state;
-
- set_cur_state(st);
+ struct connection *const c = st->st_connection;
+ struct state *old_cur_state = cur_state == st? NULL : cur_state;
- /* If DPD is enabled on this state object, clear any pending events */
- if(st->st_dpd_event != NULL)
- delete_dpd_event(st);
+ set_cur_state(st);
- /* if there is a suspended state transition, disconnect us */
- if (st->st_suspended_md != NULL)
- {
- passert(st->st_suspended_md->st == st);
- st->st_suspended_md->st = NULL;
- }
+ /* If DPD is enabled on this state object, clear any pending events */
+ if(st->st_dpd_event != NULL)
+ delete_dpd_event(st);
- /* tell the other side of any IPSEC SAs that are going down */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- send_delete(st);
+ /* if there is a suspended state transition, disconnect us */
+ if (st->st_suspended_md != NULL)
+ {
+ passert(st->st_suspended_md->st == st);
+ st->st_suspended_md->st = NULL;
+ }
- delete_event(st); /* delete any pending timer event */
+ /* tell the other side of any IPSEC SAs that are going down */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ send_delete(st);
- /* Ditch anything pending on ISAKMP SA being established.
- * Note: this must be done before the unhash_state to prevent
- * flush_pending_by_state inadvertently and prematurely
- * deleting our connection.
- */
- flush_pending_by_state(st);
+ delete_event(st); /* delete any pending timer event */
- /* effectively, this deletes any ISAKMP SA that this state represents */
- unhash_state(st);
+ /* Ditch anything pending on ISAKMP SA being established.
+ * Note: this must be done before the unhash_state to prevent
+ * flush_pending_by_state inadvertently and prematurely
+ * deleting our connection.
+ */
+ flush_pending_by_state(st);
- /* tell kernel to delete any IPSEC SA
- * ??? we ought to tell peer to delete IPSEC SAs
- */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- delete_ipsec_sa(st, FALSE);
- else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
- delete_ipsec_sa(st, TRUE);
+ /* effectively, this deletes any ISAKMP SA that this state represents */
+ unhash_state(st);
- if (c->newest_ipsec_sa == st->st_serialno)
- c->newest_ipsec_sa = SOS_NOBODY;
+ /* tell kernel to delete any IPSEC SA
+ * ??? we ought to tell peer to delete IPSEC SAs
+ */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ delete_ipsec_sa(st, FALSE);
+ else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
+ delete_ipsec_sa(st, TRUE);
- if (c->newest_isakmp_sa == st->st_serialno)
- c->newest_isakmp_sa = SOS_NOBODY;
+ if (c->newest_ipsec_sa == st->st_serialno)
+ c->newest_ipsec_sa = SOS_NOBODY;
- st->st_connection = NULL; /* we might be about to free it */
- cur_state = old_cur_state; /* without st_connection, st isn't complete */
- connection_discard(c);
+ if (c->newest_isakmp_sa == st->st_serialno)
+ c->newest_isakmp_sa = SOS_NOBODY;
- release_whack(st);
+ st->st_connection = NULL; /* we might be about to free it */
+ cur_state = old_cur_state; /* without st_connection, st isn't complete */
+ connection_discard(c);
- /* from here on we are just freeing RAM */
+ release_whack(st);
- {
- struct msgid_list *p = st->st_used_msgids;
+ /* from here on we are just freeing RAM */
- while (p != NULL)
{
- struct msgid_list *q = p;
- p = p->next;
- pfree(q);
+ struct msgid_list *p = st->st_used_msgids;
+
+ while (p != NULL)
+ {
+ struct msgid_list *q = p;
+ p = p->next;
+ free(q);
+ }
}
- }
-
- unreference_key(&st->st_peer_pubkey);
-
- if (st->st_sec_in_use)
- mpz_clear(&(st->st_sec));
-
- pfreeany(st->st_tpacket.ptr);
- pfreeany(st->st_rpacket.ptr);
- pfreeany(st->st_p1isa.ptr);
- pfreeany(st->st_gi.ptr);
- pfreeany(st->st_gr.ptr);
- pfreeany(st->st_shared.ptr);
- pfreeany(st->st_ni.ptr);
- pfreeany(st->st_nr.ptr);
- pfreeany(st->st_skeyid.ptr);
- pfreeany(st->st_skeyid_d.ptr);
- pfreeany(st->st_skeyid_a.ptr);
- pfreeany(st->st_skeyid_e.ptr);
- pfreeany(st->st_enc_key.ptr);
- pfreeany(st->st_ah.our_keymat);
- pfreeany(st->st_ah.peer_keymat);
- pfreeany(st->st_esp.our_keymat);
- pfreeany(st->st_esp.peer_keymat);
-
- pfree(st);
+
+ unreference_key(&st->st_peer_pubkey);
+
+ DESTROY_IF(st->st_dh);
+
+ free(st->st_tpacket.ptr);
+ free(st->st_rpacket.ptr);
+ free(st->st_p1isa.ptr);
+ free(st->st_gi.ptr);
+ free(st->st_gr.ptr);
+ free(st->st_shared.ptr);
+ free(st->st_ni.ptr);
+ free(st->st_nr.ptr);
+ free(st->st_skeyid.ptr);
+ free(st->st_skeyid_d.ptr);
+ free(st->st_skeyid_a.ptr);
+ free(st->st_skeyid_e.ptr);
+ free(st->st_enc_key.ptr);
+ free(st->st_ah.our_keymat);
+ free(st->st_ah.peer_keymat);
+ free(st->st_esp.our_keymat);
+ free(st->st_esp.peer_keymat);
+
+ free(st);
}
-/*
+/**
* Is a connection in use by some state?
*/
-bool
-states_use_connection(struct connection *c)
+bool states_use_connection(struct connection *c)
{
- /* are there any states still using it? */
- struct state *st = NULL;
- int i;
+ /* are there any states still using it? */
+ struct state *st = NULL;
+ int i;
- for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_connection == c)
- return TRUE;
+ for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ if (st->st_connection == c)
+ return TRUE;
- return FALSE;
+ return FALSE;
}
-/*
- * delete all states that were created for a given connection.
+/**
+ * Delete all states that were created for a given connection.
* if relations == TRUE, then also delete states that share
* the same phase 1 SA.
*/
-void
-delete_states_by_connection(struct connection *c, bool relations)
+void delete_states_by_connection(struct connection *c, bool relations)
{
- int pass;
- /* this kludge avoids an n^2 algorithm */
- enum connection_kind ck = c->kind;
- struct spd_route *sr;
-
- /* save this connection's isakmp SA, since it will get set to later SOS_NOBODY */
- so_serial_t parent_sa = c->newest_isakmp_sa;
-
- if (ck == CK_INSTANCE)
- c->kind = CK_GOING_AWAY;
-
- /* We take two passes so that we delete any ISAKMP SAs last.
- * This allows Delete Notifications to be sent.
- * ?? We could probably double the performance by caching any
- * ISAKMP SA states found in the first pass, avoiding a second.
- */
- for (pass = 0; pass != 2; pass++)
- {
- int i;
-
- /* For each hash chain... */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
+ int pass;
+ /* this kludge avoids an n^2 algorithm */
+ enum connection_kind ck = c->kind;
+ struct spd_route *sr;
+
+ /* save this connection's isakmp SA, since it will get set to later SOS_NOBODY */
+ so_serial_t parent_sa = c->newest_isakmp_sa;
+
+ if (ck == CK_INSTANCE)
+ c->kind = CK_GOING_AWAY;
+
+ /* We take two passes so that we delete any ISAKMP SAs last.
+ * This allows Delete Notifications to be sent.
+ * ?? We could probably double the performance by caching any
+ * ISAKMP SA states found in the first pass, avoiding a second.
+ */
+ for (pass = 0; pass != 2; pass++)
{
- struct state *st;
+ int i;
- /* For each state in the hash chain... */
- for (st = statetable[i]; st != NULL; )
- {
- struct state *this = st;
+ /* For each hash chain... */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ {
+ struct state *st;
+
+ /* For each state in the hash chain... */
+ for (st = statetable[i]; st != NULL; )
+ {
+ struct state *this = st;
- st = st->st_hashchain_next; /* before this is deleted */
+ st = st->st_hashchain_next; /* before this is deleted */
- if ((this->st_connection == c
- || (relations && parent_sa != SOS_NOBODY
- && this->st_clonedfrom == parent_sa))
- && (pass == 1 || !IS_ISAKMP_SA_ESTABLISHED(this->st_state)))
- {
- struct state *old_cur_state
- = cur_state == this? NULL : cur_state;
+ if ((this->st_connection == c
+ || (relations && parent_sa != SOS_NOBODY
+ && this->st_clonedfrom == parent_sa))
+ && (pass == 1 || !IS_ISAKMP_SA_ESTABLISHED(this->st_state)))
+ {
+ struct state *old_cur_state
+ = cur_state == this? NULL : cur_state;
#ifdef DEBUG
- lset_t old_cur_debugging = cur_debugging;
+ lset_t old_cur_debugging = cur_debugging;
#endif
- set_cur_state(this);
- plog("deleting state (%s)"
- , enum_show(&state_names, this->st_state));
- delete_state(this);
- cur_state = old_cur_state;
+ set_cur_state(this);
+ plog("deleting state (%s)"
+ , enum_show(&state_names, this->st_state));
+ delete_state(this);
+ cur_state = old_cur_state;
#ifdef DEBUG
- cur_debugging = old_cur_debugging;
+ cur_debugging = old_cur_debugging;
#endif
+ }
+ }
}
- }
}
- }
-
- sr = &c->spd;
- while (sr != NULL)
- {
- passert(sr->eroute_owner == SOS_NOBODY);
- passert(sr->routing != RT_ROUTED_TUNNEL);
- sr = sr->next;
- }
- c->kind = ck;
+
+ sr = &c->spd;
+ while (sr != NULL)
+ {
+ passert(sr->eroute_owner == SOS_NOBODY);
+ passert(sr->routing != RT_ROUTED_TUNNEL);
+ sr = sr->next;
+ }
+ c->kind = ck;
}
-/* Walk through the state table, and delete each state whose phase 1 (IKE)
+/**
+ * Walk through the state table, and delete each state whose phase 1 (IKE)
* peer is among those given.
*/
-void
-delete_states_by_peer(ip_address *peer)
+void delete_states_by_peer(ip_address *peer)
{
- char peerstr[ADDRTOT_BUF];
- int i;
-
- addrtot(peer, 0, peerstr, sizeof(peerstr));
+ char peerstr[ADDRTOT_BUF];
+ int i;
- /* For each hash chain... */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
+ addrtot(peer, 0, peerstr, sizeof(peerstr));
- /* For each state in the hash chain... */
- for (st = statetable[i]; st != NULL; )
+ /* For each hash chain... */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- struct state *this = st;
- struct spd_route *sr;
- struct connection *c = this->st_connection;
-
- st = st->st_hashchain_next; /* before this is deleted */
+ struct state *st;
- /* ??? Is it not the case that the peer is the same for all spds? */
- for (sr = &c->spd; sr != NULL; sr = sr->next)
- {
- if (sameaddr(&sr->that.host_addr, peer))
+ /* For each state in the hash chain... */
+ for (st = statetable[i]; st != NULL; )
{
- plog("peer %s for connection %s deleting - claimed to have crashed"
- , peerstr
- , c->name);
- delete_states_by_connection(c, TRUE);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, TRUE);
- break; /* can only delete it once */
+ struct state *this = st;
+ struct spd_route *sr;
+ struct connection *c = this->st_connection;
+
+ st = st->st_hashchain_next; /* before this is deleted */
+
+ /* ??? Is it not the case that the peer is the same for all spds? */
+ for (sr = &c->spd; sr != NULL; sr = sr->next)
+ {
+ if (sameaddr(&sr->that.host_addr, peer))
+ {
+ plog("peer %s for connection %s deleting - claimed to have crashed"
+ , peerstr
+ , c->name);
+ delete_states_by_connection(c, TRUE);
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, TRUE);
+ break; /* can only delete it once */
+ }
+ }
}
- }
}
- }
}
/* Duplicate a Phase 1 state object, to create a Phase 2 object.
* Caller must schedule an event for this object so that it doesn't leak.
* Caller must insert_state().
*/
-struct state *
-duplicate_state(struct state *st)
+struct state *duplicate_state(struct state *st)
{
- struct state *nst;
-
- DBG(DBG_CONTROL, DBG_log("duplicating state object #%lu",
- st->st_serialno));
-
- /* record use of the Phase 1 state */
- st->st_outbound_count++;
- st->st_outbound_time = now();
-
- nst = new_state();
-
- memcpy(nst->st_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(nst->st_rcookie, st->st_rcookie, COOKIE_SIZE);
-
- nst->st_connection = st->st_connection;
- nst->st_doi = st->st_doi;
- nst->st_situation = st->st_situation;
- nst->st_clonedfrom = st->st_serialno;
- nst->st_oakley = st->st_oakley;
- nst->st_modecfg = st->st_modecfg;
-
-# define clone_chunk(ch, name) \
- clonetochunk(nst->ch, st->ch.ptr, st->ch.len, name)
-
- clone_chunk(st_skeyid_d, "st_skeyid_d in duplicate_state");
- clone_chunk(st_skeyid_a, "st_skeyid_a in duplicate_state");
- clone_chunk(st_skeyid_e, "st_skeyid_e in duplicate_state");
- clone_chunk(st_enc_key, "st_enc_key in duplicate_state");
-
-# undef clone_chunk
-
- return nst;
+ struct state *nst;
+
+ DBG(DBG_CONTROL, DBG_log("duplicating state object #%lu",
+ st->st_serialno));
+
+ /* record use of the Phase 1 state */
+ st->st_outbound_count++;
+ st->st_outbound_time = now();
+
+ nst = new_state();
+
+ memcpy(nst->st_icookie, st->st_icookie, COOKIE_SIZE);
+ memcpy(nst->st_rcookie, st->st_rcookie, COOKIE_SIZE);
+
+ nst->st_connection = st->st_connection;
+ nst->st_doi = st->st_doi;
+ nst->st_situation = st->st_situation;
+ nst->st_clonedfrom = st->st_serialno;
+ nst->st_oakley = st->st_oakley;
+ nst->st_modecfg = st->st_modecfg;
+ nst->st_skeyid_d = chunk_clone(st->st_skeyid_d);
+ nst->st_skeyid_a = chunk_clone(st->st_skeyid_a);
+ nst->st_skeyid_e = chunk_clone(st->st_skeyid_e);
+ nst->st_enc_key = chunk_clone(st->st_enc_key);
+
+ return nst;
}
#if 1
void for_each_state(void *(f)(struct state *, void *data), void *data)
{
- struct state *st, *ocs = cur_state;
- int i;
- for (i=0; i<STATE_TABLE_SIZE; i++) {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next) {
- set_cur_state(st);
- f(st, data);
+ struct state *st, *ocs = cur_state;
+ int i;
+ for (i=0; i<STATE_TABLE_SIZE; i++) {
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next) {
+ set_cur_state(st);
+ f(st, data);
+ }
}
- }
- cur_state = ocs;
+ cur_state = ocs;
}
#endif
-/*
+/**
* Find a state object.
*/
-struct state *
-find_state(const u_char *icookie
-, const u_char *rcookie
-, const ip_address *peer
-, msgid_t /*network order*/ msgid)
+struct state *find_state(const u_char *icookie, const u_char *rcookie,
+ const ip_address *peer, msgid_t msgid)
{
- struct state *st = *state_hash(icookie, rcookie, peer);
-
- while (st != (struct state *) NULL)
- if (sameaddr(peer, &st->st_connection->spd.that.host_addr)
- && memcmp(icookie, st->st_icookie, COOKIE_SIZE) == 0
- && memcmp(rcookie, st->st_rcookie, COOKIE_SIZE) == 0
- && msgid == st->st_msgid)
- break;
- else
- st = st->st_hashchain_next;
-
- DBG(DBG_CONTROL,
- if (st == NULL)
- DBG_log("state object not found");
- else
- DBG_log("state object #%lu found, in %s"
- , st->st_serialno
- , enum_show(&state_names, st->st_state)));
+ struct state *st = *state_hash(icookie, rcookie, peer);
- return st;
+ while (st != (struct state *) NULL)
+ {
+ if (sameaddr(peer, &st->st_connection->spd.that.host_addr)
+ && memeq(icookie, st->st_icookie, COOKIE_SIZE)
+ && memeq(rcookie, st->st_rcookie, COOKIE_SIZE)
+ && msgid == st->st_msgid)
+ {
+ break;
+ }
+ else
+ {
+ st = st->st_hashchain_next;
+ }
+ }
+ DBG(DBG_CONTROL,
+ if (st == NULL)
+ DBG_log("state object not found");
+ else
+ DBG_log("state object #%lu found, in %s"
+ , st->st_serialno
+ , enum_show(&state_names, st->st_state)));
+
+ return st;
}
-/* Find the state that sent a packet
+/**
+ * Find the state that sent a packet
* ??? this could be expensive -- it should be rate-limited to avoid DoS
*/
-struct state *
-find_sender(size_t packet_len, u_char *packet)
+struct state *find_sender(size_t packet_len, u_char *packet)
{
- int i;
- struct state *st;
-
- if (packet_len >= sizeof(struct isakmp_hdr))
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_tpacket.ptr != NULL
- && st->st_tpacket.len == packet_len
- && memcmp(st->st_tpacket.ptr, packet, packet_len) == 0)
- return st;
+ int i;
+ struct state *st;
- return NULL;
+ if (packet_len >= sizeof(struct isakmp_hdr))
+ {
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ {
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
+ if (st->st_tpacket.ptr != NULL
+ && st->st_tpacket.len == packet_len
+ && memeq(st->st_tpacket.ptr, packet, packet_len))
+ {
+ return st;
+ }
+ }
+ }
+ }
+ return NULL;
}
-struct state *
-find_phase2_state_to_delete(const struct state *p1st
-, u_int8_t protoid
-, ipsec_spi_t spi
-, bool *bogus)
+struct state *find_phase2_state_to_delete(const struct state *p1st,
+ u_int8_t protoid, ipsec_spi_t spi,
+ bool *bogus)
{
- struct state *st;
- int i;
+ struct state *st;
+ int i;
- *bogus = FALSE;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ *bogus = FALSE;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- && p1st->st_connection->host_pair == st->st_connection->host_pair
- && same_peer_ids(p1st->st_connection, st->st_connection, NULL))
- {
- struct ipsec_proto_info *pr = protoid == PROTO_IPSEC_AH
- ? &st->st_ah : &st->st_esp;
-
- if (pr->present)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- if (pr->attrs.spi == spi)
- return st;
- if (pr->our_spi == spi)
- *bogus = TRUE;
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ && p1st->st_connection->host_pair == st->st_connection->host_pair
+ && same_peer_ids(p1st->st_connection, st->st_connection, NULL))
+ {
+ struct ipsec_proto_info *pr = protoid == PROTO_IPSEC_AH
+ ? &st->st_ah : &st->st_esp;
+
+ if (pr->present)
+ {
+ if (pr->attrs.spi == spi)
+ return st;
+ if (pr->our_spi == spi)
+ *bogus = TRUE;
+ }
+ }
}
- }
}
- }
- return NULL;
+ return NULL;
}
-/* Find newest Phase 1 negotiation state object for suitable for connection c
+/**
+ * Find newest Phase 1 negotiation state object for suitable for connection c
*/
-struct state *
-find_phase1_state(const struct connection *c, lset_t ok_states)
+struct state *find_phase1_state(const struct connection *c, lset_t ok_states)
{
- struct state
- *st,
- *best = NULL;
- int i;
-
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (LHAS(ok_states, st->st_state)
- && c->host_pair == st->st_connection->host_pair
- && same_peer_ids(c, st->st_connection, NULL)
- && (best == NULL || best->st_serialno < st->st_serialno))
- best = st;
-
- return best;
+ struct state
+ *st,
+ *best = NULL;
+ int i;
+
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ if (LHAS(ok_states, st->st_state)
+ && c->host_pair == st->st_connection->host_pair
+ && same_peer_ids(c, st->st_connection, NULL)
+ && (best == NULL || best->st_serialno < st->st_serialno))
+ best = st;
+
+ return best;
}
-void
-state_eroute_usage(ip_subnet *ours, ip_subnet *his
-, unsigned long count, time_t nw)
+void state_eroute_usage(ip_subnet *ours, ip_subnet *his, unsigned long count,
+ time_t nw)
{
- struct state *st;
- int i;
+ struct state *st;
+ int i;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- struct connection *c = st->st_connection;
-
- /* XXX spd-enum */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- && c->spd.eroute_owner == st->st_serialno
- && c->spd.routing == RT_ROUTED_TUNNEL
- && samesubnet(&c->spd.this.client, ours)
- && samesubnet(&c->spd.that.client, his))
- {
- if (st->st_outbound_count != count)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- st->st_outbound_count = count;
- st->st_outbound_time = nw;
+ struct connection *c = st->st_connection;
+
+ /* XXX spd-enum */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ && c->spd.eroute_owner == st->st_serialno
+ && c->spd.routing == RT_ROUTED_TUNNEL
+ && samesubnet(&c->spd.this.client, ours)
+ && samesubnet(&c->spd.that.client, his))
+ {
+ if (st->st_outbound_count != count)
+ {
+ st->st_outbound_count = count;
+ st->st_outbound_time = nw;
+ }
+ return;
+ }
}
- return;
- }
}
- }
- DBG(DBG_CONTROL,
- {
- char ourst[SUBNETTOT_BUF];
- char hist[SUBNETTOT_BUF];
-
- subnettot(ours, 0, ourst, sizeof(ourst));
- subnettot(his, 0, hist, sizeof(hist));
- DBG_log("unknown tunnel eroute %s -> %s found in scan"
- , ourst, hist);
- });
+ DBG(DBG_CONTROL,
+ {
+ char ourst[SUBNETTOT_BUF];
+ char hist[SUBNETTOT_BUF];
+
+ subnettot(ours, 0, ourst, sizeof(ourst));
+ subnettot(his, 0, hist, sizeof(hist));
+ DBG_log("unknown tunnel eroute %s -> %s found in scan"
+ , ourst, hist);
+ });
}
-void fmt_state(bool all, struct state *st, time_t n
-, char *state_buf, size_t state_buf_len
-, char *state_buf2, size_t state_buf2_len)
+void fmt_state(bool all, struct state *st, time_t n, char *state_buf,
+ size_t state_buf_len, char *state_buf2, size_t state_buf2_len)
{
- /* what the heck is interesting about a state? */
- const struct connection *c = st->st_connection;
-
- long delta = st->st_event->ev_time >= n
- ? (long)(st->st_event->ev_time - n)
- : -(long)(n - st->st_event->ev_time);
-
- char inst[CONN_INST_BUF];
- const char *np1 = c->newest_isakmp_sa == st->st_serialno
- ? "; newest ISAKMP" : "";
- const char *np2 = c->newest_ipsec_sa == st->st_serialno
- ? "; newest IPSEC" : "";
- /* XXX spd-enum */
- const char *eo = c->spd.eroute_owner == st->st_serialno
- ? "; eroute owner" : "";
- const char *dpd = (all && st->st_dpd && c->dpd_action != DPD_ACTION_NONE)
- ? "; DPD active" : "";
-
- passert(st->st_event != 0);
-
- fmt_conn_instance(c, inst);
-
- snprintf(state_buf, state_buf_len
- , "#%lu: \"%s\"%s %s (%s); %s in %lds%s%s%s%s"
- , st->st_serialno
- , c->name, inst
- , enum_name(&state_names, st->st_state)
- , state_story[st->st_state - STATE_MAIN_R0]
- , enum_name(&timer_event_names, st->st_event->ev_type)
- , delta
- , np1, np2, eo, dpd);
-
- /* print out SPIs if SAs are established */
- if (state_buf2_len != 0)
- state_buf2[0] = '\0'; /* default to empty */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
-
- bool tunnel;
- char buf[SATOT_BUF*6 + 2*20 + 1];
- const char *p_end = buf + sizeof(buf);
- char *p = buf;
-
-# define add_said(adst, aspi, aproto) { \
- ip_said s; \
- \
- initsaid(adst, aspi, aproto, &s); \
- if (p < p_end - 1) \
- { \
- *p++ = ' '; \
- p += satot(&s, 0, p, p_end - p) - 1; \
- } \
- }
+ /* what the heck is interesting about a state? */
+ const struct connection *c = st->st_connection;
+
+ long delta = st->st_event->ev_time >= n
+ ? (long)(st->st_event->ev_time - n)
+ : -(long)(n - st->st_event->ev_time);
+
+ char inst[CONN_INST_BUF];
+ const char *np1 = c->newest_isakmp_sa == st->st_serialno
+ ? "; newest ISAKMP" : "";
+ const char *np2 = c->newest_ipsec_sa == st->st_serialno
+ ? "; newest IPSEC" : "";
+ /* XXX spd-enum */
+ const char *eo = c->spd.eroute_owner == st->st_serialno
+ ? "; eroute owner" : "";
+ const char *dpd = (all && st->st_dpd && c->dpd_action != DPD_ACTION_NONE)
+ ? "; DPD active" : "";
+
+ passert(st->st_event != 0);
+
+ fmt_conn_instance(c, inst);
+
+ snprintf(state_buf, state_buf_len
+ , "#%lu: \"%s\"%s %s (%s); %N in %lds%s%s%s%s"
+ , st->st_serialno
+ , c->name, inst
+ , enum_name(&state_names, st->st_state)
+ , state_story[st->st_state - STATE_MAIN_R0]
+ , timer_event_names, st->st_event->ev_type
+ , delta
+ , np1, np2, eo, dpd);
+
+ /* print out SPIs if SAs are established */
+ if (state_buf2_len != 0)
+ state_buf2[0] = '\0'; /* default to empty */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ {
-# define add_sa_info(st, inbound) { \
- u_int bytes; \
- time_t use_time; \
- \
- if (get_sa_info(st, inbound, &bytes, &use_time)) \
- { \
- p += snprintf(p, p_end - p, " (%'u bytes", bytes); \
- if (bytes > 0 && use_time != UNDEFINED_TIME) \
- p += snprintf(p, p_end - p, ", %ds ago", (int)(now - use_time)); \
- p += snprintf(p, p_end - p, ")"); \
- } \
- }
+ bool tunnel;
+ char buf[SATOT_BUF*6 + 2*20 + 1];
+ const char *p_end = buf + sizeof(buf);
+ char *p = buf;
+
+# define add_said(adst, aspi, aproto) { \
+ ip_said s; \
+ \
+ initsaid(adst, aspi, aproto, &s); \
+ if (p < p_end - 1) \
+ { \
+ *p++ = ' '; \
+ p += satot(&s, 0, p, p_end - p) - 1; \
+ } \
+ }
- *p = '\0';
- if (st->st_ah.present)
- {
- add_said(&c->spd.that.host_addr, st->st_ah.attrs.spi, SA_AH);
- add_said(&c->spd.this.host_addr, st->st_ah.our_spi, SA_AH);
- }
- if (st->st_esp.present)
- {
- time_t now = time(NULL);
+# define add_sa_info(st, inbound) { \
+ u_int bytes; \
+ time_t use_time; \
+ \
+ if (get_sa_info(st, inbound, &bytes, &use_time)) \
+ { \
+ p += snprintf(p, p_end - p, " (%'u bytes", bytes); \
+ if (bytes > 0 && use_time != UNDEFINED_TIME) \
+ p += snprintf(p, p_end - p, ", %ds ago", (int)(now - use_time)); \
+ p += snprintf(p, p_end - p, ")"); \
+ } \
+ }
- add_said(&c->spd.that.host_addr, st->st_esp.attrs.spi, SA_ESP);
- add_sa_info(st, FALSE);
- add_said(&c->spd.this.host_addr, st->st_esp.our_spi, SA_ESP);
- add_sa_info(st, TRUE);
- }
- if (st->st_ipcomp.present)
- {
- add_said(&c->spd.that.host_addr, st->st_ipcomp.attrs.spi, SA_COMP);
- add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, SA_COMP);
- }
+ *p = '\0';
+ if (st->st_ah.present)
+ {
+ add_said(&c->spd.that.host_addr, st->st_ah.attrs.spi, SA_AH);
+ add_said(&c->spd.this.host_addr, st->st_ah.our_spi, SA_AH);
+ }
+ if (st->st_esp.present)
+ {
+ time_t now = time(NULL);
+
+ add_said(&c->spd.that.host_addr, st->st_esp.attrs.spi, SA_ESP);
+ add_sa_info(st, FALSE);
+ add_said(&c->spd.this.host_addr, st->st_esp.our_spi, SA_ESP);
+ add_sa_info(st, TRUE);
+ }
+ if (st->st_ipcomp.present)
+ {
+ add_said(&c->spd.that.host_addr, st->st_ipcomp.attrs.spi, SA_COMP);
+ add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, SA_COMP);
+ }
#ifdef KLIPS
- tunnel = st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
- p += snprintf(p, p_end - p, "; %s", tunnel? "tunnel":"transport");
+ tunnel = st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
+ p += snprintf(p, p_end - p, "; %s", tunnel? "tunnel":"transport");
#endif
- snprintf(state_buf2, state_buf2_len
- , "#%lu: \"%s\"%s%s"
- , st->st_serialno
- , c->name, inst
- , buf);
+ snprintf(state_buf2, state_buf2_len
+ , "#%lu: \"%s\"%s%s"
+ , st->st_serialno
+ , c->name, inst
+ , buf);
-# undef add_said
-# undef add_sa_info
- }
+# undef add_said
+# undef add_sa_info
+ }
}
/*
@@ -831,82 +820,80 @@ void fmt_state(bool all, struct state *st, time_t n
* isakmp_sa (XXX probably wrong)
*
*/
-static int
-state_compare(const void *a, const void *b)
+static int state_compare(const void *a, const void *b)
{
- const struct state *sap = *(const struct state *const *)a;
- struct connection *ca = sap->st_connection;
- const struct state *sbp = *(const struct state *const *)b;
- struct connection *cb = sbp->st_connection;
+ const struct state *sap = *(const struct state *const *)a;
+ struct connection *ca = sap->st_connection;
+ const struct state *sbp = *(const struct state *const *)b;
+ struct connection *cb = sbp->st_connection;
- /* DBG_log("comparing %s to %s", ca->name, cb->name); */
+ /* DBG_log("comparing %s to %s", ca->name, cb->name); */
- return connection_compare(ca, cb);
+ return connection_compare(ca, cb);
}
-void
-show_states_status(bool all, const char *name)
+void show_states_status(bool all, const char *name)
{
- time_t n = now();
- int i;
- char state_buf[LOG_WIDTH];
- char state_buf2[LOG_WIDTH];
- int count;
- struct state **array;
-
- /* make count of states */
- count = 0;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
+ time_t n = now();
+ int i;
+ char state_buf[LOG_WIDTH];
+ char state_buf2[LOG_WIDTH];
+ int count;
+ struct state **array;
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ /* make count of states */
+ count = 0;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (name == NULL || streq(name, st->st_connection->name))
- count++;
- }
- }
+ struct state *st;
- /* build the array */
- array = alloc_bytes(sizeof(struct state *)*count, "state array");
- count = 0;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
+ if (name == NULL || streq(name, st->st_connection->name))
+ count++;
+ }
+ }
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ /* build the array */
+ array = malloc(sizeof(struct state *)*count);
+ count = 0;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (name == NULL || streq(name, st->st_connection->name))
- array[count++]=st;
+ struct state *st;
+
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
+ if (name == NULL || streq(name, st->st_connection->name))
+ array[count++]=st;
+ }
}
- }
- /* sort it! */
- qsort(array, count, sizeof(struct state *), state_compare);
+ /* sort it! */
+ qsort(array, count, sizeof(struct state *), state_compare);
- /* now print sorted results */
- for (i = 0; i < count; i++)
- {
- struct state *st;
+ /* now print sorted results */
+ for (i = 0; i < count; i++)
+ {
+ struct state *st;
- st = array[i];
+ st = array[i];
- fmt_state(all, st, n
- , state_buf, sizeof(state_buf)
- , state_buf2, sizeof(state_buf2));
- whack_log(RC_COMMENT, state_buf);
- if (state_buf2[0] != '\0')
- whack_log(RC_COMMENT, state_buf2);
+ fmt_state(all, st, n
+ , state_buf, sizeof(state_buf)
+ , state_buf2, sizeof(state_buf2));
+ whack_log(RC_COMMENT, state_buf);
+ if (state_buf2[0] != '\0')
+ whack_log(RC_COMMENT, state_buf2);
- /* show any associated pending Phase 2s */
- if (IS_PHASE1(st->st_state))
- show_pending_phase2(st->st_connection->host_pair, st);
- }
- if (count > 0)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
+ /* show any associated pending Phase 2s */
+ if (IS_PHASE1(st->st_state))
+ show_pending_phase2(st->st_connection->host_pair, st);
+ }
+ if (count > 0)
+ whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
- /* free the array */
- pfree(array);
+ /* free the array */
+ free(array);
}
/* Given that we've used up a range of unused CPI's,
@@ -915,49 +902,48 @@ show_states_status(bool all, const char *name)
* If we can't find one easily, choose 0 (a bad SPI,
* no matter what order) indicating failure.
*/
-void
-find_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi)
+void find_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi)
{
- int tries = 0;
- cpi_t base = *latest_cpi;
- cpi_t closest;
- int i;
+ int tries = 0;
+ cpi_t base = *latest_cpi;
+ cpi_t closest;
+ int i;
startover:
- closest = ~0; /* not close at all */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
-
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ closest = ~0; /* not close at all */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (st->st_ipcomp.present)
- {
- cpi_t c = ntohl(st->st_ipcomp.our_spi) - base;
+ struct state *st;
- if (c < closest)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- if (c == 0)
- {
- /* oops: next spot is occupied; start over */
- if (++tries == 20)
+ if (st->st_ipcomp.present)
{
- /* FAILURE */
- *latest_cpi = *first_busy_cpi = 0;
- return;
+ cpi_t c = ntohl(st->st_ipcomp.our_spi) - base;
+
+ if (c < closest)
+ {
+ if (c == 0)
+ {
+ /* oops: next spot is occupied; start over */
+ if (++tries == 20)
+ {
+ /* FAILURE */
+ *latest_cpi = *first_busy_cpi = 0;
+ return;
+ }
+ base++;
+ if (base > IPCOMP_LAST_NEGOTIATED)
+ base = IPCOMP_FIRST_NEGOTIATED;
+ goto startover; /* really a tail call */
+ }
+ closest = c;
+ }
}
- base++;
- if (base > IPCOMP_LAST_NEGOTIATED)
- base = IPCOMP_FIRST_NEGOTIATED;
- goto startover; /* really a tail call */
- }
- closest = c;
}
- }
}
- }
- *latest_cpi = base; /* base is first in next free range */
- *first_busy_cpi = closest + base; /* and this is the roof */
+ *latest_cpi = base; /* base is first in next free range */
+ *first_busy_cpi = closest + base; /* and this is the roof */
}
/* Muck with high-order 16 bits of this SPI in order to make
@@ -968,38 +954,42 @@ startover:
* If we can't find one easily, return 0 (a bad SPI,
* no matter what order) indicating failure.
*/
-ipsec_spi_t
-uniquify_his_cpi(ipsec_spi_t cpi, struct state *st)
+ipsec_spi_t uniquify_his_cpi(ipsec_spi_t cpi, struct state *st)
{
- int tries = 0;
- int i;
+ int tries = 0;
+ int i;
+ rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
startover:
- /* network order makes first two bytes our target */
- get_rnd_bytes((u_char *)&cpi, 2);
-
- /* Make sure that the result is unique.
- * Hard work. If there is no unique value, we'll loop forever!
- */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *s;
+ /* network order makes first two bytes our target */
+ rng->get_bytes(rng, 2, (u_char *)&cpi);
- for (s = statetable[i]; s != NULL; s = s->st_hashchain_next)
+ /* Make sure that the result is unique.
+ * Hard work. If there is no unique value, we'll loop forever!
+ */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (s->st_ipcomp.present
- && sameaddr(&s->st_connection->spd.that.host_addr
- , &st->st_connection->spd.that.host_addr)
- && cpi == s->st_ipcomp.attrs.spi)
- {
- if (++tries == 20)
- return 0; /* FAILURE */
- goto startover;
- }
+ struct state *s;
+
+ for (s = statetable[i]; s != NULL; s = s->st_hashchain_next)
+ {
+ if (s->st_ipcomp.present
+ && sameaddr(&s->st_connection->spd.that.host_addr
+ , &st->st_connection->spd.that.host_addr)
+ && cpi == s->st_ipcomp.attrs.spi)
+ {
+ if (++tries == 20)
+ {
+ rng->destroy(rng);
+ return 0; /* FAILURE */
+ }
+ goto startover;
+ }
+ }
}
- }
- return cpi;
+ rng->destroy(rng);
+ return cpi;
}
/*
diff --git a/src/pluto/state.h b/src/pluto/state.h
index 220dce341..a059c52b4 100644
--- a/src/pluto/state.h
+++ b/src/pluto/state.h
@@ -1,6 +1,7 @@
/* state and event objects
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2001 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -11,15 +12,14 @@
* 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: state.h 3252 2007-10-06 21:24:50Z andreas $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
-#include <gmp.h> /* GNU MP library */
+
+#include <crypto/diffie_hellman.h>
#include "connections.h"
@@ -40,10 +40,10 @@
* than specified by draft-jenkins-ipsec-rekeying-06.txt.
*/
-typedef u_int32_t msgid_t; /* Network order! */
+typedef u_int32_t msgid_t; /* Network order! */
#define MAINMODE_MSGID ((msgid_t) 0)
-struct state; /* forward declaration of tag */
+struct state; /* forward declaration of tag */
extern bool reserve_msgid(struct state *isakmp_sa, msgid_t msgid);
extern msgid_t generate_msgid(struct state *isakmp_sa);
@@ -54,17 +54,17 @@ extern msgid_t generate_msgid(struct state *isakmp_sa);
* Names are chosen to match corresponding names in state.
*/
struct oakley_trans_attrs {
- u_int16_t encrypt; /* Encryption algorithm */
- u_int16_t enckeylen; /* encryption key len (bits) */
- const struct encrypt_desc *encrypter; /* package of encryption routines */
- u_int16_t hash; /* Hash algorithm */
- const struct hash_desc *hasher; /* package of hashing routines */
- u_int16_t auth; /* Authentication method */
- const struct oakley_group_desc *group; /* Oakley group */
- time_t life_seconds; /* When this SA expires (seconds) */
- u_int32_t life_kilobytes; /* When this SA is exhausted (kilobytes) */
+ u_int16_t encrypt; /* Encryption algorithm */
+ u_int16_t enckeylen; /* encryption key len (bits) */
+ const struct encrypt_desc *encrypter; /* package of encryption routines */
+ u_int16_t hash; /* Hash algorithm */
+ const struct hash_desc *hasher; /* package of hashing routines */
+ u_int16_t auth; /* Authentication method */
+ const struct dh_desc *group; /* Diffie-Hellman group */
+ time_t life_seconds; /* When this SA expires (seconds) */
+ u_int32_t life_kilobytes; /* When this SA is exhausted (kilobytes) */
#if 0 /* not yet */
- u_int16_t prf; /* Pseudo Random Function */
+ u_int16_t prf; /* Pseudo Random Function */
#endif
};
@@ -74,28 +74,28 @@ struct oakley_trans_attrs {
* for ESP, and a funny one for IPCOMP.
*/
struct ipsec_trans_attrs {
- u_int8_t transid; /* transform id */
- ipsec_spi_t spi; /* his SPI */
- time_t life_seconds; /* When this SA expires */
- u_int32_t life_kilobytes; /* When this SA expires */
- u_int16_t encapsulation;
- u_int16_t auth;
- u_int16_t key_len;
- u_int16_t key_rounds;
+ u_int8_t transid; /* transform id */
+ ipsec_spi_t spi; /* his SPI */
+ time_t life_seconds; /* When this SA expires */
+ u_int32_t life_kilobytes; /* When this SA expires */
+ u_int16_t encapsulation;
+ u_int16_t auth;
+ u_int16_t key_len;
+ u_int16_t key_rounds;
#if 0 /* not implemented yet */
- u_int16_t cmprs_dict_sz;
- u_int32_t cmprs_alg;
+ u_int16_t cmprs_dict_sz;
+ u_int32_t cmprs_alg;
#endif
};
/* IPsec per protocol state information */
struct ipsec_proto_info {
- bool present; /* was this transform specified? */
- struct ipsec_trans_attrs attrs;
- ipsec_spi_t our_spi;
- u_int16_t keymat_len; /* same for both */
- u_char *our_keymat;
- u_char *peer_keymat;
+ bool present; /* was this transform specified? */
+ struct ipsec_trans_attrs attrs;
+ ipsec_spi_t our_spi;
+ u_int16_t keymat_len; /* same for both */
+ u_char *our_keymat;
+ u_char *peer_keymat;
};
/* state object: record the state of a (possibly nascent) SA
@@ -107,135 +107,133 @@ struct ipsec_proto_info {
*/
struct state
{
- so_serial_t st_serialno; /* serial number (for seniority) */
- so_serial_t st_clonedfrom; /* serial number of parent */
+ so_serial_t st_serialno; /* serial number (for seniority) */
+ so_serial_t st_clonedfrom; /* serial number of parent */
- struct connection *st_connection; /* connection for this SA */
+ struct connection *st_connection; /* connection for this SA */
- int st_whack_sock; /* fd for our Whack TCP socket.
- * Single copy: close when freeing struct.
- */
+ int st_whack_sock; /* fd for our Whack TCP socket.
+ * Single copy: close when freeing struct.
+ */
- struct msg_digest *st_suspended_md; /* suspended state-transition */
+ struct msg_digest *st_suspended_md; /* suspended state-transition */
- struct oakley_trans_attrs st_oakley;
+ struct oakley_trans_attrs st_oakley;
- struct ipsec_proto_info st_ah;
- struct ipsec_proto_info st_esp;
- struct ipsec_proto_info st_ipcomp;
+ struct ipsec_proto_info st_ah;
+ struct ipsec_proto_info st_esp;
+ struct ipsec_proto_info st_ipcomp;
#ifdef KLIPS
- ipsec_spi_t st_tunnel_in_spi; /* KLUDGE */
- ipsec_spi_t st_tunnel_out_spi; /* KLUDGE */
+ ipsec_spi_t st_tunnel_in_spi; /* KLUDGE */
+ ipsec_spi_t st_tunnel_out_spi; /* KLUDGE */
#endif
- const struct oakley_group_desc *st_pfs_group; /* group for Phase 2 PFS */
+ const struct dh_desc *st_pfs_group; /* group for Phase 2 PFS */
- u_int32_t st_doi; /* Domain of Interpretation */
- u_int32_t st_situation;
+ u_int32_t st_doi; /* Domain of Interpretation */
+ u_int32_t st_situation;
- lset_t st_policy; /* policy for IPsec SA */
+ lset_t st_policy; /* policy for IPsec SA */
- msgid_t st_msgid; /* MSG-ID from header. Network Order! */
+ msgid_t st_msgid; /* MSG-ID from header. Network Order! */
- /* only for a state representing an ISAKMP SA */
- struct msgid_list *st_used_msgids; /* used-up msgids */
+ /* only for a state representing an ISAKMP SA */
+ struct msgid_list *st_used_msgids; /* used-up msgids */
/* symmetric stuff */
/* initiator stuff */
- chunk_t st_gi; /* Initiator public value */
- u_int8_t st_icookie[COOKIE_SIZE];/* Initiator Cookie */
- chunk_t st_ni; /* Ni nonce */
+ chunk_t st_gi; /* Initiator public value */
+ u_int8_t st_icookie[COOKIE_SIZE];/* Initiator Cookie */
+ chunk_t st_ni; /* Ni nonce */
/* responder stuff */
- chunk_t st_gr; /* Responder public value */
- u_int8_t st_rcookie[COOKIE_SIZE];/* Responder Cookie */
- chunk_t st_nr; /* Nr nonce */
+ chunk_t st_gr; /* Responder public value */
+ u_int8_t st_rcookie[COOKIE_SIZE];/* Responder Cookie */
+ chunk_t st_nr; /* Nr nonce */
/* my stuff */
- chunk_t st_tpacket; /* Transmitted packet */
+ chunk_t st_tpacket; /* Transmitted packet */
- /* Phase 2 ID payload info about my user */
- u_int8_t st_myuserprotoid; /* IDcx.protoid */
- u_int16_t st_myuserport;
+ /* Phase 2 ID payload info about my user */
+ u_int8_t st_myuserprotoid; /* IDcx.protoid */
+ u_int16_t st_myuserport;
/* his stuff */
- chunk_t st_rpacket; /* Received packet */
+ chunk_t st_rpacket; /* Received packet */
- /* Phase 2 ID payload info about peer's user */
- u_int8_t st_peeruserprotoid; /* IDcx.protoid */
- u_int16_t st_peeruserport;
+ /* Phase 2 ID payload info about peer's user */
+ u_int8_t st_peeruserprotoid; /* IDcx.protoid */
+ u_int16_t st_peeruserport;
/* end of symmetric stuff */
- u_int8_t st_sec_in_use; /* bool: does st_sec hold a value */
- MP_INT st_sec; /* Our local secret value */
-
- chunk_t st_shared; /* Derived shared secret
- * Note: during Quick Mode,
- * presence indicates PFS
- * selected.
- */
-
- /* In a Phase 1 state, preserve peer's public key after authentication */
- struct pubkey *st_peer_pubkey;
-
- enum state_kind st_state; /* State of exchange */
- u_int8_t st_retransmit; /* Number of retransmits */
- unsigned long st_try; /* number of times rekeying attempted */
- /* 0 means the only time */
- time_t st_margin; /* life after EVENT_SA_REPLACE */
- unsigned long st_outbound_count; /* traffic through eroute */
- time_t st_outbound_time; /* time of last change to st_outbound_count */
- chunk_t st_p1isa; /* Phase 1 initiator SA (Payload) for HASH */
- chunk_t st_skeyid; /* Key material */
- chunk_t st_skeyid_d; /* KM for non-ISAKMP key derivation */
- chunk_t st_skeyid_a; /* KM for ISAKMP authentication */
- chunk_t st_skeyid_e; /* KM for ISAKMP encryption */
- u_char st_iv[MAX_DIGEST_LEN]; /* IV for encryption */
- u_char st_new_iv[MAX_DIGEST_LEN];
- u_char st_ph1_iv[MAX_DIGEST_LEN]; /* IV at end if phase 1 */
- unsigned int st_iv_len;
- unsigned int st_new_iv_len;
- unsigned int st_ph1_iv_len;
-
- chunk_t st_enc_key; /* Oakley Encryption key */
-
- struct event *st_event; /* backpointer for certain events */
- struct state *st_hashchain_next; /* Next in list */
- struct state *st_hashchain_prev; /* Previous in list */
-
- struct {
- bool vars_set;
- bool started;
- } st_modecfg;
-
- struct {
- int attempt;
- bool started;
- bool status;
- } st_xauth;
-
- u_int32_t nat_traversal;
- ip_address nat_oa;
-
- /* RFC 3706 Dead Peer Detection */
- bool st_dpd; /* Peer supports DPD */
- time_t st_last_dpd; /* Time of last DPD transmit */
- u_int32_t st_dpd_seqno; /* Next R_U_THERE to send */
- u_int32_t st_dpd_expectseqno; /* Next R_U_THERE_ACK to receive */
- u_int32_t st_dpd_peerseqno; /* global variables */
- struct event *st_dpd_event; /* backpointer for DPD events */
-
- u_int32_t st_seen_vendorid; /* Bit field about recognized Vendor ID */
+ diffie_hellman_t *st_dh; /* Our local DH secret value */
+ chunk_t st_shared; /* Derived shared secret
+ * Note: during Quick Mode,
+ * presence indicates PFS
+ * selected.
+ */
+
+ /* In a Phase 1 state, preserve peer's public key after authentication */
+ struct pubkey *st_peer_pubkey;
+
+ enum state_kind st_state; /* State of exchange */
+ u_int8_t st_retransmit; /* Number of retransmits */
+ unsigned long st_try; /* number of times rekeying attempted */
+ /* 0 means the only time */
+ time_t st_margin; /* life after EVENT_SA_REPLACE */
+ unsigned long st_outbound_count; /* traffic through eroute */
+ time_t st_outbound_time; /* time of last change to st_outbound_count */
+ chunk_t st_p1isa; /* Phase 1 initiator SA (Payload) for HASH */
+ chunk_t st_skeyid; /* Key material */
+ chunk_t st_skeyid_d; /* KM for non-ISAKMP key derivation */
+ chunk_t st_skeyid_a; /* KM for ISAKMP authentication */
+ chunk_t st_skeyid_e; /* KM for ISAKMP encryption */
+ u_char st_iv[MAX_DIGEST_LEN]; /* IV for encryption */
+ u_char st_new_iv[MAX_DIGEST_LEN];
+ u_char st_ph1_iv[MAX_DIGEST_LEN]; /* IV at end if phase 1 */
+ unsigned int st_iv_len;
+ unsigned int st_new_iv_len;
+ unsigned int st_ph1_iv_len;
+
+ chunk_t st_enc_key; /* Oakley Encryption key */
+
+ struct event *st_event; /* backpointer for certain events */
+ struct state *st_hashchain_next; /* Next in list */
+ struct state *st_hashchain_prev; /* Previous in list */
+
+ struct {
+ bool vars_set;
+ bool started;
+ } st_modecfg;
+
+ struct {
+ int attempt;
+ bool started;
+ bool status;
+ } st_xauth;
+
+ u_int32_t nat_traversal;
+ ip_address nat_oa;
+
+ /* RFC 3706 Dead Peer Detection */
+ bool st_dpd; /* Peer supports DPD */
+ time_t st_last_dpd; /* Time of last DPD transmit */
+ u_int32_t st_dpd_seqno; /* Next R_U_THERE to send */
+ u_int32_t st_dpd_expectseqno; /* Next R_U_THERE_ACK to receive */
+ u_int32_t st_dpd_peerseqno; /* global variables */
+ struct event *st_dpd_event; /* backpointer for DPD events */
+
+ u_int32_t st_seen_vendorid; /* Bit field about recognized Vendor ID */
};
/* global variables */
-extern u_int16_t pluto_port; /* Pluto's port */
+extern u_int16_t pluto_port; /* Pluto's port */
extern bool states_use_connection(struct connection *c);
@@ -247,27 +245,27 @@ extern void insert_state(struct state *st);
extern void unhash_state(struct state *st);
extern void release_whack(struct state *st);
extern void state_eroute_usage(ip_subnet *ours, ip_subnet *his
- , unsigned long count, time_t nw);
+ , unsigned long count, time_t nw);
extern void delete_state(struct state *st);
extern void delete_states_by_connection(struct connection *c, bool relations);
extern struct state
- *duplicate_state(struct state *st),
- *find_state(const u_char *icookie
- , const u_char *rcookie
- , const ip_address *peer
- , msgid_t msgid),
- *state_with_serialno(so_serial_t sn),
- *find_phase2_state_to_delete(const struct state *p1st, u_int8_t protoid
- , ipsec_spi_t spi, bool *bogus),
- *find_phase1_state(const struct connection *c, lset_t ok_states),
- *find_sender(size_t packet_len, u_char *packet);
+ *duplicate_state(struct state *st),
+ *find_state(const u_char *icookie
+ , const u_char *rcookie
+ , const ip_address *peer
+ , msgid_t msgid),
+ *state_with_serialno(so_serial_t sn),
+ *find_phase2_state_to_delete(const struct state *p1st, u_int8_t protoid
+ , ipsec_spi_t spi, bool *bogus),
+ *find_phase1_state(const struct connection *c, lset_t ok_states),
+ *find_sender(size_t packet_len, u_char *packet);
extern void show_states_status(bool all, const char *name);
extern void for_each_state(void *(f)(struct state *, void *data), void *data);
extern void find_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi);
extern ipsec_spi_t uniquify_his_cpi(ipsec_spi_t cpi, struct state *st);
extern void fmt_state(bool all, struct state *st, time_t n
- , char *state_buf, size_t state_buf_len
- , char *state_buf2, size_t state_buf_len2);
+ , char *state_buf, size_t state_buf_len
+ , char *state_buf2, size_t state_buf_len2);
extern void delete_states_by_peer(ip_address *peer);
diff --git a/src/pluto/timer.c b/src/pluto/timer.c
index aea293098..ecbee740f 100644
--- a/src/pluto/timer.c
+++ b/src/pluto/timer.c
@@ -11,8 +11,6 @@
* 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: timer.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdio.h>
@@ -26,36 +24,39 @@
#include <freeswan.h>
+#include <library.h>
+#include <crypto/rngs/rng.h>
+
#include "constants.h"
#include "defs.h"
#include "connections.h"
#include "state.h"
#include "demux.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "kernel.h"
#include "server.h"
#include "log.h"
-#include "rnd.h"
#include "timer.h"
#include "whack.h"
#include "nat_traversal.h"
-/* monotonic version of time(3) */
-time_t
-now(void)
+/**
+ * monotonic version of time(3)
+ */
+time_t now(void)
{
- static time_t delta = 0
- , last_time = 0;
- time_t n = time((time_t)NULL);
-
- passert(n != (time_t)-1);
- if (last_time > n)
- {
- plog("time moved backwards %ld seconds", (long)(last_time - n));
- delta += last_time - n;
- }
- last_time = n;
- return n + delta;
+ static time_t delta = 0
+ , last_time = 0;
+ time_t n = time((time_t)NULL);
+
+ passert(n != (time_t)-1);
+ if (last_time > n)
+ {
+ plog("time moved backwards %ld seconds", (long)(last_time - n));
+ delta += last_time - n;
+ }
+ last_time = n;
+ return n + delta;
}
/* This file has the event handling routines. Events are
@@ -66,467 +67,495 @@ now(void)
static struct event *evlist = (struct event *) NULL;
-/*
+/**
* This routine places an event in the event list.
*/
-void
-event_schedule(enum event_type type, time_t tm, struct state *st)
+void event_schedule(enum event_type type, time_t tm, struct state *st)
{
- struct event *ev = alloc_thing(struct event, "struct event in event_schedule()");
-
- ev->ev_type = type;
- ev->ev_time = tm + now();
- ev->ev_state = st;
-
- /* If the event is associated with a state, put a backpointer to the
- * event in the state object, so we can find and delete the event
- * if we need to (for example, if we receive a reply).
- */
- if (st != NULL)
- {
- if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)
+ struct event *ev = malloc_thing(struct event);
+
+ ev->ev_type = type;
+ ev->ev_time = tm + now();
+ ev->ev_state = st;
+
+ /* If the event is associated with a state, put a backpointer to the
+ * event in the state object, so we can find and delete the event
+ * if we need to (for example, if we receive a reply).
+ */
+ if (st != NULL)
+ {
+ if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)
+ {
+ passert(st->st_dpd_event == NULL);
+ st->st_dpd_event = ev;
+ }
+ else
+ {
+ passert(st->st_event == NULL);
+ st->st_event = ev;
+ }
+ }
+
+ DBG(DBG_CONTROL,
+ if (st == NULL)
+ DBG_log("inserting event %N, timeout in %lu seconds"
+ , timer_event_names, type, (unsigned long)tm);
+ else
+ DBG_log("inserting event %N, timeout in %lu seconds for #%lu"
+ , timer_event_names, type, (unsigned long)tm
+ , ev->ev_state->st_serialno));
+
+ if (evlist == (struct event *) NULL
+ || evlist->ev_time >= ev->ev_time)
{
- passert(st->st_dpd_event == NULL);
- st->st_dpd_event = ev;
+ ev->ev_next = evlist;
+ evlist = ev;
}
else
{
- passert(st->st_event == NULL);
- st->st_event = ev;
- }
- }
+ struct event *evt;
- DBG(DBG_CONTROL,
- if (st == NULL)
- DBG_log("inserting event %s, timeout in %lu seconds"
- , enum_show(&timer_event_names, type), (unsigned long)tm);
- else
- DBG_log("inserting event %s, timeout in %lu seconds for #%lu"
- , enum_show(&timer_event_names, type), (unsigned long)tm
- , ev->ev_state->st_serialno));
-
- if (evlist == (struct event *) NULL
- || evlist->ev_time >= ev->ev_time)
- {
- ev->ev_next = evlist;
- evlist = ev;
- }
- else
- {
- struct event *evt;
-
- for (evt = evlist; evt->ev_next != NULL; evt = evt->ev_next)
- if (evt->ev_next->ev_time >= ev->ev_time)
- break;
-
-#ifdef NEVER /* this seems to be overkill */
- DBG(DBG_CONTROL,
- if (evt->ev_state == NULL)
- DBG_log("event added after event %s"
- , enum_show(&timer_event_names, evt->ev_type));
- else
- DBG_log("event added after event %s for #%lu"
- , enum_show(&timer_event_names, evt->ev_type)
- , evt->ev_state->st_serialno));
+ for (evt = evlist; evt->ev_next != NULL; evt = evt->ev_next)
+ if (evt->ev_next->ev_time >= ev->ev_time)
+ break;
+
+#ifdef NEVER /* this seems to be overkill */
+ DBG(DBG_CONTROL,
+ if (evt->ev_state == NULL)
+ DBG_log("event added after event %N"
+ , timer_event_names, evt->ev_type);
+ else
+ DBG_log("event added after event %N for #%lu"
+ , timer_event_names, evt->ev_type,
+ , evt->ev_state->st_serialno));
#endif /* NEVER */
- ev->ev_next = evt->ev_next;
- evt->ev_next = ev;
- }
+ ev->ev_next = evt->ev_next;
+ evt->ev_next = ev;
+ }
+}
+
+/**
+ * Generate the secret value for responder cookies, and
+ * schedule an event for refresh.
+ */
+void init_secret(void)
+{
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ rng->get_bytes(rng, sizeof(secret_of_the_day), secret_of_the_day);
+ rng->destroy(rng);
+ event_schedule(EVENT_REINIT_SECRET, EVENT_REINIT_SECRET_DELAY, NULL);
}
-/*
+/**
* Handle the first event on the list.
*/
-void
-handle_timer_event(void)
+void handle_timer_event(void)
{
- time_t tm;
- struct event *ev = evlist;
- int type;
- struct state *st;
- struct connection *c = NULL;
- ip_address peer;
-
- if (ev == (struct event *) NULL) /* Just paranoid */
- {
- DBG(DBG_CONTROL, DBG_log("empty event list, yet we're called"));
- return;
- }
-
- type = ev->ev_type;
- st = ev->ev_state;
-
- tm = now();
-
- if (tm < ev->ev_time)
- {
- DBG(DBG_CONTROL, DBG_log("called while no event expired (%lu/%lu, %s)"
- , (unsigned long)tm, (unsigned long)ev->ev_time
- , enum_show(&timer_event_names, type)));
-
- /* This will happen if the most close-to-expire event was
- * a retransmission or cleanup, and we received a packet
- * at the same time as the event expired. Due to the processing
- * order in call_server(), the packet processing will happen first,
- * and the event will be removed.
- */
- return;
- }
-
- evlist = evlist->ev_next; /* Ok, we'll handle this event */
-
- DBG(DBG_CONTROL,
- if (evlist != (struct event *) NULL)
- DBG_log("event after this is %s in %ld seconds"
- , enum_show(&timer_event_names, evlist->ev_type)
- , (long) (evlist->ev_time - tm)));
-
- /* for state-associated events, pick up the state pointer
- * and remove the backpointer from the state object.
- * We'll eventually either schedule a new event, or delete the state.
- */
- passert(GLOBALS_ARE_RESET());
- if (st != NULL)
- {
- c = st->st_connection;
- if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)
+ time_t tm;
+ struct event *ev = evlist;
+ int type;
+ struct state *st;
+ struct connection *c = NULL;
+ ip_address peer;
+
+ if (ev == (struct event *) NULL) /* Just paranoid */
{
- passert(st->st_dpd_event == ev);
- st->st_dpd_event = NULL;
+ DBG(DBG_CONTROL, DBG_log("empty event list, yet we're called"));
+ return;
}
- else
+
+ type = ev->ev_type;
+ st = ev->ev_state;
+
+ tm = now();
+
+ if (tm < ev->ev_time)
{
- passert(st->st_event == ev);
- st->st_event = NULL;
+ DBG(DBG_CONTROL, DBG_log("called while no event expired (%lu/%lu, %N)"
+ , (unsigned long)tm, (unsigned long)ev->ev_time
+ , timer_event_names, type));
+
+ /* This will happen if the most close-to-expire event was
+ * a retransmission or cleanup, and we received a packet
+ * at the same time as the event expired. Due to the processing
+ * order in call_server(), the packet processing will happen first,
+ * and the event will be removed.
+ */
+ return;
}
- peer = c->spd.that.host_addr;
- set_cur_state(st);
- }
-
- switch (type)
- {
- case EVENT_REINIT_SECRET:
- passert(st == NULL);
- DBG(DBG_CONTROL, DBG_log("event EVENT_REINIT_SECRET handled"));
- init_secret();
- break;
-#ifdef KLIPS
- case EVENT_SHUNT_SCAN:
- passert(st == NULL);
- scan_proc_shunts();
- break;
-#endif
+ evlist = evlist->ev_next; /* Ok, we'll handle this event */
- case EVENT_LOG_DAILY:
- daily_log_event();
- break;
-
- case EVENT_RETRANSMIT:
- /* Time to retransmit, or give up.
- *
- * Generally, we'll only try to send the message
- * MAXIMUM_RETRANSMISSIONS times. Each time we double
- * our patience.
- *
- * As a special case, if this is the first initiating message
- * of a Main Mode exchange, and we have been directed to try
- * forever, we'll extend the number of retransmissions to
- * MAXIMUM_RETRANSMISSIONS_INITIAL times, with all these
- * extended attempts having the same patience. The intention
- * is to reduce the bother when nobody is home.
- */
- {
- time_t delay = 0;
-
- DBG(DBG_CONTROL, DBG_log(
- "handling event EVENT_RETRANSMIT for %s \"%s\" #%lu"
- , ip_str(&peer), c->name, st->st_serialno));
-
- if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
- delay = EVENT_RETRANSMIT_DELAY_0 << (st->st_retransmit + 1);
- else if (st->st_state == STATE_MAIN_I1
- && c->sa_keying_tries == 0
- && st->st_retransmit < MAXIMUM_RETRANSMISSIONS_INITIAL)
- delay = EVENT_RETRANSMIT_DELAY_0 << MAXIMUM_RETRANSMISSIONS;
-
- if (delay != 0)
+ DBG(DBG_CONTROL,
+ if (evlist != (struct event *) NULL)
+ DBG_log("event after this is %N in %ld seconds"
+ , timer_event_names, evlist->ev_type
+ , (long) (evlist->ev_time - tm)));
+
+ /* for state-associated events, pick up the state pointer
+ * and remove the backpointer from the state object.
+ * We'll eventually either schedule a new event, or delete the state.
+ */
+ passert(GLOBALS_ARE_RESET());
+ if (st != NULL)
+ {
+ c = st->st_connection;
+ if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)
{
- st->st_retransmit++;
- whack_log(RC_RETRANSMISSION
- , "%s: retransmission; will wait %lus for response"
- , enum_name(&state_names, st->st_state)
- , (unsigned long)delay);
- send_packet(st, "EVENT_RETRANSMIT");
- event_schedule(EVENT_RETRANSMIT, delay, st);
+ passert(st->st_dpd_event == ev);
+ st->st_dpd_event = NULL;
}
- else
+ else
{
- /* check if we've tried rekeying enough times.
- * st->st_try == 0 means that this should be the only try.
- * c->sa_keying_tries == 0 means that there is no limit.
- */
- unsigned long try = st->st_try;
- unsigned long try_limit = c->sa_keying_tries;
- const char *details = "";
-
- switch (st->st_state)
- {
- case STATE_MAIN_I3:
- details = ". Possible authentication failure:"
- " no acceptable response to our"
- " first encrypted message";
- break;
- case STATE_MAIN_I1:
- details = ". No response (or no acceptable response) to our"
- " first IKE message";
- break;
- case STATE_QUICK_I1:
- if (c->newest_ipsec_sa == SOS_NOBODY)
- details = ". No acceptable response to our"
- " first Quick Mode message:"
- " perhaps peer likes no proposal";
+ passert(st->st_event == ev);
+ st->st_event = NULL;
+ }
+ peer = c->spd.that.host_addr;
+ set_cur_state(st);
+ }
+
+ switch (type)
+ {
+ case EVENT_REINIT_SECRET:
+ passert(st == NULL);
+ DBG(DBG_CONTROL, DBG_log("event EVENT_REINIT_SECRET handled"));
+ init_secret();
break;
- default:
+
+#ifdef KLIPS
+ case EVENT_SHUNT_SCAN:
+ passert(st == NULL);
+ scan_proc_shunts();
break;
- }
- loglog(RC_NORETRANSMISSION
- , "max number of retransmissions (%d) reached %s%s"
- , st->st_retransmit
- , enum_show(&state_names, st->st_state), details);
- if (try != 0 && try != try_limit)
- {
- /* A lot like EVENT_SA_REPLACE, but over again.
- * Since we know that st cannot be in use,
- * we can delete it right away.
- */
- char story[80]; /* arbitrary limit */
+#endif
- try++;
- snprintf(story, sizeof(story), try_limit == 0
- ? "starting keying attempt %ld of an unlimited number"
- : "starting keying attempt %ld of at most %ld"
- , try, try_limit);
+ case EVENT_LOG_DAILY:
+ daily_log_event();
+ break;
- if (st->st_whack_sock != NULL_FD)
+ case EVENT_RETRANSMIT:
+ /* Time to retransmit, or give up.
+ *
+ * Generally, we'll only try to send the message
+ * MAXIMUM_RETRANSMISSIONS times. Each time we double
+ * our patience.
+ *
+ * As a special case, if this is the first initiating message
+ * of a Main Mode exchange, and we have been directed to try
+ * forever, we'll extend the number of retransmissions to
+ * MAXIMUM_RETRANSMISSIONS_INITIAL times, with all these
+ * extended attempts having the same patience. The intention
+ * is to reduce the bother when nobody is home.
+ */
{
- /* Release whack because the observer will get bored. */
- loglog(RC_COMMENT, "%s, but releasing whack"
- , story);
- release_pending_whacks(st, story);
+ time_t delay = 0;
+
+ DBG(DBG_CONTROL, DBG_log(
+ "handling event EVENT_RETRANSMIT for %s \"%s\" #%lu"
+ , ip_str(&peer), c->name, st->st_serialno));
+
+ if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
+ delay = EVENT_RETRANSMIT_DELAY_0 << (st->st_retransmit + 1);
+ else if (st->st_state == STATE_MAIN_I1
+ && c->sa_keying_tries == 0
+ && st->st_retransmit < MAXIMUM_RETRANSMISSIONS_INITIAL)
+ delay = EVENT_RETRANSMIT_DELAY_0 << MAXIMUM_RETRANSMISSIONS;
+
+ if (delay != 0)
+ {
+ st->st_retransmit++;
+ whack_log(RC_RETRANSMISSION
+ , "%s: retransmission; will wait %lus for response"
+ , enum_name(&state_names, st->st_state)
+ , (unsigned long)delay);
+ send_packet(st, "EVENT_RETRANSMIT");
+ event_schedule(EVENT_RETRANSMIT, delay, st);
+ }
+ else
+ {
+ /* check if we've tried rekeying enough times.
+ * st->st_try == 0 means that this should be the only try.
+ * c->sa_keying_tries == 0 means that there is no limit.
+ */
+ unsigned long try = st->st_try;
+ unsigned long try_limit = c->sa_keying_tries;
+ const char *details = "";
+
+ switch (st->st_state)
+ {
+ case STATE_MAIN_I3:
+ details = ". Possible authentication failure:"
+ " no acceptable response to our"
+ " first encrypted message";
+ break;
+ case STATE_MAIN_I1:
+ details = ". No response (or no acceptable response) to our"
+ " first IKE message";
+ break;
+ case STATE_QUICK_I1:
+ if (c->newest_ipsec_sa == SOS_NOBODY)
+ details = ". No acceptable response to our"
+ " first Quick Mode message:"
+ " perhaps peer likes no proposal";
+ break;
+ default:
+ break;
+ }
+ loglog(RC_NORETRANSMISSION
+ , "max number of retransmissions (%d) reached %s%s"
+ , st->st_retransmit
+ , enum_show(&state_names, st->st_state), details);
+ if (try != 0 && try != try_limit)
+ {
+ /* A lot like EVENT_SA_REPLACE, but over again.
+ * Since we know that st cannot be in use,
+ * we can delete it right away.
+ */
+ char story[80]; /* arbitrary limit */
+
+ try++;
+ snprintf(story, sizeof(story), try_limit == 0
+ ? "starting keying attempt %ld of an unlimited number"
+ : "starting keying attempt %ld of at most %ld"
+ , try, try_limit);
+
+ if (st->st_whack_sock != NULL_FD)
+ {
+ /* Release whack because the observer will get bored. */
+ loglog(RC_COMMENT, "%s, but releasing whack"
+ , story);
+ release_pending_whacks(st, story);
+ }
+ else
+ {
+ /* no whack: just log to syslog */
+ plog("%s", story);
+ }
+ ipsecdoi_replace(st, try);
+ }
+ delete_state(st);
+ }
}
- else
+ break;
+
+ case EVENT_SA_REPLACE:
+ case EVENT_SA_REPLACE_IF_USED:
{
- /* no whack: just log to syslog */
- plog("%s", story);
+ so_serial_t newest = IS_PHASE1(st->st_state)
+ ? c->newest_isakmp_sa : c->newest_ipsec_sa;
+
+ if (newest != st->st_serialno
+ && newest != SOS_NOBODY)
+ {
+ /* not very interesting: no need to replace */
+ DBG(DBG_LIFECYCLE
+ , plog("not replacing stale %s SA: #%lu will do"
+ , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
+ , newest));
+ }
+ else if (type == EVENT_SA_REPLACE_IF_USED
+ && st->st_outbound_time <= tm - c->sa_rekey_margin)
+ {
+ /* we observed no recent use: no need to replace
+ *
+ * The sampling effects mean that st_outbound_time
+ * could be up to SHUNT_SCAN_INTERVAL more recent
+ * than actual traffic because the sampler looks at change
+ * over that interval.
+ * st_outbound_time could also not yet reflect traffic
+ * in the last SHUNT_SCAN_INTERVAL.
+ * We expect that SHUNT_SCAN_INTERVAL is smaller than
+ * c->sa_rekey_margin so that the effects of this will
+ * be unimportant.
+ * This is just an optimization: correctness is not
+ * at stake.
+ *
+ * Note: we are abusing the DBG mechanism to control
+ * normal log output.
+ */
+ DBG(DBG_LIFECYCLE
+ , plog("not replacing stale %s SA: inactive for %lus"
+ , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
+ , (unsigned long)(tm - st->st_outbound_time)));
+ }
+ else
+ {
+ DBG(DBG_LIFECYCLE
+ , plog("replacing stale %s SA"
+ , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"));
+ ipsecdoi_replace(st, 1);
+ }
+ delete_dpd_event(st);
+ event_schedule(EVENT_SA_EXPIRE, st->st_margin, st);
}
- ipsecdoi_replace(st, try);
- }
- delete_state(st);
- }
- }
- break;
-
- case EVENT_SA_REPLACE:
- case EVENT_SA_REPLACE_IF_USED:
- {
- so_serial_t newest = IS_PHASE1(st->st_state)
- ? c->newest_isakmp_sa : c->newest_ipsec_sa;
-
- if (newest != st->st_serialno
- && newest != SOS_NOBODY)
- {
- /* not very interesting: no need to replace */
- DBG(DBG_LIFECYCLE
- , plog("not replacing stale %s SA: #%lu will do"
- , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
- , newest));
- }
- else if (type == EVENT_SA_REPLACE_IF_USED
- && st->st_outbound_time <= tm - c->sa_rekey_margin)
- {
- /* we observed no recent use: no need to replace
- *
- * The sampling effects mean that st_outbound_time
- * could be up to SHUNT_SCAN_INTERVAL more recent
- * than actual traffic because the sampler looks at change
- * over that interval.
- * st_outbound_time could also not yet reflect traffic
- * in the last SHUNT_SCAN_INTERVAL.
- * We expect that SHUNT_SCAN_INTERVAL is smaller than
- * c->sa_rekey_margin so that the effects of this will
- * be unimportant.
- * This is just an optimization: correctness is not
- * at stake.
- *
- * Note: we are abusing the DBG mechanism to control
- * normal log output.
- */
- DBG(DBG_LIFECYCLE
- , plog("not replacing stale %s SA: inactive for %lus"
- , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
- , (unsigned long)(tm - st->st_outbound_time)));
- }
- else
- {
- DBG(DBG_LIFECYCLE
- , plog("replacing stale %s SA"
- , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"));
- ipsecdoi_replace(st, 1);
- }
- delete_dpd_event(st);
- event_schedule(EVENT_SA_EXPIRE, st->st_margin, st);
- }
- break;
+ break;
- case EVENT_SA_EXPIRE:
- {
- const char *satype;
- so_serial_t latest;
+ case EVENT_SA_EXPIRE:
+ {
+ const char *satype;
+ so_serial_t latest;
+
+ if (IS_PHASE1(st->st_state))
+ {
+ satype = "ISAKMP";
+ latest = c->newest_isakmp_sa;
+ }
+ else
+ {
+ satype = "IPsec";
+ latest = c->newest_ipsec_sa;
+ }
+
+ if (st->st_serialno != latest)
+ {
+ /* not very interesting: already superseded */
+ DBG(DBG_LIFECYCLE
+ , plog("%s SA expired (superseded by #%lu)"
+ , satype, latest));
+ }
+ else
+ {
+ plog("%s SA expired (%s)", satype
+ , (c->policy & POLICY_DONT_REKEY)
+ ? "--dontrekey"
+ : "LATEST!"
+ );
+ }
+ }
+ /* FALLTHROUGH */
+ case EVENT_SO_DISCARD:
+ /* Delete this state object. It must be in the hash table. */
+ delete_state(st);
+ break;
- if (IS_PHASE1(st->st_state))
- {
- satype = "ISAKMP";
- latest = c->newest_isakmp_sa;
- }
- else
- {
- satype = "IPsec";
- latest = c->newest_ipsec_sa;
- }
+ case EVENT_DPD:
+ dpd_outI(st);
+ break;
+ case EVENT_DPD_TIMEOUT:
+ dpd_timeout(st);
+ break;
+ case EVENT_NAT_T_KEEPALIVE:
+ nat_traversal_ka_event();
+ break;
+ default:
+ loglog(RC_LOG_SERIOUS, "INTERNAL ERROR: ignoring unknown expiring event %N"
+ , timer_event_names, type);
+ }
- if (st->st_serialno != latest)
- {
- /* not very interesting: already superseded */
- DBG(DBG_LIFECYCLE
- , plog("%s SA expired (superseded by #%lu)"
- , satype, latest));
- }
- else
- {
- plog("%s SA expired (%s)", satype
- , (c->policy & POLICY_DONT_REKEY)
- ? "--dontrekey"
- : "LATEST!"
- );
- }
- }
- /* FALLTHROUGH */
- case EVENT_SO_DISCARD:
- /* Delete this state object. It must be in the hash table. */
- delete_state(st);
- break;
-
- case EVENT_DPD:
- dpd_outI(st);
- break;
- case EVENT_DPD_TIMEOUT:
- dpd_timeout(st);
- break;
- case EVENT_NAT_T_KEEPALIVE:
- nat_traversal_ka_event();
- break;
- default:
- loglog(RC_LOG_SERIOUS, "INTERNAL ERROR: ignoring unknown expiring event %s"
- , enum_show(&timer_event_names, type));
- }
-
- pfree(ev);
- reset_cur_state();
+ free(ev);
+ reset_cur_state();
}
-/*
+/**
* Return the time until the next event in the queue
* expires (never negative), or -1 if no jobs in queue.
*/
-long
-next_event(void)
+long next_event(void)
{
- time_t tm;
+ time_t tm;
+
+ if (evlist == (struct event *) NULL)
+ return -1;
- if (evlist == (struct event *) NULL)
- return -1;
+ tm = now();
- tm = now();
+ DBG(DBG_CONTROL,
+ if (evlist->ev_state == NULL)
+ DBG_log("next event %N in %ld seconds"
+ , timer_event_names, evlist->ev_type
+ , (long)evlist->ev_time - (long)tm);
+ else
+ DBG_log("next event %N in %ld seconds for #%lu"
+ , timer_event_names, evlist->ev_type
+ , (long)evlist->ev_time - (long)tm
+ , evlist->ev_state->st_serialno));
- DBG(DBG_CONTROL,
- if (evlist->ev_state == NULL)
- DBG_log("next event %s in %ld seconds"
- , enum_show(&timer_event_names, evlist->ev_type)
- , (long)evlist->ev_time - (long)tm);
+ if (evlist->ev_time - tm <= 0)
+ return 0;
else
- DBG_log("next event %s in %ld seconds for #%lu"
- , enum_show(&timer_event_names, evlist->ev_type)
- , (long)evlist->ev_time - (long)tm
- , evlist->ev_state->st_serialno));
-
- if (evlist->ev_time - tm <= 0)
- return 0;
- else
- return evlist->ev_time - tm;
+ return evlist->ev_time - tm;
}
-/*
+/**
* Delete an event.
*/
-void
-delete_event(struct state *st)
+void delete_event(struct state *st)
{
- if (st->st_event != (struct event *) NULL)
- {
- struct event **ev;
-
- for (ev = &evlist; ; ev = &(*ev)->ev_next)
+ if (st->st_event != (struct event *) NULL)
{
- if (*ev == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("event %s to be deleted not found",
- enum_show(&timer_event_names, st->st_event->ev_type)));
- break;
- }
- if ((*ev) == st->st_event)
- {
- *ev = (*ev)->ev_next;
-
- if (st->st_event->ev_type == EVENT_RETRANSMIT)
- st->st_retransmit = 0;
- pfree(st->st_event);
- st->st_event = (struct event *) NULL;
-
- break;
- }
+ struct event **ev;
+
+ for (ev = &evlist; ; ev = &(*ev)->ev_next)
+ {
+ if (*ev == NULL)
+ {
+ DBG(DBG_CONTROL, DBG_log("event %N to be deleted not found",
+ timer_event_names, st->st_event->ev_type));
+ break;
+ }
+ if ((*ev) == st->st_event)
+ {
+ *ev = (*ev)->ev_next;
+
+ if (st->st_event->ev_type == EVENT_RETRANSMIT)
+ {
+ st->st_retransmit = 0;
+ }
+ free(st->st_event);
+ st->st_event = (struct event *) NULL;
+
+ break;
+ }
+ }
}
- }
}
-/*
+/**
* Delete a DPD event.
*/
-void
-delete_dpd_event(struct state *st)
+void delete_dpd_event(struct state *st)
{
- if (st->st_dpd_event != (struct event *) NULL)
- {
- struct event **ev;
-
- for (ev = &evlist; ; ev = &(*ev)->ev_next)
- {
- if (*ev == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("event %s to be deleted not found",
- enum_show(&timer_event_names, st->st_dpd_event->ev_type)));
- break;
- }
- if ((*ev) == st->st_dpd_event)
- {
- *ev = (*ev)->ev_next;
- pfree(st->st_dpd_event);
- st->st_dpd_event = (struct event *) NULL;
- break;
- }
- }
- }
+ if (st->st_dpd_event != (struct event *) NULL)
+ {
+ struct event **ev;
+
+ for (ev = &evlist; ; ev = &(*ev)->ev_next)
+ {
+ if (*ev == NULL)
+ {
+ DBG(DBG_CONTROL, DBG_log("event %N to be deleted not found",
+ timer_event_names, st->st_dpd_event->ev_type));
+ break;
+ }
+ if ((*ev) == st->st_dpd_event)
+ {
+ *ev = (*ev)->ev_next;
+ free(st->st_dpd_event);
+ st->st_dpd_event = (struct event *) NULL;
+ break;
+ }
+ }
+ }
}
+/**
+ * Free remaining events
+ */
+void free_events(void)
+{
+ struct event *ev_tmp, *ev;
+
+ ev = evlist;
+ evlist = NULL;
+
+ while (ev)
+ {
+ ev_tmp = ev;
+ ev = ev->ev_next;
+ free(ev_tmp);
+ }
+}
diff --git a/src/pluto/timer.h b/src/pluto/timer.h
index c772d37f9..322aeba6a 100644
--- a/src/pluto/timer.h
+++ b/src/pluto/timer.h
@@ -10,20 +10,18 @@
* 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: timer.h 3252 2007-10-06 21:24:50Z andreas $
*/
-extern time_t now(void); /* careful version of time(2) */
+extern time_t now(void); /* careful version of time(2) */
-struct state; /* forward declaration */
+struct state; /* forward declaration */
struct event
{
- time_t ev_time;
- int ev_type; /* Event type */
- struct state *ev_state; /* Pointer to relevant state (if any) */
- struct event *ev_next; /* Pointer to next event */
+ time_t ev_time;
+ int ev_type; /* Event type */
+ struct state *ev_state; /* Pointer to relevant state (if any) */
+ struct event *ev_next; /* Pointer to next event */
};
extern void event_schedule(enum event_type type, time_t tm, struct state *st);
@@ -32,3 +30,5 @@ extern long next_event(void);
extern void delete_event(struct state *st);
extern void delete_dpd_event(struct state *st);
extern void daily_log_event(void);
+extern void free_events(void);
+extern void init_secret(void);
diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c
index f957bf39b..ff145eb38 100644
--- a/src/pluto/vendor.c
+++ b/src/pluto/vendor.c
@@ -1,5 +1,6 @@
/* ISAKMP VendorID
* Copyright (C) 2002-2005 Mathieu Lafon - Arkoon Network Security
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -10,8 +11,6 @@
* 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: vendor.c 5052 2009-03-30 03:47:14Z andreas $
*/
#include <stdlib.h>
@@ -20,10 +19,12 @@
#include <sys/queue.h>
#include <freeswan.h>
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "md5.h"
#include "connections.h"
#include "packet.h"
#include "demux.h"
@@ -88,232 +89,226 @@
#define VID_SUBSTRING (VID_SUBSTRING_DUMPHEXA | VID_SUBSTRING_DUMPASCII | VID_SUBSTRING_MATCH)
struct vid_struct {
- enum known_vendorid id;
- unsigned short flags;
- const char *data;
- const char *descr;
- const char *vid;
- u_int vid_len;
+ enum known_vendorid id;
+ unsigned short flags;
+ const char *data;
+ const char *descr;
+ chunk_t vid;
};
#define DEC_MD5_VID_D(id,str,descr) \
- { VID_##id, VID_MD5HASH, str, descr, NULL, 0 },
+ { VID_##id, VID_MD5HASH, str, descr, { NULL, 0 } },
#define DEC_MD5_VID(id,str) \
- { VID_##id, VID_MD5HASH, str, NULL, NULL, 0 },
-#define DEC_FSWAN_VID(id,str,descr) \
- { VID_##id, VID_FSWAN_HASH, str, descr, NULL, 0 },
+ { VID_##id, VID_MD5HASH, str, NULL, { NULL, 0 } },
static struct vid_struct _vid_tab[] = {
- /* Implementation names */
-
- { VID_OPENPGP, VID_STRING, "OpenPGP10171", "OpenPGP", NULL, 0 },
-
- DEC_MD5_VID(KAME_RACOON, "KAME/racoon")
-
- { VID_MS_NT5, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
- "MS NT5 ISAKMPOAKLEY", NULL, NULL, 0 },
-
- DEC_MD5_VID(SSH_SENTINEL, "SSH Sentinel")
- DEC_MD5_VID(SSH_SENTINEL_1_1, "SSH Sentinel 1.1")
- DEC_MD5_VID(SSH_SENTINEL_1_2, "SSH Sentinel 1.2")
- DEC_MD5_VID(SSH_SENTINEL_1_3, "SSH Sentinel 1.3")
- DEC_MD5_VID(SSH_SENTINEL_1_4, "SSH Sentinel 1.4")
- DEC_MD5_VID(SSH_SENTINEL_1_4_1, "SSH Sentinel 1.4.1")
-
- /* These ones come from SSH vendors.txt */
- DEC_MD5_VID(SSH_IPSEC_1_1_0,
- "Ssh Communications Security IPSEC Express version 1.1.0")
- DEC_MD5_VID(SSH_IPSEC_1_1_1,
- "Ssh Communications Security IPSEC Express version 1.1.1")
- DEC_MD5_VID(SSH_IPSEC_1_1_2,
- "Ssh Communications Security IPSEC Express version 1.1.2")
- DEC_MD5_VID(SSH_IPSEC_1_2_1,
- "Ssh Communications Security IPSEC Express version 1.2.1")
- DEC_MD5_VID(SSH_IPSEC_1_2_2,
- "Ssh Communications Security IPSEC Express version 1.2.2")
- DEC_MD5_VID(SSH_IPSEC_2_0_0,
- "SSH Communications Security IPSEC Express version 2.0.0")
- DEC_MD5_VID(SSH_IPSEC_2_1_0,
- "SSH Communications Security IPSEC Express version 2.1.0")
- DEC_MD5_VID(SSH_IPSEC_2_1_1,
- "SSH Communications Security IPSEC Express version 2.1.1")
- DEC_MD5_VID(SSH_IPSEC_2_1_2,
- "SSH Communications Security IPSEC Express version 2.1.2")
- DEC_MD5_VID(SSH_IPSEC_3_0_0,
- "SSH Communications Security IPSEC Express version 3.0.0")
- DEC_MD5_VID(SSH_IPSEC_3_0_1,
- "SSH Communications Security IPSEC Express version 3.0.1")
- DEC_MD5_VID(SSH_IPSEC_4_0_0,
- "SSH Communications Security IPSEC Express version 4.0.0")
- DEC_MD5_VID(SSH_IPSEC_4_0_1,
- "SSH Communications Security IPSEC Express version 4.0.1")
- DEC_MD5_VID(SSH_IPSEC_4_1_0,
- "SSH Communications Security IPSEC Express version 4.1.0")
- DEC_MD5_VID(SSH_IPSEC_4_2_0,
- "SSH Communications Security IPSEC Express version 4.2.0")
-
- /* note: md5('CISCO-UNITY') = 12f5f28c457168a9702d9fe274cc02d4 */
- { VID_CISCO_UNITY, VID_KEEP, NULL, "Cisco-Unity",
- "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00",
- 16 },
-
- { VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH,
- NULL, "Cisco VPN 3000 Series" , "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14},
-
- { VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH,
- NULL, "Cisco IOS Device", "\x3e\x98\x40\x48", 4},
-
- /*
- * Timestep VID seen:
- * - 54494d455354455020312053475720313532302033313520322e303145303133
- * = 'TIMESTEP 1 SGW 1520 315 2.01E013'
- */
- { VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP",
- NULL, NULL, 0 },
-
- /*
- * Netscreen:
- * 4865617274426561745f4e6f74696679386b0100 (HeartBeat_Notify + 386b0100)
- */
- { VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA,
- "HeartBeat_Notify", "HeartBeat Notify", NULL, 0 },
-
- /*
- * MacOS X
- */
- { VID_MACOSX, VID_STRING|VID_SUBSTRING_DUMPHEXA, "Mac OSX 10.x",
- "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62", NULL, 0},
-
- /*
- * Openswan
- */
- DEC_FSWAN_VID(OPENSWAN2, "Openswan 2.2.0", "Openswan 2.2.0")
-
- /* NCP */
- { VID_NCP_SERVER, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Server",
- "\xc6\xf5\x7a\xc3\x98\xf4\x93\x20\x81\x45\xb7\x58", 12},
- { VID_NCP_CLIENT, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Client",
- "\xeb\x4c\x1b\x78\x8a\xfd\x4a\x9c\xb7\x73\x0a\x68", 12},
-
- /*
- * Windows Vista (and Windows Server 2008?)
- */
- DEC_MD5_VID(VISTA_AUTHIP, "MS-Negotiation Discovery Capable")
- DEC_MD5_VID(VISTA_AUTHIP2, "IKE CGA version 1")
- DEC_MD5_VID(VISTA_AUTHIP3, "MS-MamieExists")
-
- /*
- * strongSwan
- */
- DEC_MD5_VID(STRONGSWAN, "strongSwan 4.2.14")
- DEC_MD5_VID(STRONGSWAN_4_2_13,"strongSwan 4.2.13")
- DEC_MD5_VID(STRONGSWAN_4_2_12,"strongSwan 4.2.12")
- DEC_MD5_VID(STRONGSWAN_4_2_11,"strongSwan 4.2.11")
- DEC_MD5_VID(STRONGSWAN_4_2_10,"strongSwan 4.2.10")
- DEC_MD5_VID(STRONGSWAN_4_2_9, "strongSwan 4.2.9")
- DEC_MD5_VID(STRONGSWAN_4_2_8, "strongSwan 4.2.8")
- DEC_MD5_VID(STRONGSWAN_4_2_7, "strongSwan 4.2.7")
- DEC_MD5_VID(STRONGSWAN_4_2_6, "strongSwan 4.2.6")
- DEC_MD5_VID(STRONGSWAN_4_2_5, "strongSwan 4.2.5")
- DEC_MD5_VID(STRONGSWAN_4_2_4, "strongSwan 4.2.4")
- DEC_MD5_VID(STRONGSWAN_4_2_3, "strongSwan 4.2.3")
- DEC_MD5_VID(STRONGSWAN_4_2_2, "strongSwan 4.2.2")
- DEC_MD5_VID(STRONGSWAN_4_2_1, "strongSwan 4.2.1")
- DEC_MD5_VID(STRONGSWAN_4_2_0, "strongSwan 4.2.0")
- DEC_MD5_VID(STRONGSWAN_4_1_11,"strongSwan 4.1.11")
- DEC_MD5_VID(STRONGSWAN_4_1_10,"strongSwan 4.1.10")
- DEC_MD5_VID(STRONGSWAN_4_1_9, "strongSwan 4.1.9")
- DEC_MD5_VID(STRONGSWAN_4_1_8, "strongSwan 4.1.8")
- DEC_MD5_VID(STRONGSWAN_4_1_7, "strongSwan 4.1.7")
- DEC_MD5_VID(STRONGSWAN_4_1_6, "strongSwan 4.1.6")
- DEC_MD5_VID(STRONGSWAN_4_1_5, "strongSwan 4.1.5")
- DEC_MD5_VID(STRONGSWAN_4_1_4, "strongSwan 4.1.4")
- DEC_MD5_VID(STRONGSWAN_4_1_3, "strongSwan 4.1.3")
- DEC_MD5_VID(STRONGSWAN_4_1_2, "strongSwan 4.1.2")
- DEC_MD5_VID(STRONGSWAN_4_1_1, "strongSwan 4.1.1")
- DEC_MD5_VID(STRONGSWAN_4_1_0, "strongSwan 4.1.0")
- DEC_MD5_VID(STRONGSWAN_4_0_7, "strongSwan 4.0.7")
- DEC_MD5_VID(STRONGSWAN_4_0_6, "strongSwan 4.0.6")
- DEC_MD5_VID(STRONGSWAN_4_0_5, "strongSwan 4.0.5")
- DEC_MD5_VID(STRONGSWAN_4_0_4, "strongSwan 4.0.4")
- DEC_MD5_VID(STRONGSWAN_4_0_3, "strongSwan 4.0.3")
- DEC_MD5_VID(STRONGSWAN_4_0_2, "strongSwan 4.0.2")
- DEC_MD5_VID(STRONGSWAN_4_0_1, "strongSwan 4.0.1")
- DEC_MD5_VID(STRONGSWAN_4_0_0, "strongSwan 4.0.0")
-
- DEC_MD5_VID(STRONGSWAN_2_8_8, "strongSwan 2.8.9")
- DEC_MD5_VID(STRONGSWAN_2_8_8, "strongSwan 2.8.8")
- DEC_MD5_VID(STRONGSWAN_2_8_7, "strongSwan 2.8.7")
- DEC_MD5_VID(STRONGSWAN_2_8_6, "strongSwan 2.8.6")
- DEC_MD5_VID(STRONGSWAN_2_8_5, "strongSwan 2.8.5")
- DEC_MD5_VID(STRONGSWAN_2_8_4, "strongSwan 2.8.4")
- DEC_MD5_VID(STRONGSWAN_2_8_3, "strongSwan 2.8.3")
- DEC_MD5_VID(STRONGSWAN_2_8_2, "strongSwan 2.8.2")
- DEC_MD5_VID(STRONGSWAN_2_8_1, "strongSwan 2.8.1")
- DEC_MD5_VID(STRONGSWAN_2_8_0, "strongSwan 2.8.0")
- DEC_MD5_VID(STRONGSWAN_2_7_3, "strongSwan 2.7.3")
- DEC_MD5_VID(STRONGSWAN_2_7_2, "strongSwan 2.7.2")
- DEC_MD5_VID(STRONGSWAN_2_7_1, "strongSwan 2.7.1")
- DEC_MD5_VID(STRONGSWAN_2_7_0, "strongSwan 2.7.0")
- DEC_MD5_VID(STRONGSWAN_2_6_4, "strongSwan 2.6.4")
- DEC_MD5_VID(STRONGSWAN_2_6_3, "strongSwan 2.6.3")
- DEC_MD5_VID(STRONGSWAN_2_6_2, "strongSwan 2.6.2")
- DEC_MD5_VID(STRONGSWAN_2_6_1, "strongSwan 2.6.1")
- DEC_MD5_VID(STRONGSWAN_2_6_0, "strongSwan 2.6.0")
- DEC_MD5_VID(STRONGSWAN_2_5_7, "strongSwan 2.5.7")
- DEC_MD5_VID(STRONGSWAN_2_5_6, "strongSwan 2.5.6")
- DEC_MD5_VID(STRONGSWAN_2_5_5, "strongSwan 2.5.5")
- DEC_MD5_VID(STRONGSWAN_2_5_4, "strongSwan 2.5.4")
- DEC_MD5_VID(STRONGSWAN_2_5_3, "strongSwan 2.5.3")
- DEC_MD5_VID(STRONGSWAN_2_5_2, "strongSwan 2.5.2")
- DEC_MD5_VID(STRONGSWAN_2_5_1, "strongSwan 2.5.1")
- DEC_MD5_VID(STRONGSWAN_2_5_0, "strongSwan 2.5.0")
- DEC_MD5_VID(STRONGSWAN_2_4_4, "strongSwan 2.4.4")
- DEC_MD5_VID(STRONGSWAN_2_4_3, "strongSwan 2.4.3")
- DEC_MD5_VID(STRONGSWAN_2_4_2, "strongSwan 2.4.2")
- DEC_MD5_VID(STRONGSWAN_2_4_1, "strongSwan 2.4.1")
- DEC_MD5_VID(STRONGSWAN_2_4_0, "strongSwan 2.4.0")
- DEC_MD5_VID(STRONGSWAN_2_3_2, "strongSwan 2.3.2")
- DEC_MD5_VID(STRONGSWAN_2_3_1, "strongSwan 2.3.1")
- DEC_MD5_VID(STRONGSWAN_2_3_0, "strongSwan 2.3.0")
- DEC_MD5_VID(STRONGSWAN_2_2_2, "strongSwan 2.2.2")
- DEC_MD5_VID(STRONGSWAN_2_2_1, "strongSwan 2.2.1")
- DEC_MD5_VID(STRONGSWAN_2_2_0, "strongSwan 2.2.0")
-
- /* NAT-Traversal */
-
- DEC_MD5_VID(NATT_STENBERG_01, "draft-stenberg-ipsec-nat-traversal-01")
- DEC_MD5_VID(NATT_STENBERG_02, "draft-stenberg-ipsec-nat-traversal-02")
- DEC_MD5_VID(NATT_HUTTUNEN, "ESPThruNAT")
- DEC_MD5_VID(NATT_HUTTUNEN_ESPINUDP, "draft-huttunen-ipsec-esp-in-udp-00.txt")
- DEC_MD5_VID(NATT_IETF_00, "draft-ietf-ipsec-nat-t-ike-00")
- DEC_MD5_VID(NATT_IETF_02, "draft-ietf-ipsec-nat-t-ike-02")
- /* hash in draft-ietf-ipsec-nat-t-ike-02 contains '\n'... Accept both */
- DEC_MD5_VID_D(NATT_IETF_02_N, "draft-ietf-ipsec-nat-t-ike-02\n", "draft-ietf-ipsec-nat-t-ike-02_n")
- DEC_MD5_VID(NATT_IETF_03, "draft-ietf-ipsec-nat-t-ike-03")
- DEC_MD5_VID(NATT_RFC, "RFC 3947")
-
- /* misc */
-
- { VID_MISC_XAUTH, VID_KEEP, NULL, "XAUTH",
- "\x09\x00\x26\x89\xdf\xd6\xb7\x12", 8 },
-
- { VID_MISC_DPD, VID_KEEP, NULL, "Dead Peer Detection",
- "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00", 16 },
-
- DEC_MD5_VID(MISC_FRAGMENTATION, "FRAGMENTATION")
-
- DEC_MD5_VID(INITIAL_CONTACT, "Vid-Initial-Contact")
-
- /**
- * Cisco VPN 3000
- */
- { VID_MISC_FRAGMENTATION, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
- "FRAGMENTATION", NULL, NULL, 0 },
-
- /* -- */
- { 0, 0, NULL, NULL, NULL, 0 }
+ /* Implementation names */
+
+ { VID_OPENPGP, VID_STRING, "OpenPGP10171", "OpenPGP", { NULL, 0 } },
+
+ DEC_MD5_VID(KAME_RACOON, "KAME/racoon")
+
+ { VID_MS_NT5, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
+ "MS NT5 ISAKMPOAKLEY", NULL, { NULL, 0 } },
+
+ DEC_MD5_VID(SSH_SENTINEL, "SSH Sentinel")
+ DEC_MD5_VID(SSH_SENTINEL_1_1, "SSH Sentinel 1.1")
+ DEC_MD5_VID(SSH_SENTINEL_1_2, "SSH Sentinel 1.2")
+ DEC_MD5_VID(SSH_SENTINEL_1_3, "SSH Sentinel 1.3")
+ DEC_MD5_VID(SSH_SENTINEL_1_4, "SSH Sentinel 1.4")
+ DEC_MD5_VID(SSH_SENTINEL_1_4_1, "SSH Sentinel 1.4.1")
+
+ /* These ones come from SSH vendors.txt */
+ DEC_MD5_VID(SSH_IPSEC_1_1_0,
+ "Ssh Communications Security IPSEC Express version 1.1.0")
+ DEC_MD5_VID(SSH_IPSEC_1_1_1,
+ "Ssh Communications Security IPSEC Express version 1.1.1")
+ DEC_MD5_VID(SSH_IPSEC_1_1_2,
+ "Ssh Communications Security IPSEC Express version 1.1.2")
+ DEC_MD5_VID(SSH_IPSEC_1_2_1,
+ "Ssh Communications Security IPSEC Express version 1.2.1")
+ DEC_MD5_VID(SSH_IPSEC_1_2_2,
+ "Ssh Communications Security IPSEC Express version 1.2.2")
+ DEC_MD5_VID(SSH_IPSEC_2_0_0,
+ "SSH Communications Security IPSEC Express version 2.0.0")
+ DEC_MD5_VID(SSH_IPSEC_2_1_0,
+ "SSH Communications Security IPSEC Express version 2.1.0")
+ DEC_MD5_VID(SSH_IPSEC_2_1_1,
+ "SSH Communications Security IPSEC Express version 2.1.1")
+ DEC_MD5_VID(SSH_IPSEC_2_1_2,
+ "SSH Communications Security IPSEC Express version 2.1.2")
+ DEC_MD5_VID(SSH_IPSEC_3_0_0,
+ "SSH Communications Security IPSEC Express version 3.0.0")
+ DEC_MD5_VID(SSH_IPSEC_3_0_1,
+ "SSH Communications Security IPSEC Express version 3.0.1")
+ DEC_MD5_VID(SSH_IPSEC_4_0_0,
+ "SSH Communications Security IPSEC Express version 4.0.0")
+ DEC_MD5_VID(SSH_IPSEC_4_0_1,
+ "SSH Communications Security IPSEC Express version 4.0.1")
+ DEC_MD5_VID(SSH_IPSEC_4_1_0,
+ "SSH Communications Security IPSEC Express version 4.1.0")
+ DEC_MD5_VID(SSH_IPSEC_4_2_0,
+ "SSH Communications Security IPSEC Express version 4.2.0")
+
+ /* note: md5('CISCO-UNITY') = 12f5f28c457168a9702d9fe274cc02d4 */
+ { VID_CISCO_UNITY, VID_KEEP, NULL, "Cisco-Unity",
+ { "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00", 16 } },
+
+ { VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "Cisco VPN 3000 Series" ,
+ { "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14 } },
+
+ { VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH,
+ NULL, "Cisco IOS Device", { "\x3e\x98\x40\x48", 4 } },
+
+ /*
+ * Timestep VID seen:
+ * - 54494d455354455020312053475720313532302033313520322e303145303133
+ * = 'TIMESTEP 1 SGW 1520 315 2.01E013'
+ */
+ { VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP",
+ NULL, { NULL, 0 } },
+
+ /*
+ * Netscreen:
+ * 4865617274426561745f4e6f74696679386b0100 (HeartBeat_Notify + 386b0100)
+ */
+ { VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA,
+ "HeartBeat_Notify", "HeartBeat Notify", { NULL, 0 } },
+ /*
+ * MacOS X
+ */
+ { VID_MACOSX, VID_STRING|VID_SUBSTRING_DUMPHEXA, "Mac OSX 10.x",
+ "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62", { NULL, 0 } },
+
+ /* NCP */
+ { VID_NCP_SERVER, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Server",
+ { "\xc6\xf5\x7a\xc3\x98\xf4\x93\x20\x81\x45\xb7\x58", 12 } },
+ { VID_NCP_CLIENT, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Client",
+ { "\xeb\x4c\x1b\x78\x8a\xfd\x4a\x9c\xb7\x73\x0a\x68", 12 } },
+
+ /*
+ * Windows Vista (and Windows Server 2008?)
+ */
+ DEC_MD5_VID(VISTA_AUTHIP, "MS-Negotiation Discovery Capable")
+ DEC_MD5_VID(VISTA_AUTHIP2, "IKE CGA version 1")
+ DEC_MD5_VID(VISTA_AUTHIP3, "MS-MamieExists")
+
+ /*
+ * strongSwan
+ */
+ DEC_MD5_VID(STRONGSWAN, "strongSwan 4.3.2")
+ DEC_MD5_VID(STRONGSWAN_4_3_1, "strongSwan 4.3.1")
+ DEC_MD5_VID(STRONGSWAN_4_3_0, "strongSwan 4.3.0")
+ DEC_MD5_VID(STRONGSWAN_4_2_15,"strongSwan 4.2.15")
+ DEC_MD5_VID(STRONGSWAN_4_2_14,"strongSwan 4.2.14")
+ DEC_MD5_VID(STRONGSWAN_4_2_13,"strongSwan 4.2.13")
+ DEC_MD5_VID(STRONGSWAN_4_2_12,"strongSwan 4.2.12")
+ DEC_MD5_VID(STRONGSWAN_4_2_11,"strongSwan 4.2.11")
+ DEC_MD5_VID(STRONGSWAN_4_2_10,"strongSwan 4.2.10")
+ DEC_MD5_VID(STRONGSWAN_4_2_9, "strongSwan 4.2.9")
+ DEC_MD5_VID(STRONGSWAN_4_2_8, "strongSwan 4.2.8")
+ DEC_MD5_VID(STRONGSWAN_4_2_7, "strongSwan 4.2.7")
+ DEC_MD5_VID(STRONGSWAN_4_2_6, "strongSwan 4.2.6")
+ DEC_MD5_VID(STRONGSWAN_4_2_5, "strongSwan 4.2.5")
+ DEC_MD5_VID(STRONGSWAN_4_2_4, "strongSwan 4.2.4")
+ DEC_MD5_VID(STRONGSWAN_4_2_3, "strongSwan 4.2.3")
+ DEC_MD5_VID(STRONGSWAN_4_2_2, "strongSwan 4.2.2")
+ DEC_MD5_VID(STRONGSWAN_4_2_1, "strongSwan 4.2.1")
+ DEC_MD5_VID(STRONGSWAN_4_2_0, "strongSwan 4.2.0")
+ DEC_MD5_VID(STRONGSWAN_4_1_11,"strongSwan 4.1.11")
+ DEC_MD5_VID(STRONGSWAN_4_1_10,"strongSwan 4.1.10")
+ DEC_MD5_VID(STRONGSWAN_4_1_9, "strongSwan 4.1.9")
+ DEC_MD5_VID(STRONGSWAN_4_1_8, "strongSwan 4.1.8")
+ DEC_MD5_VID(STRONGSWAN_4_1_7, "strongSwan 4.1.7")
+ DEC_MD5_VID(STRONGSWAN_4_1_6, "strongSwan 4.1.6")
+ DEC_MD5_VID(STRONGSWAN_4_1_5, "strongSwan 4.1.5")
+ DEC_MD5_VID(STRONGSWAN_4_1_4, "strongSwan 4.1.4")
+ DEC_MD5_VID(STRONGSWAN_4_1_3, "strongSwan 4.1.3")
+ DEC_MD5_VID(STRONGSWAN_4_1_2, "strongSwan 4.1.2")
+ DEC_MD5_VID(STRONGSWAN_4_1_1, "strongSwan 4.1.1")
+ DEC_MD5_VID(STRONGSWAN_4_1_0, "strongSwan 4.1.0")
+ DEC_MD5_VID(STRONGSWAN_4_0_7, "strongSwan 4.0.7")
+ DEC_MD5_VID(STRONGSWAN_4_0_6, "strongSwan 4.0.6")
+ DEC_MD5_VID(STRONGSWAN_4_0_5, "strongSwan 4.0.5")
+ DEC_MD5_VID(STRONGSWAN_4_0_4, "strongSwan 4.0.4")
+ DEC_MD5_VID(STRONGSWAN_4_0_3, "strongSwan 4.0.3")
+ DEC_MD5_VID(STRONGSWAN_4_0_2, "strongSwan 4.0.2")
+ DEC_MD5_VID(STRONGSWAN_4_0_1, "strongSwan 4.0.1")
+ DEC_MD5_VID(STRONGSWAN_4_0_0, "strongSwan 4.0.0")
+
+ DEC_MD5_VID(STRONGSWAN_2_8_9, "strongSwan 2.8.9")
+ DEC_MD5_VID(STRONGSWAN_2_8_8, "strongSwan 2.8.8")
+ DEC_MD5_VID(STRONGSWAN_2_8_7, "strongSwan 2.8.7")
+ DEC_MD5_VID(STRONGSWAN_2_8_6, "strongSwan 2.8.6")
+ DEC_MD5_VID(STRONGSWAN_2_8_5, "strongSwan 2.8.5")
+ DEC_MD5_VID(STRONGSWAN_2_8_4, "strongSwan 2.8.4")
+ DEC_MD5_VID(STRONGSWAN_2_8_3, "strongSwan 2.8.3")
+ DEC_MD5_VID(STRONGSWAN_2_8_2, "strongSwan 2.8.2")
+ DEC_MD5_VID(STRONGSWAN_2_8_1, "strongSwan 2.8.1")
+ DEC_MD5_VID(STRONGSWAN_2_8_0, "strongSwan 2.8.0")
+ DEC_MD5_VID(STRONGSWAN_2_7_3, "strongSwan 2.7.3")
+ DEC_MD5_VID(STRONGSWAN_2_7_2, "strongSwan 2.7.2")
+ DEC_MD5_VID(STRONGSWAN_2_7_1, "strongSwan 2.7.1")
+ DEC_MD5_VID(STRONGSWAN_2_7_0, "strongSwan 2.7.0")
+ DEC_MD5_VID(STRONGSWAN_2_6_4, "strongSwan 2.6.4")
+ DEC_MD5_VID(STRONGSWAN_2_6_3, "strongSwan 2.6.3")
+ DEC_MD5_VID(STRONGSWAN_2_6_2, "strongSwan 2.6.2")
+ DEC_MD5_VID(STRONGSWAN_2_6_1, "strongSwan 2.6.1")
+ DEC_MD5_VID(STRONGSWAN_2_6_0, "strongSwan 2.6.0")
+ DEC_MD5_VID(STRONGSWAN_2_5_7, "strongSwan 2.5.7")
+ DEC_MD5_VID(STRONGSWAN_2_5_6, "strongSwan 2.5.6")
+ DEC_MD5_VID(STRONGSWAN_2_5_5, "strongSwan 2.5.5")
+ DEC_MD5_VID(STRONGSWAN_2_5_4, "strongSwan 2.5.4")
+ DEC_MD5_VID(STRONGSWAN_2_5_3, "strongSwan 2.5.3")
+ DEC_MD5_VID(STRONGSWAN_2_5_2, "strongSwan 2.5.2")
+ DEC_MD5_VID(STRONGSWAN_2_5_1, "strongSwan 2.5.1")
+ DEC_MD5_VID(STRONGSWAN_2_5_0, "strongSwan 2.5.0")
+ DEC_MD5_VID(STRONGSWAN_2_4_4, "strongSwan 2.4.4")
+ DEC_MD5_VID(STRONGSWAN_2_4_3, "strongSwan 2.4.3")
+ DEC_MD5_VID(STRONGSWAN_2_4_2, "strongSwan 2.4.2")
+ DEC_MD5_VID(STRONGSWAN_2_4_1, "strongSwan 2.4.1")
+ DEC_MD5_VID(STRONGSWAN_2_4_0, "strongSwan 2.4.0")
+ DEC_MD5_VID(STRONGSWAN_2_3_2, "strongSwan 2.3.2")
+ DEC_MD5_VID(STRONGSWAN_2_3_1, "strongSwan 2.3.1")
+ DEC_MD5_VID(STRONGSWAN_2_3_0, "strongSwan 2.3.0")
+ DEC_MD5_VID(STRONGSWAN_2_2_2, "strongSwan 2.2.2")
+ DEC_MD5_VID(STRONGSWAN_2_2_1, "strongSwan 2.2.1")
+ DEC_MD5_VID(STRONGSWAN_2_2_0, "strongSwan 2.2.0")
+
+ /* NAT-Traversal */
+
+ DEC_MD5_VID(NATT_STENBERG_01, "draft-stenberg-ipsec-nat-traversal-01")
+ DEC_MD5_VID(NATT_STENBERG_02, "draft-stenberg-ipsec-nat-traversal-02")
+ DEC_MD5_VID(NATT_HUTTUNEN, "ESPThruNAT")
+ DEC_MD5_VID(NATT_HUTTUNEN_ESPINUDP, "draft-huttunen-ipsec-esp-in-udp-00.txt")
+ DEC_MD5_VID(NATT_IETF_00, "draft-ietf-ipsec-nat-t-ike-00")
+ DEC_MD5_VID(NATT_IETF_02, "draft-ietf-ipsec-nat-t-ike-02")
+ /* hash in draft-ietf-ipsec-nat-t-ike-02 contains '\n'... Accept both */
+ DEC_MD5_VID_D(NATT_IETF_02_N, "draft-ietf-ipsec-nat-t-ike-02\n", "draft-ietf-ipsec-nat-t-ike-02_n")
+ DEC_MD5_VID(NATT_IETF_03, "draft-ietf-ipsec-nat-t-ike-03")
+ DEC_MD5_VID(NATT_RFC, "RFC 3947")
+
+ /* misc */
+
+ { VID_MISC_XAUTH, VID_KEEP, NULL, "XAUTH",
+ { "\x09\x00\x26\x89\xdf\xd6\xb7\x12", 8 } },
+
+ { VID_MISC_DPD, VID_KEEP, NULL, "Dead Peer Detection",
+ { "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00", 16 } },
+
+ DEC_MD5_VID(MISC_FRAGMENTATION, "FRAGMENTATION")
+
+ DEC_MD5_VID(INITIAL_CONTACT, "Vid-Initial-Contact")
+
+ /**
+ * Cisco VPN 3000
+ */
+ { VID_MISC_FRAGMENTATION, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
+ "FRAGMENTATION", NULL, { NULL, 0 } },
+
+ /* -- */
+ { 0, 0, NULL, NULL, { NULL, 0 } }
};
@@ -321,239 +316,211 @@ static const char _hexdig[] = "0123456789abcdef";
static int _vid_struct_init = 0;
-void
-init_vendorid(void)
+void init_vendorid(void)
{
- struct vid_struct *vid;
- MD5_CTX ctx;
- int i;
+ hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ struct vid_struct *vid;
- for (vid = _vid_tab; vid->id; vid++)
- {
- if (vid->flags & VID_STRING)
- {
- /** VendorID is a string **/
- vid->vid = strdup(vid->data);
- vid->vid_len = strlen(vid->data);
- }
- else if (vid->flags & VID_MD5HASH)
+ for (vid = _vid_tab; vid->id; vid++)
{
- /** VendorID is a string to hash with MD5 **/
- char *vidm = malloc(MD5_DIGEST_SIZE);
-
- vid->vid = vidm;
- if (vidm)
- {
- MD5Init(&ctx);
- MD5Update(&ctx, (const u_char *)vid->data, strlen(vid->data));
- MD5Final(vidm, &ctx);
- vid->vid_len = MD5_DIGEST_SIZE;
- }
- }
- else if (vid->flags & VID_FSWAN_HASH)
- {
- /** FreeS/WAN 2.00+ specific hash **/
-#define FSWAN_VID_SIZE 12
- unsigned char hash[MD5_DIGEST_SIZE];
- char *vidm = malloc(FSWAN_VID_SIZE);
-
- vid->vid = vidm;
- if (vidm)
- {
- MD5Init(&ctx);
- MD5Update(&ctx, (const u_char *)vid->data, strlen(vid->data));
- MD5Final(hash, &ctx);
- vidm[0] = 'O';
- vidm[1] = 'E';
-#if FSWAN_VID_SIZE - 2 <= MD5_DIGEST_SIZE
- memcpy(vidm + 2, hash, FSWAN_VID_SIZE - 2);
-#else
- memcpy(vidm + 2, hash, MD5_DIGEST_SIZE);
- memset(vidm + 2 + MD5_DIGEST_SIZE, '\0',
- FSWAN_VID_SIZE - 2 - MD5_DIGEST_SIZE);
-#endif
- for (i = 2; i < FSWAN_VID_SIZE; i++)
+ if (vid->flags & VID_STRING)
+ {
+ /** VendorID is a string **/
+ vid->vid = chunk_create((u_char *)vid->data, strlen(vid->data));
+ vid->vid = chunk_clone(vid->vid);
+ }
+ else if (vid->flags & VID_MD5HASH)
+ {
+ chunk_t vid_data = { (u_char *)vid->data, strlen(vid->data) };
+
+ /** VendorID is a string to hash with MD5 **/
+ hasher->allocate_hash(hasher, vid_data, &vid->vid);
+ }
+
+ if (vid->descr == NULL)
{
- vidm[i] &= 0x7f;
- vidm[i] |= 0x40;
+ /** Find something to display **/
+ vid->descr = vid->data;
}
- vid->vid_len = FSWAN_VID_SIZE;
- }
}
+ hasher->destroy(hasher);
+ _vid_struct_init = 1;
+}
+
+void free_vendorid(void)
+{
+ struct vid_struct *vid;
- if (vid->descr == NULL)
+ for (vid = _vid_tab; vid->id; vid++)
{
- /** Find something to display **/
- vid->descr = vid->data;
+ if (vid->flags & (VID_STRING | VID_MD5HASH | VID_FSWAN_HASH))
+ {
+ free(vid->vid.ptr);
+ }
}
- }
- _vid_struct_init = 1;
}
-static void
-handle_known_vendorid (struct msg_digest *md
-, const char *vidstr, size_t len, struct vid_struct *vid)
+static void handle_known_vendorid (struct msg_digest *md, const char *vidstr,
+ size_t len, struct vid_struct *vid)
{
- char vid_dump[128];
- bool vid_useful = FALSE;
- size_t i, j;
-
- switch (vid->id) {
- /* Remote side supports OpenPGP certificates */
- case VID_OPENPGP:
- md->openpgp = TRUE;
- vid_useful = TRUE;
- break;
-
- /*
- * Use most recent supported NAT-Traversal method and ignore the
- * other ones (implementations will send all supported methods but
- * only one will be used)
- *
- * Note: most recent == higher id in vendor.h
- */
- case VID_NATT_IETF_00:
- if (!nat_traversal_support_non_ike)
- break;
- if ((nat_traversal_enabled) && (!md->nat_traversal_vid))
- {
- md->nat_traversal_vid = vid->id;
- vid_useful = TRUE;
+ char vid_dump[128];
+ bool vid_useful = FALSE;
+ size_t i, j;
+
+ switch (vid->id) {
+ /* Remote side supports OpenPGP certificates */
+ case VID_OPENPGP:
+ md->openpgp = TRUE;
+ vid_useful = TRUE;
+ break;
+
+ /*
+ * Use most recent supported NAT-Traversal method and ignore the
+ * other ones (implementations will send all supported methods but
+ * only one will be used)
+ *
+ * Note: most recent == higher id in vendor.h
+ */
+ case VID_NATT_IETF_00:
+ if (!nat_traversal_support_non_ike)
+ break;
+ if ((nat_traversal_enabled) && (!md->nat_traversal_vid))
+ {
+ md->nat_traversal_vid = vid->id;
+ vid_useful = TRUE;
+ }
+ break;
+ case VID_NATT_IETF_02:
+ case VID_NATT_IETF_02_N:
+ case VID_NATT_IETF_03:
+ case VID_NATT_RFC:
+ if (nat_traversal_support_port_floating
+ && md->nat_traversal_vid < vid->id)
+ {
+ md->nat_traversal_vid = vid->id;
+ vid_useful = TRUE;
+ }
+ break;
+
+ /* Remote side would like to do DPD with us on this connection */
+ case VID_MISC_DPD:
+ md->dpd = TRUE;
+ vid_useful = TRUE;
+ break;
+ case VID_MISC_XAUTH:
+ vid_useful = TRUE;
+ break;
+ default:
+ break;
}
- break;
- case VID_NATT_IETF_02:
- case VID_NATT_IETF_02_N:
- case VID_NATT_IETF_03:
- case VID_NATT_RFC:
- if (nat_traversal_support_port_floating
- && md->nat_traversal_vid < vid->id)
+
+ if (vid->flags & VID_SUBSTRING_DUMPHEXA)
{
- md->nat_traversal_vid = vid->id;
- vid_useful = TRUE;
+ /* Dump description + Hexa */
+ memset(vid_dump, 0, sizeof(vid_dump));
+ snprintf(vid_dump, sizeof(vid_dump), "%s ",
+ vid->descr ? vid->descr : "");
+ for (i = strlen(vid_dump), j = vid->vid.len;
+ j < len && i < sizeof(vid_dump) - 2;
+ i += 2, j++)
+ {
+ vid_dump[i] = _hexdig[(vidstr[j] >> 4) & 0xF];
+ vid_dump[i+1] = _hexdig[vidstr[j] & 0xF];
+ }
}
- break;
-
- /* Remote side would like to do DPD with us on this connection */
- case VID_MISC_DPD:
- md->dpd = TRUE;
- vid_useful = TRUE;
- break;
- case VID_MISC_XAUTH:
- vid_useful = TRUE;
- break;
- default:
- break;
- }
-
- if (vid->flags & VID_SUBSTRING_DUMPHEXA)
- {
- /* Dump description + Hexa */
- memset(vid_dump, 0, sizeof(vid_dump));
- snprintf(vid_dump, sizeof(vid_dump), "%s ",
- vid->descr ? vid->descr : "");
- for (i = strlen(vid_dump), j = vid->vid_len;
- j < len && i < sizeof(vid_dump) - 2;
- i += 2, j++)
+ else if (vid->flags & VID_SUBSTRING_DUMPASCII)
{
- vid_dump[i] = _hexdig[(vidstr[j] >> 4) & 0xF];
- vid_dump[i+1] = _hexdig[vidstr[j] & 0xF];
+ /* Dump ASCII content */
+ memset(vid_dump, 0, sizeof(vid_dump));
+ for (i = 0; i < len && i < sizeof(vid_dump) - 1; i++)
+ {
+ vid_dump[i] = (isprint(vidstr[i])) ? vidstr[i] : '.';
+ }
}
- }
- else if (vid->flags & VID_SUBSTRING_DUMPASCII)
- {
- /* Dump ASCII content */
- memset(vid_dump, 0, sizeof(vid_dump));
- for (i = 0; i < len && i < sizeof(vid_dump) - 1; i++)
+ else
{
- vid_dump[i] = (isprint(vidstr[i])) ? vidstr[i] : '.';
+ /* Dump description (descr) */
+ snprintf(vid_dump, sizeof(vid_dump), "%s",
+ vid->descr ? vid->descr : "");
}
- }
- else
- {
- /* Dump description (descr) */
- snprintf(vid_dump, sizeof(vid_dump), "%s",
- vid->descr ? vid->descr : "");
- }
-
- loglog(RC_LOG_SERIOUS, "%s Vendor ID payload [%s]",
- vid_useful ? "received" : "ignoring", vid_dump);
+
+ loglog(RC_LOG_SERIOUS, "%s Vendor ID payload [%s]",
+ vid_useful ? "received" : "ignoring", vid_dump);
}
-void
-handle_vendorid (struct msg_digest *md, const char *vid, size_t len)
+void handle_vendorid (struct msg_digest *md, const char *vid, size_t len)
{
- struct vid_struct *pvid;
+ struct vid_struct *pvid;
- if (!_vid_struct_init)
- init_vendorid();
+ if (!_vid_struct_init)
+ init_vendorid();
- /*
- * Find known VendorID in _vid_tab
- */
- for (pvid = _vid_tab; pvid->id; pvid++)
- {
- if (pvid->vid && vid && pvid->vid_len && len)
+ /*
+ * Find known VendorID in _vid_tab
+ */
+ for (pvid = _vid_tab; pvid->id; pvid++)
{
- if (pvid->vid_len == len)
- {
- if (memcmp(pvid->vid, vid, len) == 0)
+ if (pvid->vid.ptr && vid && pvid->vid.len && len)
{
- handle_known_vendorid(md, vid, len, pvid);
- return;
+ if (pvid->vid.len == len)
+ {
+ if (memeq(pvid->vid.ptr, vid, len))
+ {
+ handle_known_vendorid(md, vid, len, pvid);
+ return;
+ }
+ }
+ else if ((pvid->vid.len < len) && (pvid->flags & VID_SUBSTRING))
+ {
+ if (memeq(pvid->vid.ptr, vid, pvid->vid.len))
+ {
+ handle_known_vendorid(md, vid, len, pvid);
+ return;
+ }
+ }
}
- }
- else if ((pvid->vid_len < len) && (pvid->flags & VID_SUBSTRING))
- {
- if (memcmp(pvid->vid, vid, pvid->vid_len) == 0)
- {
- handle_known_vendorid(md, vid, len, pvid);
- return;
- }
- }
}
- }
- /*
- * Unknown VendorID. Log the beginning.
- */
- {
- char log_vid[2*MAX_LOG_VID_LEN+1];
- size_t i;
+ /*
+ * Unknown VendorID. Log the beginning.
+ */
+ {
+ char log_vid[2*MAX_LOG_VID_LEN+1];
+ size_t i;
- memset(log_vid, 0, sizeof(log_vid));
+ memset(log_vid, 0, sizeof(log_vid));
- for (i = 0; i < len && i < MAX_LOG_VID_LEN; i++)
- {
- log_vid[2*i] = _hexdig[(vid[i] >> 4) & 0xF];
- log_vid[2*i+1] = _hexdig[vid[i] & 0xF];
+ for (i = 0; i < len && i < MAX_LOG_VID_LEN; i++)
+ {
+ log_vid[2*i] = _hexdig[(vid[i] >> 4) & 0xF];
+ log_vid[2*i+1] = _hexdig[vid[i] & 0xF];
+ }
+ loglog(RC_LOG_SERIOUS, "ignoring Vendor ID payload [%s%s]",
+ log_vid, (len>MAX_LOG_VID_LEN) ? "..." : "");
}
- loglog(RC_LOG_SERIOUS, "ignoring Vendor ID payload [%s%s]",
- log_vid, (len>MAX_LOG_VID_LEN) ? "..." : "");
- }
}
/**
* Add a vendor id payload to the msg
*/
-bool
-out_vendorid (u_int8_t np, pb_stream *outs, enum known_vendorid vid)
+bool out_vendorid (u_int8_t np, pb_stream *outs, enum known_vendorid vid)
{
- struct vid_struct *pvid;
+ struct vid_struct *pvid;
- if (!_vid_struct_init)
- init_vendorid();
+ if (!_vid_struct_init)
+ init_vendorid();
- for (pvid = _vid_tab; pvid->id && pvid->id != vid; pvid++);
+ for (pvid = _vid_tab; pvid->id && pvid->id != vid; pvid++);
- if (pvid->id != vid)
- return STF_INTERNAL_ERROR; /* not found */
- if (!pvid->vid)
- return STF_INTERNAL_ERROR; /* not initialized */
+ if (pvid->id != vid)
+ return STF_INTERNAL_ERROR; /* not found */
+ if (!pvid->vid.ptr)
+ return STF_INTERNAL_ERROR; /* not initialized */
- DBG(DBG_EMITTING,
- DBG_log("out_vendorid(): sending [%s]", pvid->descr)
- )
- return out_generic_raw(np, &isakmp_vendor_id_desc, outs,
- pvid->vid, pvid->vid_len, "V_ID");
+ DBG(DBG_EMITTING,
+ DBG_log("out_vendorid(): sending [%s]", pvid->descr)
+ )
+ return out_generic_raw(np, &isakmp_vendor_id_desc, outs,
+ pvid->vid.ptr, pvid->vid.len, "V_ID");
}
diff --git a/src/pluto/vendor.h b/src/pluto/vendor.h
index 2c8c24b34..164c1aa6d 100644
--- a/src/pluto/vendor.h
+++ b/src/pluto/vendor.h
@@ -10,8 +10,6 @@
* 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: vendor.h 5052 2009-03-30 03:47:14Z andreas $
*/
#ifndef _VENDOR_H_
@@ -19,140 +17,144 @@
enum known_vendorid {
/* 1 - 100 : Implementation names */
- VID_OPENPGP = 1,
- VID_KAME_RACOON = 2,
- VID_MS_NT5 = 3,
- VID_SSH_SENTINEL = 4,
- VID_SSH_SENTINEL_1_1 = 5,
- VID_SSH_SENTINEL_1_2 = 6,
- VID_SSH_SENTINEL_1_3 = 7,
- VID_SSH_SENTINEL_1_4 = 8,
- VID_SSH_SENTINEL_1_4_1 = 9,
- VID_SSH_IPSEC_1_1_0 = 10,
- VID_SSH_IPSEC_1_1_1 = 11,
- VID_SSH_IPSEC_1_1_2 = 12,
- VID_SSH_IPSEC_1_2_1 = 13,
- VID_SSH_IPSEC_1_2_2 = 14,
- VID_SSH_IPSEC_2_0_0 = 15,
- VID_SSH_IPSEC_2_1_0 = 16,
- VID_SSH_IPSEC_2_1_1 = 17,
- VID_SSH_IPSEC_2_1_2 = 18,
- VID_SSH_IPSEC_3_0_0 = 19,
- VID_SSH_IPSEC_3_0_1 = 20,
- VID_SSH_IPSEC_4_0_0 = 21,
- VID_SSH_IPSEC_4_0_1 = 22,
- VID_SSH_IPSEC_4_1_0 = 23,
- VID_SSH_IPSEC_4_2_0 = 24,
- VID_CISCO_UNITY = 25,
- VID_CISCO3K = 26,
- VID_CISCO_IOS = 27,
- VID_TIMESTEP = 28,
- VID_SAFENET = 29,
- VID_MACOSX = 30,
- VID_OPENSWAN2 = 31,
- VID_NCP_SERVER = 32,
- VID_NCP_CLIENT = 33,
- VID_VISTA_AUTHIP = 34,
- VID_VISTA_AUTHIP2 = 35,
- VID_VISTA_AUTHIP3 = 36,
+ VID_OPENPGP = 1,
+ VID_KAME_RACOON = 2,
+ VID_MS_NT5 = 3,
+ VID_SSH_SENTINEL = 4,
+ VID_SSH_SENTINEL_1_1 = 5,
+ VID_SSH_SENTINEL_1_2 = 6,
+ VID_SSH_SENTINEL_1_3 = 7,
+ VID_SSH_SENTINEL_1_4 = 8,
+ VID_SSH_SENTINEL_1_4_1 = 9,
+ VID_SSH_IPSEC_1_1_0 = 10,
+ VID_SSH_IPSEC_1_1_1 = 11,
+ VID_SSH_IPSEC_1_1_2 = 12,
+ VID_SSH_IPSEC_1_2_1 = 13,
+ VID_SSH_IPSEC_1_2_2 = 14,
+ VID_SSH_IPSEC_2_0_0 = 15,
+ VID_SSH_IPSEC_2_1_0 = 16,
+ VID_SSH_IPSEC_2_1_1 = 17,
+ VID_SSH_IPSEC_2_1_2 = 18,
+ VID_SSH_IPSEC_3_0_0 = 19,
+ VID_SSH_IPSEC_3_0_1 = 20,
+ VID_SSH_IPSEC_4_0_0 = 21,
+ VID_SSH_IPSEC_4_0_1 = 22,
+ VID_SSH_IPSEC_4_1_0 = 23,
+ VID_SSH_IPSEC_4_2_0 = 24,
+ VID_CISCO_UNITY = 25,
+ VID_CISCO3K = 26,
+ VID_CISCO_IOS = 27,
+ VID_TIMESTEP = 28,
+ VID_SAFENET = 29,
+ VID_MACOSX = 30,
+ VID_NCP_SERVER = 31,
+ VID_NCP_CLIENT = 32,
+ VID_VISTA_AUTHIP = 33,
+ VID_VISTA_AUTHIP2 = 34,
+ VID_VISTA_AUTHIP3 = 35,
- VID_STRONGSWAN = 37,
- VID_STRONGSWAN_2_2_0 = 38,
- VID_STRONGSWAN_2_2_1 = 39,
- VID_STRONGSWAN_2_2_2 = 40,
- VID_STRONGSWAN_2_3_0 = 41,
- VID_STRONGSWAN_2_3_1 = 42,
- VID_STRONGSWAN_2_3_2 = 43,
- VID_STRONGSWAN_2_4_0 = 44,
- VID_STRONGSWAN_2_4_1 = 45,
- VID_STRONGSWAN_2_4_2 = 46,
- VID_STRONGSWAN_2_4_3 = 47,
- VID_STRONGSWAN_2_4_4 = 48,
- VID_STRONGSWAN_2_5_0 = 49,
- VID_STRONGSWAN_2_5_1 = 50,
- VID_STRONGSWAN_2_5_2 = 51,
- VID_STRONGSWAN_2_5_3 = 52,
- VID_STRONGSWAN_2_5_4 = 53,
- VID_STRONGSWAN_2_5_5 = 54,
- VID_STRONGSWAN_2_5_6 = 55,
- VID_STRONGSWAN_2_5_7 = 56,
- VID_STRONGSWAN_2_6_0 = 57,
- VID_STRONGSWAN_2_6_1 = 58,
- VID_STRONGSWAN_2_6_2 = 59,
- VID_STRONGSWAN_2_6_3 = 60,
- VID_STRONGSWAN_2_6_4 = 61,
- VID_STRONGSWAN_2_7_0 = 62,
- VID_STRONGSWAN_2_7_1 = 63,
- VID_STRONGSWAN_2_7_2 = 64,
- VID_STRONGSWAN_2_7_3 = 65,
- VID_STRONGSWAN_2_8_0 = 66,
- VID_STRONGSWAN_2_8_1 = 67,
- VID_STRONGSWAN_2_8_2 = 68,
- VID_STRONGSWAN_2_8_3 = 69,
- VID_STRONGSWAN_2_8_4 = 70,
- VID_STRONGSWAN_2_8_5 = 71,
- VID_STRONGSWAN_2_8_6 = 72,
- VID_STRONGSWAN_2_8_7 = 73,
- VID_STRONGSWAN_2_8_8 = 74,
- VID_STRONGSWAN_2_8_9 = 75,
+ VID_STRONGSWAN = 37,
+ VID_STRONGSWAN_2_2_0 = 38,
+ VID_STRONGSWAN_2_2_1 = 39,
+ VID_STRONGSWAN_2_2_2 = 40,
+ VID_STRONGSWAN_2_3_0 = 41,
+ VID_STRONGSWAN_2_3_1 = 42,
+ VID_STRONGSWAN_2_3_2 = 43,
+ VID_STRONGSWAN_2_4_0 = 44,
+ VID_STRONGSWAN_2_4_1 = 45,
+ VID_STRONGSWAN_2_4_2 = 46,
+ VID_STRONGSWAN_2_4_3 = 47,
+ VID_STRONGSWAN_2_4_4 = 48,
+ VID_STRONGSWAN_2_5_0 = 49,
+ VID_STRONGSWAN_2_5_1 = 50,
+ VID_STRONGSWAN_2_5_2 = 51,
+ VID_STRONGSWAN_2_5_3 = 52,
+ VID_STRONGSWAN_2_5_4 = 53,
+ VID_STRONGSWAN_2_5_5 = 54,
+ VID_STRONGSWAN_2_5_6 = 55,
+ VID_STRONGSWAN_2_5_7 = 56,
+ VID_STRONGSWAN_2_6_0 = 57,
+ VID_STRONGSWAN_2_6_1 = 58,
+ VID_STRONGSWAN_2_6_2 = 59,
+ VID_STRONGSWAN_2_6_3 = 60,
+ VID_STRONGSWAN_2_6_4 = 61,
+ VID_STRONGSWAN_2_7_0 = 62,
+ VID_STRONGSWAN_2_7_1 = 63,
+ VID_STRONGSWAN_2_7_2 = 64,
+ VID_STRONGSWAN_2_7_3 = 65,
+ VID_STRONGSWAN_2_8_0 = 66,
+ VID_STRONGSWAN_2_8_1 = 67,
+ VID_STRONGSWAN_2_8_2 = 68,
+ VID_STRONGSWAN_2_8_3 = 69,
+ VID_STRONGSWAN_2_8_4 = 70,
+ VID_STRONGSWAN_2_8_5 = 71,
+ VID_STRONGSWAN_2_8_6 = 72,
+ VID_STRONGSWAN_2_8_7 = 73,
+ VID_STRONGSWAN_2_8_8 = 74,
+ VID_STRONGSWAN_2_8_9 = 75,
- VID_STRONGSWAN_4_0_0 = 80,
- VID_STRONGSWAN_4_0_1 = 81,
- VID_STRONGSWAN_4_0_2 = 82,
- VID_STRONGSWAN_4_0_3 = 83,
- VID_STRONGSWAN_4_0_4 = 84,
- VID_STRONGSWAN_4_0_5 = 85,
- VID_STRONGSWAN_4_0_6 = 86,
- VID_STRONGSWAN_4_0_7 = 87,
- VID_STRONGSWAN_4_1_0 = 88,
- VID_STRONGSWAN_4_1_1 = 89,
- VID_STRONGSWAN_4_1_2 = 90,
- VID_STRONGSWAN_4_1_3 = 91,
- VID_STRONGSWAN_4_1_4 = 92,
- VID_STRONGSWAN_4_1_5 = 93,
- VID_STRONGSWAN_4_1_6 = 94,
- VID_STRONGSWAN_4_1_7 = 95,
- VID_STRONGSWAN_4_1_8 = 96,
- VID_STRONGSWAN_4_1_9 = 97,
- VID_STRONGSWAN_4_1_10 = 98,
- VID_STRONGSWAN_4_1_11 = 99,
+ VID_STRONGSWAN_4_0_0 = 80,
+ VID_STRONGSWAN_4_0_1 = 81,
+ VID_STRONGSWAN_4_0_2 = 82,
+ VID_STRONGSWAN_4_0_3 = 83,
+ VID_STRONGSWAN_4_0_4 = 84,
+ VID_STRONGSWAN_4_0_5 = 85,
+ VID_STRONGSWAN_4_0_6 = 86,
+ VID_STRONGSWAN_4_0_7 = 87,
+ VID_STRONGSWAN_4_1_0 = 88,
+ VID_STRONGSWAN_4_1_1 = 89,
+ VID_STRONGSWAN_4_1_2 = 90,
+ VID_STRONGSWAN_4_1_3 = 91,
+ VID_STRONGSWAN_4_1_4 = 92,
+ VID_STRONGSWAN_4_1_5 = 93,
+ VID_STRONGSWAN_4_1_6 = 94,
+ VID_STRONGSWAN_4_1_7 = 95,
+ VID_STRONGSWAN_4_1_8 = 96,
+ VID_STRONGSWAN_4_1_9 = 97,
+ VID_STRONGSWAN_4_1_10 = 98,
+ VID_STRONGSWAN_4_1_11 = 99,
- VID_STRONGSWAN_4_2_0 =100,
- VID_STRONGSWAN_4_2_1 =101,
- VID_STRONGSWAN_4_2_2 =102,
- VID_STRONGSWAN_4_2_3 =103,
- VID_STRONGSWAN_4_2_4 =104,
- VID_STRONGSWAN_4_2_5 =105,
- VID_STRONGSWAN_4_2_6 =106,
- VID_STRONGSWAN_4_2_7 =107,
- VID_STRONGSWAN_4_2_8 =108,
- VID_STRONGSWAN_4_2_9 =109,
- VID_STRONGSWAN_4_2_10 =110,
- VID_STRONGSWAN_4_2_11 =111,
- VID_STRONGSWAN_4_2_12 =112,
- VID_STRONGSWAN_4_2_13 =113,
+ VID_STRONGSWAN_4_2_0 =100,
+ VID_STRONGSWAN_4_2_1 =101,
+ VID_STRONGSWAN_4_2_2 =102,
+ VID_STRONGSWAN_4_2_3 =103,
+ VID_STRONGSWAN_4_2_4 =104,
+ VID_STRONGSWAN_4_2_5 =105,
+ VID_STRONGSWAN_4_2_6 =106,
+ VID_STRONGSWAN_4_2_7 =107,
+ VID_STRONGSWAN_4_2_8 =108,
+ VID_STRONGSWAN_4_2_9 =109,
+ VID_STRONGSWAN_4_2_10 =110,
+ VID_STRONGSWAN_4_2_11 =111,
+ VID_STRONGSWAN_4_2_12 =112,
+ VID_STRONGSWAN_4_2_13 =113,
+ VID_STRONGSWAN_4_2_14 =114,
+ VID_STRONGSWAN_4_2_15 =115,
+ VID_STRONGSWAN_4_3_0 =116,
+ VID_STRONGSWAN_4_3_1 =117,
/* 101 - 200 : NAT-Traversal */
- VID_NATT_STENBERG_01 =151,
- VID_NATT_STENBERG_02 =152,
- VID_NATT_HUTTUNEN =153,
- VID_NATT_HUTTUNEN_ESPINUDP =154,
- VID_NATT_IETF_00 =155,
- VID_NATT_IETF_02_N =156,
- VID_NATT_IETF_02 =157,
- VID_NATT_IETF_03 =158,
- VID_NATT_RFC =159,
+ VID_NATT_STENBERG_01 =151,
+ VID_NATT_STENBERG_02 =152,
+ VID_NATT_HUTTUNEN =153,
+ VID_NATT_HUTTUNEN_ESPINUDP =154,
+ VID_NATT_IETF_00 =155,
+ VID_NATT_IETF_02_N =156,
+ VID_NATT_IETF_02 =157,
+ VID_NATT_IETF_03 =158,
+ VID_NATT_RFC =159,
/* 201 - 300 : Misc */
- VID_MISC_XAUTH =201,
- VID_MISC_DPD =202,
- VID_MISC_HEARTBEAT_NOTIFY =203,
- VID_MISC_FRAGMENTATION =204,
- VID_INITIAL_CONTACT =205,
- VID_CISCO3K_FRAGMENTATION =206
+ VID_MISC_XAUTH =201,
+ VID_MISC_DPD =202,
+ VID_MISC_HEARTBEAT_NOTIFY =203,
+ VID_MISC_FRAGMENTATION =204,
+ VID_INITIAL_CONTACT =205,
+ VID_CISCO3K_FRAGMENTATION =206
};
void init_vendorid(void);
+void free_vendorid(void);
struct msg_digest;
void handle_vendorid (struct msg_digest *md, const char *vid, size_t len);
diff --git a/src/pluto/virtual.c b/src/pluto/virtual.c
index 4a81ee283..2067bde01 100644
--- a/src/pluto/virtual.c
+++ b/src/pluto/virtual.c
@@ -10,8 +10,6 @@
* 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: virtual.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <freeswan.h>
@@ -35,9 +33,9 @@
#define F_VIRTUAL_HOST 32
struct virtual_t {
- unsigned short flags;
- unsigned short n_net;
- ip_subnet net[0];
+ unsigned short flags;
+ unsigned short n_net;
+ ip_subnet net[0];
};
static ip_subnet *private_net_ok=NULL, *private_net_ko=NULL;
@@ -49,123 +47,119 @@ static unsigned short private_net_ok_len=0, private_net_ko_len=0;
*/
static bool
_read_subnet(const char *src, size_t len, ip_subnet *dst, ip_subnet *dstko,
- bool *isok)
+ bool *isok)
{
- bool ok;
- int af;
-
- if ((len > 4) && (strncmp(src, "%v4:", 4)==0))
- {
- af = AF_INET;
- }
- else if ((len > 4) && (strncmp(src, "%v6:", 4)==0))
- {
- af = AF_INET6;
- }
- else
- {
- return FALSE;
- }
+ bool ok;
+ int af;
+
+ if ((len > 4) && (strneq(src, "%v4:", 4)))
+ {
+ af = AF_INET;
+ }
+ else if ((len > 4) && (strneq(src, "%v6:", 4)))
+ {
+ af = AF_INET6;
+ }
+ else
+ {
+ return FALSE;
+ }
- ok = (src[4] != '!');
- src += ok ? 4 : 5;
- len -= ok ? 4 : 5;
+ ok = (src[4] != '!');
+ src += ok ? 4 : 5;
+ len -= ok ? 4 : 5;
- if (!len)
- return FALSE;
- if (!ok && !dstko)
- return FALSE;
+ if (!len)
+ return FALSE;
+ if (!ok && !dstko)
+ return FALSE;
- passert ( ((ok)?(dst):(dstko))!=NULL );
+ passert ( ((ok)?(dst):(dstko))!=NULL );
- if (ttosubnet(src, len, af, ((ok)?(dst):(dstko))))
- {
- return FALSE;
- }
- if (isok)
- *isok = ok;
- return TRUE;
+ if (ttosubnet(src, len, af, ((ok)?(dst):(dstko))))
+ {
+ return FALSE;
+ }
+ if (isok)
+ *isok = ok;
+ return TRUE;
}
void
init_virtual_ip(const char *private_list)
{
- const char *next, *str=private_list;
- unsigned short ign = 0, i_ok, i_ko;
- ip_subnet sub;
- bool ok;
-
- /** Count **/
- private_net_ok_len=0;
- private_net_ko_len=0;
-
- while (str)
- {
- next = strchr(str,',');
- if (!next)
- next = str + strlen(str);
- if (_read_subnet(str, next-str, &sub, &sub, &ok))
- if (ok)
- private_net_ok_len++;
- else
- private_net_ko_len++;
- else
- ign++;
- str = *next ? next+1 : NULL;
- }
-
- if (!ign)
- {
- /** Allocate **/
- if (private_net_ok_len)
- {
- private_net_ok = (ip_subnet *)alloc_bytes(
- (private_net_ok_len*sizeof(ip_subnet)),
- "private_net_ok subnets");
- }
- if (private_net_ko_len)
- {
- private_net_ko = (ip_subnet *)alloc_bytes(
- (private_net_ko_len*sizeof(ip_subnet)),
- "private_net_ko subnets");
- }
- if ((private_net_ok_len && !private_net_ok)
- || (private_net_ko_len && !private_net_ko))
- {
- loglog(RC_LOG_SERIOUS,
- "can't alloc in init_virtual_ip");
- pfreeany(private_net_ok);
- private_net_ok = NULL;
- pfreeany(private_net_ko);
- private_net_ko = NULL;
- }
- else
- {
- /** Fill **/
- str = private_list;
- i_ok = 0;
- i_ko = 0;
+ const char *next, *str=private_list;
+ unsigned short ign = 0, i_ok, i_ko;
+ ip_subnet sub;
+ bool ok;
- while (str)
- {
+ /** Count **/
+ private_net_ok_len=0;
+ private_net_ko_len=0;
+
+ while (str)
+ {
next = strchr(str,',');
if (!next)
- next = str + strlen(str);
- if (_read_subnet(str, next-str,
- &(private_net_ok[i_ok]), &(private_net_ko[i_ko]), &ok))
+ next = str + strlen(str);
+ if (_read_subnet(str, next-str, &sub, &sub, &ok))
+ if (ok)
+ private_net_ok_len++;
+ else
+ private_net_ko_len++;
+ else
+ ign++;
+ str = *next ? next+1 : NULL;
+ }
+
+ if (!ign)
+ {
+ /** Allocate **/
+ if (private_net_ok_len)
{
- if (ok)
- i_ok++;
- else
- i_ko++;
+ private_net_ok = (ip_subnet *)malloc(private_net_ok_len * sizeof(ip_subnet));
+ }
+ if (private_net_ko_len)
+ {
+ private_net_ko = (ip_subnet *)malloc(private_net_ko_len * sizeof(ip_subnet));
+ }
+ if ((private_net_ok_len && !private_net_ok)
+ || (private_net_ko_len && !private_net_ko))
+ {
+ loglog(RC_LOG_SERIOUS,
+ "can't alloc in init_virtual_ip");
+ free(private_net_ok);
+ private_net_ok = NULL;
+ free(private_net_ko);
+ private_net_ko = NULL;
+ }
+ else
+ {
+ /** Fill **/
+ str = private_list;
+ i_ok = 0;
+ i_ko = 0;
+
+ while (str)
+ {
+ next = strchr(str,',');
+ if (!next)
+ next = str + strlen(str);
+ if (_read_subnet(str, next-str,
+ &(private_net_ok[i_ok]), &(private_net_ko[i_ko]), &ok))
+ {
+ if (ok)
+ i_ok++;
+ else
+ i_ko++;
+ }
+ str = *next ? next+1 : NULL;
+ }
}
- str = *next ? next+1 : NULL;
- }
}
- }
- else
- loglog(RC_LOG_SERIOUS,
- "%d bad entries in virtual_private - none loaded", ign);
+ else
+ loglog(RC_LOG_SERIOUS,
+ "%d bad entries in virtual_private - none loaded", ign);
}
/**
@@ -188,147 +182,146 @@ init_virtual_ip(const char *private_list)
struct virtual_t
*create_virtual(const struct connection *c, const char *string)
{
- unsigned short flags=0, n_net=0, i;
- const char *str = string, *next, *first_net=NULL;
- ip_subnet sub;
- struct virtual_t *v;
+ unsigned short flags=0, n_net=0, i;
+ const char *str = string, *next, *first_net=NULL;
+ ip_subnet sub;
+ struct virtual_t *v;
- if (!string || string[0] == '\0')
- return NULL;
+ if (!string || string[0] == '\0')
+ return NULL;
- if (strlen(string) >= 6 && strncmp(string,"vhost:",6) == 0)
- {
- flags |= F_VIRTUAL_HOST;
- str += 6;
- }
- else if (strlen(string) >= 5 && strncmp(string,"vnet:",5) == 0)
- str += 5;
- else
- goto fail;
-
- /**
- * Parse string : fill flags & count subnets
- */
- while ((str) && (*str))
- {
- next = strchr(str,',');
- if (!next) next = str + strlen(str);
- if (next-str == 3 && strncmp(str, "%no", 3) == 0)
- flags |= F_VIRTUAL_NO;
-#if 0
- else if (next-str == 4 && strncmp(str, "%ike", 4) == 0)
- flags |= F_VIRTUAL_IKE_CONFIG;
- else if (next-str == 5 && strncmp(str, "%dhcp", 5) == 0)
- flags |= F_VIRTUAL_DHCP;
-#endif
- else if (next-str == 5 && strncmp(str, "%priv", 5) == 0)
- flags |= F_VIRTUAL_PRIVATE;
- else if (next-str == 4 && strncmp(str, "%all", 4) == 0)
- flags |= F_VIRTUAL_ALL;
- else if (_read_subnet(str, next-str, &sub, NULL, NULL))
+ if (strlen(string) >= 6 && strneq(string,"vhost:",6))
{
- n_net++;
- if (!first_net)
- first_net = str;
+ flags |= F_VIRTUAL_HOST;
+ str += 6;
}
+ else if (strlen(string) >= 5 && strneq(string,"vnet:",5))
+ str += 5;
else
- goto fail;
-
- str = *next ? next+1 : NULL;
- }
-
- v = (struct virtual_t *)alloc_bytes(
- sizeof(struct virtual_t) + (n_net*sizeof(ip_subnet)),
- "virtual description");
- if (!v) goto fail;
-
- v->flags = flags;
- v->n_net = n_net;
- if (n_net && first_net)
- {
+ goto fail;
+
/**
- * Save subnets in newly allocated struct
+ * Parse string : fill flags & count subnets
*/
- for (str = first_net, i = 0; str && *str; )
+ while ((str) && (*str))
{
- next = strchr(str,',');
- if (!next) next = str + strlen(str);
- if (_read_subnet(str, next-str, &(v->net[i]), NULL, NULL))
- i++;
- str = *next ? next+1 : NULL;
+ next = strchr(str,',');
+ if (!next) next = str + strlen(str);
+ if (next-str == 3 && strneq(str, "%no", 3))
+ flags |= F_VIRTUAL_NO;
+#if 0
+ else if (next-str == 4 && strneq(str, "%ike", 4))
+ flags |= F_VIRTUAL_IKE_CONFIG;
+ else if (next-str == 5 && strneq(str, "%dhcp", 5))
+ flags |= F_VIRTUAL_DHCP;
+#endif
+ else if (next-str == 5 && strneq(str, "%priv", 5))
+ flags |= F_VIRTUAL_PRIVATE;
+ else if (next-str == 4 && strneq(str, "%all", 4))
+ flags |= F_VIRTUAL_ALL;
+ else if (_read_subnet(str, next-str, &sub, NULL, NULL))
+ {
+ n_net++;
+ if (!first_net)
+ first_net = str;
+ }
+ else
+ goto fail;
+
+ str = *next ? next+1 : NULL;
}
- }
- return v;
+ v = (struct virtual_t *)malloc(sizeof(struct virtual_t) +
+ (n_net * sizeof(ip_subnet)));
+ if (!v) goto fail;
+
+ v->flags = flags;
+ v->n_net = n_net;
+ if (n_net && first_net)
+ {
+ /**
+ * Save subnets in newly allocated struct
+ */
+ for (str = first_net, i = 0; str && *str; )
+ {
+ next = strchr(str,',');
+ if (!next) next = str + strlen(str);
+ if (_read_subnet(str, next-str, &(v->net[i]), NULL, NULL))
+ i++;
+ str = *next ? next+1 : NULL;
+ }
+ }
+
+ return v;
fail:
- plog("invalid virtual string [%s] - "
- "virtual selection disabled for connection '%s'", string, c->name);
- return NULL;
+ plog("invalid virtual string [%s] - "
+ "virtual selection disabled for connection '%s'", string, c->name);
+ return NULL;
}
bool
is_virtual_end(const struct end *that)
{
- return ((that->virt)?TRUE:FALSE);
+ return ((that->virt)?TRUE:FALSE);
}
bool
is_virtual_connection(const struct connection *c)
{
- return ((c->spd.that.virt)?TRUE:FALSE);
+ return ((c->spd.that.virt)?TRUE:FALSE);
}
static bool
net_in_list(const ip_subnet *peer_net, const ip_subnet *list,
- unsigned short len)
+ unsigned short len)
{
- unsigned short i;
+ unsigned short i;
- if (!list || !len)
- return FALSE;
+ if (!list || !len)
+ return FALSE;
- for (i = 0; i < len; i++)
- {
- if (subnetinsubnet(peer_net, &(list[i])))
- return TRUE;
- }
- return FALSE;
+ for (i = 0; i < len; i++)
+ {
+ if (subnetinsubnet(peer_net, &(list[i])))
+ return TRUE;
+ }
+ return FALSE;
}
bool
is_virtual_net_allowed(const struct connection *c, const ip_subnet *peer_net,
- const ip_address *his_addr)
+ const ip_address *his_addr)
{
- if (c->spd.that.virt == NULL)
- return FALSE;
+ if (c->spd.that.virt == NULL)
+ return FALSE;
- if ((c->spd.that.virt->flags & F_VIRTUAL_HOST)
- && !subnetishost(peer_net))
- return FALSE;
+ if ((c->spd.that.virt->flags & F_VIRTUAL_HOST)
+ && !subnetishost(peer_net))
+ return FALSE;
- if ((c->spd.that.virt->flags & F_VIRTUAL_NO)
- && subnetishost(peer_net) && addrinsubnet(his_addr, peer_net))
- return TRUE;
+ if ((c->spd.that.virt->flags & F_VIRTUAL_NO)
+ && subnetishost(peer_net) && addrinsubnet(his_addr, peer_net))
+ return TRUE;
- if ((c->spd.that.virt->flags & F_VIRTUAL_PRIVATE)
- && net_in_list(peer_net, private_net_ok, private_net_ok_len)
- && !net_in_list(peer_net, private_net_ko, private_net_ko_len))
- return TRUE;
+ if ((c->spd.that.virt->flags & F_VIRTUAL_PRIVATE)
+ && net_in_list(peer_net, private_net_ok, private_net_ok_len)
+ && !net_in_list(peer_net, private_net_ko, private_net_ko_len))
+ return TRUE;
- if (c->spd.that.virt->n_net
- && net_in_list(peer_net, c->spd.that.virt->net, c->spd.that.virt->n_net))
- return TRUE;
-
- if (c->spd.that.virt->flags & F_VIRTUAL_ALL)
- {
- /** %all must only be used for testing - log it **/
- loglog(RC_LOG_SERIOUS, "Warning - "
- "v%s:%%all must only be used for testing",
- (c->spd.that.virt->flags & F_VIRTUAL_HOST) ? "host" : "net");
- return TRUE;
- }
+ if (c->spd.that.virt->n_net
+ && net_in_list(peer_net, c->spd.that.virt->net, c->spd.that.virt->n_net))
+ return TRUE;
+
+ if (c->spd.that.virt->flags & F_VIRTUAL_ALL)
+ {
+ /** %all must only be used for testing - log it **/
+ loglog(RC_LOG_SERIOUS, "Warning - "
+ "v%s:%%all must only be used for testing",
+ (c->spd.that.virt->flags & F_VIRTUAL_HOST) ? "host" : "net");
+ return TRUE;
+ }
- return FALSE;
+ return FALSE;
}
diff --git a/src/pluto/virtual.h b/src/pluto/virtual.h
index 9fe9bdd8d..e64407c81 100644
--- a/src/pluto/virtual.h
+++ b/src/pluto/virtual.h
@@ -10,8 +10,6 @@
* 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: virtual.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _VIRTUAL_IP_H
@@ -20,12 +18,12 @@
extern void init_virtual_ip(const char *private_list);
extern struct virtual_t *create_virtual(const struct connection *c,
- const char *string);
+ const char *string);
extern bool is_virtual_end(const struct end *that);
extern bool is_virtual_connection(const struct connection *c);
extern bool is_virtual_net_allowed(const struct connection *c,
- const ip_subnet *peer_net, const ip_address *his_addr);
+ const ip_subnet *peer_net, const ip_address *his_addr);
#endif /* _VIRTUAL_IP_H */
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
index c61de6edc..0953f18f5 100644
--- a/src/pluto/x509.c
+++ b/src/pluto/x509.c
@@ -2,7 +2,7 @@
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
* Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2000-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -13,8 +13,6 @@
* 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: x509.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdlib.h>
@@ -26,16 +24,16 @@
#include <sys/types.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
+#include <crypto/hashers/hasher.h>
#include "constants.h"
#include "defs.h"
-#include "mp_defs.h"
#include "log.h"
#include "id.h"
-#include "asn1.h"
-#include <asn1/oid.h>
-#include "pkcs1.h"
#include "x509.h"
#include "crl.h"
#include "ca.h"
@@ -44,298 +42,243 @@
#include "whack.h"
#include "fetch.h"
#include "ocsp.h"
-#include "sha1.h"
-
-/* chained lists of X.509 end certificates */
+/**
+ * Chained lists of X.509 end certificates
+ */
static x509cert_t *x509certs = NULL;
-/* ASN.1 definition of a basicConstraints extension */
-
+/**
+ * ASN.1 definition of a basicConstraints extension
+ */
static const asn1Object_t basicConstraintsObjects[] = {
- { 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "CA", ASN1_BOOLEAN, ASN1_DEF |
- ASN1_BODY }, /* 1 */
- { 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT |
- ASN1_BODY }, /* 2 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */
+ { 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "CA", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 1 */
+ { 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 2 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define BASIC_CONSTRAINTS_CA 1
-#define BASIC_CONSTRAINTS_ROOF 4
-
-/* ASN.1 definition of time */
-static const asn1Object_t timeObjects[] = {
- { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT |
- ASN1_BODY }, /* 0 */
- { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
- { 0, "generalizeTime", ASN1_GENERALIZEDTIME, ASN1_OPT |
- ASN1_BODY }, /* 2 */
- { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */
-};
-
-#define TIME_UTC 0
-#define TIME_GENERALIZED 2
-#define TIME_ROOF 4
-
-/* ASN.1 definition of a keyIdentifier */
-
-static const asn1Object_t keyIdentifierObjects[] = {
- { 0, "keyIdentifier", ASN1_OCTET_STRING, ASN1_BODY } /* 0 */
-};
-
-/* ASN.1 definition of a authorityKeyIdentifier extension */
-
-static const asn1Object_t authorityKeyIdentifierObjects[] = {
- { 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT |
- ASN1_OBJ }, /* 1 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
- { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT |
- ASN1_OBJ }, /* 3 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
- { 1, "authorityCertSerialNumber", ASN1_CONTEXT_S_2, ASN1_OPT |
- ASN1_BODY }, /* 5 */
- { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */
+/**
+ * ASN.1 definition of a authorityKeyIdentifier extension
+ */
+static const asn1Object_t authKeyIdentifierObjects[] = {
+ { 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT|ASN1_BODY }, /* 1 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
+ { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_OBJ }, /* 3 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
+ { 1, "authorityCertSerialNumber", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 5 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
-#define AUTH_KEY_ID_KEY_ID 1
+#define AUTH_KEY_ID_KEY_ID 1
#define AUTH_KEY_ID_CERT_ISSUER 3
#define AUTH_KEY_ID_CERT_SERIAL 5
-#define AUTH_KEY_ID_ROOF 7
-
-/* ASN.1 definition of a authorityInfoAccess extension */
-static const asn1Object_t authorityInfoAccessObjects[] = {
- { 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
- { 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
- { 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */
- { 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */
- { 0, "end loop", ASN1_EOC, ASN1_END } /* 4 */
+/**
+ * ASN.1 definition of a authorityInfoAccess extension
+ */
+static const asn1Object_t authInfoAccessObjects[] = {
+ { 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
+ { 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
+ { 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */
+ { 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define AUTH_INFO_ACCESS_METHOD 2
#define AUTH_INFO_ACCESS_LOCATION 3
-#define AUTH_INFO_ACCESS_ROOF 5
-
-/* ASN.1 definition of a extendedKeyUsage extension */
+/**
+ * ASN.1 definition of a extendedKeyUsage extension
+ */
static const asn1Object_t extendedKeyUsageObjects[] = {
- { 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
- { 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */
- { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
+ { 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
+ { 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define EXT_KEY_USAGE_PURPOSE_ID 1
-#define EXT_KEY_USAGE_ROOF 3
-
-/* ASN.1 definition of generalNames */
+/**
+ * ASN.1 definition of generalNames
+ */
static const asn1Object_t generalNamesObjects[] = {
- { 0, "generalNames", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
- { 1, "generalName", ASN1_EOC, ASN1_RAW }, /* 1 */
- { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */
+ { 0, "generalNames", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
+ { 1, "generalName", ASN1_EOC, ASN1_RAW }, /* 1 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define GENERAL_NAMES_GN 1
-#define GENERAL_NAMES_ROOF 3
-
-/* ASN.1 definition of generalName */
+/**
+ * ASN.1 definition of generalName
+ */
static const asn1Object_t generalNameObjects[] = {
- { 0, "otherName", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_BODY }, /* 0 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 1 */
- { 0, "rfc822Name", ASN1_CONTEXT_S_1, ASN1_OPT |
- ASN1_BODY }, /* 2 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 3 */
- { 0, "dnsName", ASN1_CONTEXT_S_2, ASN1_OPT |
- ASN1_BODY }, /* 4 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
- { 0, "x400Address", ASN1_CONTEXT_S_3, ASN1_OPT |
- ASN1_BODY }, /* 6 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
- { 0, "directoryName", ASN1_CONTEXT_C_4, ASN1_OPT |
- ASN1_BODY }, /* 8 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
- { 0, "ediPartyName", ASN1_CONTEXT_C_5, ASN1_OPT |
- ASN1_BODY }, /* 10 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 11 */
- { 0, "uniformResourceIdentifier", ASN1_CONTEXT_S_6, ASN1_OPT |
- ASN1_BODY }, /* 12 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 13 */
- { 0, "ipAddress", ASN1_CONTEXT_S_7, ASN1_OPT |
- ASN1_BODY }, /* 14 */
- { 0, "end choice", ASN1_EOC, ASN1_END }, /* 15 */
- { 0, "registeredID", ASN1_CONTEXT_S_8, ASN1_OPT |
- ASN1_BODY }, /* 16 */
- { 0, "end choice", ASN1_EOC, ASN1_END } /* 17 */
+ { 0, "otherName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 0 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 1 */
+ { 0, "rfc822Name", ASN1_CONTEXT_S_1, ASN1_OPT|ASN1_BODY }, /* 2 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "dnsName", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 4 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
+ { 0, "x400Address", ASN1_CONTEXT_S_3, ASN1_OPT|ASN1_BODY }, /* 6 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
+ { 0, "directoryName", ASN1_CONTEXT_C_4, ASN1_OPT|ASN1_BODY }, /* 8 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
+ { 0, "ediPartyName", ASN1_CONTEXT_C_5, ASN1_OPT|ASN1_BODY }, /* 10 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 11 */
+ { 0, "URI", ASN1_CONTEXT_S_6, ASN1_OPT|ASN1_BODY }, /* 12 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 13 */
+ { 0, "ipAddress", ASN1_CONTEXT_S_7, ASN1_OPT|ASN1_BODY }, /* 14 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 15 */
+ { 0, "registeredID", ASN1_CONTEXT_S_8, ASN1_OPT|ASN1_BODY }, /* 16 */
+ { 0, "end choice", ASN1_EOC, ASN1_END }, /* 17 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
-#define GN_OBJ_OTHER_NAME 0
-#define GN_OBJ_RFC822_NAME 2
-#define GN_OBJ_DNS_NAME 4
-#define GN_OBJ_X400_ADDRESS 6
+#define GN_OBJ_OTHER_NAME 0
+#define GN_OBJ_RFC822_NAME 2
+#define GN_OBJ_DNS_NAME 4
+#define GN_OBJ_X400_ADDRESS 6
#define GN_OBJ_DIRECTORY_NAME 8
#define GN_OBJ_EDI_PARTY_NAME 10
-#define GN_OBJ_URI 12
-#define GN_OBJ_IP_ADDRESS 14
+#define GN_OBJ_URI 12
+#define GN_OBJ_IP_ADDRESS 14
#define GN_OBJ_REGISTERED_ID 16
-#define GN_OBJ_ROOF 18
-
-/* ASN.1 definition of otherName */
+/**
+ * ASN.1 definition of otherName
+ */
static const asn1Object_t otherNameObjects[] = {
- {0, "type-id", ASN1_OID, ASN1_BODY }, /* 0 */
- {0, "value", ASN1_CONTEXT_C_0, ASN1_BODY } /* 1 */
+ {0, "type-id", ASN1_OID, ASN1_BODY }, /* 0 */
+ {0, "value", ASN1_CONTEXT_C_0, ASN1_BODY }, /* 1 */
+ {0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define ON_OBJ_ID_TYPE 0
#define ON_OBJ_VALUE 1
-#define ON_OBJ_ROOF 2
-
-/* ASN.1 definition of crlDistributionPoints */
+/**
+ * ASN.1 definition of crlDistributionPoints
+ */
static const asn1Object_t crlDistributionPointsObjects[] = {
- { 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
- { 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
- { 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_LOOP }, /* 2 */
- { 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT |
- ASN1_OBJ }, /* 3 */
- { 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
- { 3, "nameRelativeToCRLIssuer", ASN1_CONTEXT_C_1, ASN1_OPT |
- ASN1_BODY }, /* 5 */
- { 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
- { 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT |
- ASN1_BODY }, /* 8 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
- { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT |
- ASN1_BODY }, /* 10 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
- { 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
+ { 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
+ { 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
+ { 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 2 */
+ { 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */
+ { 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
+ { 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */
+ { 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
+ { 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
+ { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_BODY }, /* 10 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
#define CRL_DIST_POINTS_FULLNAME 3
-#define CRL_DIST_POINTS_ROOF 13
-
-/* ASN.1 definition of an X.509v3 certificate */
+/**
+ * ASN.1 definition of an X.509v3 x509_cert
+ */
static const asn1Object_t certObjects[] = {
- { 0, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
- { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
- { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
- { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */
- { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */
- { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
- { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */
- { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */
- { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */
- { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
- { 2, "subjectPublicKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
- { 3, "algorithm", ASN1_EOC, ASN1_RAW }, /* 12 */
- { 3, "subjectPublicKey", ASN1_BIT_STRING, ASN1_NONE }, /* 13 */
- { 4, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 14 */
- { 5, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 15 */
- { 5, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 16 */
- { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 17 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 18 */
- { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 19 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
- { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 21 */
- { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 22 */
- { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 23 */
- { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 24 */
- { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
- ASN1_BODY }, /* 25 */
- { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 26 */
- { 3, "end loop", ASN1_EOC, ASN1_END }, /* 27 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 28 */
- { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 29 */
- { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 30 */
+ { 0, "x509", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
+ { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
+ { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
+ { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */
+ { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */
+ { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
+ { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */
+ { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */
+ { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */
+ { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
+ { 2, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_RAW }, /* 11 */
+ { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
+ { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 14 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
+ { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 16 */
+ { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 17 */
+ { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 18 */
+ { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 19 */
+ { 5, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 20 */
+ { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 21 */
+ { 3, "end loop", ASN1_EOC, ASN1_END }, /* 22 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 23 */
+ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 24 */
+ { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 25 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
-
-#define X509_OBJ_CERTIFICATE 0
-#define X509_OBJ_TBS_CERTIFICATE 1
-#define X509_OBJ_VERSION 3
-#define X509_OBJ_SERIAL_NUMBER 4
-#define X509_OBJ_SIG_ALG 5
-#define X509_OBJ_ISSUER 6
-#define X509_OBJ_NOT_BEFORE 8
-#define X509_OBJ_NOT_AFTER 9
-#define X509_OBJ_SUBJECT 10
-#define X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM 12
-#define X509_OBJ_SUBJECT_PUBLIC_KEY 13
-#define X509_OBJ_RSA_PUBLIC_KEY 14
-#define X509_OBJ_MODULUS 15
-#define X509_OBJ_PUBLIC_EXPONENT 16
-#define X509_OBJ_EXTN_ID 24
-#define X509_OBJ_CRITICAL 25
-#define X509_OBJ_EXTN_VALUE 26
-#define X509_OBJ_ALGORITHM 29
-#define X509_OBJ_SIGNATURE 30
-#define X509_OBJ_ROOF 31
-
+#define X509_OBJ_CERTIFICATE 0
+#define X509_OBJ_TBS_CERTIFICATE 1
+#define X509_OBJ_VERSION 3
+#define X509_OBJ_SERIAL_NUMBER 4
+#define X509_OBJ_SIG_ALG 5
+#define X509_OBJ_ISSUER 6
+#define X509_OBJ_NOT_BEFORE 8
+#define X509_OBJ_NOT_AFTER 9
+#define X509_OBJ_SUBJECT 10
+#define X509_OBJ_SUBJECT_PUBLIC_KEY_INFO 11
+#define X509_OBJ_EXTN_ID 19
+#define X509_OBJ_CRITICAL 20
+#define X509_OBJ_EXTN_VALUE 21
+#define X509_OBJ_ALGORITHM 24
+#define X509_OBJ_SIGNATURE 25
const x509cert_t empty_x509cert = {
- NULL , /* *next */
- UNDEFINED_TIME, /* installed */
- 0 , /* count */
- FALSE , /* smartcard */
- AUTH_NONE , /* authority_flags */
- { NULL, 0 } , /* certificate */
- { NULL, 0 } , /* tbsCertificate */
- 1 , /* version */
- { NULL, 0 } , /* serialNumber */
- OID_UNKNOWN , /* sigAlg */
- { NULL, 0 } , /* issuer */
- /* validity */
- 0 , /* notBefore */
- 0 , /* notAfter */
- { NULL, 0 } , /* subject */
- /* subjectPublicKeyInfo */
- OID_UNKNOWN , /* subjectPublicKeyAlgorithm */
- { NULL, 0 } , /* subjectPublicKey */
- { NULL, 0 } , /* modulus */
- { NULL, 0 } , /* publicExponent */
- /* issuerUniqueID */
- /* subjectUniqueID */
- /* extensions */
- /* extension */
- /* extnID */
- /* critical */
- /* extnValue */
- FALSE , /* isCA */
- FALSE , /* isOcspSigner */
- { NULL, 0 } , /* subjectKeyID */
- { NULL, 0 } , /* authKeyID */
- { NULL, 0 } , /* authKeySerialNumber */
- { NULL, 0 } , /* accessLocation */
- NULL , /* subjectAltName */
- NULL , /* crlDistributionPoints */
- OID_UNKNOWN , /* algorithm */
- { NULL, 0 } /* signature */
+ NULL , /* *next */
+ UNDEFINED_TIME, /* installed */
+ 0 , /* count */
+ FALSE , /* smartcard */
+ AUTH_NONE , /* authority_flags */
+ { NULL, 0 } , /* certificate */
+ { NULL, 0 } , /* tbsCertificate */
+ 1 , /* version */
+ { NULL, 0 } , /* serialNumber */
+ OID_UNKNOWN , /* sigAlg */
+ { NULL, 0 } , /* issuer */
+ /* validity */
+ 0 , /* notBefore */
+ 0 , /* notAfter */
+ { NULL, 0 } , /* subject */
+ NULL , /* public_key */
+ /* issuerUniqueID */
+ /* subjectUniqueID */
+ /* extensions */
+ /* extension */
+ /* extnID */
+ /* critical */
+ /* extnValue */
+ FALSE , /* isCA */
+ FALSE , /* isOcspSigner */
+ { NULL, 0 } , /* subjectKeyID */
+ { NULL, 0 } , /* authKeyID */
+ { NULL, 0 } , /* authKeySerialNumber */
+ { NULL, 0 } , /* accessLocation */
+ NULL , /* subjectAltName */
+ NULL , /* crlDistributionPoints */
+ OID_UNKNOWN , /* algorithm */
+ { NULL, 0 } /* signature */
};
/* coding of X.501 distinguished name */
typedef struct {
- const u_char *name;
- chunk_t oid;
- u_char type;
+ const u_char *name;
+ chunk_t oid;
+ u_char type;
} x501rdn_t;
/* X.501 acronyms for well known object identifiers (OIDs) */
static u_char oid_ND[] = {0x02, 0x82, 0x06, 0x01,
- 0x0A, 0x07, 0x14};
+ 0x0A, 0x07, 0x14};
static u_char oid_UID[] = {0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x01};
+ 0xF2, 0x2C, 0x64, 0x01, 0x01};
static u_char oid_DC[] = {0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x19};
+ 0xF2, 0x2C, 0x64, 0x01, 0x19};
static u_char oid_CN[] = {0x55, 0x04, 0x03};
static u_char oid_S[] = {0x55, 0x04, 0x04};
static u_char oid_SN[] = {0x55, 0x04, 0x05};
@@ -351,13 +294,13 @@ static u_char oid_G[] = {0x55, 0x04, 0x2A};
static u_char oid_I[] = {0x55, 0x04, 0x2B};
static u_char oid_ID[] = {0x55, 0x04, 0x2D};
static u_char oid_EN[] = {0x60, 0x86, 0x48, 0x01, 0x86,
- 0xF8, 0x42, 0x03, 0x01, 0x03};
+ 0xF8, 0x42, 0x03, 0x01, 0x03};
static u_char oid_E[] = {0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x01};
+ 0x0D, 0x01, 0x09, 0x01};
static u_char oid_UN[] = {0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x02};
+ 0x0D, 0x01, 0x09, 0x02};
static u_char oid_TCGID[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0x89,
- 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B};
+ 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B};
static const x501rdn_t x501rdns[] = {
{"ND" , {oid_ND, 7}, ASN1_PRINTABLESTRING},
@@ -391,1850 +334,1804 @@ static const x501rdn_t x501rdns[] = {
#define X501_RDN_ROOF 26
static u_char ASN1_subjectAltName_oid_str[] = {
- 0x06, 0x03, 0x55, 0x1D, 0x11
+ 0x06, 0x03, 0x55, 0x1D, 0x11
};
-static const chunk_t ASN1_subjectAltName_oid = strchunk(ASN1_subjectAltName_oid_str);
+static const chunk_t ASN1_subjectAltName_oid = chunk_from_buf(ASN1_subjectAltName_oid_str);
-static void
-update_chunk(chunk_t *ch, int n)
+static void update_chunk(chunk_t *ch, int n)
{
- n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
- ch->ptr += n; ch->len -= n;
+ n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
+ ch->ptr += n; ch->len -= n;
}
-/*
+/**
* Pointer is set to the first RDN in a DN
*/
-static err_t
-init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
+static err_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
{
- *rdn = empty_chunk;
- *attribute = empty_chunk;
-
- /* a DN is a SEQUENCE OF RDNs */
+ *rdn = chunk_empty;
+ *attribute = chunk_empty;
- if (*dn.ptr != ASN1_SEQUENCE)
- {
- return "DN is not a SEQUENCE";
- }
+ /* a DN is a SEQUENCE OF RDNs */
- rdn->len = asn1_length(&dn);
+ if (*dn.ptr != ASN1_SEQUENCE)
+ {
+ return "DN is not a SEQUENCE";
+ }
- if (rdn->len == ASN1_INVALID_LENGTH)
- return "Invalid RDN length";
+ rdn->len = asn1_length(&dn);
- rdn->ptr = dn.ptr;
+ if (rdn->len == ASN1_INVALID_LENGTH)
+ {
+ return "Invalid RDN length";
+ }
+ rdn->ptr = dn.ptr;
- /* are there any RDNs ? */
- *next = rdn->len > 0;
+ /* are there any RDNs ? */
+ *next = rdn->len > 0;
- return NULL;
+ return NULL;
}
-/*
+/**
* Fetches the next RDN in a DN
*/
-static err_t
-get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value
-, asn1_t *type, bool *next)
+static err_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid,
+ chunk_t *value, asn1_t *type, bool *next)
{
- chunk_t body;
+ chunk_t body;
- /* initialize return values */
- *oid = empty_chunk;
- *value = empty_chunk;
+ /* initialize return values */
+ *oid = chunk_empty;
+ *value = chunk_empty;
- /* if all attributes have been parsed, get next rdn */
- if (attribute->len <= 0)
- {
- /* an RDN is a SET OF attributeTypeAndValue */
- if (*rdn->ptr != ASN1_SET)
- return "RDN is not a SET";
-
- attribute->len = asn1_length(rdn);
-
- if (attribute->len == ASN1_INVALID_LENGTH)
- return "Invalid attribute length";
-
- attribute->ptr = rdn->ptr;
-
- /* advance to start of next RDN */
- rdn->ptr += attribute->len;
- rdn->len -= attribute->len;
- }
-
- /* an attributeTypeAndValue is a SEQUENCE */
- if (*attribute->ptr != ASN1_SEQUENCE)
- return "attributeTypeAndValue is not a SEQUENCE";
-
- /* extract the attribute body */
- body.len = asn1_length(attribute);
-
- if (body.len == ASN1_INVALID_LENGTH)
- return "Invalid attribute body length";
+ /* if all attributes have been parsed, get next rdn */
+ if (attribute->len <= 0)
+ {
+ /* an RDN is a SET OF attributeTypeAndValue */
+ if (*rdn->ptr != ASN1_SET)
+ {
+ return "RDN is not a SET";
+ }
+ attribute->len = asn1_length(rdn);
+
+ if (attribute->len == ASN1_INVALID_LENGTH)
+ {
+ return "Invalid attribute length";
+ }
+ attribute->ptr = rdn->ptr;
- body.ptr = attribute->ptr;
-
- /* advance to start of next attribute */
- attribute->ptr += body.len;
- attribute->len -= body.len;
+ /* advance to start of next RDN */
+ rdn->ptr += attribute->len;
+ rdn->len -= attribute->len;
+ }
- /* attribute type is an OID */
- if (*body.ptr != ASN1_OID)
- return "attributeType is not an OID";
+ /* an attributeTypeAndValue is a SEQUENCE */
+ if (*attribute->ptr != ASN1_SEQUENCE)
+ {
+ return "attributeTypeAndValue is not a SEQUENCE";
+ }
- /* extract OID */
- oid->len = asn1_length(&body);
-
- if (oid->len == ASN1_INVALID_LENGTH)
- return "Invalid attribute OID length";
+ /* extract the attribute body */
+ body.len = asn1_length(attribute);
+
+ if (body.len == ASN1_INVALID_LENGTH)
+ {
+ return "Invalid attribute body length";
+ }
+ body.ptr = attribute->ptr;
+
+ /* advance to start of next attribute */
+ attribute->ptr += body.len;
+ attribute->len -= body.len;
- oid->ptr = body.ptr;
+ /* attribute type is an OID */
+ if (*body.ptr != ASN1_OID)
+ {
+ return "attributeType is not an OID";
+ }
- /* advance to the attribute value */
- body.ptr += oid->len;
- body.len -= oid->len;
+ /* extract OID */
+ oid->len = asn1_length(&body);
+
+ if (oid->len == ASN1_INVALID_LENGTH)
+ {
+ return "Invalid attribute OID length";
+ }
+ oid->ptr = body.ptr;
- /* extract string type */
- *type = *body.ptr;
+ /* advance to the attribute value */
+ body.ptr += oid->len;
+ body.len -= oid->len;
- /* extract string value */
- value->len = asn1_length(&body);
-
- if (value->len == ASN1_INVALID_LENGTH)
- return "Invalid attribute string length";
+ /* extract string type */
+ *type = *body.ptr;
- value->ptr = body.ptr;
+ /* extract string value */
+ value->len = asn1_length(&body);
+
+ if (value->len == ASN1_INVALID_LENGTH)
+ {
+ return "Invalid attribute string length";
+ }
+ value->ptr = body.ptr;
- /* are there any RDNs left? */
- *next = rdn->len > 0 || attribute->len > 0;
+ /* are there any RDNs left? */
+ *next = rdn->len > 0 || attribute->len > 0;
- return NULL;
+ return NULL;
}
-/*
+/**
* Parses an ASN.1 distinguished name int its OID/value pairs
*/
-static err_t
-dn_parse(chunk_t dn, chunk_t *str)
+static err_t dn_parse(chunk_t dn, chunk_t *str)
{
- chunk_t rdn, oid, attribute, value;
- asn1_t type;
- int oid_code;
- bool next;
- bool first = TRUE;
+ chunk_t rdn, oid, attribute, value;
+ asn1_t type;
+ int oid_code;
+ bool next;
+ bool first = TRUE;
- err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
+ err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
- if (ugh != NULL) /* a parsing error has occured */
- return ugh;
+ if (ugh != NULL) /* a parsing error has occured */
+ {
+ return ugh;
+ }
- while (next)
- {
- ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
+ while (next)
+ {
+ ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
- if (ugh != NULL) /* a parsing error has occured */
- return ugh;
+ if (ugh != NULL) /* a parsing error has occured */
+ {
+ return ugh;
+ }
- if (first) /* first OID/value pair */
- first = FALSE;
- else /* separate OID/value pair by a comma */
- update_chunk(str, snprintf(str->ptr,str->len,", "));
+ if (first) /* first OID/value pair */
+ {
+ first = FALSE;
+ }
+ else /* separate OID/value pair by a comma */
+ {
+ update_chunk(str, snprintf(str->ptr,str->len,", "));
+ }
- /* print OID */
- oid_code = known_oid(oid);
- if (oid_code == OID_UNKNOWN) /* OID not found in list */
- hex_str(oid, str);
- else
- update_chunk(str, snprintf(str->ptr,str->len,"%s",
- oid_names[oid_code].name));
+ /* print OID */
+ oid_code = asn1_known_oid(oid);
+ if (oid_code == OID_UNKNOWN) /* OID not found in list */
+ {
+ hex_str(oid, str);
+ }
+ else
+ {
+ update_chunk(str, snprintf(str->ptr,str->len,"%s",
+ oid_names[oid_code].name));
+ }
- /* print value */
- update_chunk(str, snprintf(str->ptr,str->len,"=%.*s",
- (int)value.len,value.ptr));
- }
- return NULL;
+ /* print value */
+ update_chunk(str, snprintf(str->ptr,str->len,"=%.*s",
+ (int)value.len,value.ptr));
+ }
+ return NULL;
}
-/*
+/**
* Count the number of wildcard RDNs in a distinguished name
*/
-int
-dn_count_wildcards(chunk_t dn)
+int dn_count_wildcards(chunk_t dn)
{
- chunk_t rdn, attribute, oid, value;
- asn1_t type;
- bool next;
- int wildcards = 0;
+ chunk_t rdn, attribute, oid, value;
+ asn1_t type;
+ bool next;
+ int wildcards = 0;
- err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
+ err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
- if (ugh != NULL) /* a parsing error has occured */
- return -1;
+ if (ugh != NULL) /* a parsing error has occured */
+ {
+ return -1;
+ }
- while (next)
- {
- ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
+ while (next)
+ {
+ ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
- if (ugh != NULL) /* a parsing error has occured */
- return -1;
- if (value.len == 1 && *value.ptr == '*')
- wildcards++; /* we have found a wildcard RDN */
- }
- return wildcards;
+ if (ugh != NULL) /* a parsing error has occured */
+ {
+ return -1;
+ }
+ if (value.len == 1 && *value.ptr == '*')
+ {
+ wildcards++; /* we have found a wildcard RDN */
+ }
+ }
+ return wildcards;
}
-/*
+/**
* Prints a binary string in hexadecimal form
*/
-void
-hex_str(chunk_t bin, chunk_t *str)
+void hex_str(chunk_t bin, chunk_t *str)
{
- u_int i;
- update_chunk(str, snprintf(str->ptr,str->len,"0x"));
- for (i=0; i < bin.len; i++)
- update_chunk(str, snprintf(str->ptr,str->len,"%02X",*bin.ptr++));
+ u_int i;
+ update_chunk(str, snprintf(str->ptr,str->len,"0x"));
+ for (i=0; i < bin.len; i++)
+ update_chunk(str, snprintf(str->ptr,str->len,"%02X",*bin.ptr++));
}
-/* Converts a binary DER-encoded ASN.1 distinguished name
+/** Converts a binary DER-encoded ASN.1 distinguished name
* into LDAP-style human-readable ASCII format
*/
-int
-dntoa(char *dst, size_t dstlen, chunk_t dn)
+int dntoa(char *dst, size_t dstlen, chunk_t dn)
{
- err_t ugh = NULL;
- chunk_t str;
-
- str.ptr = dst;
- str.len = dstlen;
- ugh = dn_parse(dn, &str);
+ err_t ugh = NULL;
+ chunk_t str;
- if (ugh != NULL) /* error, print DN as hex string */
- {
- DBG(DBG_PARSING,
- DBG_log("error in DN parsing: %s", ugh)
- )
str.ptr = dst;
str.len = dstlen;
- hex_str(dn, &str);
- }
- return (int)(dstlen - str.len);
+ ugh = dn_parse(dn, &str);
+
+ if (ugh != NULL) /* error, print DN as hex string */
+ {
+ DBG(DBG_PARSING,
+ DBG_log("error in DN parsing: %s", ugh)
+ )
+ str.ptr = dst;
+ str.len = dstlen;
+ hex_str(dn, &str);
+ }
+ return (int)(dstlen - str.len);
}
-/*
+/**
* Same as dntoa but prints a special string for a null dn
*/
-int
-dntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn)
+int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn)
{
- if (dn.ptr == NULL)
- return snprintf(dst, dstlen, "%s", null_dn);
+ if (dn.ptr == NULL)
+ {
+ return snprintf(dst, dstlen, "%s", null_dn);
+ }
+ else
+ {
+ return dntoa(dst, dstlen, dn);
+ }
+}
+
+
+/**
+ * Codes ASN.1 lengths up to a size of 16'777'215 bytes
+ */
+static void code_asn1_length(size_t length, chunk_t *code)
+{
+ if (length < 128)
+ {
+ code->ptr[0] = length;
+ code->len = 1;
+ }
+ else if (length < 256)
+ {
+ code->ptr[0] = 0x81;
+ code->ptr[1] = (u_char) length;
+ code->len = 2;
+ }
+ else if (length < 65536)
+ {
+ code->ptr[0] = 0x82;
+ code->ptr[1] = length >> 8;
+ code->ptr[2] = length & 0x00ff;
+ code->len = 3;
+ }
else
- return dntoa(dst, dstlen, dn);
+ {
+ code->ptr[0] = 0x83;
+ code->ptr[1] = length >> 16;
+ code->ptr[2] = (length >> 8) & 0x00ff;
+ code->ptr[3] = length & 0x0000ff;
+ code->len = 4;
+ }
}
-/* Converts an LDAP-style human-readable ASCII-encoded
+/**
+ * Converts an LDAP-style human-readable ASCII-encoded
* ASN.1 distinguished name into binary DER-encoded format
*/
-err_t
-atodn(char *src, chunk_t *dn)
+err_t atodn(char *src, chunk_t *dn)
{
/* finite state machine for atodn */
- typedef enum {
- SEARCH_OID = 0,
- READ_OID = 1,
- SEARCH_NAME = 2,
- READ_NAME = 3,
- UNKNOWN_OID = 4
- } state_t;
-
- u_char oid_len_buf[3];
- u_char name_len_buf[3];
- u_char rdn_seq_len_buf[3];
- u_char rdn_set_len_buf[3];
- u_char dn_seq_len_buf[3];
-
- chunk_t asn1_oid_len = { oid_len_buf, 0 };
- chunk_t asn1_name_len = { name_len_buf, 0 };
- chunk_t asn1_rdn_seq_len = { rdn_seq_len_buf, 0 };
- chunk_t asn1_rdn_set_len = { rdn_set_len_buf, 0 };
- chunk_t asn1_dn_seq_len = { dn_seq_len_buf, 0 };
- chunk_t oid = empty_chunk;
- chunk_t name = empty_chunk;
-
- int whitespace = 0;
- int rdn_seq_len = 0;
- int rdn_set_len = 0;
- int dn_seq_len = 0;
- int pos = 0;
-
- err_t ugh = NULL;
-
- u_char *dn_ptr = dn->ptr + 4;
-
- state_t state = SEARCH_OID;
-
- do
- {
- switch (state)
+ typedef enum {
+ SEARCH_OID = 0,
+ READ_OID = 1,
+ SEARCH_NAME = 2,
+ READ_NAME = 3,
+ UNKNOWN_OID = 4
+ } state_t;
+
+ u_char oid_len_buf[3];
+ u_char name_len_buf[3];
+ u_char rdn_seq_len_buf[3];
+ u_char rdn_set_len_buf[3];
+ u_char dn_seq_len_buf[3];
+
+ chunk_t asn1_oid_len = { oid_len_buf, 0 };
+ chunk_t asn1_name_len = { name_len_buf, 0 };
+ chunk_t asn1_rdn_seq_len = { rdn_seq_len_buf, 0 };
+ chunk_t asn1_rdn_set_len = { rdn_set_len_buf, 0 };
+ chunk_t asn1_dn_seq_len = { dn_seq_len_buf, 0 };
+ chunk_t oid = chunk_empty;
+ chunk_t name = chunk_empty;
+
+ int whitespace = 0;
+ int rdn_seq_len = 0;
+ int rdn_set_len = 0;
+ int dn_seq_len = 0;
+ int pos = 0;
+
+ err_t ugh = NULL;
+
+ u_char *dn_ptr = dn->ptr + 4;
+
+ state_t state = SEARCH_OID;
+
+ do
{
- case SEARCH_OID:
- if (*src != ' ' && *src != '/' && *src != ',')
- {
- oid.ptr = src;
- oid.len = 1;
- state = READ_OID;
- }
- break;
- case READ_OID:
- if (*src != ' ' && *src != '=')
- oid.len++;
- else
- {
- for (pos = 0; pos < X501_RDN_ROOF; pos++)
+ switch (state)
{
- if (strlen(x501rdns[pos].name) == oid.len &&
- strncasecmp(x501rdns[pos].name, oid.ptr, oid.len) == 0)
- break; /* found a valid OID */
- }
- if (pos == X501_RDN_ROOF)
- {
- ugh = "unknown OID in distinguished name";
- state = UNKNOWN_OID;
- break;
+ case SEARCH_OID:
+ if (*src != ' ' && *src != '/' && *src != ',')
+ {
+ oid.ptr = src;
+ oid.len = 1;
+ state = READ_OID;
+ }
+ break;
+ case READ_OID:
+ if (*src != ' ' && *src != '=')
+ {
+ oid.len++;
+ }
+ else
+ {
+ for (pos = 0; pos < X501_RDN_ROOF; pos++)
+ {
+ if (strlen(x501rdns[pos].name) == oid.len &&
+ strncasecmp(x501rdns[pos].name, oid.ptr, oid.len) == 0)
+ {
+ break; /* found a valid OID */
+ }
+ }
+ if (pos == X501_RDN_ROOF)
+ {
+ ugh = "unknown OID in distinguished name";
+ state = UNKNOWN_OID;
+ break;
+ }
+ code_asn1_length(x501rdns[pos].oid.len, &asn1_oid_len);
+
+ /* reset oid and change state */
+ oid = chunk_empty;
+ state = SEARCH_NAME;
+ }
+ break;
+ case SEARCH_NAME:
+ if (*src != ' ' && *src != '=')
+ {
+ name.ptr = src;
+ name.len = 1;
+ whitespace = 0;
+ state = READ_NAME;
+ }
+ break;
+ case READ_NAME:
+ if (*src != ',' && *src != '/' && *src != '\0')
+ {
+ name.len++;
+ if (*src == ' ')
+ {
+ whitespace++;
+ }
+ else
+ {
+ whitespace = 0;
+ }
+ }
+ else
+ {
+ name.len -= whitespace;
+ code_asn1_length(name.len, &asn1_name_len);
+
+ /* compute the length of the relative distinguished name sequence */
+ rdn_seq_len = 1 + asn1_oid_len.len + x501rdns[pos].oid.len +
+ 1 + asn1_name_len.len + name.len;
+ code_asn1_length(rdn_seq_len, &asn1_rdn_seq_len);
+
+ /* compute the length of the relative distinguished name set */
+ rdn_set_len = 1 + asn1_rdn_seq_len.len + rdn_seq_len;
+ code_asn1_length(rdn_set_len, &asn1_rdn_set_len);
+
+ /* encode the relative distinguished name */
+ *dn_ptr++ = ASN1_SET;
+ chunkcpy(dn_ptr, asn1_rdn_set_len);
+ *dn_ptr++ = ASN1_SEQUENCE;
+ chunkcpy(dn_ptr, asn1_rdn_seq_len);
+ *dn_ptr++ = ASN1_OID;
+ chunkcpy(dn_ptr, asn1_oid_len);
+ chunkcpy(dn_ptr, x501rdns[pos].oid);
+ /* encode the ASN.1 character string type of the name */
+ *dn_ptr++ = (x501rdns[pos].type == ASN1_PRINTABLESTRING
+ && !asn1_is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type;
+ chunkcpy(dn_ptr, asn1_name_len);
+ chunkcpy(dn_ptr, name);
+
+ /* accumulate the length of the distinguished name sequence */
+ dn_seq_len += 1 + asn1_rdn_set_len.len + rdn_set_len;
+
+ /* reset name and change state */
+ name = chunk_empty;
+ state = SEARCH_OID;
+ }
+ break;
+ case UNKNOWN_OID:
+ break;
}
- code_asn1_length(x501rdns[pos].oid.len, &asn1_oid_len);
-
- /* reset oid and change state */
- oid = empty_chunk;
- state = SEARCH_NAME;
- }
- break;
- case SEARCH_NAME:
- if (*src != ' ' && *src != '=')
- {
- name.ptr = src;
- name.len = 1;
- whitespace = 0;
- state = READ_NAME;
- }
- break;
- case READ_NAME:
- if (*src != ',' && *src != '/' && *src != '\0')
- {
- name.len++;
- if (*src == ' ')
- whitespace++;
- else
- whitespace = 0;
- }
- else
- {
- name.len -= whitespace;
- code_asn1_length(name.len, &asn1_name_len);
-
- /* compute the length of the relative distinguished name sequence */
- rdn_seq_len = 1 + asn1_oid_len.len + x501rdns[pos].oid.len +
- 1 + asn1_name_len.len + name.len;
- code_asn1_length(rdn_seq_len, &asn1_rdn_seq_len);
-
- /* compute the length of the relative distinguished name set */
- rdn_set_len = 1 + asn1_rdn_seq_len.len + rdn_seq_len;
- code_asn1_length(rdn_set_len, &asn1_rdn_set_len);
-
- /* encode the relative distinguished name */
- *dn_ptr++ = ASN1_SET;
- chunkcpy(dn_ptr, asn1_rdn_set_len);
- *dn_ptr++ = ASN1_SEQUENCE;
- chunkcpy(dn_ptr, asn1_rdn_seq_len);
- *dn_ptr++ = ASN1_OID;
- chunkcpy(dn_ptr, asn1_oid_len);
- chunkcpy(dn_ptr, x501rdns[pos].oid);
- /* encode the ASN.1 character string type of the name */
- *dn_ptr++ = (x501rdns[pos].type == ASN1_PRINTABLESTRING
- && !is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type;
- chunkcpy(dn_ptr, asn1_name_len);
- chunkcpy(dn_ptr, name);
-
- /* accumulate the length of the distinguished name sequence */
- dn_seq_len += 1 + asn1_rdn_set_len.len + rdn_set_len;
-
- /* reset name and change state */
- name = empty_chunk;
- state = SEARCH_OID;
- }
- break;
- case UNKNOWN_OID:
- break;
- }
- } while (*src++ != '\0');
-
- /* complete the distinguished name sequence*/
- code_asn1_length(dn_seq_len, &asn1_dn_seq_len);
- dn->ptr += 3 - asn1_dn_seq_len.len;
- dn->len = 1 + asn1_dn_seq_len.len + dn_seq_len;
- dn_ptr = dn->ptr;
- *dn_ptr++ = ASN1_SEQUENCE;
- chunkcpy(dn_ptr, asn1_dn_seq_len);
- return ugh;
+ } while (*src++ != '\0');
+
+ /* complete the distinguished name sequence*/
+ code_asn1_length(dn_seq_len, &asn1_dn_seq_len);
+ dn->ptr += 3 - asn1_dn_seq_len.len;
+ dn->len = 1 + asn1_dn_seq_len.len + dn_seq_len;
+ dn_ptr = dn->ptr;
+ *dn_ptr++ = ASN1_SEQUENCE;
+ chunkcpy(dn_ptr, asn1_dn_seq_len);
+ return ugh;
}
-/* compare two distinguished names by
- * comparing the individual RDNs
+/**
+ * compare two distinguished names by comparing the individual RDNs
*/
-bool
-same_dn(chunk_t a, chunk_t b)
+bool same_dn(chunk_t a, chunk_t b)
{
- chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
- chunk_t oid_a, oid_b, value_a, value_b;
- asn1_t type_a, type_b;
- bool next_a, next_b;
+ chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
+ chunk_t oid_a, oid_b, value_a, value_b;
+ asn1_t type_a, type_b;
+ bool next_a, next_b;
- /* same lengths for the DNs */
- if (a.len != b.len)
- return FALSE;
+ /* same lengths for the DNs */
+ if (a.len != b.len)
+ {
+ return FALSE;
+ }
- /* try a binary comparison first */
- if (memcmp(a.ptr, b.ptr, b.len) == 0)
- return TRUE;
-
- /* initialize DN parsing */
- if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
- || init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
- return FALSE;
+ /* try a binary comparison first */
+ if (memeq(a.ptr, b.ptr, b.len))
+ {
+ return TRUE;
+ }
- /* fetch next RDN pair */
- while (next_a && next_b)
- {
- /* parse next RDNs and check for errors */
- if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL
- || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)
+ /* initialize DN parsing */
+ if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
+ || init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
{
- return FALSE;
+ return FALSE;
}
- /* OIDs must agree */
- if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
- return FALSE;
+ /* fetch next RDN pair */
+ while (next_a && next_b)
+ {
+ /* parse next RDNs and check for errors */
+ if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL
+ || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)
+ {
+ return FALSE;
+ }
+
+ /* OIDs must agree */
+ if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
+ {
+ return FALSE;
+ }
- /* same lengths for values */
- if (value_a.len != value_b.len)
- return FALSE;
+ /* same lengths for values */
+ if (value_a.len != value_b.len)
+ {
+ return FALSE;
+ }
- /* printableStrings and email RDNs require uppercase comparison */
- if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
- (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
- {
- if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- return FALSE;
+ /* printableStrings and email RDNs require uppercase comparison */
+ if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
+ (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_PKCS9_EMAIL)))
+ {
+ if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
+ return FALSE;
+ }
+ }
}
- else
+ /* both DNs must have same number of RDNs */
+ if (next_a || next_b)
{
- if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
return FALSE;
}
- }
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- return FALSE;
- /* the two DNs are equal! */
- return TRUE;
+ /* the two DNs are equal! */
+ return TRUE;
}
-/* compare two distinguished names by comparing the individual RDNs.
+/**
+ * Compare two distinguished names by comparing the individual RDNs.
* A single'*' character designates a wildcard RDN in DN b.
*/
-bool
-match_dn(chunk_t a, chunk_t b, int *wildcards)
+bool match_dn(chunk_t a, chunk_t b, int *wildcards)
{
- chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
- chunk_t oid_a, oid_b, value_a, value_b;
- asn1_t type_a, type_b;
- bool next_a, next_b;
+ chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
+ chunk_t oid_a, oid_b, value_a, value_b;
+ asn1_t type_a, type_b;
+ bool next_a, next_b;
- /* initialize wildcard counter */
- *wildcards = 0;
+ /* initialize wildcard counter */
+ *wildcards = 0;
- /* initialize DN parsing */
- if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
- || init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
- return FALSE;
-
- /* fetch next RDN pair */
- while (next_a && next_b)
- {
- /* parse next RDNs and check for errors */
- if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL
- || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)
+ /* initialize DN parsing */
+ if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
+ || init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
{
- return FALSE;
+ return FALSE;
}
- /* OIDs must agree */
- if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
- return FALSE;
-
- /* does rdn_b contain a wildcard? */
- if (value_b.len == 1 && *value_b.ptr == '*')
+ /* fetch next RDN pair */
+ while (next_a && next_b)
{
- (*wildcards)++;
- continue;
- }
+ /* parse next RDNs and check for errors */
+ if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL
+ || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)
+ {
+ return FALSE;
+ }
- /* same lengths for values */
- if (value_a.len != value_b.len)
- return FALSE;
+ /* OIDs must agree */
+ if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
+ {
+ return FALSE;
+ }
- /* printableStrings and email RDNs require uppercase comparison */
- if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
- (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
- {
- if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- return FALSE;
+ /* does rdn_b contain a wildcard? */
+ if (value_b.len == 1 && *value_b.ptr == '*')
+ {
+ (*wildcards)++;
+ continue;
+ }
+
+ /* same lengths for values */
+ if (value_a.len != value_b.len)
+ {
+ return FALSE;
+ }
+
+ /* printableStrings and email RDNs require uppercase comparison */
+ if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
+ (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_PKCS9_EMAIL)))
+ {
+ if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
+ return FALSE;
+ }
+ }
}
- else
+
+ /* both DNs must have same number of RDNs */
+ if (next_a || next_b)
{
- if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
return FALSE;
}
- }
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- return FALSE;
- /* the two DNs match! */
- return TRUE;
+ /* the two DNs match! */
+ return TRUE;
}
-/*
- * compare two X.509 certificates by comparing their signatures
+/**
+ * Compare two X.509 certificates by comparing their signatures
*/
-bool
-same_x509cert(const x509cert_t *a, const x509cert_t *b)
+bool same_x509cert(const x509cert_t *a, const x509cert_t *b)
{
- return same_chunk(a->signature, b->signature);
+ return chunk_equals(a->signature, b->signature);
}
-/* for each link pointing to the certificate
- " increase the count by one
+/**
+ * For each link pointing to the certificate increase the count by one
*/
-void
-share_x509cert(x509cert_t *cert)
+void share_x509cert(x509cert_t *cert)
{
- if (cert != NULL)
- cert->count++;
+ if (cert != NULL)
+ {
+ cert->count++;
+ }
}
-/*
- * add a X.509 user/host certificate to the chained list
+/**
+ * Add a X.509 user/host certificate to the chained list
*/
-x509cert_t*
-add_x509cert(x509cert_t *cert)
+x509cert_t* add_x509cert(x509cert_t *cert)
{
- x509cert_t *c = x509certs;
+ x509cert_t *c = x509certs;
- while (c != NULL)
- {
- if (same_x509cert(c, cert)) /* already in chain, free cert */
+ while (c != NULL)
{
- free_x509cert(cert);
- return c;
+ if (same_x509cert(c, cert)) /* already in chain, free cert */
+ {
+ free_x509cert(cert);
+ return c;
+ }
+ c = c->next;
}
- c = c->next;
- }
- /* insert new cert at the root of the chain */
- lock_certs_and_keys("add_x509cert");
- cert->next = x509certs;
- x509certs = cert;
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" x509 cert inserted")
- )
- unlock_certs_and_keys("add_x509cert");
- return cert;
+ /* insert new cert at the root of the chain */
+ lock_certs_and_keys("add_x509cert");
+ cert->next = x509certs;
+ x509certs = cert;
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log(" x509 cert inserted")
+ )
+ unlock_certs_and_keys("add_x509cert");
+ return cert;
}
-/*
- * choose either subject DN or a subjectAltName as connection end ID
+/**
+ * Choose either subject DN or a subjectAltName as connection end ID
*/
-void
-select_x509cert_id(x509cert_t *cert, struct id *end_id)
+void select_x509cert_id(x509cert_t *cert, struct id *end_id)
{
- bool copy_subject_dn = TRUE; /* ID is subject DN */
+ bool copy_subject_dn = TRUE; /* ID is subject DN */
- if (end_id->kind != ID_NONE) /* check for matching subjectAltName */
- {
- generalName_t *gn = cert->subjectAltName;
-
- while (gn != NULL)
+ if (end_id->kind != ID_ANY) /* check for matching subjectAltName */
{
- struct id id = empty_id;
+ generalName_t *gn = cert->subjectAltName;
- gntoid(&id, gn);
- if (same_id(&id, end_id))
- {
- copy_subject_dn = FALSE; /* take subjectAltName instead */
- break;
- }
- gn = gn->next;
+ while (gn != NULL)
+ {
+ struct id id = empty_id;
+
+ gntoid(&id, gn);
+ if (same_id(&id, end_id))
+ {
+ copy_subject_dn = FALSE; /* take subjectAltName instead */
+ break;
+ }
+ gn = gn->next;
+ }
}
- }
- if (copy_subject_dn)
- {
- if (end_id->kind != ID_NONE && end_id->kind != ID_DER_ASN1_DN)
+ if (copy_subject_dn)
{
- char buf[BUF_LEN];
+ if (end_id->kind != ID_ANY && end_id->kind != ID_DER_ASN1_DN)
+ {
+ char buf[BUF_LEN];
- idtoa(end_id, buf, BUF_LEN);
- plog(" no subjectAltName matches ID '%s', replaced by subject DN", buf);
+ idtoa(end_id, buf, BUF_LEN);
+ plog(" no subjectAltName matches ID '%s', replaced by subject DN", buf);
+ }
+ end_id->kind = ID_DER_ASN1_DN;
+ end_id->name.len = cert->subject.len;
+ end_id->name.ptr = temporary_cyclic_buffer();
+ memcpy(end_id->name.ptr, cert->subject.ptr, cert->subject.len);
}
- end_id->kind = ID_DER_ASN1_DN;
- end_id->name.len = cert->subject.len;
- end_id->name.ptr = temporary_cyclic_buffer();
- memcpy(end_id->name.ptr, cert->subject.ptr, cert->subject.len);
- }
}
-/*
- * check for equality between two key identifiers
+/**
+ * Check for equality between two key identifiers
*/
-bool
-same_keyid(chunk_t a, chunk_t b)
+bool same_keyid(chunk_t a, chunk_t b)
{
- if (a.ptr == NULL || b.ptr == NULL)
- return FALSE;
-
- return same_chunk(a, b);
+ if (a.ptr == NULL || b.ptr == NULL)
+ {
+ return FALSE;
+ }
+ return chunk_equals(a, b);
}
-/*
- * check for equality between two serial numbers
+/**
+ * Check for equality between two serial numbers
*/
-bool
-same_serial(chunk_t a, chunk_t b)
+bool same_serial(chunk_t a, chunk_t b)
{
- /* do not compare serial numbers if one of them is not defined */
- if (a.ptr == NULL || b.ptr == NULL)
- return TRUE;
-
- return same_chunk(a, b);
+ /* do not compare serial numbers if one of them is not defined */
+ if (a.ptr == NULL || b.ptr == NULL)
+ {
+ return TRUE;
+ }
+ return chunk_equals(a, b);
}
-/*
- * get a X.509 certificate with a given issuer found at a certain position
+/**
+ * Get a X.509 certificate with a given issuer found at a certain position
*/
-x509cert_t*
-get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid, x509cert_t *chain)
+x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid,
+ x509cert_t *chain)
{
- x509cert_t *cert = (chain != NULL)? chain->next : x509certs;
+ x509cert_t *cert = (chain != NULL)? chain->next : x509certs;
- while (cert != NULL)
- {
- if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->authKeyID)
- : (same_dn(issuer, cert->issuer)
- && same_serial(serial, cert->authKeySerialNumber)))
+ while (cert != NULL)
{
- return cert;
+ if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->authKeyID)
+ : (same_dn(issuer, cert->issuer)
+ && same_serial(serial, cert->authKeySerialNumber)))
+ {
+ return cert;
+ }
+ cert = cert->next;
}
- cert = cert->next;
- }
- return NULL;
+ return NULL;
}
-/*
- * encode a linked list of subjectAltNames
+/**
+ * Encode a linked list of subjectAltNames
*/
-chunk_t
-build_subjectAltNames(generalName_t *subjectAltNames)
+chunk_t build_subjectAltNames(generalName_t *subjectAltNames)
{
- u_char *pos;
- chunk_t names;
- size_t len = 0;
- generalName_t *gn = subjectAltNames;
-
+ u_char *pos;
+ chunk_t names;
+ size_t len = 0;
+ generalName_t *gn = subjectAltNames;
+
/* compute the total size of the ASN.1 attributes object */
- while (gn != NULL)
- {
- len += gn->name.len;
- gn = gn->next;
- }
+ while (gn != NULL)
+ {
+ len += gn->name.len;
+ gn = gn->next;
+ }
- pos = build_asn1_object(&names, ASN1_SEQUENCE, len);
+ pos = asn1_build_object(&names, ASN1_SEQUENCE, len);
- gn = subjectAltNames;
- while (gn != NULL)
- {
- chunkcpy(pos, gn->name);
- gn = gn->next;
- }
+ gn = subjectAltNames;
+ while (gn != NULL)
+ {
+ chunkcpy(pos, gn->name);
+ gn = gn->next;
+ }
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_subjectAltName_oid
- , asn1_wrap(ASN1_OCTET_STRING, "m", names));
+ return asn1_wrap(ASN1_SEQUENCE, "cm"
+ , ASN1_subjectAltName_oid
+ , asn1_wrap(ASN1_OCTET_STRING, "m", names));
}
-/*
- * build a to-be-signed X.509 certificate body
+/**
+ * Build a to-be-signed X.509 certificate body
*/
-static chunk_t
-build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa)
+static chunk_t build_tbs_x509cert(x509cert_t *cert, public_key_t *rsa)
{
- /* version is always X.509v3 */
- chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2);
+ /* version is always X.509v3 */
+ chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2);
- chunk_t extensions = empty_chunk;
+ chunk_t extensions = chunk_empty;
- if (cert->subjectAltName != NULL)
- {
- extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m"
- , asn1_wrap(ASN1_SEQUENCE, "m"
- , build_subjectAltNames(cert->subjectAltName)));
- }
+ chunk_t key = rsa->get_encoding(rsa);
- return asn1_wrap(ASN1_SEQUENCE, "mmccmcmm"
- , version
- , asn1_simple_object(ASN1_INTEGER, cert->serialNumber)
- , asn1_algorithmIdentifier(cert->sigAlg)
- , cert->issuer
- , asn1_wrap(ASN1_SEQUENCE, "mm"
- , timetoasn1(&cert->notBefore, ASN1_UTCTIME)
- , timetoasn1(&cert->notAfter, ASN1_UTCTIME)
- )
- , cert->subject
- , pkcs1_build_publicKeyInfo(rsa)
- , extensions
- );
+ chunk_t keyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ asn1_bitstring("m", key));
+
+ if (cert->subjectAltName != NULL)
+ {
+ extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m"
+ , asn1_wrap(ASN1_SEQUENCE, "m"
+ , build_subjectAltNames(cert->subjectAltName)));
+ }
+
+ return asn1_wrap(ASN1_SEQUENCE, "mmccmcmm"
+ , version
+ , asn1_integer("c", cert->serialNumber)
+ , asn1_algorithmIdentifier(cert->sigAlg)
+ , cert->issuer
+ , asn1_wrap(ASN1_SEQUENCE, "mm"
+ , asn1_from_time(&cert->notBefore, ASN1_UTCTIME)
+ , asn1_from_time(&cert->notAfter, ASN1_UTCTIME)
+ )
+ , cert->subject
+ , keyInfo
+ , extensions
+ );
}
-/*
- * build a DER-encoded X.509 certificate
+/**
+ * Build a DER-encoded X.509 certificate
*/
-void
-build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key
-, const RSA_private_key_t *signer_key)
+void build_x509cert(x509cert_t *cert, public_key_t *cert_key,
+ private_key_t *signer_key)
{
- chunk_t tbs_cert = build_tbs_x509cert(cert, cert_key);
+ chunk_t tbs_cert = build_tbs_x509cert(cert, cert_key);
- chunk_t signature = pkcs1_build_signature(tbs_cert, cert->sigAlg
- , signer_key, TRUE);
+ chunk_t signature = x509_build_signature(tbs_cert, cert->sigAlg
+ , signer_key, TRUE);
- cert->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm"
- , tbs_cert
- , asn1_algorithmIdentifier(cert->sigAlg)
- , signature);
+ cert->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm"
+ , tbs_cert
+ , asn1_algorithmIdentifier(cert->sigAlg)
+ , signature);
}
-/*
- * free the dynamic memory used to store generalNames
+/**
+ * Free the dynamic memory used to store generalNames
*/
-void
-free_generalNames(generalName_t* gn, bool free_name)
+void free_generalNames(generalName_t* gn, bool free_name)
{
- while (gn != NULL)
- {
- generalName_t *gn_top = gn;
- if (free_name)
+ while (gn != NULL)
{
- pfree(gn->name.ptr);
+ generalName_t *gn_top = gn;
+ if (free_name)
+ {
+ free(gn->name.ptr);
+ }
+ gn = gn->next;
+ free(gn_top);
}
- gn = gn->next;
- pfree(gn_top);
- }
}
-/*
- * free a X.509 certificate
+/**
+ * Free a X.509 certificate
*/
-void
-free_x509cert(x509cert_t *cert)
+void free_x509cert(x509cert_t *cert)
{
- if (cert != NULL)
- {
- free_generalNames(cert->subjectAltName, FALSE);
- free_generalNames(cert->crlDistributionPoints, FALSE);
- pfreeany(cert->certificate.ptr);
- pfree(cert);
- cert = NULL;
- }
+ if (cert != NULL)
+ {
+ DESTROY_IF(cert->public_key);
+ free_generalNames(cert->subjectAltName, FALSE);
+ free_generalNames(cert->crlDistributionPoints, FALSE);
+ free(cert->certificate.ptr);
+ free(cert);
+ cert = NULL;
+ }
}
-/* release of a certificate decreases the count by one
- " the certificate is freed when the counter reaches zero
+/**
+ * Release of a certificate decreases the count by one
+ * the certificate is freed when the counter reaches zero
*/
-void
-release_x509cert(x509cert_t *cert)
+void release_x509cert(x509cert_t *cert)
{
- if (cert != NULL && --cert->count == 0)
- {
- x509cert_t **pp = &x509certs;
- while (*pp != cert)
- pp = &(*pp)->next;
- *pp = cert->next;
- free_x509cert(cert);
- }
+ if (cert != NULL && --cert->count == 0)
+ {
+ x509cert_t **pp = &x509certs;
+ while (*pp != cert)
+ {
+ pp = &(*pp)->next;
+ }
+ *pp = cert->next;
+ free_x509cert(cert);
+ }
}
-
-/*
- * stores a chained list of end certs and CA certs
+/**
+ * Stores a chained list of end certs and CA certs
*/
-void
-store_x509certs(x509cert_t **firstcert, bool strict)
+void store_x509certs(x509cert_t **firstcert, bool strict)
{
- x509cert_t *cacerts = NULL;
- x509cert_t **pp = firstcert;
+ x509cert_t *cacerts = NULL;
+ x509cert_t **pp = firstcert;
- /* first extract CA certs, discarding root CA certs */
+ /* first extract CA certs, discarding root CA certs */
- while (*pp != NULL)
- {
- x509cert_t *cert = *pp;
-
- if (cert->isCA)
+ while (*pp != NULL)
{
- *pp = cert->next;
-
- /* we don't accept self-signed CA certs */
- if (same_dn(cert->issuer, cert->subject))
- {
- plog("self-signed cacert rejected");
- free_x509cert(cert);
- }
- else
- {
- /* insertion into temporary chain of candidate CA certs */
- cert->next = cacerts;
- cacerts = cert;
- }
+ x509cert_t *cert = *pp;
+
+ if (cert->isCA)
+ {
+ *pp = cert->next;
+
+ /* we don't accept self-signed CA certs */
+ if (same_dn(cert->issuer, cert->subject))
+ {
+ plog("self-signed cacert rejected");
+ free_x509cert(cert);
+ }
+ else
+ {
+ /* insertion into temporary chain of candidate CA certs */
+ cert->next = cacerts;
+ cacerts = cert;
+ }
+ }
+ else
+ {
+ pp = &cert->next;
+ }
}
- else
- pp = &cert->next;
- }
- /* now verify the candidate CA certs */
-
- while (cacerts != NULL)
- {
- x509cert_t *cert = cacerts;
+ /* now verify the candidate CA certs */
- cacerts = cacerts->next;
-
- if (trust_authcert_candidate(cert, cacerts))
- {
- add_authcert(cert, AUTH_CA);
- }
- else
+ while (cacerts != NULL)
{
- plog("intermediate cacert rejected");
- free_x509cert(cert);
- }
- }
-
- /* now verify the end certificates */
+ x509cert_t *cert = cacerts;
+
+ cacerts = cacerts->next;
- pp = firstcert;
+ if (trust_authcert_candidate(cert, cacerts))
+ {
+ add_authcert(cert, AUTH_CA);
+ }
+ else
+ {
+ plog("intermediate cacert rejected");
+ free_x509cert(cert);
+ }
+ }
+
+ /* now verify the end certificates */
- while (*pp != NULL)
- {
- time_t valid_until;
- x509cert_t *cert = *pp;
+ pp = firstcert;
- if (verify_x509cert(cert, strict, &valid_until))
+ while (*pp != NULL)
{
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("public key validated")
- )
- add_x509_public_key(cert, valid_until, DAL_SIGNED);
- }
- else
- {
- plog("X.509 certificate rejected");
+ time_t valid_until;
+ x509cert_t *cert = *pp;
+
+ if (verify_x509cert(cert, strict, &valid_until))
+ {
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log("public key validated")
+ )
+ add_x509_public_key(cert, valid_until, DAL_SIGNED);
+ }
+ else
+ {
+ plog("X.509 certificate rejected");
+ }
+ *pp = cert->next;
+ free_x509cert(cert);
}
- *pp = cert->next;
- free_x509cert(cert);
- }
}
-/*
- * decrypts an RSA signature using the issuer's certificate
+/**
+ * Check if a signature over binary blob is genuine
*/
-static bool
-decrypt_sig(chunk_t sig, int alg, const x509cert_t *issuer_cert,
- chunk_t *digest)
+bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
+ const x509cert_t *issuer_cert)
{
- switch (alg)
- {
- chunk_t decrypted;
-
- case OID_RSA_ENCRYPTION:
- case OID_MD2_WITH_RSA:
- case OID_MD5_WITH_RSA:
- case OID_SHA1_WITH_RSA:
- case OID_SHA1_WITH_RSA_OIW:
- case OID_SHA256_WITH_RSA:
- case OID_SHA384_WITH_RSA:
- case OID_SHA512_WITH_RSA:
+ public_key_t *key = issuer_cert->public_key;
+ signature_scheme_t scheme = signature_scheme_from_oid(algorithm);
+
+ if (scheme == SIGN_UNKNOWN)
{
- mpz_t s;
- RSA_public_key_t rsa;
-
- init_RSA_public_key(&rsa, issuer_cert->publicExponent
- , issuer_cert->modulus);
-
- /* decrypt the signature s = s^e mod n */
- n_to_mpz(s, sig.ptr, sig.len);
- mpz_powm(s, s, &rsa.e, &rsa.n);
-
- /* convert back to bytes */
- decrypted = mpz_to_n(s, rsa.k);
- DBG(DBG_PARSING,
- DBG_dump_chunk(" decrypted signature: ", decrypted)
- )
-
- /* copy the least significant bits of decrypted signature
- * into the digest string
- */
- memcpy(digest->ptr, decrypted.ptr + decrypted.len - digest->len,
- digest->len);
-
- /* free memory */
- free_RSA_public_content(&rsa);
- pfree(decrypted.ptr);
- mpz_clear(s);
- return TRUE;
+ return FALSE;
}
- default:
- digest->len = 0;
- return FALSE;
- }
+ return key->verify(key, scheme, tbs, sig);
}
-/*
- * Check if a signature over binary blob is genuine
+/**
+ * Build an ASN.1 encoded PKCS#1 signature over a binary blob
*/
-bool
-check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg
-, const x509cert_t *issuer_cert)
+chunk_t x509_build_signature(chunk_t tbs, int algorithm, private_key_t *key,
+ bool bit_string)
{
- u_char digest_buf[MAX_DIGEST_LEN];
- u_char decrypted_buf[MAX_DIGEST_LEN];
- chunk_t digest = {digest_buf, MAX_DIGEST_LEN};
- chunk_t decrypted = {decrypted_buf, MAX_DIGEST_LEN};
-
- DBG(DBG_PARSING,
- if (digest_alg != OID_UNKNOWN)
- DBG_log("signature digest algorithm: '%s'",oid_names[digest_alg].name);
- else
- DBG_log("unknown signature digest algorithm");
- )
+ chunk_t signature;
+ signature_scheme_t scheme = signature_scheme_from_oid(algorithm);
- if (!compute_digest(tbs, digest_alg, &digest))
- {
- plog(" digest algorithm not supported");
- return FALSE;
- }
-
- DBG(DBG_PARSING,
- DBG_dump_chunk(" digest:", digest)
- )
-
- decrypted.len = digest.len; /* we want the same digest length */
-
- DBG(DBG_PARSING,
- if (enc_alg != OID_UNKNOWN)
- DBG_log("signature encryption algorithm: '%s'",oid_names[enc_alg].name);
- else
- DBG_log("unknown signature encryption algorithm");
- )
-
- if (!decrypt_sig(sig, enc_alg, issuer_cert, &decrypted))
- {
- plog(" decryption algorithm not supported");
- return FALSE;
- }
-
- /* check if digests are equal */
- return !memcmp(decrypted.ptr, digest.ptr, digest.len);
+ if (scheme == SIGN_UNKNOWN || !key->sign(key, scheme, tbs, &signature))
+ {
+ return chunk_empty;
+ }
+ return (bit_string) ? asn1_bitstring("m", signature)
+ : asn1_wrap(ASN1_OCTET_STRING, "m", signature);
}
-/*
- * extracts the basicConstraints extension
+/**
+ * Extracts the basicConstraints extension
*/
-static bool
-parse_basicConstraints(chunk_t blob, int level0)
+static bool parse_basicConstraints(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
- bool isCA = FALSE;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < BASIC_CONSTRAINTS_ROOF) {
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ bool isCA = FALSE;
- if (!extract_object(basicConstraintsObjects, &objectID,
- &object,&level, &ctx))
- break;
+ parser = asn1_parser_create(basicConstraintsObjects, blob);
+ parser->set_top_level(parser, level0);
- if (objectID == BASIC_CONSTRAINTS_CA)
+ while (parser->iterate(parser, &objectID, &object))
{
- isCA = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(isCA)?"TRUE":"FALSE");
- )
+ if (objectID == BASIC_CONSTRAINTS_CA)
+ {
+ isCA = object.len && *object.ptr;
+ DBG(DBG_PARSING,
+ DBG_log(" %s",(isCA)?"TRUE":"FALSE");
+ )
+ }
}
- objectID++;
- }
- return isCA;
+ parser->destroy(parser);
+
+ return isCA;
}
-/*
+/**
* Converts a X.500 generalName into an ID
*/
-void
-gntoid(struct id *id, const generalName_t *gn)
+void gntoid(struct id *id, const generalName_t *gn)
{
- switch(gn->kind)
- {
- case GN_DNS_NAME: /* ID type: ID_FQDN */
- id->kind = ID_FQDN;
- id->name = gn->name;
- break;
- case GN_IP_ADDRESS: /* ID type: ID_IPV4_ADDR */
+ switch(gn->kind)
{
- const struct af_info *afi = &af_inet4_info;
- err_t ugh = NULL;
+ case GN_DNS_NAME: /* ID type: ID_FQDN */
+ id->kind = ID_FQDN;
+ id->name = gn->name;
+ break;
+ case GN_IP_ADDRESS: /* ID type: ID_IPV4_ADDR */
+ {
+ const struct af_info *afi = &af_inet4_info;
+ err_t ugh = NULL;
- id->kind = afi->id_addr;
- ugh = initaddr(gn->name.ptr, gn->name.len, afi->af, &id->ip_addr);
+ id->kind = afi->id_addr;
+ ugh = initaddr(gn->name.ptr, gn->name.len, afi->af, &id->ip_addr);
+ }
+ break;
+ case GN_RFC822_NAME: /* ID type: ID_USER_FQDN */
+ id->kind = ID_USER_FQDN;
+ id->name = gn->name;
+ break;
+ default:
+ id->kind = ID_ANY;
+ id->name = chunk_empty;
}
- break;
- case GN_RFC822_NAME: /* ID type: ID_USER_FQDN */
- id->kind = ID_USER_FQDN;
- id->name = gn->name;
- break;
- default:
- id->kind = ID_NONE;
- id->name = empty_chunk;
- }
}
-/* compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280
+/**
+ * Compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280
* as the 160 bit SHA-1 hash of the public key
*/
-void
-compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID)
+bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID)
{
- SHA1_CTX context;
-
- SHA1Init(&context);
- SHA1Update(&context
- , cert->subjectPublicKey.ptr
- , cert->subjectPublicKey.len);
- SHA1Final(subjectKeyID.ptr, &context);
- subjectKeyID.len = SHA1_DIGEST_SIZE;
+ identification_t *keyid;
+ chunk_t encoding;
+
+ keyid = cert->public_key->get_id(cert->public_key, ID_PUBKEY_SHA1);
+ if (keyid == NULL)
+ {
+ plog(" unable to compute subjectKeyID");
+ return FALSE;
+ }
+ encoding = keyid->get_encoding(keyid);
+ memcpy(subjectKeyID.ptr, encoding.ptr, subjectKeyID.len);
+ return TRUE;
}
-/*
- * extracts an otherName
+/**
+ * Extracts an otherName
*/
-static bool
-parse_otherName(chunk_t blob, int level0)
+static bool parse_otherName(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
- chunk_t object;
- int objectID = 0;
- u_int level;
- int oid = OID_UNKNOWN;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ int oid = OID_UNKNOWN;
+ bool success = FALSE;
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < ON_OBJ_ROOF)
- {
- if (!extract_object(otherNameObjects, &objectID, &object, &level, &ctx))
- return FALSE;
+ parser = asn1_parser_create(otherNameObjects, blob);
+ parser->set_top_level(parser, level0);
- switch (objectID)
+ while (parser->iterate(parser, &objectID, &object))
{
- case ON_OBJ_ID_TYPE:
- oid = known_oid(object);
- break;
- case ON_OBJ_VALUE:
- if (oid == OID_XMPP_ADDR)
- {
- if (!parse_asn1_simple_object(&object, ASN1_UTF8STRING
- , level + 1, "xmppAddr"))
+ switch (objectID)
{
- return FALSE;
+ case ON_OBJ_ID_TYPE:
+ oid = asn1_known_oid(object);
+ break;
+ case ON_OBJ_VALUE:
+ if (oid == OID_XMPP_ADDR)
+ {
+ if (!asn1_parse_simple_object(&object, ASN1_UTF8STRING,
+ parser->get_level(parser) + 1, "xmppAddr"))
+ {
+ goto end;
+ }
+ }
+ break;
+ default:
+ break;
}
- }
- break;
- default:
- break;
}
- objectID++;
- }
- return TRUE;
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ return success;
}
-/*
- * extracts a generalName
+/**
+ * Extracts a generalName
*/
-static generalName_t*
-parse_generalName(chunk_t blob, int level0)
+static generalName_t* parse_generalName(chunk_t blob, int level0)
{
- u_char buf[BUF_LEN];
- asn1_ctx_t ctx;
- chunk_t object;
- int objectID = 0;
- u_int level;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ u_char buf[BUF_LEN];
+ asn1_parser_t *parser;
+ chunk_t object;
+ generalName_t *gn = NULL;
+ int objectID;
- while (objectID < GN_OBJ_ROOF)
- {
- bool valid_gn = FALSE;
+ parser = asn1_parser_create(generalNameObjects, blob);
+ parser->set_top_level(parser, level0);
- if (!extract_object(generalNameObjects, &objectID, &object, &level, &ctx))
- return NULL;
-
- switch (objectID) {
- case GN_OBJ_RFC822_NAME:
- case GN_OBJ_DNS_NAME:
- case GN_OBJ_URI:
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", (int)object.len, object.ptr);
- )
- valid_gn = TRUE;
- break;
- case GN_OBJ_DIRECTORY_NAME:
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'", buf)
- )
- valid_gn = TRUE;
- break;
- case GN_OBJ_IP_ADDRESS:
- DBG(DBG_PARSING,
- DBG_log(" '%d.%d.%d.%d'", *object.ptr, *(object.ptr+1),
- *(object.ptr+2), *(object.ptr+3));
- )
- valid_gn = TRUE;
- break;
- case GN_OBJ_OTHER_NAME:
- if (!parse_otherName(object, level + 1))
- return NULL;
- break;
- case GN_OBJ_X400_ADDRESS:
- case GN_OBJ_EDI_PARTY_NAME:
- case GN_OBJ_REGISTERED_ID:
- break;
- default:
- break;
- }
-
- if (valid_gn)
+ while (parser->iterate(parser, &objectID, &object))
{
- generalName_t *gn = alloc_thing(generalName_t, "generalName");
- gn->kind = (objectID - GN_OBJ_OTHER_NAME) / 2;
- gn->name = object;
- gn->next = NULL;
- return gn;
- }
- objectID++;
- }
- return NULL;
-}
-
-
-/*
- * extracts one or several GNs and puts them into a chained list
- */
-static generalName_t*
-parse_generalNames(chunk_t blob, int level0, bool implicit)
-{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
-
- generalName_t *top_gn = NULL;
-
- asn1_init(&ctx, blob, level0, implicit, DBG_RAW);
+ bool valid_gn = FALSE;
+
+ switch (objectID) {
+ case GN_OBJ_RFC822_NAME:
+ case GN_OBJ_DNS_NAME:
+ case GN_OBJ_URI:
+ DBG(DBG_PARSING,
+ DBG_log(" '%.*s'", (int)object.len, object.ptr);
+ )
+ valid_gn = TRUE;
+ break;
+ case GN_OBJ_DIRECTORY_NAME:
+ DBG(DBG_PARSING,
+ dntoa(buf, BUF_LEN, object);
+ DBG_log(" '%s'", buf)
+ )
+ valid_gn = TRUE;
+ break;
+ case GN_OBJ_IP_ADDRESS:
+ DBG(DBG_PARSING,
+ DBG_log(" '%d.%d.%d.%d'", *object.ptr, *(object.ptr+1),
+ *(object.ptr+2), *(object.ptr+3));
+ )
+ valid_gn = TRUE;
+ break;
+ case GN_OBJ_OTHER_NAME:
+ if (!parse_otherName(object, parser->get_level(parser)+1))
+ {
+ goto end;
+ }
+ break;
+ case GN_OBJ_X400_ADDRESS:
+ case GN_OBJ_EDI_PARTY_NAME:
+ case GN_OBJ_REGISTERED_ID:
+ break;
+ default:
+ break;
+ }
- while (objectID < GENERAL_NAMES_ROOF)
- {
- if (!extract_object(generalNamesObjects, &objectID, &object, &level, &ctx))
- return NULL;
-
- if (objectID == GENERAL_NAMES_GN)
- {
- generalName_t *gn = parse_generalName(object, level+1);
- if (gn != NULL)
- {
- gn->next = top_gn;
- top_gn = gn;
- }
+ if (valid_gn)
+ {
+ gn = malloc_thing(generalName_t);
+ gn->kind = (objectID - GN_OBJ_OTHER_NAME) / 2;
+ gn->name = object;
+ gn->next = NULL;
+ goto end;
+ }
}
- objectID++;
- }
- return top_gn;
+
+end:
+ parser->destroy(parser);
+ return gn;
}
-/*
- * returns a directoryName
+/**
+ * Extracts one or several GNs and puts them into a chained list
*/
-chunk_t get_directoryName(chunk_t blob, int level, bool implicit)
+static generalName_t* parse_generalNames(chunk_t blob, int level0, bool implicit)
{
- chunk_t name = empty_chunk;
- generalName_t * gn = parse_generalNames(blob, level, implicit);
-
- if (gn != NULL && gn->kind == GN_DIRECTORY_NAME)
- name= gn->name;
-
- free_generalNames(gn, FALSE);
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ generalName_t *top_gn = NULL;
+
+ parser = asn1_parser_create(generalNamesObjects, blob);
+ parser->set_top_level(parser, level0);
+ parser->set_flags(parser, implicit, FALSE);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ if (objectID == GENERAL_NAMES_GN)
+ {
+ generalName_t *gn = parse_generalName(object,
+ parser->get_level(parser)+1);
+ if (gn)
+ {
+ gn->next = top_gn;
+ top_gn = gn;
+ }
+ }
+ }
+ parser->destroy(parser);
- return name;
+ return top_gn;
}
-/*
- * extracts and converts a UTCTIME or GENERALIZEDTIME object
+/**
+ * Returns a directoryName
*/
-time_t
-parse_time(chunk_t blob, int level0)
+chunk_t get_directoryName(chunk_t blob, int level, bool implicit)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ chunk_t name = chunk_empty;
+ generalName_t * gn = parse_generalNames(blob, level, implicit);
- while (objectID < TIME_ROOF)
- {
- if (!extract_object(timeObjects, &objectID, &object, &level, &ctx))
- return UNDEFINED_TIME;
-
- if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
+ if (gn != NULL && gn->kind == GN_DIRECTORY_NAME)
{
- return asn1totime(&object, (objectID == TIME_UTC)
- ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
+ name= gn->name;
}
- objectID++;
- }
- return UNDEFINED_TIME;
- }
-
-/*
- * extracts a keyIdentifier
- */
-static chunk_t
-parse_keyIdentifier(chunk_t blob, int level0, bool implicit)
-{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
-
- asn1_init(&ctx, blob, level0, implicit, DBG_RAW);
-
- extract_object(keyIdentifierObjects, &objectID, &object, &level, &ctx);
- return object;
+ free_generalNames(gn, FALSE);
+ return name;
}
-/*
- * extracts an authoritykeyIdentifier
+/**
+ * Extracts an authoritykeyIdentifier
*/
-void
-parse_authorityKeyIdentifier(chunk_t blob, int level0
- , chunk_t *authKeyID, chunk_t *authKeySerialNumber)
+void parse_authorityKeyIdentifier(chunk_t blob, int level0,
+ chunk_t *authKeyID,
+ chunk_t *authKeySerialNumber)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ parser = asn1_parser_create(authKeyIdentifierObjects, blob);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ switch (objectID)
+ {
+ case AUTH_KEY_ID_KEY_ID:
+ *authKeyID = object;
+ break;
+ case AUTH_KEY_ID_CERT_ISSUER:
+ {
+ generalName_t * gn = parse_generalNames(object,
+ parser->get_level(parser) + 1, TRUE);
- while (objectID < AUTH_KEY_ID_ROOF)
- {
- if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx))
- return;
-
- switch (objectID) {
- case AUTH_KEY_ID_KEY_ID:
- *authKeyID = parse_keyIdentifier(object, level+1, TRUE);
- break;
- case AUTH_KEY_ID_CERT_ISSUER:
- {
- generalName_t * gn = parse_generalNames(object, level+1, TRUE);
-
- free_generalNames(gn, FALSE);
- }
- break;
- case AUTH_KEY_ID_CERT_SERIAL:
- *authKeySerialNumber = object;
- break;
- default:
- break;
+ free_generalNames(gn, FALSE);
+ }
+ break;
+ case AUTH_KEY_ID_CERT_SERIAL:
+ *authKeySerialNumber = object;
+ break;
+ default:
+ break;
+ }
}
- objectID++;
- }
+ parser->destroy(parser);
}
-/*
- * extracts an authorityInfoAcess location
+/**
+ * Extracts an authorityInfoAcess location
*/
-static void
-parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation)
+static void parse_authorityInfoAccess(chunk_t blob, int level0,
+ chunk_t *accessLocation)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
- int accessMethod = OID_UNKNOWN;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ int accessMethod = OID_UNKNOWN;
- while (objectID < AUTH_INFO_ACCESS_ROOF)
- {
- if (!extract_object(authorityInfoAccessObjects, &objectID, &object, &level, &ctx))
- return;
-
- switch (objectID) {
- case AUTH_INFO_ACCESS_METHOD:
- accessMethod = known_oid(object);
- break;
- case AUTH_INFO_ACCESS_LOCATION:
- {
- switch (accessMethod)
+ parser = asn1_parser_create(authInfoAccessObjects, blob);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ switch (objectID)
{
- case OID_OCSP:
- if (*object.ptr == ASN1_CONTEXT_S_6)
- {
- if (asn1_length(&object) == ASN1_INVALID_LENGTH)
- return;
-
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'",(int)object.len, object.ptr)
- )
-
- /* only HTTP(S) URIs accepted */
- if (strncasecmp(object.ptr, "http", 4) == 0)
+ case AUTH_INFO_ACCESS_METHOD:
+ accessMethod = asn1_known_oid(object);
+ break;
+ case AUTH_INFO_ACCESS_LOCATION:
{
- *accessLocation = object;
- return;
+ switch (accessMethod)
+ {
+ case OID_OCSP:
+ if (*object.ptr == ASN1_CONTEXT_S_6)
+ {
+ if (asn1_length(&object) == ASN1_INVALID_LENGTH)
+ {
+ goto end;
+ }
+ DBG(DBG_PARSING,
+ DBG_log(" '%.*s'",(int)object.len, object.ptr)
+ )
+
+ /* only HTTP(S) URIs accepted */
+ if (strncasecmp(object.ptr, "http", 4) == 0)
+ {
+ *accessLocation = object;
+ goto end;
+ }
+ }
+ plog("warning: ignoring OCSP InfoAccessLocation with unkown protocol");
+ break;
+ default:
+ /* unkown accessMethod, ignoring */
+ break;
+ }
}
- }
- plog("warning: ignoring OCSP InfoAccessLocation with unkown protocol");
- break;
+ break;
default:
- /* unkown accessMethod, ignoring */
- break;
+ break;
}
- }
- break;
- default:
- break;
}
- objectID++;
- }
-
+
+end:
+ parser->destroy(parser);
}
-/*
- * extracts extendedKeyUsage OIDs
+/**
+ * Extracts extendedKeyUsage OIDs
*/
-static bool
-parse_extendedKeyUsage(chunk_t blob, int level0)
+static bool parse_extendedKeyUsage(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ bool ocsp_signing = FALSE;
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
+ parser = asn1_parser_create(extendedKeyUsageObjects, blob);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ if (objectID == EXT_KEY_USAGE_PURPOSE_ID
+ && asn1_known_oid(object) == OID_OCSP_SIGNING)
+ {
+ ocsp_signing = TRUE;
+ }
+ }
+ parser->destroy(parser);
- while (objectID < EXT_KEY_USAGE_ROOF)
- {
- if (!extract_object(extendedKeyUsageObjects, &objectID
- , &object, &level, &ctx))
- return FALSE;
-
- if (objectID == EXT_KEY_USAGE_PURPOSE_ID
- && known_oid(object) == OID_OCSP_SIGNING)
- return TRUE;
- objectID++;
- }
- return FALSE;
+ return ocsp_signing;
}
-/* extracts one or several crlDistributionPoints and puts them into
- * a chained list
+/**
+ * Extracts one or several crlDistributionPoints
+ * and puts them into a chained list
*/
-static generalName_t*
-parse_crlDistributionPoints(chunk_t blob, int level0)
+static generalName_t* parse_crlDistributionPoints(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
- chunk_t object;
- u_int level;
- int objectID = 0;
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
- generalName_t *top_gn = NULL; /* top of the chained list */
- generalName_t **tail_gn = &top_gn; /* tail of the chained list */
+ generalName_t *top_gn = NULL; /* top of the chained list */
+ generalName_t **tail_gn = &top_gn; /* tail of the chained list */
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < CRL_DIST_POINTS_ROOF)
- {
- if (!extract_object(crlDistributionPointsObjects, &objectID,
- &object, &level, &ctx))
- return NULL;
-
- if (objectID == CRL_DIST_POINTS_FULLNAME)
+ parser = asn1_parser_create(crlDistributionPointsObjects, blob);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
{
- generalName_t *gn = parse_generalNames(object, level+1, TRUE);
- /* append extracted generalNames to existing chained list */
- *tail_gn = gn;
- /* find new tail of the chained list */
- while (gn != NULL)
- {
- tail_gn = &gn->next; gn = gn->next;
- }
+ if (objectID == CRL_DIST_POINTS_FULLNAME)
+ {
+ generalName_t *gn;
+
+ gn = parse_generalNames(object, parser->get_level(parser)+1, TRUE);
+ /* append extracted generalNames to existing chained list */
+ *tail_gn = gn;
+ /* find new tail of the chained list */
+ while (gn != NULL)
+ {
+ tail_gn = &gn->next; gn = gn->next;
+ }
+ }
}
- objectID++;
- }
- return top_gn;
-}
+ parser->destroy(parser);
+ return top_gn;
+}
-/*
+/**
* Parses an X.509v3 certificate
*/
-bool
-parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
+bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
{
- u_char buf[BUF_LEN];
- asn1_ctx_t ctx;
- bool critical;
- chunk_t object;
- u_int level;
- int objectID = 0;
- int extn_oid = OID_UNKNOWN;
-
- asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
-
- while (objectID < X509_OBJ_ROOF)
- {
- if (!extract_object(certObjects, &objectID, &object, &level, &ctx))
- return FALSE;
-
- /* those objects which will parsed further need the next higher level */
- level++;
-
- switch (objectID) {
- case X509_OBJ_CERTIFICATE:
- cert->certificate = object;
- break;
- case X509_OBJ_TBS_CERTIFICATE:
- cert->tbsCertificate = object;
- break;
- case X509_OBJ_VERSION:
- cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
- DBG(DBG_PARSING,
- DBG_log(" v%d", cert->version);
- )
- break;
- case X509_OBJ_SERIAL_NUMBER:
- cert->serialNumber = object;
- break;
- case X509_OBJ_SIG_ALG:
- cert->sigAlg = parse_algorithmIdentifier(object, level, NULL);
- break;
- case X509_OBJ_ISSUER:
- cert->issuer = object;
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'",buf)
- )
- break;
- case X509_OBJ_NOT_BEFORE:
- cert->notBefore = parse_time(object, level);
- break;
- case X509_OBJ_NOT_AFTER:
- cert->notAfter = parse_time(object, level);
- break;
- case X509_OBJ_SUBJECT:
- cert->subject = object;
- DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'",buf)
- )
- break;
- case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM:
- if (parse_algorithmIdentifier(object, level, NULL) == OID_RSA_ENCRYPTION)
- cert->subjectPublicKeyAlgorithm = PUBKEY_ALG_RSA;
- else
- {
- plog(" unsupported public key algorithm");
- return FALSE;
- }
- break;
- case X509_OBJ_SUBJECT_PUBLIC_KEY:
- if (ctx.blobs[4].len > 0 && *ctx.blobs[4].ptr == 0x00)
- {
- /* skip initial bit string octet defining 0 unused bits */
- ctx.blobs[4].ptr++; ctx.blobs[4].len--;
- }
- else
- {
- plog(" invalid RSA public key format");
- return FALSE;
- }
- break;
- case X509_OBJ_RSA_PUBLIC_KEY:
- cert->subjectPublicKey = object;
- break;
- case X509_OBJ_MODULUS:
- if (object.len < RSA_MIN_OCTETS + 1)
- {
- plog(" " RSA_MIN_OCTETS_UGH);
- return FALSE;
- }
- if (object.len > RSA_MAX_OCTETS + (size_t)(*object.ptr == 0x00))
- {
- plog(" " RSA_MAX_OCTETS_UGH);
- return FALSE;
- }
- cert->modulus = object;
- break;
- case X509_OBJ_PUBLIC_EXPONENT:
- cert->publicExponent = object;
- break;
- case X509_OBJ_EXTN_ID:
- extn_oid = known_oid(object);
- break;
- case X509_OBJ_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- break;
- case X509_OBJ_EXTN_VALUE:
- {
- switch (extn_oid) {
- case OID_SUBJECT_KEY_ID:
- cert->subjectKeyID =
- parse_keyIdentifier(object, level, FALSE);
- break;
- case OID_SUBJECT_ALT_NAME:
- cert->subjectAltName =
- parse_generalNames(object, level, FALSE);
- break;
- case OID_BASIC_CONSTRAINTS:
- cert->isCA =
- parse_basicConstraints(object, level);
- break;
- case OID_CRL_DISTRIBUTION_POINTS:
- cert->crlDistributionPoints =
- parse_crlDistributionPoints(object, level);
- break;
- case OID_AUTHORITY_KEY_ID:
- parse_authorityKeyIdentifier(object, level
- , &cert->authKeyID, &cert->authKeySerialNumber);
- break;
- case OID_AUTHORITY_INFO_ACCESS:
- parse_authorityInfoAccess(object, level, &cert->accessLocation);
- break;
- case OID_EXTENDED_KEY_USAGE:
- cert->isOcspSigner = parse_extendedKeyUsage(object, level);
- break;
- case OID_NS_REVOCATION_URL:
- case OID_NS_CA_REVOCATION_URL:
- case OID_NS_CA_POLICY_URL:
- case OID_NS_COMMENT:
- if (!parse_asn1_simple_object(&object, ASN1_IA5STRING
- , level, oid_names[extn_oid].name))
- {
- return FALSE;
- }
- break;
+ u_char buf[BUF_LEN];
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ int extn_oid = OID_UNKNOWN;
+ bool critical;
+ bool success = FALSE;
+
+ parser = asn1_parser_create(certObjects, blob);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser) + 1;
+
+ switch (objectID) {
+ case X509_OBJ_CERTIFICATE:
+ cert->certificate = object;
+ break;
+ case X509_OBJ_TBS_CERTIFICATE:
+ cert->tbsCertificate = object;
+ break;
+ case X509_OBJ_VERSION:
+ cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
+ DBG(DBG_PARSING,
+ DBG_log(" v%d", cert->version);
+ )
+ break;
+ case X509_OBJ_SERIAL_NUMBER:
+ cert->serialNumber = object;
+ break;
+ case X509_OBJ_SIG_ALG:
+ cert->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case X509_OBJ_ISSUER:
+ cert->issuer = object;
+ DBG(DBG_PARSING,
+ dntoa(buf, BUF_LEN, object);
+ DBG_log(" '%s'",buf)
+ )
+ break;
+ case X509_OBJ_NOT_BEFORE:
+ cert->notBefore = asn1_parse_time(object, level);
+ break;
+ case X509_OBJ_NOT_AFTER:
+ cert->notAfter = asn1_parse_time(object, level);
+ break;
+ case X509_OBJ_SUBJECT:
+ cert->subject = object;
+ DBG(DBG_PARSING,
+ dntoa(buf, BUF_LEN, object);
+ DBG_log(" '%s'",buf)
+ )
+ break;
+ case X509_OBJ_SUBJECT_PUBLIC_KEY_INFO:
+ cert->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
+ KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
+ if (cert->public_key == NULL)
+ {
+ goto end;
+ }
+ break;
+ case X509_OBJ_EXTN_ID:
+ extn_oid = asn1_known_oid(object);
+ break;
+ case X509_OBJ_CRITICAL:
+ critical = object.len && *object.ptr;
+ DBG(DBG_PARSING,
+ DBG_log(" %s",(critical)?"TRUE":"FALSE");
+ )
+ break;
+ case X509_OBJ_EXTN_VALUE:
+ {
+ switch (extn_oid) {
+ case OID_SUBJECT_KEY_ID:
+ if (!asn1_parse_simple_object(&object, ASN1_OCTET_STRING,
+ level, "keyIdentifier"))
+ {
+ goto end;
+ }
+ cert->subjectKeyID = object;
+ break;
+ case OID_SUBJECT_ALT_NAME:
+ cert->subjectAltName =
+ parse_generalNames(object, level, FALSE);
+ break;
+ case OID_BASIC_CONSTRAINTS:
+ cert->isCA =
+ parse_basicConstraints(object, level);
+ break;
+ case OID_CRL_DISTRIBUTION_POINTS:
+ cert->crlDistributionPoints =
+ parse_crlDistributionPoints(object, level);
+ break;
+ case OID_AUTHORITY_KEY_ID:
+ parse_authorityKeyIdentifier(object, level
+ , &cert->authKeyID, &cert->authKeySerialNumber);
+ break;
+ case OID_AUTHORITY_INFO_ACCESS:
+ parse_authorityInfoAccess(object, level, &cert->accessLocation);
+ break;
+ case OID_EXTENDED_KEY_USAGE:
+ cert->isOcspSigner = parse_extendedKeyUsage(object, level);
+ break;
+ case OID_NS_REVOCATION_URL:
+ case OID_NS_CA_REVOCATION_URL:
+ case OID_NS_CA_POLICY_URL:
+ case OID_NS_COMMENT:
+ if (!asn1_parse_simple_object(&object, ASN1_IA5STRING
+ , level, oid_names[extn_oid].name))
+ {
+ goto end;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case X509_OBJ_ALGORITHM:
+ cert->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case X509_OBJ_SIGNATURE:
+ cert->signature = object;
+ break;
default:
- break;
+ break;
}
- }
- break;
- case X509_OBJ_ALGORITHM:
- cert->algorithm = parse_algorithmIdentifier(object, level, NULL);
- break;
- case X509_OBJ_SIGNATURE:
- cert->signature = object;
- break;
- default:
- break;
}
- objectID++;
- }
- time(&cert->installed);
- return TRUE;
+ success = parser->success(parser);
+ time(&cert->installed);
+
+end:
+ parser->destroy(parser);
+ return success;
}
-/* verify the validity of a certificate by
+/**
+ * Verify the validity of a certificate by
* checking the notBefore and notAfter dates
*/
-err_t
-check_validity(const x509cert_t *cert, time_t *until)
+err_t check_validity(const x509cert_t *cert, time_t *until)
{
- time_t current_time;
+ time_t current_time;
- time(&current_time);
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log(" not before : %s", timetoa(&cert->notBefore, TRUE));
- DBG_log(" current time: %s", timetoa(&current_time, TRUE));
- DBG_log(" not after : %s", timetoa(&cert->notAfter, TRUE));
- )
-
- if (cert->notAfter < *until) *until = cert->notAfter;
+ time(&current_time);
+ DBG(DBG_CONTROL | DBG_PARSING ,
+ DBG_log(" not before : %T", &cert->notBefore, TRUE);
+ DBG_log(" current time: %T", &current_time, TRUE);
+ DBG_log(" not after : %T", &cert->notAfter, TRUE);
+ )
- if (current_time < cert->notBefore)
- return "certificate is not valid yet";
- if (current_time > cert->notAfter)
- return "certificate has expired";
- else
- return NULL;
+ if (cert->notAfter < *until)
+ {
+ *until = cert->notAfter;
+ }
+ if (current_time < cert->notBefore)
+ {
+ return "certificate is not valid yet";
+ }
+ if (current_time > cert->notAfter)
+ {
+ return "certificate has expired";
+ }
+ else
+ {
+ return NULL;
+ }
}
-/*
- * verifies a X.509 certificate
+/**
+ * Verifies a X.509 certificate
*/
-bool
-verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
+bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
{
- int pathlen;
+ int pathlen;
- *until = cert->notAfter;
+ *until = cert->notAfter;
- for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
- {
- x509cert_t *issuer_cert;
- u_char buf[BUF_LEN];
- err_t ugh = NULL;
-
- DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, cert->subject);
- DBG_log("subject: '%s'",buf);
- dntoa(buf, BUF_LEN, cert->issuer);
- DBG_log("issuer: '%s'",buf);
- if (cert->authKeyID.ptr != NULL)
- {
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
- }
- )
+ for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+ {
+ x509cert_t *issuer_cert;
+ u_char buf[BUF_LEN];
+ err_t ugh = NULL;
- ugh = check_validity(cert, until);
+ DBG(DBG_CONTROL,
+ dntoa(buf, BUF_LEN, cert->subject);
+ DBG_log("subject: '%s'",buf);
+ dntoa(buf, BUF_LEN, cert->issuer);
+ DBG_log("issuer: '%s'",buf);
+ if (cert->authKeyID.ptr != NULL)
+ {
+ datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
+ , buf, BUF_LEN);
+ DBG_log("authkey: %s", buf);
+ }
+ )
- if (ugh != NULL)
- {
- plog("%s", ugh);
- return FALSE;
- }
+ ugh = check_validity(cert, until);
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
+ if (ugh != NULL)
+ {
+ plog("%s", ugh);
+ return FALSE;
+ }
- lock_authcert_list("verify_x509cert");
- issuer_cert = get_authcert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, AUTH_CA);
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is valid")
+ )
- if (issuer_cert == NULL)
- {
- plog("issuer cacert not found");
- unlock_authcert_list("verify_x509cert");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("issuer cacert found")
- )
+ lock_authcert_list("verify_x509cert");
+ issuer_cert = get_authcert(cert->issuer, cert->authKeySerialNumber
+ , cert->authKeyID, AUTH_CA);
- if (!check_signature(cert->tbsCertificate, cert->signature
- , cert->algorithm, cert->algorithm, issuer_cert))
- {
- plog("certificate signature is invalid");
- unlock_authcert_list("verify_x509cert");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate signature is valid")
- )
- unlock_authcert_list("verify_x509cert");
+ if (issuer_cert == NULL)
+ {
+ plog("issuer cacert not found");
+ unlock_authcert_list("verify_x509cert");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("issuer cacert found")
+ )
- /* check if cert is a self-signed root ca */
- if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
- {
- DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca")
- )
- return TRUE;
- }
- else
- {
- time_t nextUpdate = *until;
- time_t revocationDate = UNDEFINED_TIME;
- crl_reason_t revocationReason = REASON_UNSPECIFIED;
-
- /* first check certificate revocation using ocsp */
- cert_status_t status = verify_by_ocsp(cert, &nextUpdate
- , &revocationDate, &revocationReason);
-
- /* if ocsp service is not available then fall back to crl */
- if ((status == CERT_UNDEFINED)
- || (status == CERT_UNKNOWN && strict))
- {
- status = verify_by_crl(cert, &nextUpdate, &revocationDate
- , &revocationReason);
- }
-
- switch (status)
- {
- case CERT_GOOD:
- /* if status information is stale */
- if (strict && nextUpdate < time(NULL))
+ if (!x509_check_signature(cert->tbsCertificate, cert->signature,
+ cert->algorithm, issuer_cert))
{
- DBG(DBG_CONTROL,
- DBG_log("certificate is good but status is stale")
- )
- remove_x509_public_key(cert);
- return FALSE;
+ plog("certificate signature is invalid");
+ unlock_authcert_list("verify_x509cert");
+ return FALSE;
}
DBG(DBG_CONTROL,
- DBG_log("certificate is good")
+ DBG_log("certificate signature is valid")
)
-
- /* with strict crl policy the public key must have the same
- * lifetime as the validity of the ocsp status or crl lifetime
- */
- if (strict && nextUpdate < *until)
- *until = nextUpdate;
- break;
- case CERT_REVOKED:
- plog("certificate was revoked on %s, reason: %s"
- , timetoa(&revocationDate, TRUE)
- , enum_name(&crl_reason_names, revocationReason));
- remove_x509_public_key(cert);
- return FALSE;
- case CERT_UNKNOWN:
- case CERT_UNDEFINED:
- default:
- plog("certificate status unknown");
- if (strict)
+ unlock_authcert_list("verify_x509cert");
+
+ /* check if cert is a self-signed root ca */
+ if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
{
- remove_x509_public_key(cert);
- return FALSE;
+ DBG(DBG_CONTROL,
+ DBG_log("reached self-signed root ca")
+ )
+ return TRUE;
}
- break;
- }
- }
+ else
+ {
+ time_t nextUpdate = *until;
+ time_t revocationDate = UNDEFINED_TIME;
+ crl_reason_t revocationReason = REASON_UNSPECIFIED;
- /* go up one step in the trust chain */
- cert = issuer_cert;
- }
- plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
- return FALSE;
+ /* first check certificate revocation using ocsp */
+ cert_status_t status = verify_by_ocsp(cert, &nextUpdate
+ , &revocationDate, &revocationReason);
+
+ /* if ocsp service is not available then fall back to crl */
+ if ((status == CERT_UNDEFINED)
+ || (status == CERT_UNKNOWN && strict))
+ {
+ status = verify_by_crl(cert, &nextUpdate, &revocationDate
+ , &revocationReason);
+ }
+
+ switch (status)
+ {
+ case CERT_GOOD:
+ /* if status information is stale */
+ if (strict && nextUpdate < time(NULL))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is good but status is stale")
+ )
+ remove_x509_public_key(cert);
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is good")
+ )
+
+ /* with strict crl policy the public key must have the same
+ * lifetime as the validity of the ocsp status or crl lifetime
+ */
+ if (strict && nextUpdate < *until)
+ {
+ *until = nextUpdate;
+ }
+ break;
+ case CERT_REVOKED:
+ plog("certificate was revoked on %T, reason: %N"
+ , &revocationDate, TRUE
+ , crl_reason_names, revocationReason);
+ remove_x509_public_key(cert);
+ return FALSE;
+ case CERT_UNKNOWN:
+ case CERT_UNDEFINED:
+ default:
+ plog("certificate status unknown");
+ if (strict)
+ {
+ remove_x509_public_key(cert);
+ return FALSE;
+ }
+ break;
+ }
+ }
+
+ /* go up one step in the trust chain */
+ cert = issuer_cert;
+ }
+ plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ return FALSE;
}
-/*
- * list all X.509 certs in a chained list
+/**
+ * List all X.509 certs in a chained list
*/
-void
-list_x509cert_chain(const char *caption, x509cert_t* cert, u_char auth_flags
- , bool utc)
+void list_x509cert_chain(const char *caption, x509cert_t* cert,
+ u_char auth_flags, bool utc)
{
- bool first = TRUE;
- time_t now;
+ bool first = TRUE;
+ time_t now;
- /* determine the current time */
- time(&now);
+ /* determine the current time */
+ time(&now);
- while (cert != NULL)
- {
- if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags))
+ while (cert != NULL)
{
- unsigned keysize;
- char keyid[KEYID_BUF];
- u_char buf[BUF_LEN];
- cert_t c;
-
- c.type = CERT_X509_SIGNATURE;
- c.u.x509 = cert;
-
- if (first)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 %s Certificates:", caption);
- whack_log(RC_COMMENT, " ");
- first = FALSE;
- }
-
- whack_log(RC_COMMENT, "%s, count: %d", timetoa(&cert->installed, utc),
- cert->count);
- dntoa(buf, BUF_LEN, cert->subject);
- whack_log(RC_COMMENT, " subject: '%s'", buf);
- dntoa(buf, BUF_LEN, cert->issuer);
- whack_log(RC_COMMENT, " issuer: '%s'", buf);
- datatot(cert->serialNumber.ptr, cert->serialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " serial: %s", buf);
- form_keyid(cert->publicExponent, cert->modulus, keyid, &keysize);
- whack_log(RC_COMMENT, " pubkey: %4d RSA Key %s%s"
- , 8*keysize, keyid
- , cert->smartcard ? ", on smartcard" :
- (has_private_key(c)? ", has private key" : ""));
- whack_log(RC_COMMENT, " validity: not before %s %s",
- timetoa(&cert->notBefore, utc),
- (cert->notBefore < now)?"ok":"fatal (not valid yet)");
- whack_log(RC_COMMENT, " not after %s %s",
- timetoa(&cert->notAfter, utc),
- check_expiry(cert->notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
- if (cert->subjectKeyID.ptr != NULL)
- {
- datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " subjkey: %s", buf);
- }
- if (cert->authKeyID.ptr != NULL)
- {
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
- }
- if (cert->authKeySerialNumber.ptr != NULL)
- {
- datatot(cert->authKeySerialNumber.ptr, cert->authKeySerialNumber.len
- , ':', buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
- }
+ if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags))
+ {
+ u_char buf[BUF_LEN];
+ public_key_t *key = cert->public_key;
+ cert_t c;
+
+ c.type = CERT_X509_SIGNATURE;
+ c.u.x509 = cert;
+
+ if (first)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of X.509 %s Certificates:", caption);
+ whack_log(RC_COMMENT, " ");
+ first = FALSE;
+ }
+
+ whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc,
+ cert->count);
+ dntoa(buf, BUF_LEN, cert->subject);
+ whack_log(RC_COMMENT, " subject: '%s'", buf);
+ dntoa(buf, BUF_LEN, cert->issuer);
+ whack_log(RC_COMMENT, " issuer: '%s'", buf);
+ datatot(cert->serialNumber.ptr, cert->serialNumber.len, ':',
+ buf, BUF_LEN);
+ whack_log(RC_COMMENT, " serial: %s", buf);
+ whack_log(RC_COMMENT, " validity: not before %T %s",
+ &cert->notBefore, utc,
+ (cert->notBefore < now)?"ok":"fatal (not valid yet)");
+ whack_log(RC_COMMENT, " not after %T %s",
+ &cert->notAfter, utc,
+ check_expiry(cert->notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
+ key_type_names, key->get_type(key),
+ key->get_keysize(key) * BITS_PER_BYTE,
+ cert->smartcard ? ", on smartcard" :
+ (has_private_key(c)? ", has private key" : ""));
+ whack_log(RC_COMMENT, " keyid: %Y",
+ key->get_id(key, ID_PUBKEY_INFO_SHA1));
+ if (cert->subjectKeyID.ptr != NULL)
+ {
+ datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':',
+ buf, BUF_LEN);
+ whack_log(RC_COMMENT, " subjkey: %s", buf);
+ }
+ if (cert->authKeyID.ptr != NULL)
+ {
+ datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':',
+ buf, BUF_LEN);
+ whack_log(RC_COMMENT, " authkey: %s", buf);
+ }
+ if (cert->authKeySerialNumber.ptr != NULL)
+ {
+ datatot(cert->authKeySerialNumber.ptr,
+ cert->authKeySerialNumber.len, ':', buf, BUF_LEN);
+ whack_log(RC_COMMENT, " aserial: %s", buf);
+ }
+ }
+ cert = cert->next;
}
- cert = cert->next;
- }
}
-/*
- * list all X.509 end certificates in a chained list
+/**
+ * List all X.509 end certificates in a chained list
*/
-void
-list_x509_end_certs(bool utc)
+void list_x509_end_certs(bool utc)
{
- list_x509cert_chain("End", x509certs, AUTH_NONE, utc);
+ list_x509cert_chain("End", x509certs, AUTH_NONE, utc);
}
diff --git a/src/pluto/x509.h b/src/pluto/x509.h
index 67730bbd0..ab0fbac9e 100644
--- a/src/pluto/x509.h
+++ b/src/pluto/x509.h
@@ -2,7 +2,7 @@
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
* Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2000-2009 Andreas Steffen, Hochschule fuer Technik Rapperswil
*
* 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
@@ -13,28 +13,29 @@
* 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: x509.h 3252 2007-10-06 21:24:50Z andreas $
*/
#ifndef _X509_H
#define _X509_H
-#include "pkcs1.h"
+#include <credentials/keys/public_key.h>
+#include <credentials/keys/private_key.h>
+
+#include "constants.h"
#include "id.h"
/* Definition of generalNames kinds */
typedef enum {
- GN_OTHER_NAME = 0,
- GN_RFC822_NAME = 1,
- GN_DNS_NAME = 2,
- GN_X400_ADDRESS = 3,
- GN_DIRECTORY_NAME = 4,
- GN_EDI_PARTY_NAME = 5,
- GN_URI = 6,
- GN_IP_ADDRESS = 7,
- GN_REGISTERED_ID = 8
+ GN_OTHER_NAME = 0,
+ GN_RFC822_NAME = 1,
+ GN_DNS_NAME = 2,
+ GN_X400_ADDRESS = 3,
+ GN_DIRECTORY_NAME = 4,
+ GN_EDI_PARTY_NAME = 5,
+ GN_URI = 6,
+ GN_IP_ADDRESS = 7,
+ GN_REGISTERED_ID = 8
} generalNames_t;
/* access structure for a GeneralName */
@@ -42,9 +43,9 @@ typedef enum {
typedef struct generalName generalName_t;
struct generalName {
- generalName_t *next;
- generalNames_t kind;
- chunk_t name;
+ generalName_t *next;
+ generalNames_t kind;
+ chunk_t name;
};
/* access structure for an X.509v3 certificate */
@@ -52,46 +53,42 @@ struct generalName {
typedef struct x509cert x509cert_t;
struct x509cert {
- x509cert_t *next;
- time_t installed;
- int count;
- bool smartcard;
- u_char authority_flags;
- chunk_t certificate;
- chunk_t tbsCertificate;
- u_int version;
- chunk_t serialNumber;
- /* signature */
- int sigAlg;
- chunk_t issuer;
- /* validity */
- time_t notBefore;
- time_t notAfter;
- chunk_t subject;
- /* subjectPublicKeyInfo */
- enum pubkey_alg subjectPublicKeyAlgorithm;
- chunk_t subjectPublicKey;
- chunk_t modulus;
- chunk_t publicExponent;
- /* issuerUniqueID */
- /* subjectUniqueID */
- /* v3 extensions */
- /* extension */
- /* extension */
- /* extnID */
- /* critical */
- /* extnValue */
- bool isCA;
- bool isOcspSigner; /* ocsp */
- chunk_t subjectKeyID;
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- chunk_t accessLocation; /* ocsp */
- generalName_t *subjectAltName;
- generalName_t *crlDistributionPoints;
- /* signatureAlgorithm */
- int algorithm;
- chunk_t signature;
+ x509cert_t *next;
+ time_t installed;
+ int count;
+ bool smartcard;
+ u_char authority_flags;
+ chunk_t certificate;
+ chunk_t tbsCertificate;
+ u_int version;
+ chunk_t serialNumber;
+ /* signature */
+ int sigAlg;
+ chunk_t issuer;
+ /* validity */
+ time_t notBefore;
+ time_t notAfter;
+ chunk_t subject;
+ public_key_t *public_key;
+ /* issuerUniqueID */
+ /* subjectUniqueID */
+ /* v3 extensions */
+ /* extension */
+ /* extension */
+ /* extnID */
+ /* critical */
+ /* extnValue */
+ bool isCA;
+ bool isOcspSigner; /* ocsp */
+ chunk_t subjectKeyID;
+ chunk_t authKeyID;
+ chunk_t authKeySerialNumber;
+ chunk_t accessLocation; /* ocsp */
+ generalName_t *subjectAltName;
+ generalName_t *crlDistributionPoints;
+ /* signatureAlgorithm */
+ int algorithm;
+ chunk_t signature;
};
/* used for initialization */
@@ -105,33 +102,37 @@ extern bool same_x509cert(const x509cert_t *a, const x509cert_t *b);
extern void hex_str(chunk_t bin, chunk_t *str);
extern int dn_count_wildcards(chunk_t dn);
extern int dntoa(char *dst, size_t dstlen, chunk_t dn);
-extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn
- , const char* null_dn);
+extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn,
+ const char* null_dn);
extern err_t atodn(char *src, chunk_t *dn);
extern void gntoid(struct id *id, const generalName_t *gn);
-extern void compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID);
+extern bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID);
extern void select_x509cert_id(x509cert_t *cert, struct id *end_id);
extern bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert);
extern time_t parse_time(chunk_t blob, int level0);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0
- , chunk_t *authKeyID, chunk_t *authKeySerialNumber);
+ , chunk_t *authKeyID, chunk_t *authKeySerialNumber);
extern chunk_t get_directoryName(chunk_t blob, int level, bool implicit);
extern err_t check_validity(const x509cert_t *cert, time_t *until);
-extern bool check_signature(chunk_t tbs, chunk_t sig, int digest_alg
- , int enc_alg, const x509cert_t *issuer_cert);
+
+extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
+ const x509cert_t *issuer_cert);
+extern chunk_t x509_build_signature(chunk_t tbs, int algorithm,
+ private_key_t *key, bool bit_string);
+
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until);
extern x509cert_t* add_x509cert(x509cert_t *cert);
-extern x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid
- , x509cert_t* chain);
-extern void build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key
- , const RSA_private_key_t *signer_key);
+extern x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid,
+ x509cert_t* chain);
+extern void build_x509cert(x509cert_t *cert, public_key_t *cert_key,
+ private_key_t *signer_key);
extern chunk_t build_subjectAltNames(generalName_t *subjectAltNames);
extern void share_x509cert(x509cert_t *cert);
extern void release_x509cert(x509cert_t *cert);
extern void free_x509cert(x509cert_t *cert);
extern void store_x509certs(x509cert_t **firstcert, bool strict);
-extern void list_x509cert_chain(const char *caption, x509cert_t* cert
- , u_char auth_flags, bool utc);
+extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
+ u_char auth_flags, bool utc);
extern void list_x509_end_certs(bool utc);
extern void free_generalNames(generalName_t* gn, bool free_name);
diff --git a/src/pluto/xauth.c b/src/pluto/xauth.c
index 8f4dc2460..af2d72d71 100644
--- a/src/pluto/xauth.c
+++ b/src/pluto/xauth.c
@@ -11,8 +11,6 @@
* 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: xauth.c 3738 2008-04-02 19:04:45Z andreas $
*/
#include <dlfcn.h>
@@ -29,51 +27,51 @@ void
xauth_init(void)
{
#ifdef XAUTH_DEFAULT_LIB
- xauth_module.handle = dlopen(XAUTH_DEFAULT_LIB, RTLD_NOW);
+ xauth_module.handle = dlopen(XAUTH_DEFAULT_LIB, RTLD_NOW);
- if (xauth_module.handle != NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("xauth module '%s' loading'", XAUTH_DEFAULT_LIB)
- )
- xauth_module.get_secret = (bool (*) (const xauth_t*))
- dlsym(xauth_module.handle, "get_secret");
- DBG(DBG_CONTROL,
- if (xauth_module.get_secret != NULL)
- {
- DBG_log("xauth module: found get_secret() function");
- }
- )
- xauth_module.verify_secret = (bool (*) (const xauth_peer_t*, const xauth_t*))
- dlsym(xauth_module.handle, "verify_secret");
- DBG(DBG_CONTROL,
- if (xauth_module.verify_secret != NULL)
- {
- DBG_log("xauth module: found verify_secret() function");
- }
- )
- }
+ if (xauth_module.handle != NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module '%s' loading'", XAUTH_DEFAULT_LIB)
+ )
+ xauth_module.get_secret = (bool (*) (const xauth_t*))
+ dlsym(xauth_module.handle, "get_secret");
+ DBG(DBG_CONTROL,
+ if (xauth_module.get_secret != NULL)
+ {
+ DBG_log("xauth module: found get_secret() function");
+ }
+ )
+ xauth_module.verify_secret = (bool (*) (const xauth_peer_t*, const xauth_t*))
+ dlsym(xauth_module.handle, "verify_secret");
+ DBG(DBG_CONTROL,
+ if (xauth_module.verify_secret != NULL)
+ {
+ DBG_log("xauth module: found verify_secret() function");
+ }
+ )
+ }
#endif
- /* any null function pointers will be filled in by default functions */
- xauth_defaults();
+ /* any null function pointers will be filled in by default functions */
+ xauth_defaults();
}
void
xauth_finalize(void)
{
#ifdef XAUTH_DEFAULT_LIB
- if (xauth_module.handle != NULL)
- {
- if (dlclose(xauth_module.handle))
- {
- plog("failed to unload xauth module");
- }
- else
+ if (xauth_module.handle != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("xauth module unloaded")
- )
+ if (dlclose(xauth_module.handle))
+ {
+ plog("failed to unload xauth module");
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module unloaded")
+ )
+ }
}
- }
#endif
}
diff --git a/src/pluto/xauth.h b/src/pluto/xauth.h
index fd7e5399f..8ab125ac4 100644
--- a/src/pluto/xauth.h
+++ b/src/pluto/xauth.h
@@ -11,8 +11,6 @@
* 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: xauth.h 3738 2008-04-02 19:04:45Z andreas $
*/
#ifndef _XAUTH_H
@@ -26,20 +24,20 @@
struct chunk_t;
typedef struct {
- char *conn_name;
- char id[BUF_LEN];
- char ip_address[ADDRTOT_BUF];
+ char *conn_name;
+ char id[BUF_LEN];
+ char ip_address[ADDRTOT_BUF];
} xauth_peer_t;
typedef struct {
- chunk_t user_name;
- chunk_t user_password;
+ chunk_t user_name;
+ chunk_t user_password;
} xauth_t;
typedef struct {
- void *handle;
- bool (*get_secret) (xauth_t *xauth_secret);
- bool (*verify_secret) (const xauth_peer_t *peer, const xauth_t *xauth_secret);
+ void *handle;
+ bool (*get_secret) (xauth_t *xauth_secret);
+ bool (*verify_secret) (const xauth_peer_t *peer, const xauth_t *xauth_secret);
} xauth_module_t;
extern xauth_module_t xauth_module;