summaryrefslogtreecommitdiff
path: root/src/pluto
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto')
-rw-r--r--src/pluto/Makefile.am16
-rw-r--r--src/pluto/Makefile.in382
-rw-r--r--src/pluto/ac.c994
-rw-r--r--src/pluto/ac.h90
-rw-r--r--src/pluto/alg_info.c59
-rw-r--r--src/pluto/alg_info.h4
-rw-r--r--src/pluto/builder.c150
-rw-r--r--src/pluto/builder.h (renamed from src/pluto/pem.h)18
-rw-r--r--src/pluto/ca.c486
-rw-r--r--src/pluto/ca.h56
-rw-r--r--src/pluto/certs.c408
-rw-r--r--src/pluto/certs.h47
-rw-r--r--src/pluto/connections.c1392
-rw-r--r--src/pluto/connections.h190
-rw-r--r--src/pluto/constants.c80
-rw-r--r--src/pluto/constants.h258
-rw-r--r--src/pluto/crl.c756
-rw-r--r--src/pluto/crl.h55
-rw-r--r--src/pluto/crypto.c111
-rw-r--r--src/pluto/db_ops.c72
-rw-r--r--src/pluto/demux.c68
-rw-r--r--src/pluto/dnskey.c292
-rw-r--r--src/pluto/dnskey.h40
-rw-r--r--src/pluto/fetch.c331
-rw-r--r--src/pluto/fetch.h33
-rw-r--r--src/pluto/foodgroups.c36
-rw-r--r--src/pluto/id.c523
-rw-r--r--src/pluto/id.h65
-rw-r--r--src/pluto/ike_alg.c47
-rw-r--r--src/pluto/ipsec_doi.c1165
-rw-r--r--src/pluto/ipsec_doi.h8
-rw-r--r--src/pluto/kernel.c189
-rw-r--r--src/pluto/kernel_alg.c79
-rw-r--r--src/pluto/kernel_netlink.c90
-rw-r--r--src/pluto/kernel_noklips.c2
-rw-r--r--src/pluto/kernel_pfkey.c4
-rw-r--r--src/pluto/keys.c353
-rw-r--r--src/pluto/keys.h30
-rw-r--r--src/pluto/log.c23
-rw-r--r--src/pluto/modecfg.c252
-rw-r--r--src/pluto/modecfg.h2
-rw-r--r--src/pluto/myid.c121
-rw-r--r--src/pluto/myid.h38
-rw-r--r--src/pluto/nat_traversal.c18
-rw-r--r--src/pluto/ocsp.c441
-rw-r--r--src/pluto/ocsp.h17
-rw-r--r--src/pluto/packet.c6
-rw-r--r--src/pluto/pem.c127
-rw-r--r--src/pluto/pgpcert.c514
-rw-r--r--src/pluto/pgpcert.h56
-rw-r--r--src/pluto/pkcs7.c349
-rw-r--r--src/pluto/pkcs7.h20
-rw-r--r--src/pluto/plutomain.c42
-rw-r--r--src/pluto/rcv_whack.c204
-rw-r--r--src/pluto/rsaref/pkcs11.h6
-rw-r--r--src/pluto/rsaref/pkcs11f.h16
-rw-r--r--src/pluto/smartcard.c310
-rw-r--r--src/pluto/smartcard.h7
-rw-r--r--src/pluto/spdb.c130
-rw-r--r--src/pluto/state.c24
-rw-r--r--src/pluto/state.h1
-rw-r--r--src/pluto/timer.c6
-rw-r--r--src/pluto/vendor.c14
-rw-r--r--src/pluto/vendor.h2
-rw-r--r--src/pluto/virtual.c18
-rw-r--r--src/pluto/x509.c2062
-rw-r--r--src/pluto/x509.h117
-rw-r--r--src/pluto/xauth.c4
-rw-r--r--src/pluto/xauth.h2
69 files changed, 5320 insertions, 8608 deletions
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am
index c9cb6651f..b83e4be33 100644
--- a/src/pluto/Makefile.am
+++ b/src/pluto/Makefile.am
@@ -20,7 +20,6 @@ demux.c demux.h \
dnskey.c dnskey.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
-id.c id.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
kameipsec.h \
@@ -32,12 +31,11 @@ kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
+myid.c myid.h \
modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
-pem.c pem.h \
-pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \
plutomain.c \
rcv_whack.c rcv_whack.h \
@@ -50,6 +48,7 @@ vendor.c vendor.h \
virtual.c virtual.h \
xauth.c xauth.h \
x509.c x509.h \
+builder.c builder.h \
rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
_pluto_adns_SOURCES = adns.c adns.h
@@ -58,26 +57,25 @@ LIBSTRONGSWANDIR=$(top_builddir)/src/libstrongswan
LIBFREESWANDIR=$(top_builddir)/src/libfreeswan
INCLUDES = \
--I${linuxdir} \
+-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/whack
AM_CFLAGS = \
-DIPSEC_DIR=\"${ipsecdir}\" \
--DIPSEC_CONFDIR=\"${confdir}\" \
+-DIPSEC_CONFDIR=\"${sysconfdir}\" \
-DIPSEC_PIDDIR=\"${piddir}\" \
--DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \
--DIPSEC_PLUGINDIR=\"${plugindir}\" \
+-DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \
-DPLUGINS=\""${pluto_plugins}\"" \
--DSTRONGSWAN_CONF=\"${strongswan_conf}\" \
+-DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" \
-DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES \
-DPLUTO -DKLIPS -DDEBUG
pluto_LDADD = \
$(LIBSTRONGSWANDIR)/libstrongswan.la \
$(LIBFREESWANDIR)/libfreeswan.a \
--lresolv -lpthread $(DLLIB)
+-lresolv $(PTHREADLIB) $(DLLIB)
_pluto_adns_LDADD = \
$(LIBFREESWANDIR)/libfreeswan.a \
diff --git a/src/pluto/Makefile.in b/src/pluto/Makefile.in
index 871f0c905..c93756c44 100644
--- a/src/pluto/Makefile.in
+++ b/src/pluto/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -20,8 +21,9 @@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -58,14 +60,21 @@ subdir = src/pluto
DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man5dir)" \
"$(DESTDIR)$(man8dir)"
-ipsecPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(ipsec_PROGRAMS)
am__pluto_adns_OBJECTS = adns.$(OBJEXT)
_pluto_adns_OBJECTS = $(am__pluto_adns_OBJECTS)
@@ -77,23 +86,24 @@ am_pluto_OBJECTS = ac.$(OBJEXT) alg_info.$(OBJEXT) ca.$(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) \
+ 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) \
+ lex.$(OBJEXT) log.$(OBJEXT) myid.$(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)
+ 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) \
+ builder.$(OBJEXT)
pluto_OBJECTS = $(am_pluto_OBJECTS)
pluto_DEPENDENCIES = $(LIBSTRONGSWANDIR)/libstrongswan.la \
$(LIBFREESWANDIR)/libfreeswan.a $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
+am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -105,6 +115,27 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(_pluto_adns_SOURCES) $(pluto_SOURCES)
DIST_SOURCES = $(_pluto_adns_SOURCES) $(pluto_SOURCES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
man5dir = $(mandir)/man5
man8dir = $(mandir)/man8
NROFF = nroff
@@ -145,25 +176,22 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@
-IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@
LD = @LD@
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@
-LINUX_HEADERS = @LINUX_HEADERS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
@@ -175,11 +203,14 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
RANLIB = @RANLIB@
+RTLIB = @RTLIB@
RUBY = @RUBY@
RUBYINCLUDE = @RUBYINCLUDE@
SED = @SED@
@@ -208,9 +239,9 @@ build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
-confdir = @confdir@
datadir = @datadir@
datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -233,7 +264,7 @@ ipsecuser = @ipsecuser@
libdir = @libdir@
libexecdir = @libexecdir@
libstrongswan_plugins = @libstrongswan_plugins@
-linuxdir = @linuxdir@
+linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
@@ -241,6 +272,7 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
piddir = @piddir@
@@ -249,10 +281,12 @@ pluto_plugins = @pluto_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+random_device = @random_device@
resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
-simreader = @simreader@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -260,6 +294,7 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
pluto_SOURCES = \
@@ -278,7 +313,6 @@ demux.c demux.h \
dnskey.c dnskey.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
-id.c id.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
kameipsec.h \
@@ -290,12 +324,11 @@ kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
+myid.c myid.h \
modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
-pem.c pem.h \
-pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \
plutomain.c \
rcv_whack.c rcv_whack.h \
@@ -308,29 +341,29 @@ vendor.c vendor.h \
virtual.c virtual.h \
xauth.c xauth.h \
x509.c x509.h \
+builder.c builder.h \
rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
_pluto_adns_SOURCES = adns.c adns.h
LIBSTRONGSWANDIR = $(top_builddir)/src/libstrongswan
LIBFREESWANDIR = $(top_builddir)/src/libfreeswan
INCLUDES = \
--I${linuxdir} \
+-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/whack
-AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_CONFDIR=\"${confdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\" \
- -DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \
- -DIPSEC_PLUGINDIR=\"${plugindir}\" \
+AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
+ -DIPSEC_CONFDIR=\"${sysconfdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \
+ -DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \
-DPLUGINS=\""${pluto_plugins}\"" \
- -DSTRONGSWAN_CONF=\"${strongswan_conf}\" -DKERNEL26_SUPPORT \
+ -DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" -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_7)
pluto_LDADD = $(LIBSTRONGSWANDIR)/libstrongswan.la \
- $(LIBFREESWANDIR)/libfreeswan.a -lresolv -lpthread $(DLLIB) \
- $(am__append_6)
+ $(LIBFREESWANDIR)/libfreeswan.a -lresolv $(PTHREADLIB) \
+ $(DLLIB) $(am__append_6)
_pluto_adns_LDADD = \
$(LIBFREESWANDIR)/libfreeswan.a \
-lresolv $(DLLIB)
@@ -349,9 +382,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pluto/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/pluto/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pluto/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/pluto/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -369,34 +402,50 @@ $(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)"
- @list='$(ipsec_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- || test -f $$p1 \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(ipsecPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(ipsecdir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(ipsecPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(ipsecdir)/$$f" || exit 1; \
- else :; fi; \
- done
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \
+ } \
+ ; done
uninstall-ipsecPROGRAMS:
@$(NORMAL_UNINSTALL)
- @list='$(ipsec_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(ipsecdir)/$$f'"; \
- rm -f "$(DESTDIR)$(ipsecdir)/$$f"; \
- done
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files
clean-ipsecPROGRAMS:
- @list='$(ipsec_PROGRAMS)'; for p in $$list; do \
- f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- echo " rm -f $$p $$f"; \
- rm -f $$p $$f ; \
- done
+ @list='$(ipsec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
_pluto_adns$(EXEEXT): $(_pluto_adns_OBJECTS) $(_pluto_adns_DEPENDENCIES)
@rm -f _pluto_adns$(EXEEXT)
$(LINK) $(_pluto_adns_OBJECTS) $(_pluto_adns_LDADD) $(LIBS)
@@ -413,6 +462,7 @@ 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)/builder.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@
@@ -426,7 +476,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnskey.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)/id.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg.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@
@@ -438,11 +487,10 @@ distclean-compile:
@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)/modecfg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/myid.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)/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)/rcv_whack.Po@am__quote@
@@ -458,21 +506,21 @@ distclean-compile:
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
@@ -482,96 +530,82 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-install-man5: $(man5_MANS) $(man_MANS)
+install-man5: $(dist_man_MANS)
@$(NORMAL_INSTALL)
test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)"
- @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.5*) list="$$list $$i" ;; \
- esac; \
+ @list=''; test -n "$(man5dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.5[a-z]*$$/p'; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ fi; \
done; \
- for i in $$list; do \
- if test -f $$i; then file=$$i; \
- else file=$(srcdir)/$$i; fi; \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 5*) ;; \
- *) ext='5' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \
- done
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+ done; }
+
uninstall-man5:
@$(NORMAL_UNINSTALL)
- @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.5*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 5*) ;; \
- *) ext='5' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \
- rm -f "$(DESTDIR)$(man5dir)/$$inst"; \
- done
-install-man8: $(man8_MANS) $(man_MANS)
+ @list=''; test -n "$(man5dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.5[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man5dir)" && rm -f $$files; }
+install-man8: $(dist_man_MANS)
@$(NORMAL_INSTALL)
test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
- @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.8*) list="$$list $$i" ;; \
- esac; \
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.8[a-z]*$$/p'; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
done; \
- for i in $$list; do \
- if test -f $$i; then file=$$i; \
- else file=$(srcdir)/$$i; fi; \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 8*) ;; \
- *) ext='8' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
- done
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
uninstall-man8:
@$(NORMAL_UNINSTALL)
- @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.8*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 8*) ;; \
- *) ext='8' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
- rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
- done
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.8[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; }
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -585,7 +619,7 @@ tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
+ set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -593,34 +627,52 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
list='$(SOURCES) $(HEADERS) $(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; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
+ $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -636,13 +688,17 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@@ -673,6 +729,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -694,6 +751,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -702,18 +761,28 @@ install-data-am: install-ipsecPROGRAMS install-man
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am:
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man: install-man5 install-man8
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -756,6 +825,7 @@ uninstall-man: uninstall-man5 uninstall-man8
uninstall-ipsecPROGRAMS uninstall-man uninstall-man5 \
uninstall-man8
+
# 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/ac.c b/src/pluto/ac.c
index 3b5df9738..d8b16112f 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -1,6 +1,7 @@
/* Support of X.509 attribute certificates
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
* Copyright (C) 2003 Martin Berner, Lukas Suter
+ * Copyright (C) 2009 Andreas Steffen
*
* 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,971 +14,284 @@
* for more details.
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
+#include <sys/stat.h>
#include <time.h>
-#include <sys/types.h>
-#include <freeswan.h>
-
-#include <utils.h>
-#include <asn1/asn1.h>
-#include <asn1/asn1_parser.h>
-#include <asn1/oid.h>
+#include <debug.h>
+#include <utils/enumerator.h>
+#include <utils/linked_list.h>
+#include <credentials/certificates/ac.h>
#include "ac.h"
-#include "x509.h"
-#include "crl.h"
#include "ca.h"
#include "certs.h"
-#include "log.h"
-#include "whack.h"
#include "fetch.h"
+#include "log.h"
/**
* Chained list of X.509 attribute certificates
*/
-static x509acert_t *x509acerts = NULL;
-
-/**
- * Chained list of ietfAttributes
- */
-static ietfAttrList_t *ietfAttributes = NULL;
-
-/**
- * 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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-
-#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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-
-/**
- * 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, "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
-
-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 */
-};
-
+static linked_list_t *acerts = NULL;
/**
- * compare two ietfAttributes, returns zero if a equals b
- * negative/positive if a is earlier/later in the alphabet than b
+ * Initialize the linked list of attribute certificates
*/
-static int cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b)
+void ac_initialize(void)
{
- 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);
-
- return (cmp_value == 0)? cmp_len : cmp_value;
+ acerts = linked_list_create();
}
/**
- * add an ietfAttribute to the chained list
+ * Free the linked list of attribute certificates
*/
-static ietfAttr_t* add_ietfAttr(ietfAttr_t *attr)
+void ac_finalize(void)
{
- 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
+ if (acerts)
{
- 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;
+ acerts->destroy_offset(acerts, offsetof(certificate_t, destroy));
}
}
/**
- * decodes a comma separated list of group attributes
+ * Get a X.509 attribute certificate for a given holder
*/
-void decode_groups(char *groups, ietfAttrList_t **listp)
+certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial)
{
- if (groups == NULL)
- return;
+ enumerator_t *enumerator;
+ certificate_t *cert, *found = NULL;
- while (strlen(groups) > 0)
+ enumerator = acerts->create_enumerator(acerts);
+ while (enumerator->enumerate(enumerator, &cert))
{
- char *end;
- char *next = strchr(groups, ',');
-
- if (next == NULL)
- end = next = groups + strlen(groups);
- else
- end = next++;
-
- /* eat preceeding whitespace */
- while (groups < end && *groups == ' ')
- groups++;
+ ac_t *ac = (ac_t*)cert;
- /* eat trailing whitespace */
- while (end > groups && *(end-1) == ' ')
- end--;
-
- if (groups < end)
+ if (issuer->equals(issuer, ac->get_holderIssuer(ac)) &&
+ chunk_equals(serial, ac->get_holderSerial(ac)))
{
- 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;
-
- el->attr = add_ietfAttr(attr);
- el->next = *listp;
- *listp = el;
+ found = cert;
+ break;
}
-
- groups = next;
}
+ enumerator->destroy(enumerator);
+ return found;
}
-static bool same_attribute(const ietfAttr_t *a, const ietfAttr_t *b)
+/**
+ * Verifies a X.509 attribute certificate
+ */
+bool ac_verify_cert(certificate_t *cert, bool strict)
{
- return (a->kind == b->kind && a->value.len == b->value.len
- && memeq(a->value.ptr, b->value.ptr, b->value.len));
-}
+ ac_t *ac = (ac_t*)cert;
+ identification_t *subject = cert->get_subject(cert);
+ identification_t *issuer = cert->get_issuer(cert);
+ chunk_t authKeyID = ac->get_authKeyIdentifier(ac);
+ cert_t *aacert;
+ time_t notBefore, valid_until;
-bool group_membership(const ietfAttrList_t *peer_list
- , const char *conn
- , const ietfAttrList_t *conn_list)
-{
- if (conn_list == NULL)
- return TRUE;
+ DBG1("holder: '%Y'", subject);
+ DBG1("issuer: '%Y'", issuer);
- while (peer_list != NULL)
+ if (!cert->get_validity(cert, NULL, NULL, &valid_until))
{
- const ietfAttr_t *peer_attr = peer_list->attr;
- const ietfAttrList_t *list = conn_list;
-
- 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;
+ DBG1("attribute certificate is invalid (valid from %T to %T)",
+ &notBefore, FALSE, &valid_until, FALSE);
+ return FALSE;
}
- DBG(DBG_CONTROL,
- DBG_log("%s: peer doesn't match any group", conn)
- )
- return FALSE;
-}
+ DBG1("attribute certificate is valid until %T", &valid_until, FALSE);
-void unshare_ietfAttrList(ietfAttrList_t **listp)
-{
- ietfAttrList_t *list = *listp;
+ lock_authcert_list("verify_x509acert");
+ aacert = get_authcert(issuer, authKeyID, X509_AA);
+ unlock_authcert_list("verify_x509acert");
- while (list != NULL)
+ if (aacert == 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;
+ DBG1("issuer aacert not found");
+ return FALSE;
}
-}
-
-/**
- * Parses ietfAttrSyntax
- */
-static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
+ DBG2("issuer aacert found");
- ietfAttrList_t *list = NULL;
-
- parser = asn1_parser_create(ietfAttrSyntaxObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
+ if (!cert->issued_by(cert, aacert->cert))
{
- 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;
- }
+ DBG1("attribute certificate signature is invalid");
+ return FALSE;
}
- parser->destroy(parser);
- return list;
-}
-
-/**
- * Parses roleSyntax
- */
-static void parse_roleSyntax(chunk_t blob, int level0)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
+ DBG1("attribute certificate signature is valid");
- parser = asn1_parser_create(roleSyntaxObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID)
- {
- default:
- break;
- }
- }
- parser->destroy(parser);
+ return verify_x509cert(aacert, strict, &valid_until);
}
/**
- * Parses an X.509 attribute certificate
+ * Add a X.509 attribute certificate to the chained list
*/
-bool parse_ac(chunk_t blob, x509acert_t *ac)
+static void ac_add_cert(certificate_t *cert)
{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- int type = OID_UNKNOWN;
- int extn_oid = OID_UNKNOWN;
- bool success = FALSE;
- bool critical;
+ ac_t *ac = (ac_t*)cert;
+ identification_t *hIssuer = ac->get_holderIssuer(ac);
+ chunk_t hSerial = ac->get_holderSerial(ac);
- parser = asn1_parser_create(acObjects, blob);
+ enumerator_t *enumerator;
+ certificate_t *cert_old;
- while (parser->iterate(parser, &objectID, &object))
+ enumerator = acerts->create_enumerator(acerts);
+ while (enumerator->enumerate(enumerator, &cert_old))
{
- u_int level = parser->get_level(parser)+1;
+ ac_t *ac_old = (ac_t*)cert_old;
- switch (objectID)
+ if (hIssuer->equals(hIssuer, ac_old->get_holderIssuer(ac_old)) &&
+ chunk_equals(hSerial, ac_old->get_holderSerial(ac_old)))
{
- 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)
+ if (cert->is_newer(cert, cert_old))
{
- plog("v%d attribute certificates are not supported"
- , ac->version);
- goto end;
+ acerts->remove_at(acerts, enumerator);
+ cert_old->destroy(cert_old);
}
- 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:
+ else
{
- 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;
- }
+ cert->destroy(cert);
+ cert = NULL;
}
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;
-
- default:
- break;
}
}
- success = parser->success(parser);
- time(&ac->installed);
-
-end:
- parser->destroy(parser);
- return success;
-}
+ enumerator->destroy(enumerator);
-/**
- * Release an ietfAttribute, free it if count reaches zero
- */
-static void release_ietfAttr(ietfAttr_t* attr)
-{
- if (--attr->count == 0)
+ if (cert)
{
- 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);
+ acerts->insert_last(acerts, cert);
}
}
/**
- * Free an ietfAttrList
+ * Check if at least one peer attribute matches a connection attribute
*/
-void free_ietfAttrList(ietfAttrList_t* list)
+bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn,
+ ietf_attributes_t *conn_attributes)
{
- while (list != NULL)
- {
- ietfAttrList_t *el = list;
-
- release_ietfAttr(el->attr);
- list = list->next;
- free(el);
- }
-}
+ bool match;
-/**
- * Free a X.509 attribute certificate
- */
-void free_acert(x509acert_t *ac)
-{
- if (ac != NULL)
+ if (conn_attributes == 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
- */
-static void free_first_acert(void)
-{
- 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();
-}
-
-/**
- * Get a X.509 attribute certificate for a given holder
- */
-x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial)
-{
- x509acert_t *ac = x509acerts;
- x509acert_t *prev_ac = NULL;
-
- while (ac != NULL)
- {
- 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;
- }
- return NULL;
-}
-
-/**
- * Add a X.509 attribute certificate to the chained list
- */
-static void add_acert(x509acert_t *ac)
-{
- 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
- {
- DBG(DBG_CONTROL,
- DBG_log("attribute cert is not newer - existing cert kept");
- )
- free_acert(ac);
- return;
- }
+ return TRUE;
}
- plog("attribute cert added");
- /* insert new attribute cert at the root of the chain */
- ac->next = x509acerts;
- x509acerts = ac;
-}
+ match = conn_attributes->matches(conn_attributes, peer_attributes);
+ DBG1("%s: peer with attributes '%s' is %sa member of the groups '%s'",
+ conn, peer_attributes->get_string(peer_attributes),
+ match ? "" : "not ", conn_attributes->get_string(conn_attributes));
-/**
- * Verify the validity of an attribute certificate by
- * checking the notBefore and notAfter dates
- */
-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 : %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;
+ return match;
}
/**
- * verifies a X.509 attribute certificate
+ * Loads X.509 attribute certificates
*/
-bool verify_x509acert(x509acert_t *ac, bool strict)
+void ac_load_certs(void)
{
- 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")
- )
+ enumerator_t *enumerator;
+ struct stat st;
+ char *file;
- 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")
- )
+ DBG1("loading attribute certificates from '%s'", A_CERT_PATH);
- if (!x509_check_signature(ac->certificateInfo, ac->signature, ac->algorithm,
- aacert))
+ enumerator = enumerator_create_directory(A_CERT_PATH);
+ if (!enumerator)
{
- plog("attribute certificate signature is invalid");
- return FALSE;
+ return;
}
- 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)
-{
- u_char buf[BUF_LEN];
-
- /* change directory to specified path */
- u_char *save_dir = getcwd(buf, BUF_LEN);
- if (!chdir(A_CERT_PATH))
+ while (enumerator->enumerate(enumerator, NULL, &file, &st))
{
- struct dirent **filelist;
- int n;
+ certificate_t *cert;
- plog("Changing to directory '%s'",A_CERT_PATH);
- n = scandir(A_CERT_PATH, &filelist, file_select, alphasort);
-
- if (n > 0)
+ if (!S_ISREG(st.st_mode))
{
- 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);
+ /* skip special file */
+ continue;
}
- }
- /* 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)
-{
- bool first_group = TRUE;
-
- while (list != NULL && len > 0)
- {
- ietfAttr_t *attr = list->attr;
-
- if (attr->kind == IETF_ATTRIBUTE_OCTETS
- || attr->kind == IETF_ATTRIBUTE_STRING)
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
+ BUILD_FROM_FILE, file, BUILD_END);
+ if (cert)
{
- 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;
+ DBG1(" loaded attribute certificate from '%s'", file);
+ ac_add_cert(cert);
}
- list = list->next;
}
+ enumerator->destroy(enumerator);
}
/**
- * list all X.509 attribute certificates in the chained list
+ * List all X.509 attribute certificates in the chained list
*/
-void list_acerts(bool utc)
+void ac_list_certs(bool utc)
{
- x509acert_t *ac = x509acerts;
+ enumerator_t *enumerator;
+ certificate_t *cert;
time_t now;
/* determine the current time */
time(&now);
- if (ac != NULL)
+ if (acerts->get_count(acerts) > 0)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
- whack_log(RC_COMMENT, " ");
}
- while (ac != NULL)
+ enumerator = acerts->create_enumerator(acerts);
+ while (enumerator->enumerate(enumerator, &cert))
{
- u_char buf[BUF_LEN];
+ ac_t *ac = (ac_t*)cert;
+ identification_t *entityName, *holderIssuer, *issuer;
+ chunk_t holderSerial, serial, authKeyID;
+ time_t notBefore, notAfter;
+ ietf_attributes_t *groups;
- 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)
+ whack_log(RC_COMMENT, " ");
+
+ entityName = cert->get_subject(cert);
+ if (entityName)
{
- datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " hserial: %s", buf);
+ whack_log(RC_COMMENT, " holder: \"%Y\"", entityName);
}
- if (ac->groups != NULL)
+
+ holderIssuer = ac->get_holderIssuer(ac);
+ if (holderIssuer)
{
- format_groups(ac->groups, buf, BUF_LEN);
- whack_log(RC_COMMENT, " groups: %s", buf);
+ whack_log(RC_COMMENT, " hissuer: \"%Y\"", holderIssuer);
}
- 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)
+
+ holderSerial = ac->get_holderSerial(ac);
+ if (holderSerial.ptr)
{
- datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ whack_log(RC_COMMENT, " hserial: %#B", &holderSerial);
}
- if (ac->authKeySerialNumber.ptr != NULL)
+
+ groups = ac->get_groups(ac);
+ if (groups)
{
- datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ whack_log(RC_COMMENT, " groups: %s", groups->get_string(groups));
+ groups->destroy(groups);
}
- ac = ac->next;
- }
-}
+ issuer = cert->get_issuer(cert);
+ whack_log(RC_COMMENT, " issuer: \"%Y\"", issuer);
-/**
- * list all group attributes in alphabetical order
- */
-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, " ");
- }
+ serial = ac->get_serial(ac);
+ whack_log(RC_COMMENT, " serial: %#B", &serial);
- while (list != NULL)
- {
- ietfAttr_t *attr = list->attr;
+ cert->get_validity(cert, &now, &notBefore, &notAfter);
+ whack_log(RC_COMMENT, " validity: not before %T %s",
+ &notBefore, utc,
+ (notBefore < now)?"ok":"fatal (not valid yet)");
+ whack_log(RC_COMMENT, " not after %T %s", &notAfter, utc,
+ check_expiry(notAfter, ACERT_WARNING_INTERVAL, TRUE));
- whack_log(RC_COMMENT, "%T, count: %d", &attr->installed, utc, attr->count);
-
- switch (attr->kind)
+ authKeyID = ac->get_authKeyIdentifier(ac);
+ if (authKeyID.ptr)
{
- 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;
+ whack_log(RC_COMMENT, " authkey: %#B", &authKeyID);
}
-
- list = list->next;
}
+ enumerator->destroy(enumerator);
}
+
diff --git a/src/pluto/ac.h b/src/pluto/ac.h
index bee016143..d4e0c1590 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
-
+ * Copyright (C) 2009 Andreas Steffen
*
* 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,85 +17,23 @@
#ifndef _AC_H
#define _AC_H
-/* definition of ietfAttribute kinds */
-
-typedef enum {
- IETF_ATTRIBUTE_OCTETS = 0,
- IETF_ATTRIBUTE_OID = 1,
- IETF_ATTRIBUTE_STRING = 2
-} ietfAttribute_t;
-
-/* access structure for an ietfAttribute */
-
-typedef struct ietfAttr ietfAttr_t;
-
-struct ietfAttr {
- time_t installed;
- int count;
- ietfAttribute_t kind;
- chunk_t value;
-};
-
-typedef struct ietfAttrList ietfAttrList_t;
-
-struct ietfAttrList {
- ietfAttrList_t *next;
- ietfAttr_t *attr;
-};
-
+#include <utils/identification.h>
+#include <credentials/certificates/certificate.h>
+#include <credentials/ietf_attributes/ietf_attributes.h>
/* access structure for an X.509 attribute certificate */
-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 */
- int sigAlg;
- chunk_t serialNumber;
- /* attrCertValidityPeriod */
- time_t notBefore;
- time_t notAfter;
- /* attributes */
- ietfAttrList_t *charging;
- ietfAttrList_t *groups;
- /* extensions */
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- bool noRevAvail;
- /* signatureAlgorithm */
- int algorithm;
- chunk_t signature;
-};
+extern void ac_initialize(void);
+extern void ac_finalize(void);
+extern void ac_load_certs(void);
+extern void ac_list_certs(bool utc);
-/* used for initialization */
-extern const x509acert_t empty_ac;
+extern certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial);
-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);
-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);
-extern void load_acerts(void);
-extern void free_acert(x509acert_t *ac);
-extern void free_acerts(void);
-extern void list_acerts(bool utc);
-extern void list_groups(bool utc);
-extern void format_groups(const ietfAttrList_t *list, char *buf, int len);
+extern bool ac_verify_cert(certificate_t *ac, bool strict);
+extern bool match_group_membership(ietf_attributes_t *peer_attributes,
+ char *conn,
+ ietf_attributes_t *conn_attributes);
-#endif /* _AH_H */
+#endif /* _AC_H */
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c
index c25418fc1..edecf14c6 100644
--- a/src/pluto/alg_info.c
+++ b/src/pluto/alg_info.c
@@ -51,19 +51,13 @@ int alg_info_esp_aa2sadb(int auth)
{
int sadb_aalg = 0;
- switch(auth) {
+ 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;
@@ -73,20 +67,13 @@ int alg_info_esp_sadb2aa(int sadb_aalg)
{
int auth = 0;
- switch(sadb_aalg) {
+ 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;
@@ -133,7 +120,7 @@ static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id,
DBG(DBG_CRYPT,
DBG_log("esp alg added: %s_%d/%s, cnt=%d",
- enum_show(&esp_transformid_names, ealg_id), ek_bits,
+ enum_show(&esp_transform_names, ealg_id), ek_bits,
enum_show(&auth_alg_names, aalg_id),
alg_info->alg_info_cnt)
)
@@ -238,12 +225,12 @@ static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id,
* merging alg_info (ike_info) contents
*/
-static int default_ike_groups[] = {
+static int default_ike_groups[] = {
MODP_1536_BIT,
MODP_1024_BIT
};
-/*
+/*
* Add IKE alg info _with_ logic (policy):
*/
static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
@@ -258,7 +245,7 @@ static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
n_groups=0;
goto in_loop;
}
-
+
for (; n_groups--; i++)
{
modp_id = default_ike_groups[i];
@@ -372,7 +359,7 @@ static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
eat_whitespace(&string);
- if (string.len > 0)
+ if (string.len > 0)
{
chunk_t alg;
@@ -397,7 +384,7 @@ static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
{
case PROTO_IPSEC_ESP:
alg_info_esp_add(alg_info, ealg, ealg_keysize,
- aalg, aalg_keysize);
+ aalg, aalg_keysize);
break;
case PROTO_ISAKMP:
alg_info_ike_add(alg_info, ealg, ealg_keysize,
@@ -461,12 +448,16 @@ struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
out:
- if (status != SUCCESS)
+ if (status == SUCCESS)
+ {
+ alg_info_esp->ref_cnt = 1;
+ return alg_info_esp;
+ }
+ else
{
free(alg_info_esp);
- alg_info_esp = NULL;
+ return NULL;
}
- return alg_info_esp;
}
struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
@@ -481,12 +472,16 @@ struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
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)
+ if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
+ {
+ alg_info_ike->ref_cnt = 1;
+ return alg_info_ike;
+ }
+ else
{
free(alg_info_ike);
return NULL;
}
- return alg_info_ike;
}
/*
@@ -494,7 +489,7 @@ struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
* several connections instances,
* handle free() with ref_cnts
*/
-void
+void
alg_info_addref(struct alg_info *alg_info)
{
if (alg_info != NULL)
@@ -529,7 +524,7 @@ alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
struct esp_info *esp_info;
struct ike_info *ike_info;
int cnt;
-
+
switch (alg_info->alg_info_protoid) {
case PROTO_IPSEC_ESP:
{
@@ -538,7 +533,7 @@ alg_info_snprint(char *buf, int buflen, struct alg_info *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));
+ enum_show(&esp_transform_names, esp_info->esp_ealg_id));
ptr += np;
buflen -= np;
if (esp_info->esp_ealg_keylen)
@@ -608,7 +603,7 @@ out:
, "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
, buflen);
}
-
+
return ptr - buf;
}
diff --git a/src/pluto/alg_info.h b/src/pluto/alg_info.h
index fcf7efca0..85b88ddff 100644
--- a/src/pluto/alg_info.h
+++ b/src/pluto/alg_info.h
@@ -74,7 +74,7 @@ extern int alg_info_snprint_esp(char *buf, int buflen
extern int alg_info_snprint_ike(char *buf, int buflen
, 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/builder.c b/src/pluto/builder.c
new file mode 100644
index 000000000..0cba32bcf
--- /dev/null
+++ b/src/pluto/builder.c
@@ -0,0 +1,150 @@
+/* Pluto certificate/CRL/AC builder hooks.
+ * Copyright (C) 2002-2009 Andreas Steffen
+ * Copyright (C) 2009 Martin Willi
+ * 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 "builder.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <freeswan.h>
+
+#include <library.h>
+#include <credentials/certificates/certificate.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "certs.h"
+#include "crl.h"
+
+/**
+ * Load a certificate
+ */
+static cert_t *builder_load_cert(certificate_type_t type, va_list args)
+{
+ x509_flag_t flags = 0;
+ chunk_t blob = chunk_empty;
+ bool pgp = FALSE;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_PGP:
+ pgp = TRUE;
+ /* FALL */
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_X509_FLAG:
+ flags |= va_arg(args, x509_flag_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+ if (blob.ptr)
+ {
+ cert_t *cert = malloc_thing(cert_t);
+
+ *cert = cert_empty;
+
+ if (pgp)
+ {
+ cert->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_GPG,
+ BUILD_BLOB_PGP, blob,
+ BUILD_END);
+ }
+ else
+ {
+ cert->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, blob,
+ BUILD_X509_FLAG, flags,
+ BUILD_END);
+ }
+ if (cert->cert)
+ {
+ return cert;
+ }
+ plog(" error in X.509 certificate");
+ cert_free(cert);
+ }
+ return NULL;
+}
+
+/**
+ * Load a CRL
+ */
+static x509crl_t *builder_load_crl(certificate_type_t type, va_list args)
+{
+ chunk_t blob = chunk_empty;
+ x509crl_t *crl;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+ if (blob.ptr)
+ {
+ crl = malloc_thing(x509crl_t);
+ crl->next = NULL;
+ crl->distributionPoints = linked_list_create();
+ crl->crl = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_CRL,
+ BUILD_BLOB_ASN1_DER, blob,
+ BUILD_END);
+ if (crl->crl)
+ {
+ return crl;
+ }
+ plog(" error in X.509 crl");
+ free_crl(crl);
+ }
+ return NULL;
+}
+
+void init_builder(void)
+{
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
+ (builder_function_t)builder_load_cert);
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
+ (builder_function_t)builder_load_crl);
+}
+
+void free_builder(void)
+{
+ lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_cert);
+ lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_crl);
+}
+
diff --git a/src/pluto/pem.h b/src/pluto/builder.h
index 5e97b99ed..784751b7c 100644
--- a/src/pluto/pem.h
+++ b/src/pluto/builder.h
@@ -1,7 +1,6 @@
-/* Loading of PEM encoded files with optional encryption
- * Copyright (C) 2001-2009 Andreas Steffen
- *
- * Hochschule fuer Technik Rapperswil
+/* Pluto certificate/CRL/AC builder hooks.
+ * Copyright (C) 2009 Martin Willi
+ * 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
@@ -14,5 +13,12 @@
* for more details.
*/
-extern err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label,
- bool *pgp);
+#ifndef _BUILDER_H
+#define _BUILDER_H
+
+/* register credential builder hooks */
+extern void init_builder();
+/* unregister credential builder hooks */
+extern void free_builder();
+
+#endif /* _BUILDER_H */
diff --git a/src/pluto/ca.c b/src/pluto/ca.c
index 4fdb8cfe7..e25e7f6f5 100644
--- a/src/pluto/ca.c
+++ b/src/pluto/ca.c
@@ -15,11 +15,14 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
#include <time.h>
+#include <sys/stat.h>
#include <sys/types.h>
+#include <debug.h>
+#include <utils/enumerator.h>
+#include <credentials/certificates/x509.h>
+
#include <freeswan.h>
#include "constants.h"
@@ -34,21 +37,7 @@
/* chained list of X.509 authority certificates (ca, aa, and ocsp) */
-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 */
-};
+static cert_t *x509authcerts = NULL;
/* chained list of X.509 certification authority information records */
@@ -57,53 +46,71 @@ static ca_info_t *ca_infos = NULL;
/*
* Checks if CA a is trusted by CA b
*/
-bool
-trusted_ca(chunk_t a, chunk_t b, int *pathlen)
+bool trusted_ca(identification_t *a, identification_t *b, int *pathlen)
{
bool match = FALSE;
/* no CA b specified -> any CA a is accepted */
- if (b.ptr == NULL)
+ if (b == NULL)
{
- *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN;
+ *pathlen = (a == NULL) ? 0 : X509_MAX_PATH_LEN;
return TRUE;
}
/* no CA a specified -> trust cannot be established */
- if (a.ptr == NULL)
+ if (a == NULL)
{
- *pathlen = MAX_CA_PATH_LEN;
+ *pathlen = X509_MAX_PATH_LEN;
return FALSE;
}
*pathlen = 0;
/* CA a equals CA b -> we have a match */
- if (same_dn(a, b))
+ if (a->equals(a, b))
+ {
return TRUE;
+ }
/* CA a might be a subordinate CA of b */
lock_authcert_list("trusted_ca");
- while ((*pathlen)++ < MAX_CA_PATH_LEN)
+ while ((*pathlen)++ < X509_MAX_PATH_LEN)
{
- x509cert_t *cacert = get_authcert(a, chunk_empty, chunk_empty, AUTH_CA);
+ certificate_t *certificate;
+ identification_t *issuer;
+ cert_t *cacert;
- /* cacert not found or self-signed root cacert-> exit */
- if (cacert == NULL || same_dn(cacert->issuer, a))
+ cacert = get_authcert(a, chunk_empty, X509_CA);
+ if (cacert == NULL)
+ {
break;
+ }
+ certificate = cacert->cert;
+
+ /* is the certificate self-signed? */
+ {
+ x509_t *x509 = (x509_t*)certificate;
+
+ if (x509->get_flags(x509) & X509_SELF_SIGNED)
+ {
+ break;
+ }
+ }
/* does the issuer of CA a match CA b? */
- match = same_dn(cacert->issuer, b);
+ issuer = certificate->get_issuer(certificate);
+ match = b->equals(b, issuer);
/* we have a match and exit the loop */
if (match)
+ {
break;
-
+ }
/* go one level up in the CA chain */
- a = cacert->issuer;
+ a = issuer;
}
-
+
unlock_authcert_list("trusted_ca");
return match;
}
@@ -111,33 +118,36 @@ trusted_ca(chunk_t a, chunk_t b, int *pathlen)
/*
* does our CA match one of the requested CAs?
*/
-bool
-match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen)
+bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca,
+ int *our_pathlen)
{
+ identification_t *ca;
+ enumerator_t *enumerator;
+
/* if no ca is requested than any ca will match */
- if (requested_ca == NULL)
+ if (requested_ca == NULL || requested_ca->get_count(requested_ca) == 0)
{
*our_pathlen = 0;
return TRUE;
}
- *our_pathlen = MAX_CA_PATH_LEN + 1;
+ *our_pathlen = X509_MAX_PATH_LEN + 1;
- while (requested_ca != NULL)
+ enumerator = requested_ca->create_enumerator(requested_ca);
+ while (enumerator->enumerate(enumerator, &ca))
{
int pathlen;
- if (trusted_ca(our_ca, requested_ca->name, &pathlen)
- && pathlen < *our_pathlen)
+ if (trusted_ca(our_ca, ca, &pathlen) && pathlen < *our_pathlen)
{
*our_pathlen = pathlen;
}
- requested_ca = requested_ca->next;
}
+ enumerator->destroy(enumerator);
- if (*our_pathlen > MAX_CA_PATH_LEN)
+ if (*our_pathlen > X509_MAX_PATH_LEN)
{
- *our_pathlen = MAX_CA_PATH_LEN;
+ *our_pathlen = X509_MAX_PATH_LEN;
return FALSE;
}
else
@@ -149,55 +159,80 @@ match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen
/*
* free the first authority certificate in the chain
*/
-static void
-free_first_authcert(void)
+static void free_first_authcert(void)
{
- x509cert_t *first = x509authcerts;
+ cert_t *first = x509authcerts;
+
x509authcerts = first->next;
- free_x509cert(first);
+ cert_free(first);
}
/*
* free all CA certificates
*/
-void
-free_authcerts(void)
+void free_authcerts(void)
{
lock_authcert_list("free_authcerts");
while (x509authcerts != NULL)
+ {
free_first_authcert();
-
+ }
unlock_authcert_list("free_authcerts");
}
/*
* get a X.509 authority certificate with a given subject or keyid
*/
-x509cert_t*
-get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags)
+cert_t* get_authcert(identification_t *subject, chunk_t keyid,
+ x509_flag_t auth_flags)
{
- x509cert_t *cert = x509authcerts;
- x509cert_t *prev_cert = NULL;
+ cert_t *cert, *prev_cert = NULL;
+
+ /* the authority certificate list is empty */
+ if (x509authcerts == NULL)
+ {
+ return NULL;
+ }
- while (cert != NULL)
+ for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
{
- if (cert->authority_flags & auth_flags
- && ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
- : (same_dn(subject, cert->subject)
- && same_serial(serial, cert->serialNumber))))
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+
+ /* skip non-matching types of authority certificates */
+ if (!(x509->get_flags(x509) & auth_flags))
+ {
+ continue;
+ }
+
+ /* compare the keyid with the certificate's subjectKeyIdentifier */
+ if (keyid.ptr)
{
- if (cert != x509authcerts)
+ chunk_t subjectKeyId;
+
+ subjectKeyId = x509->get_subjectKeyIdentifier(x509);
+ if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
{
- /* bring the certificate up front */
- prev_cert->next = cert->next;
- cert->next = x509authcerts;
- x509authcerts = cert;
+ continue;
}
- return cert;
}
- prev_cert = cert;
- cert = cert->next;
+
+ /* compare the subjectDistinguishedNames */
+ if (!certificate->has_subject(certificate, subject))
+ {
+ continue;
+ }
+
+ /* found the authcert */
+ if (cert != x509authcerts)
+ {
+ /* bring the certificate up front */
+ prev_cert->next = cert->next;
+ cert->next = x509authcerts;
+ x509authcerts = cert;
+ }
+ return cert;
}
return NULL;
}
@@ -205,31 +240,27 @@ get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags)
/*
* add an authority certificate to the chained list
*/
-x509cert_t*
-add_authcert(x509cert_t *cert, u_char auth_flags)
+cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags)
{
- x509cert_t *old_cert;
-
- /* set authority flags */
- cert->authority_flags |= auth_flags;
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+ cert_t *old_cert;
lock_authcert_list("add_authcert");
- old_cert = get_authcert(cert->subject, cert->serialNumber
- , cert->subjectKeyID, auth_flags);
-
- if (old_cert != NULL)
+ old_cert = get_authcert(certificate->get_subject(certificate),
+ x509->get_subjectKeyIdentifier(x509),
+ auth_flags);
+ if (old_cert)
{
- if (same_x509cert(cert, old_cert))
+ if (certificate->equals(certificate, old_cert->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);
+ cert_free(cert);
return old_cert;
}
else
@@ -245,7 +276,7 @@ add_authcert(x509cert_t *cert, u_char auth_flags)
/* add new authcert to chained list */
cert->next = x509authcerts;
x509authcerts = cert;
- share_x509cert(cert); /* set count to one */
+ cert_share(cert); /* set count to one */
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" authcert inserted")
)
@@ -256,51 +287,43 @@ add_authcert(x509cert_t *cert, u_char auth_flags)
/*
* Loads authority certificates
*/
-void
-load_authcerts(const char *type, const char *path, u_char auth_flags)
+void load_authcerts(char *type, char *path, x509_flag_t auth_flags)
{
- struct dirent **filelist;
- u_char buf[BUF_LEN];
- u_char *save_dir;
- int n;
+ enumerator_t *enumerator;
+ struct stat st;
+ char *file;
- /* change directory to specified path */
- save_dir = getcwd(buf, BUF_LEN);
+ DBG1("loading %s certificates from '%s'", type, path);
- if (chdir(path))
+ enumerator = enumerator_create_directory(path);
+ if (!enumerator)
{
- plog("Could not change to directory '%s'", path);
+ DBG1(" reading directory '%s' failed");
+ return;
}
- else
+
+ while (enumerator->enumerate(enumerator, NULL, &file, &st))
{
- plog("Changing to directory '%s'", path);
- n = scandir(path, &filelist, file_select, alphasort);
+ cert_t *cert;
- if (n < 0)
- plog(" scandir() error");
- else
+ if (!S_ISREG(st.st_mode))
{
- 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);
+ /* skip special file */
+ continue;
+ }
+ cert = load_cert(file, type, auth_flags);
+ if (cert)
+ {
+ add_authcert(cert, auth_flags);
}
}
- /* restore directory path */
- ignore_result(chdir(save_dir));
+ enumerator->destroy(enumerator);
}
/*
* list all X.509 authcerts with given auth flags in a chained list
*/
-void
-list_authcerts(const char *caption, u_char auth_flags, bool utc)
+void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc)
{
lock_authcert_list("list_authcerts");
list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
@@ -310,19 +333,38 @@ list_authcerts(const char *caption, u_char auth_flags, bool utc)
/*
* get a cacert with a given subject or keyid from an alternative list
*/
-static const x509cert_t*
-get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid
- , const x509cert_t *cert)
+static const cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
+ const cert_t *cert)
{
- while (cert != NULL)
+ if (cert == NULL)
{
- if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID)
- : (same_dn(subject, cert->subject)
- && same_serial(serial, cert->serialNumber)))
+ return NULL;
+ }
+ for (; cert != NULL; cert = cert->next)
+ {
+ certificate_t *certificate = cert->cert;
+
+ /* compare the keyid with the certificate's subjectKeyIdentifier */
+ if (keyid.ptr)
+ {
+ x509_t *x509 = (x509_t*)certificate;
+ chunk_t subjectKeyId;
+
+ subjectKeyId = x509->get_subjectKeyIdentifier(x509);
+ if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
+ {
+ continue;
+ }
+ }
+
+ /* compare the subjectDistinguishedNames */
+ if (!certificate->has_subject(certificate, subject))
{
- return cert;
+ continue;
}
- cert = cert->next;
+
+ /* we found the cacert */
+ return cert;
}
return NULL;
}
@@ -330,34 +372,32 @@ get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid
/* establish trust into a candidate authcert by going up the trust chain.
* validity and revocation status are not checked.
*/
-bool
-trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
+bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain)
{
int pathlen;
lock_authcert_list("trust_authcert_candidate");
- for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+ for (pathlen = 0; pathlen < X509_MAX_PATH_LEN; pathlen++)
{
- const x509cert_t *authcert = NULL;
- u_char buf[BUF_LEN];
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+ identification_t *subject = certificate->get_subject(certificate);
+ identification_t *issuer = certificate->get_issuer(certificate);
+ chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
+ const cert_t *authcert = 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)
+ DBG_log("subject: '%Y'", subject);
+ DBG_log("issuer: '%Y'", issuer);
+ if (authKeyID.ptr != NULL)
{
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
+ DBG_log("authkey: %#B", &authKeyID);
}
)
/* search in alternative chain first */
- authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, alt_chain);
+ authcert = get_alt_cacert(issuer, authKeyID, alt_chain);
if (authcert != NULL)
{
@@ -368,8 +408,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
else
{
/* search in trusted chain */
- authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, AUTH_CA);
+ authcert = get_authcert(issuer, authKeyID, X509_CA);
if (authcert != NULL)
{
@@ -385,8 +424,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
}
}
- if (!x509_check_signature(cert->tbsCertificate, cert->signature,
- cert->algorithm, authcert))
+ if (!certificate->issued_by(certificate, authcert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("trust_authcert_candidate");
@@ -397,7 +435,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
)
/* check if cert is a self-signed root ca */
- if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
+ if (pathlen > 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
{
DBG(DBG_CONTROL,
DBG_log("reached self-signed root ca")
@@ -409,7 +447,7 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
/* go up one step in the trust chain */
cert = authcert;
}
- plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ plog("maximum ca path length of %d levels exceeded", X509_MAX_PATH_LEN);
unlock_authcert_list("trust_authcert_candidate");
return FALSE;
}
@@ -417,16 +455,14 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
/*
* get a CA info record with a given authName or authKeyID
*/
-ca_info_t*
-get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid)
+ca_info_t* get_ca_info(identification_t *name, chunk_t keyid)
{
ca_info_t *ca= ca_infos;
- while (ca!= NULL)
+ while (ca != NULL)
{
- if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID)
- : (same_dn(authname, ca->authName)
- && same_serial(serial, ca->authKeySerialNumber)))
+ if ((keyid.ptr) ? same_keyid(keyid, ca->authKeyID)
+ : name->equals(name, ca->authName))
{
return ca;
}
@@ -443,24 +479,23 @@ static void
free_ca_info(ca_info_t* ca_info)
{
if (ca_info == NULL)
+ {
return;
-
+ }
+ ca_info->crluris->destroy_function(ca_info->crluris, free);
+ DESTROY_IF(ca_info->authName);
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);
}
/*
* free all CA certificates
*/
-void
-free_ca_infos(void)
+void free_ca_infos(void)
{
while (ca_infos != NULL)
{
@@ -474,8 +509,7 @@ free_ca_infos(void)
/*
* find a CA information record by name and optionally delete it
*/
-bool
-find_ca_info_by_name(const char *name, bool delete)
+bool find_ca_info_by_name(const char *name, bool delete)
{
ca_info_t **ca_p = &ca_infos;
ca_info_t *ca = *ca_p;
@@ -501,16 +535,26 @@ find_ca_info_by_name(const char *name, bool delete)
return FALSE;
}
+/*
+ * Create an empty ca_info_t record
+ */
+ca_info_t* create_ca_info(void)
+{
+ ca_info_t *ca_info = malloc_thing(ca_info_t);
+
+ memset(ca_info, 0, sizeof(ca_info_t));
+ ca_info->crluris = linked_list_create();
- /*
- * adds a CA description to a chained list
+ return ca_info;
+}
+
+/**
+ * Adds a CA description to a chained list
*/
-void
-add_ca_info(const whack_message_t *msg)
+void add_ca_info(const whack_message_t *msg)
{
smartcard_t *sc = NULL;
- cert_t cert;
- bool valid_cert = FALSE;
+ cert_t *cert = NULL;
bool cached_cert = FALSE;
if (find_ca_info_by_name(msg->name, FALSE))
@@ -522,60 +566,54 @@ add_ca_info(const whack_message_t *msg)
if (scx_on_smartcard(msg->cacert))
{
/* load CA cert from smartcard */
- valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert);
+ cert = scx_load_cert(msg->cacert, &sc, &cached_cert);
}
else
{
/* load CA cert from file */
- valid_cert = load_ca_cert(msg->cacert, &cert);
+ cert = load_ca_cert(msg->cacert);
}
- if (valid_cert)
+ if (cert)
{
- char buf[BUF_LEN];
- x509cert_t *cacert = cert.u.x509;
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+ identification_t *subject = certificate->get_subject(certificate);
+ chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
ca_info_t *ca = NULL;
/* does the authname already exist? */
- ca = get_ca_info(cacert->subject, cacert->serialNumber
- , cacert->subjectKeyID);
-
+ ca = get_ca_info(subject, 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);
+ cert_free(cert);
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;
+ ca = create_ca_info();
/* name */
ca->name = clone_str(msg->name);
-
+
/* authName */
- ca->authName = chunk_clone(cacert->subject);
- dntoa(buf, BUF_LEN, ca->authName);
+ ca->authName = subject->clone(subject);
DBG(DBG_CONTROL,
- DBG_log("authname: '%s'", buf)
+ DBG_log("authname: '%Y'", subject)
)
- /* authSerialNumber */
- ca->authKeySerialNumber = chunk_clone(cacert->serialNumber);
-
/* authKeyID */
- if (cacert->subjectKeyID.ptr != NULL)
+ if (subjectKeyID.ptr)
{
- ca->authKeyID = chunk_clone(cacert->subjectKeyID);
- datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':'
- , buf, BUF_LEN);
+ ca->authKeyID = chunk_clone(subjectKeyID);
DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log("authkey: %s", buf)
+ DBG_log("authkey: %#B", &subjectKeyID)
)
}
@@ -594,23 +632,9 @@ add_ca_info(const whack_message_t *msg)
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);
- }
+ /* add crl uris */
+ add_distribution_point(ca->crluris, msg->crluri);
+ add_distribution_point(ca->crluris, msg->crluri2);
/* strictrlpolicy */
ca->strictcrlpolicy = msg->whack_strict;
@@ -620,17 +644,19 @@ add_ca_info(const whack_message_t *msg)
ca->next = ca_infos;
ca_infos = ca;
- ca->installed = time(NULL);
-
+
unlock_ca_info_list("add_ca_info");
/* add cacert to list of authcerts */
+ cert = add_authcert(cert, X509_CA);
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->last_cert != NULL)
+ {
+ sc->last_cert->count--;
+ }
+ sc->last_cert = cert;
+ cert_share(sc->last_cert);
}
if (sc != NULL)
time(&sc->last_load);
@@ -640,54 +666,46 @@ add_ca_info(const whack_message_t *msg)
/*
* list all ca_info records in the chained list
*/
-void
-list_ca_infos(bool utc)
+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, "%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)
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, " authname: \"%Y\"", ca->authName);
+ if (ca->ldaphost)
+ {
+ whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost);
+ }
+ if (ca->ldapbase)
{
- datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase);
}
- if (ca->authKeySerialNumber.ptr != NULL)
+ if (ca->ocspuri)
{
- datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
+ }
+
+ list_distribution_points(ca->crluris);
+
+ if (ca->authKeyID.ptr)
+ {
+ whack_log(RC_COMMENT, " authkey: %#B", &ca->authKeyID);
}
ca = ca->next;
}
}
-
diff --git a/src/pluto/ca.h b/src/pluto/ca.h
index 44d079b4c..d964a694a 100644
--- a/src/pluto/ca.h
+++ b/src/pluto/ca.h
@@ -15,49 +15,39 @@
#ifndef _CA_H
#define _CA_H
-#include "x509.h"
-#include "whack.h"
-
-#define MAX_CA_PATH_LEN 7
+#include <utils/linked_list.h>
+#include <utils/identification.h>
-/* 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 */
+#include "certs.h"
+#include "whack.h"
/* 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;
+ identification_t *authName;
+ chunk_t authKeyID;
+ char *ldaphost;
+ char *ldapbase;
+ char *ocspuri;
+ linked_list_t *crluris;
+ 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);
-extern x509cert_t* get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid
- , u_char auth_flags);
-extern void load_authcerts(const char *type, const char *path
- , u_char auth_flags);
-extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags);
+extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen);
+extern bool match_requested_ca(linked_list_t *requested_ca,
+ identification_t *our_ca, int *our_pathlen);
+extern cert_t* get_authcert(identification_t *subject, chunk_t keyid,
+ x509_flag_t auth_flags);
+extern void load_authcerts(char *type, char *path, x509_flag_t auth_flags);
+extern cert_t* add_authcert(cert_t *cert, x509_flag_t 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);
-extern ca_info_t* get_ca_info(chunk_t name, chunk_t serial, chunk_t keyid);
+extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
+extern bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain);
+extern ca_info_t* get_ca_info(identification_t *name, 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);
extern void delete_ca_info(const char *name);
diff --git a/src/pluto/certs.c b/src/pluto/certs.c
index ca3019b9b..8bce4c5c2 100644
--- a/src/pluto/certs.c
+++ b/src/pluto/certs.c
@@ -17,153 +17,166 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
+#include <time.h>
#include <freeswan.h>
-#include "library.h"
-#include "asn1/asn1.h"
+#include <library.h>
+#include <asn1/asn1.h>
+#include <credentials/certificates/certificate.h>
+#include <credentials/certificates/pgp_certificate.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
-#include "pem.h"
#include "certs.h"
+#include "whack.h"
+#include "fetch.h"
+#include "keys.h"
+#include "builder.h"
/**
- * used for initializatin of certs
+ * Initialization
*/
-const cert_t cert_empty = {CERT_NONE, {NULL}};
+const cert_t cert_empty = {
+ NULL , /* cert */
+ NULL , /* *next */
+ 0 , /* count */
+ FALSE /* smartcard */
+};
/**
- * extracts the certificate to be sent to the peer
+ * Chained lists of X.509 and PGP end entity certificates
*/
-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 chunk_empty;
- }
-}
+static cert_t *certs = NULL;
-public_key_t* cert_get_public_key(const cert_t cert)
+/**
+ * Free a pluto certificate
+ */
+void cert_free(cert_t *cert)
{
- switch (cert.type)
+ if (cert)
{
- case CERT_PGP:
- return cert.u.pgp->public_key;
- break;
- case CERT_X509_SIGNATURE:
- return cert.u.x509->public_key;
- break;
- default:
- return NULL;
+ certificate_t *certificate = cert->cert;
+
+ if (certificate)
+ {
+ certificate->destroy(certificate);
+ }
+ free(cert);
}
}
-/* load a coded key or certificate file with autodetection
- * of binary DER or base64 PEM ASN.1 formats and armored PGP format
+/**
+ * Add a pluto end entity certificate to the chained list
*/
-bool load_coded_file(char *filename, prompt_pass_t *pass, const char *type,
- chunk_t *blob, bool *pgp)
+cert_t* cert_add(cert_t *cert)
{
- err_t ugh = NULL;
-
- FILE *fd = fopen(filename, "r");
+ certificate_t *certificate = cert->cert;
+ cert_t *c = certs;
- if (fd)
+ while (c != NULL)
{
- 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);
-
- *pgp = FALSE;
-
- /* try DER format */
- if (is_asn1(*blob))
+ if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
{
- DBG(DBG_PARSING,
- DBG_log(" file coded in DER format");
- )
- return TRUE;
+ cert_free(cert);
+ return c;
}
+ c = c->next;
+ }
- /* try PEM format */
- ugh = pemtobin(blob, pass, filename, pgp);
+ /* insert new cert at the root of the chain */
+ lock_certs_and_keys("cert_add");
+ cert->next = certs;
+ certs = cert;
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log(" cert inserted")
+ )
+ unlock_certs_and_keys("cert_add");
+ return cert;
+}
- 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";
- }
+/**
+ * Passphrase callback to read from whack fd
+ */
+chunk_t whack_pass_cb(prompt_pass_t *pass, int try)
+{
+ int n;
- /* a conversion error has occured */
- plog(" %s", ugh);
- free(blob->ptr);
- *blob = chunk_empty;
+ if (try > MAX_PROMPT_PASS_TRIALS)
+ {
+ whack_log(RC_LOG_SERIOUS, "invalid passphrase, too many trials");
+ return chunk_empty;
+ }
+ if (try == 1)
+ {
+ whack_log(RC_ENTERSECRET, "need passphrase for 'private key'");
}
else
{
- plog(" could not open %s file '%s'", type, filename);
+ whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
+ }
+
+ n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
+
+ if (n == -1)
+ {
+ whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
+ return chunk_empty;
}
- return FALSE;
+
+ pass->secret[n-1] = '\0';
+
+ if (strlen(pass->secret) == 0)
+ {
+ whack_log(RC_LOG_SERIOUS, "no passphrase entered, aborted");
+ return chunk_empty;
+ }
+ return chunk_create(pass->secret, strlen(pass->secret));
}
/**
- * Loads a PKCS#1 or PGP privatekey file
+ * Loads a PKCS#1 or PGP private key file
*/
private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
key_type_t type)
{
private_key_t *key = NULL;
- chunk_t blob = chunk_empty;
- bool pgp = FALSE;
-
- char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
+ char *path;
- if (load_coded_file(path, pass, "private key", &blob, &pgp))
- {
- if (pgp)
- {
- parse_pgp(blob, NULL, &key);
- }
- else
+ path = concatenate_paths(PRIVATE_KEY_PATH, filename);
+ if (pass && pass->prompt && pass->fd != NULL_FD)
+ { /* use passphrase callback */
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE_CALLBACK, whack_pass_cb, pass,
+ BUILD_END);
+ if (key)
{
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_BLOB_ASN1_DER, blob, BUILD_END);
+ whack_log(RC_SUCCESS, "valid passphrase");
}
- if (key == NULL)
- {
- plog(" syntax error in %s private key file", pgp ? "PGP":"PKCS#");
- }
- free(blob.ptr);
+ }
+ else if (pass)
+ { /* use a given passphrase */
+ chunk_t password = chunk_create(pass->secret, strlen(pass->secret));
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_FROM_FILE, path,
+ BUILD_PASSPHRASE, password, BUILD_END);
+ }
+ else
+ { /* no passphrase */
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_FROM_FILE, path, BUILD_END);
+
+ }
+ if (key)
+ {
+ plog(" loaded private key from '%s'", filename);
}
else
{
- plog(" error loading private key file");
+ plog(" syntax error in private key file");
}
return key;
}
@@ -171,125 +184,166 @@ private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
/**
* Loads a X.509 or OpenPGP certificate
*/
-bool load_cert(char *filename, const char *label, cert_t *cert)
+cert_t* load_cert(char *filename, const char *label, x509_flag_t flags)
{
- bool pgp = FALSE;
- chunk_t blob = chunk_empty;
-
- /* initialize cert struct */
- cert->type = CERT_NONE;
- cert->u.x509 = NULL;
+ cert_t *cert;
- if (load_coded_file(filename, NULL, label, &blob, &pgp))
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
+ BUILD_FROM_FILE, filename,
+ BUILD_X509_FLAG, flags,
+ BUILD_END);
+ if (cert)
{
- 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;
- }
- }
+ plog(" loaded %s certificate from '%s'", label, filename);
}
- return FALSE;
+ return cert;
}
/**
* Loads a host certificate
*/
-bool load_host_cert(char *filename, cert_t *cert)
+cert_t* load_host_cert(char *filename)
{
char *path = concatenate_paths(HOST_CERT_PATH, filename);
- return load_cert(path, "host cert", cert);
+ return load_cert(path, "host", X509_NONE);
}
/**
* Loads a CA certificate
*/
-bool load_ca_cert(char *filename, cert_t *cert)
+cert_t* load_ca_cert(char *filename)
{
char *path = concatenate_paths(CA_CERT_PATH, filename);
- return load_cert(path, "CA cert", cert);
+ return load_cert(path, "CA", X509_NONE);
}
/**
- * establish equality of two certificates
+ * for each link pointing to the certificate increase the count by one
*/
-bool same_cert(const cert_t *a, const cert_t *b)
+void cert_share(cert_t *cert)
{
- return a->type == b->type && a->u.x509 == b->u.x509;
+ if (cert != NULL)
+ {
+ cert->count++;
+ }
+}
+
+/* release of a certificate decreases the count by one
+ * the certificate is freed when the counter reaches zero
+ */
+void cert_release(cert_t *cert)
+{
+ if (cert && --cert->count == 0)
+ {
+ cert_t **pp = &certs;
+ while (*pp != cert)
+ {
+ pp = &(*pp)->next;
+ }
+ *pp = cert->next;
+ cert_free(cert);
+ }
}
/**
- * for each link pointing to the certificate increase the count by one
+ * Get a X.509 certificate with a given issuer found at a certain position
*/
-void share_cert(cert_t cert)
+cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t *chain)
{
- switch (cert.type)
+ cert_t *cert = chain ? chain->next : certs;
+
+ while (cert)
{
- case CERT_PGP:
- share_pgpcert(cert.u.pgp);
- break;
- case CERT_X509_SIGNATURE:
- share_x509cert(cert.u.x509);
- break;
- default:
- break;
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+ chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
+
+ if (keyid.ptr ? same_keyid(keyid, authKeyID) :
+ certificate->has_issuer(certificate, issuer))
+ {
+ return cert;
+ }
+ cert = cert->next;
}
+ return NULL;
}
-/* release of a certificate decreases the count by one
- " the certificate is freed when the counter reaches zero
+/**
+ * List all PGP end certificates in a chained list
*/
-void
-release_cert(cert_t cert)
+void list_pgp_end_certs(bool utc)
{
- switch (cert.type)
+ cert_t *cert = certs;
+ time_t now = time(NULL);
+ bool first = TRUE;
+
+
+ while (cert != NULL)
{
- case CERT_PGP:
- release_pgpcert(cert.u.pgp);
- break;
- case CERT_X509_SIGNATURE:
- release_x509cert(cert.u.x509);
- break;
- default:
- break;
+ certificate_t *certificate = cert->cert;
+
+ if (certificate->get_type(certificate) == CERT_GPG)
+ {
+ time_t created, until;
+ public_key_t *key;
+ identification_t *userid = certificate->get_subject(certificate);
+ pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
+ chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
+
+ if (first)
+ {
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
+ first = false;
+ }
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, " userid: '%Y'", userid);
+ whack_log(RC_COMMENT, " digest: %#B", &fingerprint);
+
+ /* list validity */
+ certificate->get_validity(certificate, &now, &created, &until);
+ whack_log(RC_COMMENT, " created: %T", &created, utc);
+ whack_log(RC_COMMENT, " until: %T %s%s", &until, utc,
+ check_expiry(until, CA_CERT_WARNING_INTERVAL, TRUE),
+ (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
+
+ key = certificate->get_public_key(certificate);
+ if (key)
+ {
+ chunk_t keyid;
+
+ 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(cert)? ", has private key" : "");
+ if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ {
+ whack_log(RC_COMMENT, " keyid: %#B", &keyid);
+ }
+ if (key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid))
+ {
+ whack_log(RC_COMMENT, " subjkey: %#B", &keyid);
+ }
+ }
+ }
+ cert = cert->next;
}
}
-/*
+/**
+ * List all X.509 end certificates in a chained list
+ */
+void list_x509_end_certs(bool utc)
+{
+ list_x509cert_chain("End Entity", certs, X509_NONE, utc);
+}
+
+/**
* list all X.509 and OpenPGP end certificates
*/
-void
-list_certs(bool utc)
+void cert_list(bool utc)
{
list_x509_end_certs(utc);
list_pgp_end_certs(utc);
diff --git a/src/pluto/certs.h b/src/pluto/certs.h
index 0810c52fa..21e856a3c 100644
--- a/src/pluto/certs.h
+++ b/src/pluto/certs.h
@@ -18,9 +18,12 @@
#define _CERTS_H
#include <credentials/keys/private_key.h>
+#include <credentials/certificates/certificate.h>
+#include <credentials/certificates/x509.h>
-#include "x509.h"
-#include "pgpcert.h"
+#include <freeswan.h>
+
+#include "defs.h"
/* path definitions for private keys, end certs,
* cacerts, attribute certs and crls
@@ -43,16 +46,16 @@
#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;
-} cert_t;
+/* access structure for a pluto certificate */
+
+typedef struct cert_t cert_t;
+
+struct cert_t {
+ certificate_t *cert;
+ cert_t *next;
+ int count;
+ bool smartcard;
+};
/* used for initialization */
extern const cert_t cert_empty;
@@ -62,19 +65,17 @@ extern const cert_t cert_empty;
*/
extern bool no_cr_send;
-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);
-extern void list_certs(bool utc);
+extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
+extern cert_t* load_host_cert(char *filename);
+extern cert_t* load_ca_cert(char *filename);
+extern cert_t* cert_add(cert_t *cert);
+extern void cert_free(cert_t *cert);
+extern void cert_share(cert_t *cert);
+extern void cert_release(cert_t *cert);
+extern void cert_list(bool utc);
+extern cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t* chain);
#endif /* _CERTS_H */
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
index b800b1665..fece34eec 100644
--- a/src/pluto/connections.c
+++ b/src/pluto/connections.c
@@ -30,15 +30,15 @@
#include <freeswan.h>
#include "kameipsec.h"
+#include <credentials/certificates/ac.h>
#include <credentials/keys/private_key.h>
#include "constants.h"
#include "defs.h"
-#include "id.h"
+#include "myid.h"
#include "x509.h"
#include "ca.h"
#include "crl.h"
-#include "pgpcert.h"
#include "certs.h"
#include "ac.h"
#include "smartcard.h"
@@ -62,9 +62,9 @@
#include "nat_traversal.h"
#include "virtual.h"
-static void flush_pending_by_connection(struct connection *c); /* forward */
+static void flush_pending_by_connection(connection_t *c); /* forward */
-static struct connection *connections = NULL;
+static connection_t *connections = NULL;
/* struct host_pair: a nexus of information about a pair of hosts.
* A host is an IP address, UDP port pair. This is a debatable choice:
@@ -82,34 +82,62 @@ struct host_pair {
u_int16_t port; /* host order */
} me, him;
bool initial_connection_sent;
- struct connection *connections; /* connections with this pair */
+ connection_t *connections; /* connections with this pair */
struct pending *pending; /* awaiting Keying Channel */
struct host_pair *next;
};
static struct host_pair *host_pairs = NULL;
-static struct connection *unoriented_connections = NULL;
+static connection_t *unoriented_connections = NULL;
-/* check to see that Ids of peers match */
-bool
-same_peer_ids(const struct connection *c, const struct connection *d
-, const struct id *his_id)
+/**
+ * Check if an id was instantiated by assigning to it the current IP address
+ */
+bool his_id_was_instantiated(const connection_t *c)
{
- 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);
+ if (c->kind != CK_INSTANCE)
+ {
+ return FALSE;
+ }
+ if (id_is_ipaddr(c->spd.that.id))
+ {
+ identification_t *host;
+ bool equal;
+
+ host = identification_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_addr);
+ equal = host->equals(host, c->spd.that.id);
+ host->destroy(host);
+ return equal;
+ }
+ else
+ {
+ return TRUE;
+ }
}
-static struct host_pair *
-find_host_pair(const ip_address *myaddr, u_int16_t myport
-, const ip_address *hisaddr, u_int16_t hisport)
+/**
+ * Check to see that IDs of peers match
+ */
+bool same_peer_ids(const connection_t *c, const connection_t *d,
+ identification_t *his_id)
+{
+ return d->spd.this.id->equals(d->spd.this.id, c->spd.this.id) &&
+ d->spd.that.id->equals(d->spd.that.id,
+ his_id ? his_id : c->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)
{
/**
@@ -125,7 +153,7 @@ find_host_pair(const ip_address *myaddr, u_int16_t myport
if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
&& sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
{
- if (prev != NULL)
+ if (prev)
{
prev->next = p->next; /* remove p from list */
p->next = host_pairs; /* and stick it on front */
@@ -138,15 +166,16 @@ find_host_pair(const ip_address *myaddr, u_int16_t myport
}
/* find head of list of connections with this pair of hosts */
-static struct connection *
-find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
-, const ip_address *hisaddr, u_int16_t hisport)
+static connection_t *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;
+ connection_t *c;
for (c = hp->connections; c != NULL; c = c->hp_next)
{
@@ -158,8 +187,7 @@ find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
return hp == NULL? NULL : hp->connections;
}
-static void
-connect_to_host_pair(struct connection *c)
+static void connect_to_host_pair(connection_t *c)
{
if (oriented(*c))
{
@@ -206,10 +234,9 @@ connect_to_host_pair(struct connection *c)
* Move the winner (if any) to the front.
* If none is found, and strict, a diagnostic is logged to whack.
*/
-struct connection *
-con_by_name(const char *nm, bool strict)
+connection_t *con_by_name(const char *nm, bool strict)
{
- struct connection *p, *prev;
+ connection_t *p, *prev;
for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
{
@@ -223,7 +250,7 @@ con_by_name(const char *nm, bool strict)
if (streq(p->name, nm)
&& (!strict || p->kind != CK_INSTANCE))
{
- if (prev != NULL)
+ if (prev)
{
prev->ac_next = p->ac_next; /* remove p from list */
p->ac_next = connections; /* and stick it on front */
@@ -235,8 +262,7 @@ con_by_name(const char *nm, bool strict)
return p;
}
-void
-release_connection(struct connection *c, bool relations)
+void release_connection(connection_t *c, bool relations)
{
if (c->kind == CK_INSTANCE)
{
@@ -264,10 +290,9 @@ release_connection(struct connection *c, bool relations)
}
-void
-delete_connection(struct connection *c, bool relations)
+void delete_connection(connection_t *c, bool relations)
{
- struct connection *old_cur_connection
+ connection_t *old_cur_connection
= cur_connection == c? NULL : cur_connection;
#ifdef DEBUG
lset_t old_cur_debugging = cur_debugging;
@@ -294,26 +319,30 @@ delete_connection(struct connection *c, bool relations)
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);
+ list_rm(connection_t, 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);
+ {
+ list_rm(connection_t, hp_next, c, unoriented_connections);
+ }
}
else
{
struct host_pair *hp = c->host_pair;
- list_rm(struct connection, hp_next, c, hp->connections);
+ list_rm(connection_t, hp_next, c, hp->connections);
c->host_pair = NULL; /* redundant, but safe */
/* if there are no more connections with this host_pair
@@ -332,25 +361,45 @@ delete_connection(struct connection *c, bool relations)
{
free(c->spd.that.virt);
}
+
+ /* release virtual IP address lease if any */
+ if (c->spd.that.modecfg && c->spd.that.pool &&
+ !isanyaddr(&c->spd.that.host_srcip))
+ {
+ host_t *vip;
+
+ vip = host_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_srcip);
+ lib->attributes->release_address(lib->attributes, c->spd.that.pool,
+ vip, c->spd.that.id);
+ vip->destroy(vip);
+ }
+
+ /* free internal data */
#ifdef DEBUG
cur_debugging = old_cur_debugging;
#endif
free(c->name);
- free_id_content(&c->spd.this.id);
+ DESTROY_IF(c->spd.this.id);
+ DESTROY_IF(c->spd.this.ca);
+ DESTROY_IF(c->spd.this.groups);
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.this.pool);
+ DESTROY_IF(c->spd.that.id);
+ DESTROY_IF(c->spd.that.ca);
+ DESTROY_IF(c->spd.that.groups);
free(c->spd.that.updown);
- free(c->spd.that.ca.ptr);
- free_ietfAttrList(c->spd.that.groups);
- free_generalNames(c->requested_ca, TRUE);
+ free(c->spd.that.pool);
+ if (c->requested_ca)
+ {
+ c->requested_ca->destroy_offset(c->requested_ca,
+ offsetof(identification_t, destroy));
+ }
gw_delref(&c->gw_info);
lock_certs_and_keys("delete_connection");
- release_cert(c->spd.this.cert);
+ cert_release(c->spd.this.cert);
scx_release(c->spd.this.sc);
- release_cert(c->spd.that.cert);
+ cert_release(c->spd.that.cert);
scx_release(c->spd.that.sc);
unlock_certs_and_keys("delete_connection");
@@ -361,30 +410,29 @@ delete_connection(struct connection *c, bool relations)
}
/* Delete connections with the specified name */
-void
-delete_connections_by_name(const char *name, bool strict)
+void delete_connections_by_name(const char *name, bool strict)
{
- struct connection *c = con_by_name(name, strict);
+ connection_t *c = con_by_name(name, strict);
for (; c != NULL; c = con_by_name(name, FALSE))
delete_connection(c, FALSE);
}
-void
-delete_every_connection(void)
+void delete_every_connection(void)
{
- while (connections != NULL)
+ while (connections)
+ {
delete_connection(connections, TRUE);
+ }
}
-void
-release_dead_interfaces(void)
+void release_dead_interfaces(void)
{
struct host_pair *hp;
for (hp = host_pairs; hp != NULL; hp = hp->next)
{
- struct connection **pp
+ connection_t **pp
, *p;
for (pp = &hp->connections; (p = *pp) != NULL; )
@@ -427,18 +475,17 @@ release_dead_interfaces(void)
}
/* adjust orientations of connections to reflect newly added interfaces */
-void
-check_orientations(void)
+void check_orientations(void)
{
/* try to orient all the unoriented connections */
{
- struct connection *c = unoriented_connections;
+ connection_t *c = unoriented_connections;
unoriented_connections = NULL;
- while (c != NULL)
+ while (c)
{
- struct connection *nxt = c->hp_next;
+ connection_t *nxt = c->hp_next;
(void)orient(c);
connect_to_host_pair(c);
@@ -472,12 +519,12 @@ check_orientations(void)
* cost of leaving it is slight and cannot
* be induced by a foe).
*/
- struct connection *c = hp->connections;
+ connection_t *c = hp->connections;
hp->connections = NULL;
- while (c != NULL)
+ while (c)
{
- struct connection *nxt = c->hp_next;
+ connection_t *nxt = c->hp_next;
c->interface = NULL;
(void)orient(c);
@@ -491,34 +538,38 @@ check_orientations(void)
}
}
-static err_t
-default_end(struct end *e, ip_address *dflt_nexthop)
+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));
+ int af = addrtypeof(&e->host_addr);
- if (afi == NULL)
+ if (af != AF_INET && af != AF_INET6)
+ {
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))
+ if (e->id->get_type(e->id) == ID_ANY && !isanyaddr(&e->host_addr))
{
- e->id.kind = afi->id_addr;
- e->id.ip_addr = e->host_addr;
+ e->id->destroy(e->id);
+ e->id = identification_create_from_sockaddr((sockaddr_t*)&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;
}
@@ -527,15 +578,10 @@ default_end(struct end *e, ip_address *dflt_nexthop)
* Note: if that==NULL, skip nexthop
* Returns strlen of formated result (length excludes NUL at end).
*/
-size_t
-format_end(char *buf
-, size_t buf_len
-, const struct end *this
-, const struct end *that
-, bool is_left
-, lset_t policy)
+size_t format_end(char *buf, size_t buf_len, const struct end *this,
+ const struct end *that, bool is_left, lset_t policy)
{
- char client[SUBNETTOT_BUF];
+ char client[BUF_LEN];
const char *client_sep = "";
char protoport[sizeof(":255/65535")];
const char *host = NULL;
@@ -591,17 +637,24 @@ format_end(char *buf
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 */
+ /* we are mode config client, or a server with a pool */
client_sep = "===";
- strcpy(client, "%modecfg");
+ client[0] = '%';
+ strcpy(client+1, this->pool ? this->pool : "modecfg");
}
/* host */
@@ -613,53 +666,50 @@ format_end(char *buf
host_port[0] = '\0';
if (this->host_port != IKE_UDP_PORT)
- snprintf(host_port, sizeof(host_port), ":%u"
- , this->host_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], "]");
- }
+ /* id */
+ snprintf(host_id, sizeof(host_id), "[%Y]", this->id);
/* [---hop] */
hop[0] = '\0';
hop_sep = "";
- if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr))
+ if (that && !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);
}
@@ -668,10 +718,9 @@ format_end(char *buf
*/
#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)
+static size_t format_connection(char *buf, size_t buf_len,
+ const connection_t *c,
+ struct spd_route *sr)
{
size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
@@ -679,22 +728,35 @@ format_connection(char *buf, size_t buf_len
return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
}
-static void
-unshare_connection_strings(struct connection *c)
+static void unshare_connection_strings(connection_t *c)
{
c->name = clone_str(c->name);
-
- unshare_id_content(&c->spd.this.id);
+ c->spd.this.id = c->spd.this.id->clone(c->spd.this.id);
+ c->spd.this.pool = clone_str(c->spd.this.pool);
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);
+ cert_share(c->spd.this.cert);
+ if (c->spd.this.ca)
+ {
+ c->spd.this.ca = c->spd.this.ca->clone(c->spd.this.ca);
+ }
+ if (c->spd.this.groups)
+ {
+ c->spd.this.groups = c->spd.this.groups->get_ref(c->spd.this.groups);
+ }
+ c->spd.that.id = c->spd.that.id->clone(c->spd.that.id);
+ c->spd.that.pool = clone_str(c->spd.that.pool);
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);
+ cert_share(c->spd.that.cert);
+ if (c->spd.that.ca)
+ {
+ c->spd.that.ca = c->spd.that.ca->clone(c->spd.that.ca);
+ }
+ if (c->spd.that.groups)
+ {
+ c->spd.that.groups = c->spd.that.groups->get_ref(c->spd.that.groups);
+ }
/* increment references to algo's */
alg_info_addref((struct alg_info *)c->alg_info_esp);
@@ -703,137 +765,116 @@ unshare_connection_strings(struct connection *c)
static void load_end_certificate(char *filename, struct end *dst)
{
- time_t valid_until;
- cert_t cert;
- bool valid_cert = FALSE;
+ time_t notBefore, notAfter;
+ cert_t *cert = NULL;
+ certificate_t *certificate;
bool cached_cert = FALSE;
-
+
/* initialize end certificate */
- dst->cert.type = CERT_NONE;
- dst->cert.u.x509 = NULL;
+ dst->cert = NULL;
/* initialize smartcard info record */
dst->sc = NULL;
- if (filename != NULL)
+ if (filename)
{
if (scx_on_smartcard(filename))
{
/* load cert from smartcard */
- valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert);
+ cert = scx_load_cert(filename, &dst->sc, &cached_cert);
}
else
{
/* load cert from file */
- valid_cert = load_host_cert(filename, &cert);
+ cert = load_host_cert(filename);
}
}
- if (valid_cert)
+ if (cert)
{
- err_t ugh = NULL;
+ certificate = cert->cert;
- switch (cert.type)
+ if (dst->id->get_type(dst->id) == ID_ANY ||
+ !certificate->has_subject(certificate, dst->id))
{
- case CERT_PGP:
- select_pgpcert_id(cert.u.pgp, &dst->id);
+ plog( " id '%Y' not confirmed by certificate, defaulting to '%Y'",
+ dst->id, certificate->get_subject(certificate));
+ dst->id->destroy(dst->id);
+ dst->id = certificate->get_subject(certificate);
+ dst->id = dst->id->clone(dst->id);
+ }
- if (cached_cert)
- dst->cert = cert;
- else
+ if (cached_cert)
+ {
+ dst->cert = cert;
+ }
+ else
+ {
+ if (!certificate->get_validity(certificate, NULL, &notBefore, &notAfter))
{
- 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);
+ plog("certificate is invalid (valid from %T to %T)",
+ &notBefore, FALSE, &notAfter, FALSE);
+ cert_free(cert);
+ return;
}
- break;
- case CERT_X509_SIGNATURE:
- select_x509cert_id(cert.u.x509, &dst->id);
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is valid")
+ )
+ add_public_key_from_cert(cert, notAfter, DAL_LOCAL);
+ dst->cert = cert_add(cert);
+ }
+ certificate = dst->cert->cert;
- 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;
- }
+ /* if no CA is defined, use issuer as default */
+ if (dst->ca == NULL && certificate->get_type(certificate) == CERT_X509)
+ {
+ identification_t *issuer;
- 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;
+ issuer = certificate->get_issuer(certificate);
+ dst->ca = issuer->clone(issuer);
}
/* cache the certificate that was last retrieved from the smartcard */
- if (dst->sc != NULL)
+ if (dst->sc)
{
- if (!same_cert(&dst->sc->last_cert, &dst->cert))
+ if (!certificate->equals(certificate, dst->sc->last_cert->cert))
{
lock_certs_and_keys("load_end_certificates");
- release_cert(dst->sc->last_cert);
+ cert_release(dst->sc->last_cert);
dst->sc->last_cert = dst->cert;
- share_cert(dst->cert);
+ cert_share(dst->cert);
unlock_certs_and_keys("load_end_certificates");
}
time(&dst->sc->last_load);
}
}
+ scx_share(dst->sc);
+ cert_share(dst->cert);
}
-static bool
-extract_end(struct end *dst, const whack_end_t *src, const char *which)
+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_ANY;
- }
- else
- {
- err_t ugh = atoid(src->id, &dst->id, TRUE);
-
- if (ugh != NULL)
- {
- loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh);
- dst->id = empty_id; /* ignore bad one */
- }
- }
-
- dst->ca = chunk_empty;
+ dst->id = identification_create_from_string(src->id);
+ dst->ca = NULL;
/* decode CA distinguished name, if any */
- if (src->ca != NULL)
+ if (src->ca)
{
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)
+ dst->ca = identification_create_from_string(src->ca);
+ if (dst->ca->get_type(dst->ca) != ID_DER_ASN1_DN)
{
- plog("bad CA string '%s': %s (ignored)", src->ca, ugh);
- dst->ca = chunk_empty;
+ plog("bad CA string '%s', ignored", src->ca);
+ dst->ca->destroy(dst->ca);
+ dst->ca = NULL;
}
}
}
@@ -842,10 +883,13 @@ extract_end(struct end *dst, const whack_end_t *src, const char *which)
load_end_certificate(src->cert, dst);
/* does id has wildcards? */
- dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
+ dst->has_id_wildcards = dst->id->contains_wildcards(dst->id);
/* decode group attributes, if any */
- decode_groups(src->groups, &dst->groups);
+ if (src->groups)
+ {
+ dst->groups = ietf_attributes_create_from_string(src->groups);
+ }
/* the rest is simple copying of corresponding fields */
dst->host_addr = src->host_addr;
@@ -863,30 +907,38 @@ extract_end(struct end *dst, const whack_end_t *src, const char *which)
dst->hostaccess = src->hostaccess;
dst->allow_any = src->allow_any;
dst->sendcert = src->sendcert;
- dst->updown = src->updown;
+ dst->updown = clone_str(src->updown);
dst->host_port = src->host_port;
+ /* if the sourceip netmask is zero a named pool exists */
+ if (src->sourceip_mask == 0)
+ {
+ dst->pool = clone_str(src->sourceip);
+ }
+
/* 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)
+ 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)
+ if (ugh)
+ {
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)
+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)
@@ -921,23 +973,23 @@ check_connection_end(const whack_end_t *this, const whack_end_t *that
return TRUE; /* happy */
}
-struct connection *
-find_connection_by_reqid(uint32_t reqid)
+connection_t *find_connection_by_reqid(uint32_t reqid)
{
- struct connection *c;
+ connection_t *c;
reqid &= ~3;
for (c = connections; c != NULL; c = c->ac_next)
{
if (c->spd.reqid == reqid)
+ {
return c;
+ }
}
return NULL;
}
-static uint32_t
-gen_reqid(void)
+static uint32_t gen_reqid(void)
{
uint32_t start;
static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
@@ -946,17 +998,20 @@ gen_reqid(void)
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)
+void add_connection(const whack_message_t *wm)
{
if (con_by_name(wm->name, FALSE) != NULL)
{
@@ -973,45 +1028,50 @@ add_connection(const whack_message_t *wm)
&& check_connection_end(&wm->left, &wm->right, wm))
{
bool same_rightca, same_leftca;
- struct connection *c = malloc_thing(struct connection);
+ connection_t *c = malloc_thing(connection_t);
zero(c);
- c->name = wm->name;
+ c->name = clone_str(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)
{
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 : "");
+ 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);
+ if (c->alg_info_esp->alg_info_cnt == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "got 0 esp transforms");
+ }
}
else
{
- loglog(RC_LOG_SERIOUS, "esp string error");
+ loglog(RC_LOG_SERIOUS, "syntax error in esp string");
}
}
-
+
if (wm->ike)
{
DBG(DBG_CONTROL,
@@ -1023,22 +1083,25 @@ add_connection(const whack_message_t *wm)
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);
+ if (c->alg_info_ike->alg_info_cnt == 0)
+ {
+ loglog(RC_LOG_SERIOUS, "got 0 ike transforms");
+ }
}
else
{
- loglog(RC_LOG_SERIOUS, "ike string error:");
+ loglog(RC_LOG_SERIOUS, "syntax error in ike string");
}
}
-
+
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;
@@ -1059,9 +1122,13 @@ add_connection(const whack_message_t *wm)
same_rightca = extract_end(&c->spd.that, &wm->right, "right");
if (same_rightca)
- c->spd.that.ca = c->spd.this.ca;
+ {
+ c->spd.that.ca = c->spd.this.ca->clone(c->spd.this.ca);
+ }
else if (same_leftca)
- c->spd.this.ca = c->spd.that.ca;
+ {
+ c->spd.this.ca = c->spd.that.ca->clone(c->spd.that.ca);
+ }
default_end(&c->spd.this, &c->spd.that.host_addr);
default_end(&c->spd.that, &c->spd.this.host_addr);
@@ -1127,16 +1194,17 @@ add_connection(const whack_message_t *wm)
c->spd.that.has_client = TRUE;
}
- unshare_connection_strings(c);
(void)orient(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];
+ char topo[BUF_LEN];
(void) format_connection(topo, sizeof(topo), c, &c->spd);
@@ -1172,12 +1240,10 @@ add_connection(const whack_message_t *wm)
* Returns name of new connection. May be NULL.
* Caller is responsible for freeing.
*/
-char *
-add_group_instance(struct connection *group, const ip_subnet *target)
+char *add_group_instance(connection_t *group, const ip_subnet *target)
{
- char namebuf[100]
- , targetbuf[SUBNETTOT_BUF];
- struct connection *t;
+ char namebuf[100], targetbuf[SUBNETTOT_BUF];
+ connection_t *t;
char *name = NULL;
passert(group->kind == CK_GROUP);
@@ -1213,7 +1279,7 @@ add_group_instance(struct connection *group, const ip_subnet *target)
if (t->spd.that.virt)
{
DBG_log("virtual_ip not supported in group instance");
- t->spd.that.virt = NULL;
+ t->spd.that.virt = NULL;
}
/* add to connections list */
@@ -1234,9 +1300,8 @@ add_group_instance(struct connection *group, const ip_subnet *target)
}
/* an old target has disappeared for a group: delete instance */
-void
-remove_group_instance(const struct connection *group USED_BY_DEBUG
-, const char *name)
+void remove_group_instance(const connection_t *group USED_BY_DEBUG,
+ const char *name)
{
passert(group->kind == CK_GROUP);
passert(oriented(*group));
@@ -1254,13 +1319,10 @@ remove_group_instance(const struct connection *group USED_BY_DEBUG
*
* Note that instantiate can only deal with a single SPD/eroute.
*/
-static struct connection *
-instantiate(struct connection *c, const ip_address *him
-, u_int16_t his_port
-, const struct id *his_id)
+static connection_t *instantiate(connection_t *c, const ip_address *him,
+ u_int16_t his_port, identification_t *his_id)
{
- struct connection *d;
- int wildcards;
+ connection_t *d;
passert(c->kind == CK_TEMPLATE);
passert(c->spd.next == NULL);
@@ -1269,15 +1331,20 @@ instantiate(struct connection *c, const ip_address *him
d = clone_thing(*c);
d->spd.that.allow_any = FALSE;
- if (his_id != NULL)
+ if (his_id)
{
- passert(match_id(his_id, &d->spd.that.id, &wildcards));
- d->spd.that.id = *his_id;
+ 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);
+ if (d->spd.this.groups)
+ {
+ d->spd.this.groups = d->spd.this.groups->get_ref(d->spd.this.groups);
+ }
+ if (d->spd.that.groups)
+ {
+ d->spd.that.groups = d->spd.that.groups->get_ref(d->spd.that.groups);
+ }
d->kind = CK_INSTANCE;
passert(oriented(*d));
@@ -1318,11 +1385,11 @@ instantiate(struct connection *c, const ip_address *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)
+connection_t *rw_instantiate(connection_t *c, const ip_address *him,
+ u_int16_t his_port, const ip_subnet *his_net,
+ identification_t *his_id)
{
- struct connection *d = instantiate(c, him, his_port, his_id);
+ connection_t *d = instantiate(c, him, his_port, his_id);
if (d && his_net && is_virtual_connection(c))
{
@@ -1345,15 +1412,12 @@ rw_instantiate(struct connection *c, const ip_address *him, u_int16_t his_port
return d;
}
-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 USED_BY_DEBUG
-, const ip_address *peer_client)
+connection_t *oppo_instantiate(connection_t *c, const ip_address *him,
+ identification_t *his_id, struct gw_info *gw,
+ const ip_address *our_client USED_BY_DEBUG,
+ const ip_address *peer_client)
{
- struct connection *d = instantiate(c, him, 0, his_id);
+ connection_t *d = instantiate(c, him, 0, his_id);
passert(d->spd.next == NULL);
@@ -1407,7 +1471,7 @@ oppo_instantiate(struct connection *c
d->instance_initiation_ok = TRUE;
DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
+ char topo[BUF_LEN];
(void) format_connection(topo, sizeof(topo), d, &d->spd);
DBG_log("instantiated \"%s\": %s", d->name, topo);
@@ -1416,14 +1480,17 @@ oppo_instantiate(struct connection *c
}
/* priority formatting */
-void
-fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
+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);
+ }
}
/* Format any information needed to identify an instance of a connection.
@@ -1431,8 +1498,8 @@ fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
* Road Warrior: peer's IP address
* Opportunistic: [" " myclient "==="] " ..." peer ["===" hisclient] '\0'
*/
-static size_t
-fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, char buf[ADDRTOT_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))
{
@@ -1452,8 +1519,7 @@ fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, ch
return strlen(buf);
}
-void
-fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
+void fmt_conn_instance(const connection_t *c, char buf[CONN_INST_BUF])
{
char *p = buf;
@@ -1510,13 +1576,12 @@ fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
*
* See also build_outgoing_opportunistic_connection.
*/
-struct connection *
-find_connection_for_clients(struct spd_route **srp,
- const ip_address *our_client,
- const ip_address *peer_client,
- int transport_proto)
+connection_t *find_connection_for_clients(struct spd_route **srp,
+ const ip_address *our_client,
+ const ip_address *peer_client,
+ int transport_proto)
{
- struct connection *c = connections, *best = NULL;
+ connection_t *c = connections, *best = NULL;
policy_prio_t best_prio = BOTTOM_PRIO;
struct spd_route *sr;
struct spd_route *best_sr = NULL;
@@ -1540,7 +1605,9 @@ find_connection_for_clients(struct spd_route **srp,
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)
{
@@ -1605,11 +1672,14 @@ find_connection_for_clients(struct spd_route **srp,
}
}
- if (best!= NULL && NEVER_NEGOTIATE(best->policy))
+ if (best && NEVER_NEGOTIATE(best->policy))
+ {
best = NULL;
-
- if (srp != NULL && best != NULL)
+ }
+ if (srp && best)
+ {
*srp = best_sr;
+ }
#ifdef DEBUG
if (DBGP(DBG_CONTROL))
@@ -1654,25 +1724,18 @@ find_connection_for_clients(struct spd_route **srp,
* find_connection_for_clients. In this case, we know the gateways
* that we need to instantiate an opportunistic connection.
*/
-struct connection *
-build_outgoing_opportunistic_connection(struct gw_info *gw
- ,const ip_address *our_client
- ,const ip_address *peer_client)
+connection_t *build_outgoing_opportunistic_connection(struct gw_info *gw,
+ const ip_address *our_client,
+ const ip_address *peer_client)
{
struct iface *p;
- struct connection *best = NULL;
+ connection_t *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)
{
@@ -1680,8 +1743,8 @@ build_outgoing_opportunistic_connection(struct gw_info *gw
* 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);
+ connection_t *c = find_host_pair_connections(&p->addr, pluto_port,
+ (ip_address *)NULL, pluto_port);
for (; c != NULL; c = c->hp_next)
{
@@ -1723,18 +1786,25 @@ build_outgoing_opportunistic_connection(struct gw_info *gw
}
}
- if (best == NULL
- || NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY
- || best->kind != CK_TEMPLATE)
+ 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);
+ {
+ chunk_t encoding = gw->gw_id->get_encoding(gw->gw_id);
+ id_type_t type = gw->gw_id->get_type(gw->gw_id);
+ ip_address ip_addr;
+
+ initaddr(encoding.ptr, encoding.len,
+ (type == ID_IPV4_ADDR) ? AF_INET : AF_INET6, &ip_addr);
+
+ return oppo_instantiate(best, &ip_addr, NULL, gw, our_client, peer_client);
+ }
}
-bool
-orient(struct connection *c)
+bool orient(connection_t *c)
{
struct spd_route *sr;
@@ -1750,7 +1820,9 @@ orient(struct connection *c)
for (p = interfaces; p != NULL; p = p->next)
{
if (p->ike_float)
+ {
continue;
+ }
for (;;)
{
@@ -1796,12 +1868,11 @@ orient(struct connection *c)
return oriented(*c);
}
-void
-initiate_connection(const char *name, int whackfd)
+void initiate_connection(const char *name, int whackfd)
{
- struct connection *c = con_by_name(name, TRUE);
+ connection_t *c = con_by_name(name, TRUE);
- if (c != NULL && c->ikev1)
+ if (c && c->ikev1)
{
set_cur_connection(c);
if (!oriented(*c))
@@ -1823,11 +1894,11 @@ initiate_connection(const char *name, int whackfd)
else
{
/* do we have to prompt for a PIN code? */
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)
+ if (c->spd.this.sc && !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)
+ if (c->spd.this.sc && !c->spd.this.sc->valid)
{
loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
}
@@ -1836,8 +1907,8 @@ initiate_connection(const char *name, int whackfd)
if (c->spd.that.allow_any)
{
- c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port
- , &c->spd.that.id);
+ 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
@@ -1928,10 +1999,7 @@ struct find_oppo_continuation {
struct find_oppo_bundle b;
};
-static void
-cannot_oppo(struct connection *c
- , struct find_oppo_bundle *b
- , err_t ugh)
+static void cannot_oppo(connection_t *c, struct find_oppo_bundle *b, err_t ugh)
{
char pcb[ADDRTOT_BUF];
char ocb[ADDRTOT_BUF];
@@ -1946,11 +2014,11 @@ cannot_oppo(struct connection *c
, "Can't Opportunistically initiate for %s to %s: %s"
, ocb, pcb, ugh);
- if (c != NULL && c->policy_next != NULL)
+ if (c && c->policy_next)
{
/* there is some policy that comes afterwards */
struct spd_route *shunt_spd;
- struct connection *nc = c->policy_next;
+ connection_t *nc = c->policy_next;
struct state *st;
passert(c->kind == CK_TEMPLATE);
@@ -2048,12 +2116,9 @@ cannot_oppo(struct connection *c
static void initiate_opportunistic_body(struct find_oppo_bundle *b
, struct adns_continuation *ac, err_t ac_ugh); /* forward */
-void
-initiate_opportunistic(const ip_address *our_client
-, const ip_address *peer_client
-, int transport_proto
-, bool held
-, int whackfd)
+void initiate_opportunistic(const ip_address *our_client,
+ const ip_address *peer_client, int transport_proto,
+ bool held, int whackfd)
{
struct find_oppo_bundle b;
@@ -2070,11 +2135,10 @@ initiate_opportunistic(const ip_address *our_client
initiate_opportunistic_body(&b, NULL, NULL);
}
-static void
-continue_oppo(struct adns_continuation *acr, err_t ugh)
+static void continue_oppo(struct adns_continuation *acr, err_t ugh)
{
struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
- struct connection *c;
+ connection_t *c;
bool was_held = cr->b.held;
int whackfd = cr->b.whackfd;
@@ -2095,7 +2159,7 @@ continue_oppo(struct adns_continuation *acr, err_t ugh)
#ifdef DEBUG
/* if we're going to ignore the error, at least note it in debugging log */
- if (cr->b.failure_ok && ugh != NULL)
+ if (cr->b.failure_ok && ugh)
{
DBG(DBG_CONTROL | DBG_DNS,
{
@@ -2110,7 +2174,7 @@ continue_oppo(struct adns_continuation *acr, err_t ugh)
}
#endif
- if (!cr->b.failure_ok && ugh != NULL)
+ if (!cr->b.failure_ok && ugh)
{
c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
, cr->b.transport_proto);
@@ -2145,10 +2209,8 @@ continue_oppo(struct adns_continuation *acr, err_t ugh)
}
#ifdef USE_KEYRR
-static err_t
-check_key_recs(enum myid_state try_state
-, const struct connection *c
-, struct adns_continuation *ac)
+static err_t check_key_recs(enum myid_state try_state, const connection_t *c,
+ struct adns_continuation *ac)
{
/* Check if KEY lookup yielded good results.
* Looking up based on our ID. Used if
@@ -2194,14 +2256,15 @@ check_key_recs(enum myid_state try_state
}
}
}
- if (ugh != NULL)
+ if (ugh)
+ {
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,
+static err_t check_txt_recs(enum myid_state try_state, const connection_t *c,
struct adns_continuation *ac)
{
/* Check if TXT lookup yielded good results.
@@ -2226,7 +2289,7 @@ static err_t check_txt_recs(enum myid_state try_state,
{
ugh = "we don't know our own RSA key";
}
- else if (!same_id(&ac->id, &c->spd.this.id))
+ else if (!ac->id->equals(ac->id, c->spd.this.id))
{
ugh = "our ID changed underfoot";
}
@@ -2251,7 +2314,7 @@ static err_t check_txt_recs(enum myid_state try_state,
}
}
}
- if (ugh != NULL)
+ if (ugh)
{
myid_state = old_myid_state;
}
@@ -2260,12 +2323,11 @@ static err_t check_txt_recs(enum myid_state try_state,
/* note: gateways_from_dns must be NULL iff this is the first call */
-static void
-initiate_opportunistic_body(struct find_oppo_bundle *b
-, struct adns_continuation *ac
-, err_t ac_ugh)
+static void initiate_opportunistic_body(struct find_oppo_bundle *b,
+ struct adns_continuation *ac,
+ err_t ac_ugh)
{
- struct connection *c;
+ connection_t *c;
struct spd_route *sr;
/* What connection shall we use?
@@ -2353,17 +2415,11 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
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 */
+ DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s",
+ c->name, (fmt_conn_instance(c, cib), cib)));
+ snprintf(mycredentialstr, BUF_LEN, "%Y", sr->this.id);
/* handle any DNS answer; select next step */
-
switch (b->step)
{
case fos_start:
@@ -2373,18 +2429,17 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
ugh = check_txt_recs(MYID_IP, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* 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));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our IP (%Y:TXT) as identity: %s",
+ myids[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);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our IP (%Y:TXT) as identity: %s",
+ myids[MYID_IP], ugh);
logged_myid_ip_txt_warning = TRUE;
}
@@ -2396,9 +2451,9 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* 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]);
+ loglog(RC_LOG_SERIOUS,
+ "using our IP (%Y:TXT) as identity!",
+ myids[MYID_IP]);
logged_myid_ip_txt_warning = TRUE;
}
@@ -2408,18 +2463,17 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* 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));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our hostname (%Y:TXT) as identity: %s",
+ myids[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);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our hostname (%Y:TXT) as identity: %s",
+ myids[MYID_HOSTNAME], ugh);
logged_myid_fqdn_txt_warning = TRUE;
}
#ifdef USE_KEYRR
@@ -2432,9 +2486,9 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* 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]);
+ loglog(RC_LOG_SERIOUS,
+ "using our hostname (%Y:TXT) as identity!",
+ myids[MYID_HOSTNAME]);
logged_myid_fqdn_txt_warning = TRUE;
}
next_step = fos_our_client;
@@ -2444,18 +2498,17 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
#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)
+ if (ugh)
{
/* 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));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our IP (%Y:KEY) as identity: %s",
+ myids[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);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our IP (%Y:KEY) as identity: %s",
+ myids[MYID_IP], ugh);
logged_myid_ip_key_warning = TRUE;
}
@@ -2467,9 +2520,9 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* 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]);
+ loglog(RC_LOG_SERIOUS,
+ "using our IP (%Y:KEY) as identity!",
+ myids[MYID_IP]);
logged_myid_ip_key_warning = TRUE;
}
next_step = fos_our_client;
@@ -2478,21 +2531,19 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
case fos_myid_hostname_key: /* KEY for our hostname as %myid */
ugh = check_key_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* 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));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our hostname (%Y:KEY) as identity: %s",
+ myids[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);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our hostname (%Y:KEY) as identity: %s",
+ myids[MYID_HOSTNAME], ugh);
logged_myid_fqdn_key_warning = TRUE;
}
-
next_step = fos_myid_hostname_key;
ugh = NULL; /* failure can be recovered from */
}
@@ -2501,9 +2552,9 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* 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]);
+ loglog(RC_LOG_SERIOUS,
+ "using our hostname (%Y:KEY) as identity!",
+ myids[MYID_HOSTNAME]);
logged_myid_fqdn_key_warning = TRUE;
}
next_step = fos_our_client;
@@ -2522,8 +2573,6 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
next_step = fos_his_client; /* normal situation */
- passert(sr != NULL);
-
if (private == NULL)
{
ugh = "we don't know our own RSA key";
@@ -2533,7 +2582,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* this wasn't true when we started -- bail */
ugh = "our IP address changed underfoot";
}
- else if (!same_id(&ac->sgw_id, &sr->this.id))
+ else if (!ac->sgw_id->equals(ac->sgw_id, sr->this.id))
{
/* this wasn't true when we started -- bail */
ugh = "our ID changed underfoot";
@@ -2548,8 +2597,6 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
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.
@@ -2592,7 +2639,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
{
ugh = "we don't know our own RSA key";
}
- else if (!same_id(&ac->id, &c->spd.this.id))
+ else if (!ac->id->equals(ac->id, c->spd.this.id))
{
ugh = "our ID changed underfoot";
}
@@ -2606,8 +2653,6 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
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))
@@ -2620,7 +2665,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
}
}
#ifdef USE_KEYRR
- if (ugh != NULL)
+ if (ugh)
{
/* if no TXT with right key, try KEY */
DBG(DBG_CONTROL,
@@ -2707,18 +2752,14 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* We cannot seem to instantiate a suitable connection:
* complain clearly.
*/
- char ocb[ADDRTOT_BUF]
- , pcb[ADDRTOT_BUF]
- , pb[ADDRTOT_BUF];
+ char ocb[ADDRTOT_BUF], pcb[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);
+ loglog(RC_OPPOFAILURE,
+ "no suitable connection for opportunism "
+ "between %s and %s with %Y as peer",
+ ocb, pcb, ac->gateways_from_dns->gw_id);
#ifdef KLIPS
if (b->held)
@@ -2774,7 +2815,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
, ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
});
- if (ugh != NULL)
+ if (ugh)
{
b->policy_prio = c->prio;
b->failure_shunt = shunt_policy_spi(c, FALSE);
@@ -2788,7 +2829,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
{
/* set up the next query */
struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation);
- struct id id;
+ identification_t *id;
b->policy_prio = c->prio;
b->failure_shunt = shunt_policy_spi(c, FALSE);
@@ -2829,23 +2870,20 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
switch (next_step)
{
case fos_myid_ip_txt:
- if (c->spd.this.id.kind == ID_MYID
+ if (c->spd.this.id->get_type(c->spd.this.id) == 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);
+ 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
+ if (c->spd.this.id->get_type(c->spd.this.id) == ID_MYID
&& myid_state != MYID_SPECIFIED)
{
#ifdef USE_KEYRR
@@ -2854,11 +2892,9 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
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);
+ ugh = start_adns_query(myids[MYID_HOSTNAME],
+ myids[MYID_HOSTNAME],
+ T_TXT, continue_oppo, &cr->ac);
break;
}
@@ -2872,11 +2908,8 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
{
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);
+ ugh = start_adns_query(myids[MYID_IP], NULL, /* security gateway meaningless */
+ T_KEY, continue_oppo, &cr->ac);
break;
}
cr->b.step = fos_myid_hostname_key;
@@ -2888,11 +2921,8 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
{
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);
+ ugh = start_adns_query(myids[MYID_HOSTNAME], NULL, /* security gateway meaningless */
+ T_KEY, continue_oppo, &cr->ac);
break;
}
#endif
@@ -2906,12 +2936,10 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
* 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);
+ id = identification_create_from_sockaddr((sockaddr_t*)&b->our_client);
+ ugh = start_adns_query(id, c->spd.this.id, /* we are the security gateway */
+ T_TXT, continue_oppo, &cr->ac);
+ id->destroy(id);
break;
}
cr->b.step = fos_our_txt;
@@ -2920,22 +2948,16 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
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);
+ ugh = start_adns_query(sr->this.id, sr->this.id, /* we are the security gateway */
+ 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);
+ ugh = start_adns_query(sr->this.id, NULL, /* security gateway meaningless */
+ T_KEY, continue_oppo, &cr->ac);
break;
#endif /* USE_KEYRR */
@@ -2943,12 +2965,10 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
/* 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);
+ id = identification_create_from_sockaddr((sockaddr_t*)&b->peer_client);
+ ugh = start_adns_query(id, NULL, /* security gateway unconstrained */
+ T_TXT, continue_oppo, &cr->ac);
+ id->destroy(id);
break;
default:
@@ -2964,20 +2984,19 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
close_any(b->whackfd);
}
-void
-terminate_connection(const char *nm)
+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);
+ connection_t *c = con_by_name(nm, TRUE);
if (c == NULL || !c->ikev1)
return;
do
{
- struct connection *n = c->ac_next; /* grab this before c might disappear */
+ connection_t *n = c->ac_next; /* grab this before c might disappear */
if (streq(c->name, nm)
&& c->kind >= CK_PERMANENT
@@ -2993,7 +3012,7 @@ terminate_connection(const char *nm)
reset_cur_connection();
}
c = n;
- } while (c != NULL);
+ } while (c);
}
/* an ISAKMP SA has been established.
@@ -3002,8 +3021,7 @@ terminate_connection(const char *nm)
*/
bool uniqueIDs = FALSE; /* --uniqueids? */
-void
-ISAKMP_SA_established(struct connection *c, so_serial_t serial)
+void ISAKMP_SA_established(connection_t *c, so_serial_t serial)
{
c->newest_isakmp_sa = serial;
@@ -3011,23 +3029,25 @@ ISAKMP_SA_established(struct connection *c, so_serial_t serial)
* 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;
+ connection_t *d;
for (d = connections; d != NULL; )
{
- struct connection *next = d->ac_next; /* might move underneath us */
+ connection_t *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))
+ if (d->kind >= CK_PERMANENT &&
+ c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
+ c->spd.that.id->equals(c->spd.that.id, d->spd.that.id) &&
+ !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
{
release_connection(d, FALSE);
}
@@ -3047,13 +3067,10 @@ ISAKMP_SA_established(struct connection *c, so_serial_t serial)
* The return value is used to find other connections sharing a route.
* *erop is used to find other connections sharing an eroute.
*/
-struct connection *
-route_owner(struct connection *c
- , struct spd_route **srp
- , struct connection **erop
- , struct spd_route **esrp)
+connection_t *route_owner(connection_t *c, struct spd_route **srp,
+ connection_t **erop, struct spd_route **esrp)
{
- struct connection *d
+ connection_t *d
, *best_ro = c
, *best_ero = c;
struct spd_route *srd, *src;
@@ -3076,11 +3093,17 @@ route_owner(struct connection *c
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)
{
@@ -3090,11 +3113,17 @@ route_owner(struct connection *c
}
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;
@@ -3123,7 +3152,7 @@ route_owner(struct connection *c
, (fmt_conn_instance(best_ro, cib), cib)
, enum_name(&routing_story, best_ro->spd.routing));
- if (erop != NULL)
+ if (erop)
{
m = builddiag("%s; eroute owner:", m);
if (!erouted(best_ero->spd.routing))
@@ -3140,14 +3169,17 @@ route_owner(struct connection *c
DBG_log("%s", m);
});
- if (erop != NULL)
+ if (erop)
+ {
*erop = erouted(best_erouting)? best_ero : NULL;
-
- if (srp != NULL )
+ }
+ if (srp)
{
*srp = best_sr;
- if (esrp != NULL )
+ if (esrp)
+ {
*esrp = best_esr;
+ }
}
return routed(best_routing)? best_ro : NULL;
@@ -3157,10 +3189,9 @@ route_owner(struct connection *c
* There ought to be only one.
* This might get to be a bottleneck -- try hashing if it does.
*/
-struct connection *
-shunt_owner(const ip_subnet *ours, const ip_subnet *his)
+connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his)
{
- struct connection *c;
+ connection_t *c;
struct spd_route *sr;
for (c = connections; c != NULL; c = c->ac_next)
@@ -3180,11 +3211,11 @@ shunt_owner(const ip_subnet *ours, const ip_subnet *his)
* We don't know enough to chose amongst those available.
* ??? no longer usefully different from find_host_pair_connections
*/
-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)
+connection_t *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);
+ connection_t *c = find_host_pair_connections(me, my_port, him, his_port);
if (policy != LEMPTY)
{
@@ -3193,7 +3224,7 @@ find_host_connection(const ip_address *me, u_int16_t my_port
/* if we have requirements for the policy,
* choose the first matching connection.
*/
- while (c != NULL)
+ while (c)
{
if (c->policy & auth_requested)
{
@@ -3266,25 +3297,25 @@ find_host_connection(const ip_address *me, u_int16_t my_port
*/
#define PRIO_NO_MATCH_FOUND 2048
-struct connection *
-refine_host_connection(const struct state *st, const struct id *peer_id
-, chunk_t peer_ca)
+connection_t *refine_host_connection(const struct state *st,
+ identification_t *peer_id,
+ identification_t *peer_ca)
{
- struct connection *c = st->st_connection;
- struct connection *d;
- struct connection *best_found = NULL;
+ connection_t *c = st->st_connection;
+ connection_t *d;
+ connection_t *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;
+ int 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)
+ if (c->spd.that.id->equals(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"
@@ -3345,8 +3376,10 @@ refine_host_connection(const struct state *st, const struct id *peer_id
{
const char *match_name[] = {"no", "ok"};
- bool matching_id = match_id(peer_id
- , &d->spd.that.id, &wildcards);
+ id_match_t match_level = peer_id->matches(peer_id, d->spd.that.id);
+
+ bool matching_id = match_level > ID_MATCH_NONE;
+
bool matching_auth = (d->policy & auth_policy) != LEMPTY;
bool matching_trust = trusted_ca(peer_ca
@@ -3355,10 +3388,11 @@ refine_host_connection(const struct state *st, const struct id *peer_id
, d->spd.this.ca, &our_pathlen);
bool match = matching_id && matching_auth && matching_trust;
- int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards;
+ int prio = (ID_MATCH_PERFECT) * !matching_request +
+ ID_MATCH_PERFECT - match_level;
- prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen;
- prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen;
+ prio = (X509_MAX_PATH_LEN + 1) * prio + peer_pathlen;
+ prio = (X509_MAX_PATH_LEN + 1) * prio + our_pathlen;
DBG(DBG_CONTROLMORE,
DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)"
@@ -3373,11 +3407,15 @@ refine_host_connection(const struct state *st, const struct id *peer_id
/* 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)
@@ -3395,12 +3433,17 @@ refine_host_connection(const struct state *st, const struct id *peer_id
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;
@@ -3415,7 +3458,9 @@ refine_host_connection(const struct state *st, const struct id *peer_id
.*/
if (d->spd.this.sc == NULL /* no smartcard */
&& get_private_key(d) == NULL) /* no private key */
+ {
continue;
+ }
break;
default:
@@ -3456,10 +3501,10 @@ refine_host_connection(const struct state *st, const struct id *peer_id
* With virtual addressing, we must not allow someone to use an already
* used (by another id) addr/net.
*/
-static bool
-is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
+static bool is_virtual_net_used(const ip_subnet *peer_net,
+ identification_t *peer_id)
{
- struct connection *d;
+ connection_t *d;
for (d = connections; d != NULL; d = d->ac_next)
{
@@ -3469,16 +3514,15 @@ is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
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))
+ && !d->spd.that.id->equals(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);
+ plog("Virtual IP %s is already used by '%Y'",
+ client, d->spd.that.id);
+ plog("Your ID is '%Y'", peer_id);
+
return TRUE; /* already used by another one */
}
break;
@@ -3516,27 +3560,27 @@ is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
*/
#define PATH_WEIGHT 1
-#define WILD_WEIGHT (MAX_CA_PATH_LEN+1)
-#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
+#define WILD_WEIGHT (X509_MAX_PATH_LEN+1)
+#define PRIO_WEIGHT (ID_MATCH_PERFECT+1) * WILD_WEIGHT
/* fc_try: a helper function for find_client_connection */
-static struct connection *
-fc_try(const struct connection *c
-, struct host_pair *hp
-, const struct id *peer_id
-, const ip_subnet *our_net
-, const ip_subnet *peer_net
-, const u_int8_t our_protocol
-, const u_int16_t our_port
-, const u_int8_t peer_protocol
-, const u_int16_t peer_port
-, chunk_t peer_ca
-, const ietfAttrList_t *peer_list)
+static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
+ identification_t *peer_id,
+ const ip_subnet *our_net,
+ const ip_subnet *peer_net,
+ const u_int8_t our_protocol,
+ const u_int16_t our_port,
+ const u_int8_t peer_protocol,
+ const u_int16_t peer_port,
+ identification_t *peer_ca,
+ ietf_attributes_t *peer_attributes)
{
- struct connection *d;
- struct connection *best = NULL;
+ connection_t *d;
+ connection_t *best = NULL;
policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
+ id_match_t match_level;
+ int pathlen;
+
const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
@@ -3545,20 +3589,28 @@ fc_try(const struct connection *c
struct spd_route *sr;
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)))
+ match_level = c->spd.that.id->matches(c->spd.that.id, d->spd.that.id);
+
+ if (!(c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
+ (match_level > ID_MATCH_NONE) &&
+ trusted_ca(peer_ca, d->spd.that.ca, &pathlen) &&
+ match_group_membership(peer_attributes, 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.
@@ -3595,29 +3647,38 @@ fc_try(const struct connection *c
#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;
+ || 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:
@@ -3629,8 +3690,8 @@ fc_try(const struct connection *c
* - 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)
+ + WILD_WEIGHT * match_level
+ + PATH_WEIGHT * (X509_MAX_PATH_LEN - pathlen)
+ 1;
if (prio > best_prio)
{
@@ -3640,9 +3701,10 @@ fc_try(const struct connection *c
}
}
- if (best != NULL && NEVER_NEGOTIATE(best->policy))
+ if (best && NEVER_NEGOTIATE(best->policy))
+ {
best = NULL;
-
+ }
DBG(DBG_CONTROLMORE,
DBG_log(" fc_try concluding with %s [%ld]"
, (best ? best->name : "none"), best_prio)
@@ -3650,22 +3712,22 @@ fc_try(const struct connection *c
return best;
}
-static struct connection *
-fc_try_oppo(const struct connection *c
-, struct host_pair *hp
-, const ip_subnet *our_net
-, const ip_subnet *peer_net
-, const u_int8_t our_protocol
-, const u_int16_t our_port
-, const u_int8_t peer_protocol
-, const u_int16_t peer_port
-, chunk_t peer_ca
-, const ietfAttrList_t *peer_list)
+static connection_t *fc_try_oppo(const connection_t *c,
+ struct host_pair *hp,
+ const ip_subnet *our_net,
+ const ip_subnet *peer_net,
+ const u_int8_t our_protocol,
+ const u_int16_t our_port,
+ const u_int8_t peer_protocol,
+ const u_int16_t peer_port,
+ identification_t *peer_ca,
+ ietf_attributes_t *peer_attributes)
{
- struct connection *d;
- struct connection *best = NULL;
+ connection_t *d;
+ connection_t *best = NULL;
policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
+ id_match_t match_level;
+ int pathlen;
for (d = hp->connections; d != NULL; d = d->hp_next)
{
@@ -3673,20 +3735,27 @@ fc_try_oppo(const struct connection *c
policy_prio_t prio;
if (d->policy & POLICY_GROUP)
+ {
continue;
+ }
+ match_level = c->spd.that.id->matches(c->spd.that.id, c->spd.that.id);
- 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)))
+ if (!(c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
+ (match_level > ID_MATCH_NONE) &&
+ trusted_ca(peer_ca, d->spd.that.ca, &pathlen) &&
+ match_group_membership(peer_attributes, 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
@@ -3714,7 +3783,9 @@ fc_try_oppo(const struct connection *c
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.
@@ -3725,8 +3796,8 @@ fc_try_oppo(const struct connection *c
* - 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);
+ + WILD_WEIGHT * match_level
+ + PATH_WEIGHT * (X509_MAX_PATH_LEN - pathlen);
if (prio > best_prio)
{
best = d;
@@ -3736,9 +3807,8 @@ fc_try_oppo(const struct connection *c
}
/* 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))
+ if (best && (NEVER_NEGOTIATE(best->policy) ||
+ (best->policy & POLICY_OPPO) == LEMPTY))
{
best = NULL;
}
@@ -3754,44 +3824,52 @@ fc_try_oppo(const struct connection *c
/*
* get the peer's CA and group attributes
*/
-chunk_t
-get_peer_ca_and_groups(struct connection *c, const ietfAttrList_t **peer_list)
+void get_peer_ca_and_groups(connection_t *c,
+ identification_t **peer_ca,
+ ietf_attributes_t **peer_attributes)
{
- struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
+ struct state *p1st;
- *peer_list = NULL;
+ *peer_ca = NULL;
+ *peer_attributes = NULL;
- if (p1st != NULL
- && p1st->st_peer_pubkey != NULL
- && p1st->st_peer_pubkey->issuer.ptr != NULL)
+ p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
+ if (p1st && p1st->st_peer_pubkey && p1st->st_peer_pubkey->issuer)
{
- x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
- , p1st->st_peer_pubkey->serial);;
+ certificate_t *cert;
- if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
- *peer_list = ac->groups;
+ cert = ac_get_cert(p1st->st_peer_pubkey->issuer,
+ p1st->st_peer_pubkey->serial);
+ if (cert && ac_verify_cert(cert, strict_crl_policy))
+ {
+ ac_t *ac = (ac_t*)cert;
+
+ *peer_attributes = ac->get_groups(ac);
+ }
else
{
DBG(DBG_CONTROL,
DBG_log("no valid attribute cert found")
)
}
- return p1st->st_peer_pubkey->issuer;
+ *peer_ca = p1st->st_peer_pubkey->issuer;
}
- return chunk_empty;
}
-struct connection *
-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 our_port
-, const u_int8_t peer_protocol, const u_int16_t peer_port)
+connection_t *find_client_connection(connection_t *c,
+ const ip_subnet *our_net,
+ const ip_subnet *peer_net,
+ 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;
+ connection_t *d;
struct spd_route *sr;
+ ietf_attributes_t *peer_attributes = NULL;
+ identification_t *peer_ca;
- const ietfAttrList_t *peer_list = NULL;
- chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
+ get_peer_ca_and_groups(c, &peer_ca, &peer_attributes);
#ifdef DEBUG
if (DBGP(DBG_CONTROLMORE))
@@ -3813,7 +3891,7 @@ find_client_connection(struct connection *c
* but even greater priority to a routed concrete connection
*/
{
- struct connection *unrouted = NULL;
+ connection_t *unrouted = NULL;
int srnum = -1;
for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next)
@@ -3838,12 +3916,14 @@ find_client_connection(struct connection *c
&& sr->this.port == our_port
&& sr->that.protocol == peer_protocol
&& sr->that.port == peer_port
- && group_membership(peer_list, c->name, sr->that.groups))
+ && match_group_membership(peer_attributes, c->name, sr->that.groups))
{
passert(oriented(*c));
if (routed(sr->routing))
+ {
+ DESTROY_IF(peer_attributes);
return c;
-
+ }
unrouted = c;
}
}
@@ -3851,7 +3931,7 @@ find_client_connection(struct connection *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);
+ , peer_ca, peer_attributes);
DBG(DBG_CONTROLMORE,
DBG_log(" fc_try %s gives %s"
@@ -3860,7 +3940,9 @@ find_client_connection(struct connection *c
)
if (d == NULL)
+ {
d = unrouted;
+ }
}
if (d == NULL)
@@ -3890,12 +3972,12 @@ find_client_connection(struct connection *c
#endif /* DEBUG */
}
- if (hp != NULL)
+ if (hp)
{
/* 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);
+ , peer_ca, peer_attributes);
if (d == NULL
&& subnetishost(our_net)
@@ -3907,7 +3989,7 @@ find_client_connection(struct connection *c
*/
d = fc_try_oppo(c, hp, our_net, peer_net
, our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
+ , peer_ca, peer_attributes);
}
}
}
@@ -3916,24 +3998,27 @@ find_client_connection(struct connection *c
DBG_log(" concluding with d = %s"
, (d ? d->name : "none"))
)
+ DESTROY_IF(peer_attributes);
return d;
}
-int
-connection_compare(const struct connection *ca
-, const struct connection *cb)
+int connection_compare(const connection_t *ca, const connection_t *cb)
{
int ret;
/* DBG_log("comparing %s to %s", ca->name, cb->name); */
ret = strcasecmp(ca->name, cb->name);
- if (ret != 0)
+ if (ret)
+ {
return ret;
+ }
ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
- if (ret != 0)
+ if (ret)
+ {
return ret;
+ }
/* same name, and same type */
switch (ca->kind)
@@ -3950,19 +4035,17 @@ connection_compare(const struct connection *ca
}
}
-static int
-connection_compare_qsort(const void *a, const void *b)
+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 connection_t *const *)a
+ , *(const connection_t *const *)b);
}
-void
-show_connections_status(bool all, const char *name)
+void show_connections_status(bool all, const char *name)
{
- struct connection *c;
+ connection_t *c;
int count, i;
- struct connection **array;
+ connection_t **array;
/* make an array of connections, and sort it */
count = 0;
@@ -3971,7 +4054,7 @@ show_connections_status(bool all, const char *name)
if (c->ikev1 && (name == NULL || streq(c->name, name)))
count++;
}
- array = malloc(sizeof(struct connection *)*count);
+ array = malloc(sizeof(connection_t *)*count);
count=0;
for (c = connections; c != NULL; c = c->ac_next)
@@ -3981,7 +4064,7 @@ show_connections_status(bool all, const char *name)
}
/* sort it! */
- qsort(array, count, sizeof(struct connection *), connection_compare_qsort);
+ qsort(array, count, sizeof(connection_t *), connection_compare_qsort);
for (i = 0; i < count; i++)
{
@@ -3999,11 +4082,11 @@ show_connections_status(bool all, const char *name)
/* show topology */
{
- char topo[CONNECTION_BUF];
+ char topo[BUF_LEN];
struct spd_route *sr = &c->spd;
int num=0;
- while (sr != NULL)
+ while (sr)
{
(void) format_connection(topo, sizeof(topo), c, sr);
whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
@@ -4018,32 +4101,30 @@ show_connections_status(bool all, const char *name)
if (all)
{
/* show CAs if defined */
- if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL)
+ if (c->spd.this.ca && c->spd.that.ca)
{
- 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: \"%Y\"...\"%Y\"",
+ c->name, instance, c->spd.this.ca, c->spd.that.ca);
+ }
+ else if (c->spd.this.ca)
+ {
+ whack_log(RC_COMMENT, "\"%s\"%s: CAs: \"%Y\"...%%any",
+ c->name, instance, c->spd.this.ca);
- whack_log(RC_COMMENT
- , "\"%s\"%s: CAs: '%s'...'%s'"
- , c->name
- , instance
- , this_ca
- , that_ca);
+ }
+ else if (c->spd.that.ca)
+ {
+ whack_log(RC_COMMENT, "\"%s\"%s: CAs: %%any...\"%Y\"",
+ c->name, instance, c->spd.that.ca);
}
/* show group attributes if defined */
- if (c->spd.that.groups != NULL)
+ if (c->spd.that.groups)
{
- char buf[BUF_LEN];
-
- format_groups(c->spd.that.groups, buf, BUF_LEN);
- whack_log(RC_COMMENT
- , "\"%s\"%s: groups: %s"
+ whack_log(RC_COMMENT, "\"%s\"%s: groups: %s"
, c->name
, instance
- , buf);
+ , c->spd.that.groups->get_string(c->spd.that.groups));
}
whack_log(RC_COMMENT
@@ -4058,7 +4139,7 @@ show_connections_status(bool all, const char *name)
, (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;"
@@ -4095,7 +4176,7 @@ show_connections_status(bool all, const char *name)
, instance
, c->newest_isakmp_sa
, c->newest_ipsec_sa);
-
+
if (all)
{
ike_alg_show_connection(c, instance);
@@ -4116,7 +4197,7 @@ show_connections_status(bool all, const char *name)
struct pending {
int whack_sock;
struct state *isakmp_sa;
- struct connection *connection;
+ connection_t *connection;
lset_t policy;
unsigned long try;
so_serial_t replacing;
@@ -4125,18 +4206,13 @@ struct pending {
};
/* queue a Quick Mode negotiation pending completion of a suitable Main Mode */
-void
-add_pending(int whack_sock
-, struct state *isakmp_sa
-, struct connection *c
-, lset_t policy
-, unsigned long try
-, so_serial_t replacing)
+void add_pending(int whack_sock, struct state *isakmp_sa, connection_t *c,
+ lset_t policy, unsigned long try, so_serial_t replacing)
{
bool already_queued = FALSE;
struct pending *p = c->host_pair->pending;
- while (p != NULL)
+ while (p)
{
if (streq(c->name, p->connection->name))
{
@@ -4169,8 +4245,7 @@ add_pending(int whack_sock
* This is accomplished by closing all the whack socket file descriptors.
* We go to a lot of trouble to tell each whack, but to not tell it twice.
*/
-void
-release_pending_whacks(struct state *st, err_t story)
+void release_pending_whacks(struct state *st, err_t story)
{
struct pending *p;
struct stat stst;
@@ -4202,20 +4277,20 @@ release_pending_whacks(struct state *st, err_t story)
}
}
-static void
-delete_pending(struct pending **pp)
+static void delete_pending(struct pending **pp)
{
struct pending *p = *pp;
*pp = p->next;
- if (p->connection != NULL)
+ if (p->connection)
+ {
connection_discard(p->connection);
+ }
close_any(p->whack_sock);
free(p);
}
-void
-unpend(struct state *st)
+void unpend(struct state *st)
{
struct pending **pp
, *p;
@@ -4241,8 +4316,7 @@ unpend(struct state *st)
}
/* a Main Mode negotiation has been replaced; update any pending */
-void
-update_pending(struct state *os, struct state *ns)
+void update_pending(struct state *os, struct state *ns)
{
struct pending *p;
@@ -4259,12 +4333,11 @@ update_pending(struct state *os, struct state *ns)
}
/* a Main Mode negotiation has failed; discard any pending */
-void
-flush_pending_by_state(struct state *st)
+void flush_pending_by_state(struct state *st)
{
struct host_pair *hp = st->st_connection->host_pair;
- if (hp != NULL)
+ if (hp)
{
struct pending **pp
, *p;
@@ -4280,10 +4353,9 @@ flush_pending_by_state(struct state *st)
}
/* a connection has been deleted; discard any related pending */
-static void
-flush_pending_by_connection(struct connection *c)
+static void flush_pending_by_connection(connection_t *c)
{
- if (c->host_pair != NULL)
+ if (c->host_pair)
{
struct pending **pp
, *p;
@@ -4303,8 +4375,7 @@ flush_pending_by_connection(struct connection *c)
}
}
-void
-show_pending_phase2(const struct host_pair *hp, const struct state *st)
+void show_pending_phase2(const struct host_pair *hp, const struct state *st)
{
const struct pending *p;
@@ -4329,8 +4400,7 @@ show_pending_phase2(const struct host_pair *hp, const struct state *st)
* We must be careful to avoid circularity:
* we don't touch it if it is CK_GOING_AWAY.
*/
-void
-connection_discard(struct connection *c)
+void connection_discard(connection_t *c)
{
if (c->kind == CK_INSTANCE)
{
@@ -4354,28 +4424,26 @@ connection_discard(struct connection *c)
long eclipse_count = 0;
-struct connection *
-eclipsed(struct connection *c, struct spd_route **esrp)
+connection_t *eclipsed(connection_t *c, struct spd_route **esrp)
{
- struct connection *ue;
+ connection_t *ue;
struct spd_route *sr1 = &c->spd;
ue = NULL;
- while (sr1 != NULL && ue != NULL)
+ while (sr1 && ue)
{
for (ue = connections; ue != NULL; ue = ue->ac_next)
{
struct spd_route *srue = &ue->spd;
- while (srue != NULL
- && srue->routing == RT_ROUTED_ECLIPSED
+ while (srue && 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)
+ if (srue && srue->routing == RT_ROUTED_ECLIPSED)
{
*esrp = srue;
break;
diff --git a/src/pluto/connections.h b/src/pluto/connections.h
index 16cbbfd72..ee2e00da6 100644
--- a/src/pluto/connections.h
+++ b/src/pluto/connections.h
@@ -1,5 +1,6 @@
/* information about connections between hosts and clients
* 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
@@ -17,9 +18,11 @@
#include <sys/queue.h>
-#include "id.h"
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <credentials/ietf_attributes/ietf_attributes.h>
+
#include "certs.h"
-#include "ac.h"
#include "smartcard.h"
#include "whack.h"
@@ -127,7 +130,7 @@ extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
struct virtual_t;
struct end {
- struct id id;
+ identification_t *id;
ip_address
host_addr,
host_nexthop,
@@ -144,13 +147,14 @@ struct end {
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 */
+ cert_t *cert; /* end certificate */
+ identification_t *ca; /* CA distinguished name */
+ ietf_attributes_t *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 */
+ char *pool; /* name of an associated virtual IP address pool */
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 */
@@ -166,6 +170,8 @@ struct spd_route {
uint32_t reqid;
};
+typedef struct connection connection_t;
+
struct connection {
char *name;
bool ikev1;
@@ -182,10 +188,10 @@ struct connection {
time_t dpd_timeout;
dpd_action_t dpd_action;
- char *log_file_name; /* name of log file */
- FILE *log_file; /* possibly open FILE */
+ 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 */
+ bool log_file_err; /* only bitch once */
struct spd_route spd;
@@ -210,119 +216,110 @@ struct connection {
sa_family_t addr_family; /* between gateways */
sa_family_t tunnel_addr_family; /* between clients */
- struct connection *policy_next; /* if multiple policies,
+ connection_t *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 host_pair *host_pair;
- struct connection *hp_next; /* host pair list link */
-
- struct connection *ac_next; /* all connections list link */
-
- generalName_t *requested_ca; /* collected certificate requests */
+ connection_t *hp_next; /* host pair list link */
+ connection_t *ac_next; /* all connections list link */
+ linked_list_t *requested_ca; /* collected certificate requests */
bool got_certrequest;
};
#define oriented(c) ((c).interface != NULL)
-extern bool orient(struct connection *c);
+extern bool orient(connection_t *c);
-extern bool same_peer_ids(const struct connection *c
- , const struct connection *d, const struct id *his_id);
+extern bool same_peer_ids(const connection_t *c, const connection_t *d,
+ identification_t *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)
-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);
+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);
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);
+extern void initiate_opportunistic(const ip_address *our_client,
+ 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);
+extern void release_connection(connection_t *c, bool relations);
+extern void delete_connection(connection_t *c, bool relations);
extern void delete_connections_by_name(const char *name, bool strict);
extern void delete_every_connection(void);
-extern char *add_group_instance(struct connection *group, const ip_subnet *target);
-extern void remove_group_instance(const struct connection *group, const char *name);
+extern char *add_group_instance(connection_t *group, const ip_subnet *target);
+extern void remove_group_instance(const connection_t *group, const char *name);
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);
-extern struct connection *shunt_owner(const ip_subnet *ours
- , const ip_subnet *his);
+extern connection_t *route_owner(connection_t *c, struct spd_route **srp,
+ connection_t **erop, struct spd_route **esrp);
+extern connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his);
extern bool uniqueIDs; /* --uniqueids? */
-extern void ISAKMP_SA_established(struct connection *c, so_serial_t serial);
+extern void ISAKMP_SA_established(connection_t *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))
+#define id_is_ipaddr(id) ((id)->get_type(id) == ID_IPV4_ADDR || \
+ (id)->get_type(id) == ID_IPV6_ADDR)
+extern bool his_id_was_instantiated(const connection_t *c);
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);
-
-extern struct connection *
-find_connection_for_clients(struct spd_route **srp
- , 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);
-
+
+extern connection_t* con_by_name(const char *nm, bool strict);
+extern connection_t* find_host_connection(const ip_address *me,
+ u_int16_t my_port,
+ const ip_address *him,
+ u_int16_t his_port, lset_t policy);
+extern connection_t* refine_host_connection(const struct state *st,
+ identification_t *id,
+ identification_t *peer_ca);
+extern connection_t* find_client_connection(connection_t *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);
+extern connection_t* find_connection_by_reqid(uint32_t reqid);
+extern connection_t* find_connection_for_clients(struct spd_route **srp,
+ const ip_address *our_client,
+ const ip_address *peer_client,
+ int transport_proto);
+extern void get_peer_ca_and_groups(connection_t *c,
+ identification_t **peer_ca,
+ ietf_attributes_t **peer_attributes);
+
/* 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) */
-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);
-
-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);
-
-extern struct connection
- *build_outgoing_opportunistic_connection(struct gw_info *gw
- , 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)
-
-extern void fmt_conn_instance(const struct connection *c
- , char buf[CONN_INST_BUF]);
+extern connection_t *rw_instantiate(connection_t *c,
+ const ip_address *him,
+ u_int16_t his_port,
+ const ip_subnet *his_net,
+ identification_t *his_id);
+
+extern connection_t *oppo_instantiate(connection_t *c,
+ const ip_address *him,
+ identification_t *his_id,
+ struct gw_info *gw,
+ const ip_address *our_client,
+ const ip_address *peer_client);
+
+extern connection_t
+ *build_outgoing_opportunistic_connection(struct gw_info *gw,
+ const ip_address *our_client,
+ const ip_address *peer_client);
+
+#define CONN_INST_BUF BUF_LEN
+
+extern void fmt_conn_instance(const connection_t *c, char buf[CONN_INST_BUF]);
/* operations on "pending", the structure representing Quick Mode
* negotiations delayed until a Keying Channel has been negotiated.
@@ -330,12 +327,9 @@ extern void fmt_conn_instance(const struct connection *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);
+extern void add_pending(int whack_sock, struct state *isakmp_sa,
+ connection_t *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);
@@ -343,7 +337,7 @@ extern void update_pending(struct state *os, struct state *ns);
extern void flush_pending_by_state(struct state *st);
extern void show_pending_phase2(const struct host_pair *hp, const struct state *st);
-extern void connection_discard(struct connection *c);
+extern void connection_discard(connection_t *c);
/* A template connection's eroute can be eclipsed by
* either a %hold or an eroute for an instance iff
@@ -351,15 +345,15 @@ extern void connection_discard(struct connection *c);
*/
#define eclipsable(sr) (subnetishost(&(sr)->this.client) && subnetishost(&(sr)->that.client))
extern long eclipse_count;
-extern struct connection *eclipsed(struct connection *c, struct spd_route **);
+extern connection_t *eclipsed(connection_t *c, struct spd_route **);
/* print connection status */
extern void show_connections_status(bool all, const char *name);
-extern int connection_compare(const struct connection *ca
- , const struct connection *cb);
-extern void update_host_pair(const char *why, struct connection *c
+extern int connection_compare(const connection_t *ca
+ , const connection_t *cb);
+extern void update_host_pair(const char *why, connection_t *c
, const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport);
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
index e46728d84..6f991fd69 100644
--- a/src/pluto/constants.c
+++ b/src/pluto/constants.c
@@ -25,6 +25,8 @@
#include <freeswan.h>
+#include <attributes/attributes.h>
+
#include "constants.h"
#include "defs.h"
#include "log.h"
@@ -61,20 +63,6 @@ enum_names version_names =
ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
version_name, NULL };
-/* RFC 2459 CRL reason codes */
-
-ENUM(crl_reason_names, REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL,
- "unspecified",
- "key compromise",
- "ca compromise",
- "affiliation changed",
- "superseded",
- "cessation of operation",
- "certificate hold",
- "reason #7",
- "remove from crl"
-);
-
/* RFC 3706 Dead Peer Detection */
ENUM(dpd_action_names, DPD_ACTION_NONE, DPD_ACTION_RESTART,
@@ -82,8 +70,8 @@ ENUM(dpd_action_names, DPD_ACTION_NONE, DPD_ACTION_RESTART,
"clear",
"hold",
"restart"
-);
-
+);
+
/* Timer events */
ENUM(timer_event_names, EVENT_NULL, EVENT_LOG_DAILY,
@@ -288,7 +276,7 @@ const char *const payload_name_nat_d[] = {
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 };
@@ -364,11 +352,21 @@ static const char *const ah_transform_name[] = {
"HMAC_SHA2_512",
"HMAC_RIPEMD",
"AES_XCBC_96",
- "SIG_RSA"
+ "SIG_RSA",
+ "AES_128_GMAC",
+ "AES_192_GMAC",
+ "AES_256_GMAC"
+};
+
+static const char *const ah_transform_name_high[] = {
+ "HMAC_SHA2_256_96"
};
-enum_names ah_transformid_names =
- { AH_MD5, AH_RSA, ah_transform_name, NULL };
+enum_names ah_transform_names_high =
+ { AH_SHA2_256_96, AH_SHA2_256_96, ah_transform_name_high, NULL };
+
+enum_names ah_transform_names =
+ { AH_MD5, AH_AES_256_GMAC, ah_transform_name, &ah_transform_names_high };
/* IPsec ESP transform values */
@@ -402,11 +400,11 @@ static const char *const esp_transform_name_high[] = {
"TWOFISH_CBC"
};
-enum_names esp_transformid_names_high =
+enum_names esp_transform_names_high =
{ 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 };
+enum_names esp_transform_names =
+ { ESP_DES_IV64, ESP_CAMELLIA, esp_transform_name, &esp_transform_names_high };
/* IPCOMP transform values */
@@ -677,15 +675,17 @@ static const char *const auth_alg_name[] = {
};
static const char *const extended_auth_alg_name[] = {
- "NULL"
- };
+ "NULL",
+ "HMAC_SHA2_256_96"
+};
enum_names extended_auth_alg_names =
- { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_NULL, extended_auth_alg_name, NULL };
+ { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_HMAC_SHA2_256_96,
+ extended_auth_alg_name, NULL };
enum_names auth_alg_names =
- { AUTH_ALGORITHM_NONE, AUTH_ALGORITHM_SIG_RSA, auth_alg_name
- , &extended_auth_alg_names };
+ { AUTH_ALGORITHM_NONE, AUTH_ALGORITHM_SIG_RSA,
+ auth_alg_name, &extended_auth_alg_names };
/* From draft-beaulieu-ike-xauth */
static const char *const xauth_type_name[] = {
@@ -859,7 +859,7 @@ static const char *const oakley_auth_name1[] = {
"ECDSA signature",
"ECDSA-256 signature",
"ECDSA-384 signature",
- "ECDSA-521-signature",
+ "ECDSA-521-signature",
};
static const char *const oakley_auth_name2[] = {
@@ -936,7 +936,7 @@ enum_names oakley_group_names_rfc3526 =
oakley_group_name_rfc3526, &oakley_group_names_rfc4753 };
enum_names oakley_group_names =
- { MODP_768_BIT, MODP_1536_BIT,
+ { MODP_768_BIT, MODP_1536_BIT,
oakley_group_name, &oakley_group_names_rfc3526 };
/* Oakley Group Type attribute */
@@ -1000,20 +1000,28 @@ static const char *const notification_dpd_name[] = {
"R_U_THERE_ACK",
};
+static const char *const notification_juniper_name[] = {
+ "NS_NHTB_INFORM",
+};
+
+enum_names notification_juniper_names =
+ { NS_NHTB_INFORM, NS_NHTB_INFORM,
+ notification_juniper_name, NULL };
+
enum_names notification_dpd_names =
{ R_U_THERE, R_U_THERE_ACK,
- notification_dpd_name, NULL };
+ notification_dpd_name, &notification_juniper_names };
enum_names ipsec_notification_names =
{ IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT,
ipsec_notification_name, &notification_dpd_names };
enum_names notification_status_names =
- { CONNECTED, CONNECTED,
+ { ISAKMP_CONNECTED, ISAKMP_CONNECTED,
notification_status_name, &ipsec_notification_names };
enum_names notification_names =
- { INVALID_PAYLOAD_TYPE, UNEQUAL_PAYLOAD_LENGTHS,
+ { ISAKMP_INVALID_PAYLOAD_TYPE, ISAKMP_UNEQUAL_PAYLOAD_LENGTHS,
notification_name, &notification_status_names };
/* MODECFG
@@ -1167,7 +1175,7 @@ const char *const natt_type_bitnames[] = {
"4", "5", "6", "7",
"8", "9", "10", "11",
"12", "13", "14", "15",
- "16", "17", "18", "19",
+ "16", "17", "18", "19",
"20", "21", "22", "23",
"24", "25", "26", "27",
"28", "29",
@@ -1210,8 +1218,8 @@ enum_show(enum_names *ed, unsigned long val)
static char bitnamesbuf[200]; /* only one! I hope that it is big enough! */
-int
-enum_search(enum_names *ed, const char *str)
+int
+enum_search(enum_names *ed, const char *str)
{
enum_names *p;
const char *ptr;
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index 5fe936e08..8c574ebc5 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -16,6 +16,8 @@
#ifndef _CONSTANTS_H
#define _CONSTANTS_H
+#include <freeswan.h>
+
#include <utils.h>
#include <utils/identification.h>
#include <crypto/hashers/hasher.h>
@@ -135,19 +137,23 @@ extern const char sparse_end[];
* 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
+ 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,
+ AH_AES_128_GMAC = 11,
+ AH_AES_192_GMAC = 12,
+ AH_AES_256_GMAC = 13,
+ AH_SHA2_256_96 = 252
};
-extern enum_names ah_transformid_names;
+extern enum_names ah_transform_names;
/* IPsec ESP transform values
* RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4
@@ -155,45 +161,45 @@ extern enum_names ah_transformid_names;
*/
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
+ 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;
+extern enum_names esp_transform_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
+ IPSCOMP_NONE = 0,
+ IPCOMP_OUI = 1,
+ IPCOMP_DEFLATE = 2,
+ IPCOMP_LZS = 3,
+ IPCOMP_LZJH = 4
};
extern enum_names ipcomp_transformid_names;
@@ -202,18 +208,18 @@ extern enum_names ipcomp_transformid_names;
* 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
+ 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 */
@@ -225,21 +231,6 @@ typedef enum {
CERT_UNDEFINED = 3
} cert_status_t;
-/* RFC 2459 CRL reason codes */
-
-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
-} crl_reason_t;
-
/* RFC 3706 Dead Peer Detection */
extern enum_name_t *dpd_action_names;
@@ -549,24 +540,6 @@ extern const char *const payload_name[];
extern enum_names attr_msg_type_names;
-/* Mode Config attribute values */
-#define INTERNAL_IP4_ADDRESS 1
-#define INTERNAL_IP4_NETMASK 2
-#define INTERNAL_IP4_DNS 3
-#define INTERNAL_IP4_NBNS 4
-#define INTERNAL_ADDRESS_EXPIRY 5
-#define INTERNAL_IP4_DHCP 6
-#define APPLICATION_VERSION 7
-#define INTERNAL_IP6_ADDRESS 8
-#define INTERNAL_IP6_NETMASK 9
-#define INTERNAL_IP6_DNS 10
-#define INTERNAL_IP6_NBNS 11
-#define INTERNAL_IP6_DHCP 12
-#define INTERNAL_IP4_SUBNET 13
-#define SUPPORTED_ATTRIBUTES 14
-#define INTERNAL_IP6_SUBNET 15
-
-
extern enum_names modecfg_attr_names;
/* XAUTH attribute values */
@@ -704,10 +677,10 @@ extern enum_name_t *cert_policy_names;
typedef enum certpolicy {
CERT_ALWAYS_SEND = 0,
- CERT_SEND_IF_ASKED = 1,
+ CERT_SEND_IF_ASKED = 1,
CERT_NEVER_SEND = 2,
- CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */
+ CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */
CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */
} certpolicy_t;
@@ -883,18 +856,22 @@ 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_AES_128_GMAC 11
+#define AUTH_ALGORITHM_AES_192_GMAC 12
+#define AUTH_ALGORITHM_AES_256_GMAC 13
+#define AUTH_ALGORITHM_NULL 251
+#define AUTH_ALGORITHM_HMAC_SHA2_256_96 252
/* Oakley Lifetime Type attribute
* draft-ietf-ipsec-ike-01.txt appendix A
@@ -1026,52 +1003,55 @@ 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_NOTHING_WRONG = 0, /* unofficial! */
+
+ ISAKMP_INVALID_PAYLOAD_TYPE = 1,
+ ISAKMP_DOI_NOT_SUPPORTED = 2,
+ ISAKMP_SITUATION_NOT_SUPPORTED = 3,
+ ISAKMP_INVALID_COOKIE = 4,
+ ISAKMP_INVALID_MAJOR_VERSION = 5,
+ ISAKMP_INVALID_MINOR_VERSION = 6,
+ ISAKMP_INVALID_EXCHANGE_TYPE = 7,
+ ISAKMP_INVALID_FLAGS = 8,
+ ISAKMP_INVALID_MESSAGE_ID = 9,
+ ISAKMP_INVALID_PROTOCOL_ID = 10,
+ ISAKMP_INVALID_SPI = 11,
+ ISAKMP_INVALID_TRANSFORM_ID = 12,
+ ISAKMP_ATTRIBUTES_NOT_SUPPORTED = 13,
+ ISAKMP_NO_PROPOSAL_CHOSEN = 14,
+ ISAKMP_BAD_PROPOSAL_SYNTAX = 15,
+ ISAKMP_PAYLOAD_MALFORMED = 16,
+ ISAKMP_INVALID_KEY_INFORMATION = 17,
+ ISAKMP_INVALID_ID_INFORMATION = 18,
+ ISAKMP_INVALID_CERT_ENCODING = 19,
+ ISAKMP_INVALID_CERTIFICATE = 20,
+ ISAKMP_CERT_TYPE_UNSUPPORTED = 21,
+ ISAKMP_INVALID_CERT_AUTHORITY = 22,
+ ISAKMP_INVALID_HASH_INFORMATION = 23,
+ ISAKMP_AUTHENTICATION_FAILED = 24,
+ ISAKMP_INVALID_SIGNATURE = 25,
+ ISAKMP_ADDRESS_NOTIFICATION = 26,
+ ISAKMP_NOTIFY_SA_LIFETIME = 27,
+ ISAKMP_CERTIFICATE_UNAVAILABLE = 28,
+ ISAKMP_UNSUPPORTED_EXCHANGE_TYPE = 29,
+ ISAKMP_UNEQUAL_PAYLOAD_LENGTHS = 30,
/* ISAKMP status type */
- CONNECTED = 16384,
+ ISAKMP_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,
+ IPSEC_RESPONDER_LIFETIME = 24576,
+ IPSEC_REPLAY_STATUS = 24577,
+ IPSEC_INITIAL_CONTACT = 24578,
/* RFC 3706 DPD */
- R_U_THERE = 36136,
- R_U_THERE_ACK = 36137
+ R_U_THERE = 36136,
+ R_U_THERE_ACK = 36137,
+
+ /* Juniper SRX private use */
+ NS_NHTB_INFORM = 40001
} notification_t;
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index c800f2acc..84fe77554 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -24,11 +24,6 @@
#include <freeswan.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"
@@ -39,145 +34,53 @@
#include "keys.h"
#include "whack.h"
#include "fetch.h"
+#include "builder.h"
/* chained lists of X.509 crls */
-static x509crl_t *x509crls = NULL;
-
-/**
- * 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 */
- { 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_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
-
-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 */
-};
+static x509crl_t *x509crls = NULL;
/**
* 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(identification_t *issuer, chunk_t keyid)
{
- x509crl_t *crl = x509crls;
+ x509crl_t *x509crl = x509crls;
x509crl_t *prev_crl = NULL;
- while (crl != NULL)
+ while (x509crl != NULL)
{
- if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL)
- ? same_keyid(keyid, crl->authKeyID)
- : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber)))
+ certificate_t *cert_crl = x509crl->crl;
+ crl_t *crl = (crl_t*)cert_crl;
+ identification_t *crl_issuer = cert_crl->get_issuer(cert_crl);
+ chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
+
+ if ((keyid.ptr && authKeyID.ptr)? same_keyid(keyid, authKeyID) :
+ issuer->equals(issuer, crl_issuer))
{
- if (crl != x509crls)
+ if (x509crl != x509crls)
{
/* bring the CRL up front */
- prev_crl->next = crl->next;
- crl->next = x509crls;
- x509crls = crl;
+ prev_crl->next = x509crl->next;
+ x509crl->next = x509crls;
+ x509crls = x509crl;
}
- return crl;
+ return x509crl;
}
- prev_crl = crl;
- crl = crl->next;
+ prev_crl = x509crl;
+ x509crl = x509crl->next;
}
return NULL;
}
/**
- * Free the dynamic memory used to store revoked certificates
- */
-static void free_revoked_certs(revokedCert_t* revokedCerts)
-{
- while (revokedCerts != NULL)
- {
- revokedCert_t * revokedCert = revokedCerts;
- revokedCerts = revokedCert->next;
- free(revokedCert);
- }
-}
-
-/**
* Free the dynamic memory used to store CRLs
*/
void free_crl(x509crl_t *crl)
{
- free_revoked_certs(crl->revokedCertificates);
- free_generalNames(crl->distributionPoints, TRUE);
- free(crl->certificateList.ptr);
+ DESTROY_IF(crl->crl);
+ crl->distributionPoints->destroy_function(crl->distributionPoints, free);
free(crl);
}
@@ -194,7 +97,9 @@ void free_crls(void)
lock_crl_list("free_crls");
while (x509crls != NULL)
+ {
free_first_crl();
+ }
unlock_crl_list("free_crls");
}
@@ -202,127 +107,109 @@ void free_crls(void)
/**
* Insert X.509 CRL into chained list
*/
-bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl)
+bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
{
- x509crl_t *crl = malloc_thing(x509crl_t);
+ certificate_t *cert_crl = x509crl->crl;
+ crl_t *crl = (crl_t*)cert_crl;
+ identification_t *issuer = cert_crl->get_issuer(cert_crl);
+ chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
+ cert_t *issuer_cert;
+ x509crl_t *oldcrl;
+ time_t now, nextUpdate;
+ bool valid_sig;
+
+ /* add distribution point */
+ add_distribution_point(x509crl->distributionPoints, crl_uri);
+
+ lock_authcert_list("insert_crl");
+
+ /* get the issuer cacert */
+ issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
+ if (issuer_cert == NULL)
+ {
+ plog("crl issuer cacert not found");
+ free_crl(x509crl);
+ unlock_authcert_list("insert_crl");
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("crl issuer cacert found")
+ )
- *crl = empty_x509crl;
+ /* check the issuer's signature of the crl */
+ valid_sig = cert_crl->issued_by(cert_crl, issuer_cert->cert);
+ unlock_authcert_list("insert_crl");
- if (parse_x509crl(blob, 0, crl))
+ if (!valid_sig)
{
- 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("crl issuer cacert found")
- )
+ free_crl(x509crl);
+ return FALSE;
+ }
+ DBG(DBG_CONTROL,
+ DBG_log("crl signature is valid")
+ )
- /* 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");
+ /* note the current time */
+ time(&now);
- 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(issuer, authKeyID);
- lock_crl_list("insert_crl");
- oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
- , crl->authKeyID);
+ if (oldcrl != NULL)
+ {
+ certificate_t *old_cert_crl = oldcrl->crl;
- if (oldcrl != NULL)
+ if (cert_crl->is_newer(cert_crl, old_cert_crl))
{
- if (crl->thisUpdate > oldcrl->thisUpdate)
- {
- /* keep any known CRL distribution points */
- add_distribution_points(oldcrl->distributionPoints
- , &crl->distributionPoints);
+ /* keep any known CRL distribution points */
+ add_distribution_points(x509crl->distributionPoints,
+ oldcrl->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;
- }
+ /* now delete the old CRL */
+ free_first_crl();
+ DBG(DBG_CONTROL,
+ DBG_log("thisUpdate is newer - existing crl deleted")
+ )
}
-
- /* 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)
+ else
{
- 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);
- }
+ unlock_crl_list("insert_crls");
+ DBG(DBG_CONTROL,
+ DBG_log("thisUpdate is not newer - existing crl not replaced");
+ )
+ free_crl(x509crl);
+ old_cert_crl->get_validity(old_cert_crl, &now, NULL, &nextUpdate);
+ return nextUpdate - now > 2*crl_check_interval;
}
-
- /* is the fetched crl valid? */
- return crl->nextUpdate - time(NULL) > 2*crl_check_interval;
}
- else
+
+ /* insert new CRL */
+ x509crl->next = x509crls;
+ x509crls = x509crl;
+
+ 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 CRL's authorityKeyIdentifier is used as a unique filename
+ */
+ if (cache_crl && strncasecmp(crl_uri, "file", 4) != 0)
{
- plog(" error in X.509 crl");
- free_crl(crl);
- return FALSE;
+ char buf[BUF_LEN];
+ chunk_t hex, encoding;
+
+ hex = chunk_to_hex(crl->get_authKeyIdentifier(crl), NULL, FALSE);
+ snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_PATH, hex);
+ free(hex.ptr);
+
+ encoding = cert_crl->get_encoding(cert_crl);
+ chunk_write(encoding, buf, "crl", 022, TRUE);
+ free(encoding.ptr);
}
+
+ /* is the fetched crl valid? */
+ cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate);
+ return nextUpdate - now > 2*crl_check_interval;
}
/**
@@ -352,22 +239,19 @@ void load_crls(void)
{
while (n--)
{
- bool pgp = FALSE;
- chunk_t blob = chunk_empty;
char *filename = filelist[n]->d_name;
+ x509crl_t *x509crl;
- if (load_coded_file(filename, NULL, "crl", &blob, &pgp))
+ x509crl = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_PLUTO_CRL,
+ BUILD_FROM_FILE, filename, BUILD_END);
+ if (x509crl)
{
- chunk_t crl_uri;
-
- crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename);
- crl_uri.ptr = malloc(crl_uri.len + 1);
+ char crl_uri[BUF_LEN];
- /* build CRL file URI */
- snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s"
- , CRL_PATH, filename);
-
- insert_crl(blob, crl_uri, FALSE);
+ plog(" loaded crl from '%s'", filename);
+ snprintf(crl_uri, BUF_LEN, "file://%s/%s", CRL_PATH, filename);
+ insert_crl(x509crl, crl_uri, FALSE);
}
free(filelist[n]);
}
@@ -378,212 +262,77 @@ void load_crls(void)
ignore_result(chdir(save_dir));
}
-/**
- * Parses a CRL revocation reason code
- */
-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(" '%N'", crl_reason_names, reason)
- )
- return reason;
-}
-
-/*
- * Parses an X.509 CRL
- */
-bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl)
-{
- 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;
- }
- }
- success = parser->success(parser);
- time(&crl->installed);
-
-end:
- parser->destroy(parser);
- return success;
-}
/* Checks if the current certificate is revoked. It goes through the
* list of revoked certificates of the corresponding crl. Either the
* status CERT_GOOD or CERT_REVOKED is returned
*/
-static cert_status_t
-check_revocation(const x509crl_t *crl, chunk_t serial
-, time_t *revocationDate, crl_reason_t * revocationReason)
+static cert_status_t check_revocation(crl_t *crl, chunk_t cert_serial,
+ time_t *revocationDate,
+ crl_reason_t *revocationReason)
{
- revokedCert_t *revokedCert = crl->revokedCertificates;
+ enumerator_t *enumerator;
+ cert_status_t status;
+ chunk_t serial;
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = REASON_UNSPECIFIED;
-
DBG(DBG_CONTROL,
- DBG_dump_chunk("serial number:", serial)
+ DBG_log("serial number: %#B", &cert_serial)
)
+ *revocationDate = UNDEFINED_TIME;
+ *revocationReason = CRL_REASON_UNSPECIFIED;
+ status = CERT_GOOD;
- while(revokedCert != NULL)
+ enumerator = crl->create_enumerator(crl);
+ while (enumerator->enumerate(enumerator, &serial,
+ revocationDate, revocationReason))
{
- /* compare serial numbers */
- if (revokedCert->userCertificate.len == serial.len &&
- memeq(revokedCert->userCertificate.ptr, serial.ptr, serial.len))
+ if (chunk_equals(serial, cert_serial))
{
- *revocationDate = revokedCert->revocationDate;
- *revocationReason = revokedCert->revocationReason;
- return CERT_REVOKED;
+ status = CERT_REVOKED;
+ break;
}
- revokedCert = revokedCert->next;
}
- return CERT_GOOD;
+ enumerator->destroy(enumerator);
+ return status;
}
/*
* check if any crls are about to expire
*/
-void
-check_crls(void)
+void check_crls(void)
{
- x509crl_t *crl;
+ x509crl_t *x509crl;
+ time_t now, nextUpdate, time_left;
lock_crl_list("check_crls");
- crl = x509crls;
+ time(&now);
+ x509crl = x509crls;
- while (crl != NULL)
+ while (x509crl != NULL)
{
- time_t time_left = crl->nextUpdate - time(NULL);
- u_char buf[BUF_LEN];
+ certificate_t *cert_crl = x509crl->crl;
+ crl_t *crl = (crl_t*)cert_crl;
+ identification_t *issuer = cert_crl->get_issuer(cert_crl);
+ chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
+
+ cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate);
+ time_left = nextUpdate - now;
DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, crl->issuer);
- DBG_log("issuer: '%s'",buf);
- if (crl->authKeyID.ptr != NULL)
+ DBG_log("issuer: '%Y'", issuer);
+ if (authKeyID.ptr)
{
- datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
+ DBG_log("authkey: %#B", &authKeyID);
}
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);
+ fetch_req_t *req = build_crl_fetch_request(issuer, authKeyID,
+ x509crl->distributionPoints);
add_crl_fetch_request(req);
}
- crl = crl->next;
+ x509crl = x509crl->next;
}
unlock_crl_list("check_crls");
}
@@ -591,112 +340,131 @@ check_crls(void)
/*
* verify if a cert hasn't been revoked by a crl
*/
-cert_status_t
-verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
-, crl_reason_t *revocationReason)
+cert_status_t verify_by_crl(cert_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);
-
- generalName_t *crluri = (ca == NULL)? NULL : ca->crluri;
-
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+ identification_t *issuer = certificate->get_issuer(certificate);
+ chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
+ x509crl_t *x509crl;
+ ca_info_t *ca;
+ enumerator_t *enumerator;
+ char *point;
+
+ ca = get_ca_info(issuer, authKeyID);
+
*revocationDate = UNDEFINED_TIME;
- *revocationReason = REASON_UNSPECIFIED;
+ *revocationReason = CRL_REASON_UNSPECIFIED;
lock_crl_list("verify_by_crl");
- crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID);
+ x509crl = get_x509crl(issuer, authKeyID);
- if (crl == NULL)
+ if (x509crl == NULL)
{
+ linked_list_t *crluris;
+
unlock_crl_list("verify_by_crl");
plog("crl not found");
- if (cert->crlDistributionPoints != NULL)
+ crluris = linked_list_create();
+ if (ca)
{
- fetch_req_t *req = build_crl_fetch_request(cert->issuer
- , cert->authKeySerialNumber
- , cert->authKeyID, cert->crlDistributionPoints);
- add_crl_fetch_request(req);
+ add_distribution_points(crluris, ca->crluris);
}
- if (crluri != NULL)
+ enumerator = x509->create_crl_uri_enumerator(x509);
+ while (enumerator->enumerate(enumerator, &point))
{
- fetch_req_t *req = build_crl_fetch_request(cert->issuer
- , cert->authKeySerialNumber
- , cert->authKeyID, crluri);
- add_crl_fetch_request(req);
+ add_distribution_point(crluris, point);
}
+ enumerator->destroy(enumerator);
- if (cert->crlDistributionPoints != 0 || crluri != NULL)
+ if (crluris->get_count(crluris) > 0)
{
+ fetch_req_t *req;
+
+ req = build_crl_fetch_request(issuer, authKeyID, crluris);
+ crluris->destroy_function(crluris, free);
+ add_crl_fetch_request(req);
wake_fetch_thread("verify_by_crl");
return CERT_UNKNOWN;
}
else
+ {
+ crluris->destroy(crluris);
return CERT_UNDEFINED;
+ }
}
else
{
- x509cert_t *issuer_cert;
- bool valid;
+ certificate_t *cert_crl = x509crl->crl;
+ crl_t *crl = (crl_t*)cert_crl;
+ chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
+ cert_t *issuer_cert;
+ bool trusted, valid;
DBG(DBG_CONTROL,
DBG_log("crl found")
)
- add_distribution_points(cert->crlDistributionPoints
- , &crl->distributionPoints);
+ if (ca)
+ {
+ add_distribution_points(x509crl->distributionPoints, ca->crluris);
+ }
- add_distribution_points(crluri
- , &crl->distributionPoints);
+ enumerator = x509->create_crl_uri_enumerator(x509);
+ while (enumerator->enumerate(enumerator, &point))
+ {
+ add_distribution_point(x509crl->distributionPoints, point);
+ }
+ enumerator->destroy(enumerator);
lock_authcert_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);
-
+ issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
+ trusted = cert_crl->issued_by(cert_crl, issuer_cert->cert);
+
unlock_authcert_list("verify_by_crl");
- if (valid)
+ if (trusted)
{
cert_status_t status;
DBG(DBG_CONTROL,
DBG_log("crl signature is valid")
)
- /* return the expiration date */
- *until = crl->nextUpdate;
+
+ /* return the expiration date */
+ valid = cert_crl->get_validity(cert_crl, NULL, NULL, until);
/* has the certificate been revoked? */
- status = check_revocation(crl, cert->serialNumber, revocationDate
+ status = check_revocation(crl, x509->get_serial(x509), revocationDate
, revocationReason);
- if (*until < time(NULL))
+ if (valid)
+ {
+ unlock_crl_list("verify_by_crl");
+ DBG(DBG_CONTROL,
+ DBG_log("crl is valid: until %T", until, FALSE)
+ )
+ }
+ else
{
fetch_req_t *req;
- plog("crl update is overdue since %T", until, TRUE);
+ DBG(DBG_CONTROL,
+ DBG_log("crl is stale: since %T", until, FALSE)
+ )
/* try to fetch a crl update */
- req = build_crl_fetch_request(crl->issuer
- , crl->authKeySerialNumber
- , crl->authKeyID, crl->distributionPoints);
+ req = build_crl_fetch_request(issuer, authKeyID,
+ x509crl->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
@@ -711,65 +479,59 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
/*
* list all X.509 crls in the chained list
*/
-void
-list_crls(bool utc, bool strict)
+void list_crls(bool utc, bool strict)
{
- x509crl_t *crl;
+ x509crl_t *x509crl;
lock_crl_list("list_crls");
- crl = x509crls;
+ x509crl = x509crls;
- if (crl != NULL)
+ if (x509crl)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of X.509 CRLs:");
- whack_log(RC_COMMENT, " ");
}
- while (crl != NULL)
+ while (x509crl)
{
- u_char buf[BUF_LEN];
+ certificate_t *cert_crl = x509crl->crl;
+ crl_t *crl = (crl_t*)cert_crl;
+ chunk_t serial, authKeyID;
+ time_t thisUpdate, nextUpdate;
u_int revoked = 0;
- revokedCert_t *revokedCert = crl->revokedCertificates;
+ enumerator_t *enumerator;
- /* count number of revoked certificates in CRL */
- while (revokedCert != NULL)
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, " issuer: \"%Y\"",
+ cert_crl->get_issuer(cert_crl));
+ serial = crl->get_serial(crl);
+ if (serial.ptr)
{
- revoked++;
- revokedCert = revokedCert->next;
+ whack_log(RC_COMMENT, " serial: %#B", &serial);
}
- 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)
+ /* count number of revoked certificates in CRL */
+ enumerator = crl->create_enumerator(crl);
+ while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
{
- datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ revoked++;
}
- if (crl->authKeySerialNumber.ptr != NULL)
+ enumerator->destroy(enumerator);
+ whack_log(RC_COMMENT, " revoked: %d certificates", revoked);
+
+ list_distribution_points(x509crl->distributionPoints);
+
+ cert_crl->get_validity(cert_crl, NULL, &thisUpdate, &nextUpdate);
+ whack_log(RC_COMMENT, " updates: this %T", &thisUpdate, utc);
+ whack_log(RC_COMMENT, " next %T %s", &nextUpdate, utc,
+ check_expiry(nextUpdate, CRL_WARNING_INTERVAL, strict));
+ authKeyID = crl->get_authKeyIdentifier(crl);
+ if (authKeyID.ptr)
{
- datatot(crl->authKeySerialNumber.ptr, crl->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ whack_log(RC_COMMENT, " authkey: %#B", &authKeyID);
}
- crl = crl->next;
+ x509crl = x509crl->next;
}
unlock_crl_list("list_crls");
}
diff --git a/src/pluto/crl.h b/src/pluto/crl.h
index 7c110ad5a..43bafe145 100644
--- a/src/pluto/crl.h
+++ b/src/pluto/crl.h
@@ -14,47 +14,18 @@
#include "constants.h"
-/* access structure for a revoked serial number */
-
-typedef struct revokedCert revokedCert_t;
-
-struct revokedCert{
- revokedCert_t *next;
- chunk_t userCertificate;
- time_t revocationDate;
- crl_reason_t revocationReason;
-};
+#include <utils/linked_list.h>
+#include <credentials/certificates/certificate.h>
+#include <credentials/certificates/crl.h>
/* storage structure for an X.509 CRL */
typedef struct x509crl x509crl_t;
struct x509crl {
- x509crl_t *next;
- time_t installed;
- generalName_t *distributionPoints;
- chunk_t certificateList;
- chunk_t tbsCertList;
- u_int version;
- /* 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;
-
- /* signatureAlgorithm */
- int algorithm;
- chunk_t signature;
+ certificate_t *crl;
+ x509crl_t *next;
+ linked_list_t *distributionPoints;
};
/* apply a strict CRL policy
@@ -69,18 +40,14 @@ extern bool cache_crls;
/*
* check periodically for expired crls
- */
+ */
extern long crl_check_interval;
-
-/* used for initialization */
-extern const x509crl_t empty_x509crl;
-
-extern bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl);
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);
+extern bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl);
+extern cert_status_t verify_by_crl(cert_t *cert, time_t *until,
+ 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 f47ad1eeb..2113cecbc 100644
--- a/src/pluto/crypto.c
+++ b/src/pluto/crypto.c
@@ -21,12 +21,12 @@
#include "log.h"
static struct encrypt_desc encrypt_desc_3des =
-{
+{
algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_3DES_CBC,
+ algo_id: OAKLEY_3DES_CBC,
algo_next: NULL,
- enc_blocksize: DES_BLOCK_SIZE,
+ 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,
@@ -40,7 +40,7 @@ static struct encrypt_desc encrypt_desc_aes =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_AES_CBC,
- algo_next: NULL,
+ algo_next: NULL,
enc_blocksize: AES_BLOCK_SIZE,
keyminlen: AES_KEY_MIN_LEN,
@@ -48,6 +48,22 @@ static struct encrypt_desc encrypt_desc_aes =
keymaxlen: AES_KEY_MAX_LEN,
};
+#define CAMELLIA_KEY_MIN_LEN 128
+#define CAMELLIA_KEY_DEF_LEN 128
+#define CAMELLIA_KEY_MAX_LEN 256
+
+static struct encrypt_desc encrypt_desc_camellia =
+{
+ algo_type: IKE_ALG_ENCRYPT,
+ algo_id: OAKLEY_CAMELLIA_CBC,
+ algo_next: NULL,
+
+ enc_blocksize: CAMELLIA_BLOCK_SIZE,
+ keyminlen: CAMELLIA_KEY_MIN_LEN,
+ keydeflen: CAMELLIA_KEY_DEF_LEN,
+ keymaxlen: CAMELLIA_KEY_MAX_LEN,
+};
+
#define BLOWFISH_KEY_MIN_LEN 128
#define BLOWFISH_KEY_MAX_LEN 448
@@ -55,7 +71,7 @@ static struct encrypt_desc encrypt_desc_blowfish =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_BLOWFISH_CBC,
- algo_next: NULL,
+ algo_next: NULL,
enc_blocksize: BLOWFISH_BLOCK_SIZE,
keyminlen: BLOWFISH_KEY_MIN_LEN,
@@ -83,7 +99,7 @@ static struct encrypt_desc encrypt_desc_serpent =
#define TWOFISH_KEY_DEF_LEN 128
#define TWOFISH_KEY_MAX_LEN 256
-static struct encrypt_desc encrypt_desc_twofish =
+static struct encrypt_desc encrypt_desc_twofish =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_TWOFISH_CBC,
@@ -108,18 +124,18 @@ static struct encrypt_desc encrypt_desc_twofish_ssh =
};
static struct hash_desc hash_desc_md5 =
-{
+{
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_MD5,
- algo_next: NULL,
+ algo_next: NULL,
hash_digest_size: HASH_SIZE_MD5,
};
static struct hash_desc hash_desc_sha1 =
-{
+{
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_SHA,
- algo_next: NULL,
+ algo_next: NULL,
hash_digest_size: HASH_SIZE_SHA1,
};
@@ -146,91 +162,91 @@ static struct hash_desc hash_desc_sha2_512 = {
const struct dh_desc unset_group = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_NONE,
+ algo_id: MODP_NONE,
algo_next: NULL,
ke_size: 0
};
-static struct dh_desc dh_desc_modp_1024 = {
+static struct dh_desc dh_desc_modp_1024 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_1024_BIT,
+ algo_id: MODP_1024_BIT,
algo_next: NULL,
ke_size: 1024 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_modp_1536 = {
+static struct dh_desc dh_desc_modp_1536 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_1536_BIT,
+ algo_id: MODP_1536_BIT,
algo_next: NULL,
ke_size: 1536 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_modp_2048 = {
+static struct dh_desc dh_desc_modp_2048 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_2048_BIT,
+ algo_id: MODP_2048_BIT,
algo_next: NULL,
ke_size: 2048 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_modp_3072 = {
+static struct dh_desc dh_desc_modp_3072 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_3072_BIT,
+ algo_id: MODP_3072_BIT,
algo_next: NULL,
ke_size: 3072 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_modp_4096 = {
+static struct dh_desc dh_desc_modp_4096 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_4096_BIT,
+ algo_id: MODP_4096_BIT,
algo_next: NULL,
ke_size: 4096 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_modp_6144 = {
+static struct dh_desc dh_desc_modp_6144 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_6144_BIT,
+ algo_id: MODP_6144_BIT,
algo_next: NULL,
ke_size: 6144 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_modp_8192 = {
+static struct dh_desc dh_desc_modp_8192 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_8192_BIT,
+ algo_id: MODP_8192_BIT,
algo_next: NULL,
ke_size: 8192 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_ecp_256 = {
+static struct dh_desc dh_desc_ecp_256 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_256_BIT,
+ algo_id: ECP_256_BIT,
algo_next: NULL,
ke_size: 2*256 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_ecp_384 = {
+static struct dh_desc dh_desc_ecp_384 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_384_BIT,
+ algo_id: ECP_384_BIT,
algo_next: NULL,
ke_size: 2*384 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_ecp_521 = {
+static struct dh_desc dh_desc_ecp_521 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_521_BIT,
+ algo_id: ECP_521_BIT,
algo_next: NULL,
ke_size: 2*528 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_ecp_192 = {
+static struct dh_desc dh_desc_ecp_192 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_192_BIT,
+ algo_id: ECP_192_BIT,
algo_next: NULL,
ke_size: 2*192 / BITS_PER_BYTE
};
-static struct dh_desc dh_desc_ecp_224 = {
+static struct dh_desc dh_desc_ecp_224 = {
algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_224_BIT,
+ algo_id: ECP_224_BIT,
algo_next: NULL,
ke_size: 2*224 / BITS_PER_BYTE
};
@@ -283,12 +299,12 @@ bool init_crypto(void)
(no_md5) ? "MD5" : "");
return FALSE;
}
-
+
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:
@@ -300,6 +316,9 @@ bool init_crypto(void)
case ENCR_AES_CBC:
desc = &encrypt_desc_aes;
break;
+ case ENCR_CAMELLIA_CBC:
+ desc = &encrypt_desc_camellia;
+ break;
case ENCR_TWOFISH_CBC:
desc = &encrypt_desc_twofish;
ike_alg_add((struct ike_alg *)&encrypt_desc_twofish_ssh);
@@ -308,7 +327,7 @@ bool init_crypto(void)
desc = &encrypt_desc_serpent;
break;
default:
- continue;
+ continue;
}
ike_alg_add((struct ike_alg *)desc);
}
@@ -381,7 +400,7 @@ encryption_algorithm_t oakley_to_encryption_algorithm(int alg)
case OAKLEY_DES_CBC:
return ENCR_DES;
case OAKLEY_IDEA_CBC:
- return ENCR_IDEA;
+ return ENCR_IDEA;
case OAKLEY_BLOWFISH_CBC:
return ENCR_BLOWFISH;
case OAKLEY_RC5_R16_B64_CBC:
@@ -392,6 +411,8 @@ encryption_algorithm_t oakley_to_encryption_algorithm(int alg)
return ENCR_CAST;
case OAKLEY_AES_CBC:
return ENCR_AES_CBC;
+ case OAKLEY_CAMELLIA_CBC:
+ return ENCR_CAMELLIA_CBC;
case OAKLEY_SERPENT_CBC:
return ENCR_SERPENT_CBC;
case OAKLEY_TWOFISH_CBC:
@@ -491,7 +512,7 @@ int oakley_from_encryption_algorithm(encryption_algorithm_t alg)
return OAKLEY_CAMELLIA_CBC;
case ENCR_SERPENT_CBC:
return OAKLEY_SERPENT_CBC;
- case ENCR_TWOFISH_CBC:
+ case ENCR_TWOFISH_CBC:
return OAKLEY_TWOFISH_CBC;
default:
return 0;
@@ -561,7 +582,7 @@ int esp_from_encryption_algorithm(encryption_algorithm_t alg)
return ESP_CAMELLIA;
case ENCR_SERPENT_CBC:
return ESP_SERPENT;
- case ENCR_TWOFISH_CBC:
+ case ENCR_TWOFISH_CBC:
return ESP_TWOFISH;
default:
return 0;
@@ -581,12 +602,20 @@ int esp_from_integrity_algorithm(integrity_algorithm_t alg)
return AUTH_ALGORITHM_HMAC_SHA1;
case AUTH_AES_XCBC_96:
return AUTH_ALGORITHM_AES_XCBC_MAC;
+ case AUTH_HMAC_SHA2_256_96:
+ return AUTH_ALGORITHM_HMAC_SHA2_256_96;
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;
+ case AUTH_AES_128_GMAC:
+ return AUTH_ALGORITHM_AES_128_GMAC;
+ case AUTH_AES_192_GMAC:
+ return AUTH_ALGORITHM_AES_192_GMAC;
+ case AUTH_AES_256_GMAC:
+ return AUTH_ALGORITHM_AES_256_GMAC;
default:
return 0;
}
diff --git a/src/pluto/db_ops.c b/src/pluto/db_ops.c
index 4ba4fa324..547ea5f22 100644
--- a/src/pluto/db_ops.c
+++ b/src/pluto/db_ops.c
@@ -1,6 +1,6 @@
/* Dynamic db (proposal, transforms, attributes) handling.
* Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
+ *
* 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
@@ -12,11 +12,11 @@
* for more details.
*/
-/*
+/*
* The stratedy is to have (full contained) struct db_prop in db_context
* pointing to ONE dynamically sizable transform vector (trans0).
* Each transform stores attrib. in ONE dyn. sizable attribute vector (attrs0)
- * in a "serialized" way (attributes storage is used in linear sequence for
+ * in a "serialized" way (attributes storage is used in linear sequence for
* subsecuent transforms).
*
* Resizing for both trans0 and attrs0 is supported:
@@ -24,7 +24,7 @@
* also update trans_cur (by offset)
* - For attrs0: after allocating and copying attrs, I must rewrite each
* trans->attrs present in trans0; to achieve this, calculate
- * attrs pointer offset (new minus old) and iterate over
+ * attrs pointer offset (new minus old) and iterate over
* each transform "adding" this difference.
* also update attrs_cur (by offset)
*
@@ -70,7 +70,7 @@
#ifdef NOT_YET
/*
* Allocator cache:
- * Because of the single-threaded nature of pluto/spdb.c,
+ * 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
@@ -84,9 +84,9 @@ struct db_ops_alloc_cache {
#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 */
@@ -100,7 +100,7 @@ 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 *malloc_bytes_st(size_t size, struct db_ops_stats *st)
+static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st)
{
void *ptr = malloc(size);
if (ptr)
@@ -108,7 +108,7 @@ static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st)
st->st_curr_cnt++;
st->st_total_cnt++;
if (size > st->st_maxsz) st->st_maxsz=size;
- }
+ }
return ptr;
}
#define ALLOC_BYTES_ST(z,st) malloc_bytes_st(z, &st);
@@ -125,13 +125,13 @@ static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st)
* as a result of "add" operations
*/
int
-db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs)
+db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs)
{
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,
+ ctx->trans0 = ALLOC_BYTES_ST ( sizeof(struct db_trans) * max_trans,
db_trans_st);
memset(ctx->trans0, '\0', sizeof(struct db_trans) * max_trans);
}
@@ -162,12 +162,12 @@ db_trans_expand(struct db_context *ctx, int delta_trans)
int offset;
old_trans = ctx->trans0;
- new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans,
+ 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) */
@@ -175,7 +175,7 @@ db_trans_expand(struct db_context *ctx, int delta_trans)
{
char *cctx = (char *)(ctx->trans_cur);
-
+
cctx += offset;
ctx->trans_cur = (struct db_trans *)cctx;
}
@@ -186,7 +186,7 @@ db_trans_expand(struct db_context *ctx, int delta_trans)
out:
return ret;
}
-/*
+/*
* Expand storage for attributes by delta_attrs number AND
* rewrite trans->attr pointers
*/
@@ -201,22 +201,22 @@ db_attrs_expand(struct db_context *ctx, int delta_attrs)
int offset;
old_attrs = ctx->attrs0;
- new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs,
+ new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs,
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;
@@ -237,13 +237,13 @@ out:
return ret;
}
/* Allocate a new db object */
-struct db_context *
-db_prop_new(u_int8_t protoid, int max_trans, int max_attrs)
+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_st);
if (!ctx) goto out;
-
+
if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) {
PFREE_ST(ctx, db_context_st);
ctx=NULL;
@@ -266,8 +266,8 @@ 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
+ /*
+ * Strategy: if more space is needed, expand by
* <current_size>/2 + 1
*
* This happens to produce a "reasonable" sequence
@@ -287,10 +287,10 @@ db_trans_add(struct db_context *ctx, u_int8_t transid)
}
/* Add attr copy to current transform, expanding attrs0 if needed */
int
-db_attr_add(struct db_context *ctx, const struct db_attr *a)
+db_attr_add(struct db_context *ctx, const struct db_attr *a)
{
- /*
- * Strategy: if more space is needed, expand by
+ /*
+ * Strategy: if more space is needed, expand by
* <current_size>/2 + 1
*/
if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) {
@@ -302,7 +302,7 @@ db_attr_add(struct db_context *ctx, const struct db_attr *a)
ctx->trans_cur->attr_cnt++;
return 0;
}
-/* Add attr copy (by value) to current transform,
+/* Add attr copy (by value) to current transform,
* expanding attrs0 if needed, just calls db_attr_add().
*/
int
@@ -317,7 +317,7 @@ db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val)
int
db_ops_show_status(void)
{
- whack_log(RC_COMMENT, "stats " __FILE__ ": "
+ whack_log(RC_COMMENT, "stats " __FILE__ ": "
DB_OPS_STATS_DESC " :"
DB_OPS_STATS_STR("context")
DB_OPS_STATS_STR("trans")
@@ -329,7 +329,7 @@ db_ops_show_status(void)
return 0;
}
#endif /* NO_DB_OPS_STATS */
-/*
+/*
* From below to end just testing stuff ....
*/
#ifdef TEST
@@ -349,7 +349,7 @@ static void db_prop_print(struct db_prop *p)
default:
continue;
}
- printf(" transid=\"%s\"\n",
+ printf(" transid=\"%s\"\n",
enum_name(n, t->transid));
for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) {
int i;
@@ -367,16 +367,16 @@ static void db_prop_print(struct db_prop *p)
default:
continue;
}
- printf(" type=\"%s\" value=\"%s\"\n",
+ 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)
+static void db_print(struct db_context *ctx)
{
- printf("trans_cur diff=%d, attrs_cur diff=%d\n",
+ 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);
diff --git a/src/pluto/demux.c b/src/pluto/demux.c
index 3cfc909af..fad1450cd 100644
--- a/src/pluto/demux.c
+++ b/src/pluto/demux.c
@@ -819,7 +819,7 @@ check_msg_errqueue(const struct iface *ifp, short interest)
bool
send_packet(struct state *st, const char *where)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
int port_buf;
bool err;
u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE];
@@ -1258,16 +1258,16 @@ process_packet(struct msg_digest **mdp)
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);
+ SEND_NOTIFICATION(ISAKMP_INVALID_MAJOR_VERSION);
return;
}
else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION)
{
- SEND_NOTIFICATION(INVALID_MINOR_VERSION);
+ SEND_NOTIFICATION(ISAKMP_INVALID_MINOR_VERSION);
return;
}
}
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
@@ -1295,14 +1295,14 @@ process_packet(struct msg_digest **mdp)
{
plog("Message ID was 0x%08lx but should be zero in Main Mode",
(unsigned long) md->hdr.isa_msgid);
- SEND_NOTIFICATION(INVALID_MESSAGE_ID);
+ SEND_NOTIFICATION(ISAKMP_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);
+ SEND_NOTIFICATION(ISAKMP_INVALID_COOKIE);
return;
}
@@ -1315,7 +1315,7 @@ process_packet(struct msg_digest **mdp)
{
plog("initial Main Mode message is invalid:"
" its Encrypted Flag is on");
- SEND_NOTIFICATION(INVALID_FLAGS);
+ SEND_NOTIFICATION(ISAKMP_INVALID_FLAGS);
return;
}
@@ -1399,7 +1399,7 @@ process_packet(struct msg_digest **mdp)
{
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)
@@ -1429,7 +1429,7 @@ process_packet(struct msg_digest **mdp)
{
plog("Quick Mode message is invalid because"
" it has an Initiator Cookie of 0");
- SEND_NOTIFICATION(INVALID_COOKIE);
+ SEND_NOTIFICATION(ISAKMP_INVALID_COOKIE);
return;
}
@@ -1437,7 +1437,7 @@ process_packet(struct msg_digest **mdp)
{
plog("Quick Mode message is invalid because"
" it has a Responder Cookie of 0");
- SEND_NOTIFICATION(INVALID_COOKIE);
+ SEND_NOTIFICATION(ISAKMP_INVALID_COOKIE);
return;
}
@@ -1445,7 +1445,7 @@ process_packet(struct msg_digest **mdp)
{
plog("Quick Mode message is invalid because"
" it has a Message ID of 0");
- SEND_NOTIFICATION(INVALID_MESSAGE_ID);
+ SEND_NOTIFICATION(ISAKMP_INVALID_MESSAGE_ID);
return;
}
@@ -1475,7 +1475,7 @@ process_packet(struct msg_digest **mdp)
{
loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because"
" it is for an incomplete ISAKMP SA");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED /* XXX ? */);
return;
}
@@ -1486,7 +1486,7 @@ process_packet(struct msg_digest **mdp)
" 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);
+ SEND_NOTIFICATION(ISAKMP_INVALID_MESSAGE_ID);
return;
}
@@ -1498,7 +1498,7 @@ process_packet(struct msg_digest **mdp)
}
else
{
- set_cur_state(st);
+ set_cur_state(st);
from_state = st->st_state;
}
@@ -1635,7 +1635,7 @@ process_packet(struct msg_digest **mdp)
default:
plog("unsupported exchange type %s in message"
, enum_show(&exchange_names, md->hdr.isa_xchg));
- SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE);
+ SEND_NOTIFICATION(ISAKMP_UNSUPPORTED_EXCHANGE_TYPE);
return;
}
@@ -1681,7 +1681,7 @@ process_packet(struct msg_digest **mdp)
default:
auth = st->st_oakley.auth;
}
-
+
while (!LHAS(smc->flags, auth))
{
smc++;
@@ -1748,14 +1748,14 @@ process_packet(struct msg_digest **mdp)
if (st == NULL)
{
plog("discarding encrypted message for an unknown ISAKMP SA");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
+ SEND_NOTIFICATION(ISAKMP_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);
+ SEND_NOTIFICATION(ISAKMP_INVALID_FLAGS);
return;
}
@@ -1795,7 +1795,7 @@ process_packet(struct msg_digest **mdp)
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);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
@@ -1823,11 +1823,11 @@ process_packet(struct msg_digest **mdp)
memcpy(new_iv, data.ptr + data.len - crypter_block_size,
crypter_block_size);
- crypter->set_key(crypter, st->st_enc_key);
+ 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);
+ memcpy(st->st_new_iv, new_iv, crypter_block_size);
if (restore_iv)
{
memcpy(st->st_new_iv, new_iv, new_iv_len);
@@ -1848,7 +1848,7 @@ process_packet(struct msg_digest **mdp)
if (smc->flags & SMF_INPUT_ENCRYPTED)
{
loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted");
- SEND_NOTIFICATION(INVALID_FLAGS);
+ SEND_NOTIFICATION(ISAKMP_INVALID_FLAGS);
return;
}
}
@@ -1875,7 +1875,7 @@ process_packet(struct msg_digest **mdp)
if (pd == &md->digest[PAYLIMIT])
{
loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
@@ -1915,7 +1915,7 @@ process_packet(struct msg_digest **mdp)
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);
+ SEND_NOTIFICATION(ISAKMP_INVALID_PAYLOAD_TYPE);
return;
}
}
@@ -1929,7 +1929,7 @@ process_packet(struct msg_digest **mdp)
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);
+ SEND_NOTIFICATION(ISAKMP_INVALID_PAYLOAD_TYPE);
return;
}
needed &= ~s;
@@ -1939,7 +1939,7 @@ process_packet(struct msg_digest **mdp)
{
loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
if (md->hdr.isa_xchg != ISAKMP_XCHG_INFO)
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
@@ -1979,7 +1979,7 @@ process_packet(struct msg_digest **mdp)
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);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
}
@@ -1995,7 +1995,7 @@ process_packet(struct msg_digest **mdp)
&& 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);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
}
@@ -2019,7 +2019,7 @@ process_packet(struct msg_digest **mdp)
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);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
@@ -2033,7 +2033,7 @@ process_packet(struct msg_digest **mdp)
if (p != &md->digest[i])
{
loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
}
@@ -2054,14 +2054,14 @@ process_packet(struct msg_digest **mdp)
loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
" if any ID payload is present,"
" there must be exactly two");
- SEND_NOTIFICATION(PAYLOAD_MALFORMED);
+ SEND_NOTIFICATION(ISAKMP_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);
+ SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
return;
}
}
@@ -2192,7 +2192,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
time_t delay = UNDEFINED_TIME;
enum event_type kind = smc->timeout_event;
bool agreed_time = FALSE;
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
switch (kind)
{
@@ -2310,7 +2310,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
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))
diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c
index ed901ade5..ec56b8530 100644
--- a/src/pluto/dnskey.c
+++ b/src/pluto/dnskey.c
@@ -36,7 +36,7 @@
#include "adns.h" /* needs <resolv.h> */
#include "defs.h"
#include "log.h"
-#include "id.h"
+#include "myid.h"
#include "connections.h"
#include "keys.h" /* needs connections.h */
#include "dnskey.h"
@@ -238,62 +238,30 @@ stop_adns(void)
#define our_TXT_attr_string "X-IPsec-Server"
static const char our_TXT_attr[] = our_TXT_attr_string;
-static err_t
-decode_iii(u_char **pp, struct id *gw_id)
+identification_t* decode_iii(u_char **pp)
{
+ identification_t *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)";
+ return NULL;
}
*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);
- }
-
+ gw_id = identification_create_from_string(p);
*e = under;
*pp = e + strspn(e, " \t");
- return NULL;
+ return gw_id;
}
-static err_t
-process_txt_rr_body(u_char *str
-, bool doit /* should we capture information? */
-, enum dns_auth_level dns_auth_level
-, struct adns_continuation *const cr)
+static err_t process_txt_rr_body(u_char *str, bool doit,
+ enum dns_auth_level dns_auth_level,
+ struct adns_continuation *const cr)
{
- const struct id *client_id = &cr->id; /* subject of query */
+ identification_t *client_id = cr->id; /* subject of query */
u_char *p = str;
unsigned long pref = 0;
struct gw_info gi;
@@ -349,10 +317,13 @@ process_txt_rr_body(u_char *str
p += strspn(p, " \t");
/* Decode iii (Security Gateway ID). */
-
zero(&gi); /* before first use */
- TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
+ gi.gw_id = decode_iii(&p);
+ if (gi.gw_id == NULL)
+ {
+ return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
+ }
if (!cr->sgw_specified)
{
@@ -360,19 +331,14 @@ process_txt_rr_body(u_char *str
* 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 (gi.gw_id->get_type(gi.gw_id) != ID_IPV4_ADDR &&
+ gi.gw_id->get_type(gi.gw_id) != ID_IPV6_ADDR)
{
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);
- });
+ DBG_log("TXT %s record for '%Y': security gateway '%Y';"
+ " ignored because gateway's IP is unspecified",
+ our_TXT_attr, client_id, gi.gw_id);
+ )
return NULL; /* we cannot use this record, but it isn't wrong */
}
}
@@ -381,23 +347,15 @@ process_txt_rr_body(u_char *str
/* 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;
+ identification_t *peer_id = cr->sgw_id;
- if (!same_id(peer_id, &gi.gw_id))
+ if (!peer_id->equals(peer_id, gi.gw_id))
{
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);
- });
+ DBG_log("TXT %s record for '%Y': security gateway '%Y';"
+ " ignored -- looking to confirm '%Y' as gateway",
+ our_TXT_attr, client_id, gi.gw_id, peer_id);
+ )
return NULL; /* we cannot use this record, but it isn't wrong */
}
}
@@ -407,7 +365,7 @@ process_txt_rr_body(u_char *str
/* really accept gateway */
struct gw_info **gwip; /* gateway insertion point */
- gi.client_id = *client_id; /* will need to unshare_id_content */
+ gi.client_id = client_id; /* will need to unshare_id_content */
/* decode optional kkk: base 64 encoding of key */
@@ -436,7 +394,7 @@ process_txt_rr_body(u_char *str
}
rfc3110_chunk = chunk_create(buf, sz);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
- BUILD_BLOB_RFC_3110, rfc3110_chunk,
+ BUILD_BLOB_DNSKEY, rfc3110_chunk,
BUILD_END);
if (key == NULL)
{
@@ -462,32 +420,26 @@ process_txt_rr_body(u_char *str
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);
+ chunk_t keyid;
+ public_key_t *key = gi.key->public_key;
- if (gi.gw_key_present)
+ if (gi.gw_key_present &&
+ key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid))
{
- DBG_log("gateway for %s is %s with key %Y"
- , cidb, gwidb, keyid);
+ DBG_log("gateway for %s is %s with key %#B",
+ client_id, gi.gw_id, &keyid);
}
else
{
- DBG_log("gateway for %s is %s; no key specified"
- , cidb, gwidb);
+ DBG_log("gateway for '%Y' is '%Y'; no key specified",
+ client_id, gi.gw_id);
}
});
gi.next = *gwip;
*gwip = clone_thing(gi);
- unshare_id_content(&(*gwip)->gw_id);
- unshare_id_content(&(*gwip)->client_id);
+ (*gwip)->gw_id = (*gwip)->gw_id->clone((*gwip)->gw_id);
+ (*gwip)->client_id = (*gwip)->client_id->clone((*gwip)->client_id);
}
return NULL;
@@ -1271,75 +1223,62 @@ process_dns_answer(struct adns_continuation *const cr
/****************************************************************/
-static err_t
-build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
-, unsigned long serial USED_BY_DEBUG
-, const struct id *id
-, const char *typename USED_BY_DEBUG
-, const char *gwname USED_BY_DEBUG)
+static err_t build_dns_name(u_char name_buf[NS_MAXDNAME + 2],
+ unsigned long serial USED_BY_DEBUG,
+ identification_t *id,
+ const char *typename USED_BY_DEBUG,
+ identification_t *gw 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:
+ switch (id->get_type(id))
{
- /* ??? 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; )
+ 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);
- }
- strcpy(op, suffix);
- break;
- }
+ chunk_t b = id->get_encoding(id);
- case ID_FQDN:
- /* strip trailing "." characters, then add one */
+ snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa.",
+ b.ptr[3], b.ptr[2], b.ptr[1], b.ptr[0]);
+ break;
+ }
+ case ID_IPV6_ADDR:
{
- size_t il = id->name.len;
+ chunk_t b = id->get_encoding(id);
+ size_t bl;
+ u_char *op = name_buf;
+ static const char suffix[] = "IP6.INT.";
- while (il > 0 && id->name.ptr[il - 1] == '.')
- il--;
- if (il > NS_MAXDNAME)
+ for (bl = b.len; bl-- != 0; )
+ {
+ if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
+ {
+ return "IPv6 reverse name too long";
+ }
+ op += sprintf(op, "%x.%x.", b.ptr[bl] & 0xF, b.ptr[bl] >> 4);
+ }
+ strcpy(op, suffix);
+ break;
+ }
+ case ID_FQDN:
+ {
+ if (snprintf(name_buf, NS_MAXDNAME + 2, "%Y.", id) > NS_MAXDNAME + 1)
+ {
return "FQDN too long for domain name";
-
- memcpy(name_buf, id->name.ptr, il);
- strcpy(name_buf + il, ".");
+ }
+ break;
}
- break;
-
- default:
- return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
+ 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));
+ DBG(DBG_CONTROL | DBG_DNS,
+ DBG_log("DNS query %lu for %s for %s (gw: %Y)", serial, typename, name_buf, gw)
+ )
return NULL;
}
-void
-gw_addref(struct gw_info *gw)
+void gw_addref(struct gw_info *gw)
{
if (gw != NULL)
{
@@ -1348,8 +1287,7 @@ gw_addref(struct gw_info *gw)
}
}
-void
-gw_delref(struct gw_info **gwp)
+void gw_delref(struct gw_info **gwp)
{
struct gw_info *gw = *gwp;
@@ -1361,10 +1299,12 @@ gw_delref(struct gw_info **gwp)
gw->refcnt--;
if (gw->refcnt == 0)
{
- free_id_content(&gw->client_id);
- free_id_content(&gw->gw_id);
+ DESTROY_IF(gw->client_id);
+ DESTROY_IF(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 */
}
@@ -1414,68 +1354,61 @@ static int adns_in_flight = 0; /* queries outstanding */
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)
+static struct adns_continuation *continuation_for_qtid(unsigned long qtid)
{
struct adns_continuation *cr = NULL;
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)
+static void release_adns_continuation(struct adns_continuation *cr)
{
passert(cr != next_query);
gw_delref(&cr->gateways_from_dns);
#ifdef USE_KEYRR
free_public_keys(&cr->keys_from_dns);
#endif /* USE_KEYRR */
- unshare_id_content(&cr->id);
- unshare_id_content(&cr->sgw_id);
+ cr->id = cr->id->clone(cr->id);
+ cr->sgw_id = cr->sgw_id->clone(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 */
-, cont_fn_t cont_fn
-, struct adns_continuation *cr)
+err_t start_adns_query(identification_t *id, /* domain to query */
+ identification_t *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)
+ 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().
*/
@@ -1483,7 +1416,6 @@ start_adns_query(const struct id *id /* domain to query */
cr->previous = continuations;
if (continuations != NULL)
{
- passert(continuations->next == NULL);
continuations->next = cr;
}
continuations = cr;
@@ -1491,11 +1423,11 @@ start_adns_query(const struct id *id /* domain to query */
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->id = id->clone(id);
+ cr->sgw_specified = (sgw_id != NULL);
+ cr->sgw_id = cr->sgw_specified ?
+ sgw_id->clone(sgw_id) :
+ identification_create_from_string("%any");
cr->gateways_from_dns = NULL;
#ifdef USE_KEYRR
cr->keys_from_dns = NULL;
@@ -1507,15 +1439,12 @@ start_adns_query(const struct id *id /* domain to query */
cr->debugging = LEMPTY;
#endif
- idtoa(&cr->sgw_id, gwidb, sizeof(gwidb));
-
zero(&cr->query);
-
{
- err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid
- , id, typename, gwidb);
+ err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid, id,
+ typename, cr->sgw_id);
- if (ugh != NULL)
+ if (ugh)
{
release_adns_continuation(cr);
return ugh;
@@ -1620,8 +1549,7 @@ send_unsent_ADNS_queries(void)
* Returns with error message iff lwdnsq result is malformed.
* Most errors will be in DNS data and will be handled by cr->cont_fn.
*/
-static err_t
-process_lwdnsq_answer(char *ts)
+static err_t process_lwdnsq_answer(char *ts)
{
err_t ugh = NULL;
char *rest;
@@ -1813,11 +1741,10 @@ process_lwdnsq_answer(char *ts)
}
#endif /* USE_LWRES */
-static void
-recover_adns_die(void)
+static void recover_adns_die(void)
{
struct adns_continuation *cr = NULL;
-
+
adns_pid = 0;
if(adns_restart_count < ADNS_RESTART_MAX) {
adns_restart_count++;
@@ -1834,7 +1761,7 @@ recover_adns_die(void)
if(continuations != NULL) {
for (; cr->previous != NULL; cr = cr->previous);
}
-
+
next_query = cr;
if(next_query != NULL) {
@@ -1848,8 +1775,7 @@ void reset_adns_restart_count(void)
adns_restart_count=0;
}
-void
-handle_adns_answer(void)
+void handle_adns_answer(void)
{
/* These are retained across calls to handle_adns_answer. */
static size_t buflen = 0; /* bytes in answer buffer */
diff --git a/src/pluto/dnskey.h b/src/pluto/dnskey.h
index 976c715bf..d26a0e64f 100644
--- a/src/pluto/dnskey.h
+++ b/src/pluto/dnskey.h
@@ -12,9 +12,10 @@
* for more details.
*/
-extern int
- adns_qfd, /* file descriptor for sending queries to adns */
- adns_afd; /* file descriptor for receiving answers from adns */
+#include <utils/identification.h>
+
+extern int adns_qfd; /* file descriptor for sending queries to adns */
+extern int 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);
@@ -33,13 +34,13 @@ 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 */
+ 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 */
+ identification_t *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 */
+ identification_t *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 */
@@ -47,7 +48,7 @@ struct adns_continuation {
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? */
+ bool used; /* have we called the cont_fn yet? */
struct {
u_char name_buf[NS_MAXDNAME + 2];
} query;
@@ -56,8 +57,8 @@ struct adns_continuation {
#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 */
+extern err_t start_adns_query(identification_t *id /* domain to query */
+ , identification_t *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);
@@ -65,18 +66,17 @@ extern err_t start_adns_query(const struct id *id /* domain to query */
/* 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) */
+ unsigned refcnt; /* reference counted! */
+ unsigned pref; /* preference: lower is better */
+#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
+ identification_t* client_id; /* id of client of peer */
+ identification_t* 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);
-
+extern void gw_addref(struct gw_info *gw);
+extern void gw_delref(struct gw_info **gwp);
extern void reset_adns_restart_count(void);
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
index 6f7f1215f..6172165bd 100644
--- a/src/pluto/fetch.c
+++ b/src/pluto/fetch.c
@@ -28,27 +28,27 @@
#include <library.h>
#include <debug.h>
#include <asn1/asn1.h>
-#include <asn1/pem.h>
+#include <credentials/certificates/certificate.h>
+#ifdef THREADS
+#include <threading/thread.h>
+#endif
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
-#include "pem.h"
#include "x509.h"
#include "ca.h"
#include "whack.h"
#include "ocsp.h"
#include "crl.h"
#include "fetch.h"
+#include "builder.h"
fetch_req_t empty_fetch_req = {
NULL , /* next */
- 0 , /* installed */
0 , /* trials */
- { NULL, 0}, /* issuer */
+ NULL , /* issuer */
{ NULL, 0}, /* authKeyID */
- { NULL, 0}, /* authKeySerialNumber */
NULL /* distributionPoints */
};
@@ -59,7 +59,7 @@ static fetch_req_t *crl_fetch_reqs = NULL;
static ocsp_location_t *ocsp_fetch_reqs = NULL;
#ifdef THREADS
-static pthread_t thread;
+static thread_t *thread;
static pthread_mutex_t certs_and_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t authcert_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t crl_list_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -251,10 +251,9 @@ void wake_fetch_thread(const char *who)
*/
static void free_fetch_request(fetch_req_t *req)
{
- free(req->issuer.ptr);
- free(req->authKeySerialNumber.ptr);
+ req->distributionPoints->destroy_function(req->distributionPoints, free);
+ DESTROY_IF(req->issuer);
free(req->authKeyID.ptr);
- free_generalNames(req->distributionPoints, TRUE);
free(req);
}
@@ -262,86 +261,63 @@ static void free_fetch_request(fetch_req_t *req)
/**
* Fetch an ASN.1 blob coded in PEM or DER format from a URL
*/
-bool fetch_asn1_blob(char *url, chunk_t *blob)
+x509crl_t* fetch_crl(char *url)
{
+ x509crl_t *crl;
+ chunk_t blob;
+
DBG1(" fetching crl from '%s' ...", url);
- if (lib->fetcher->fetch(lib->fetcher, url, blob, FETCH_END) != SUCCESS)
+ if (lib->fetcher->fetch(lib->fetcher, url, &blob, FETCH_END) != SUCCESS)
{
DBG1("crl fetching failed");
return FALSE;
}
-
- if (is_asn1(*blob))
+ crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
+ BUILD_BLOB_PEM, blob, BUILD_END);
+ free(blob.ptr);
+ if (!crl)
{
- DBG2(" fetched blob coded in DER format");
+ DBG1("crl fetched successfully but data coded in unknown format");
}
- else
- {
- bool pgp = FALSE;
-
- if (pem_to_bin(blob, chunk_empty, &pgp) != SUCCESS)
- {
- free(blob->ptr);
- return FALSE;
- }
- if (is_asn1(*blob))
- {
- DBG2(" fetched blob coded in PEM format");
- }
- else
- {
- DBG1("crl fetched successfully but data coded in unknown format");
- free(blob->ptr);
- return FALSE;
- }
- }
- return TRUE;
+ return crl;
}
/**
* Complete a distributionPoint URI with ca information
*/
-static char* complete_uri(chunk_t distPoint, const char *ldaphost)
+static char* complete_uri(char *distPoint, const char *ldaphost)
{
- char *uri;
- char *ptr = distPoint.ptr;
- size_t len = distPoint.len;
+ char *symbol = strchr(distPoint, ':');
- char *symbol = memchr(ptr, ':', len);
-
- if (symbol != NULL)
+ if (symbol)
{
- size_t type_len = symbol - ptr;
-
- if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0)
+ int type_len = symbol - distPoint;
+
+ if (type_len >= 4 && strncasecmp(distPoint, "ldap", 4) == 0)
{
- ptr = symbol + 1;
- len -= (type_len + 1);
+ char *ptr = symbol + 1;
+ int len = strlen(distPoint) - (type_len + 1);
if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
{
len -= 2;
- symbol = memchr(ptr, '/', len);
-
- if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL)
+ symbol = strchr(ptr, '/');
+
+ if (symbol && symbol - ptr == 0 && ldaphost)
{
- uri = malloc(distPoint.len + strlen(ldaphost) + 1);
+ char uri[BUF_LEN];
/* insert the ldaphost into the uri */
- sprintf(uri, "%.*s%s%.*s"
- , (int)(distPoint.len - len), distPoint.ptr
- , ldaphost
- , (int)len, symbol);
- return uri;
+ snprintf(uri, BUF_LEN, "%.*s%s%.*s", strlen(distPoint)-len,
+ distPoint, ldaphost, len, symbol);
+ return strdup(uri);
}
}
}
}
-
+
/* default action: copy distributionPoint without change */
- uri = malloc(distPoint.len + 1);
- sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr);
- return uri;
+ return strdup(distPoint);
}
/**
@@ -358,39 +334,40 @@ static void fetch_crls(bool cache_crls)
while (req != NULL)
{
+ enumerator_t *enumerator;
+ char *point;
bool valid_crl = FALSE;
- chunk_t blob = chunk_empty;
- generalName_t *gn = req->distributionPoints;
const char *ldaphost;
ca_info_t *ca;
lock_ca_info_list("fetch_crls");
- ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID);
+ ca = get_ca_info(req->issuer, req->authKeyID);
ldaphost = (ca == NULL)? NULL : ca->ldaphost;
- while (gn != NULL)
+ enumerator = req->distributionPoints->create_enumerator(req->distributionPoints);
+ while (enumerator->enumerate(enumerator, &point))
{
- char *uri = complete_uri(gn->name, ldaphost);
+ x509crl_t *crl;
+ char *uri;
- if (fetch_asn1_blob(uri, &blob))
- {
- chunk_t crl_uri = chunk_clone(gn->name);
+ uri = complete_uri(point, ldaphost);
+ crl = fetch_crl(uri);
+ free(uri);
- if (insert_crl(blob, crl_uri, cache_crls))
+ if (crl)
+ {
+ if (insert_crl(crl, point, cache_crls))
{
DBG(DBG_CONTROL,
DBG_log("we have a valid crl")
)
valid_crl = TRUE;
- free(uri);
break;
}
}
- free(uri);
- gn = gn->next;
}
-
+ enumerator->destroy(enumerator);
unlock_ca_info_list("fetch_crls");
if (valid_crl)
@@ -415,19 +392,11 @@ static void fetch_crls(bool cache_crls)
static void fetch_ocsp_status(ocsp_location_t* location)
{
- chunk_t request, response;
- char *uri;
+ chunk_t request = build_ocsp_request(location);
+ chunk_t response = chunk_empty;
- 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';
-
- DBG1(" requesting ocsp status from '%s' ...", uri);
- if (lib->fetcher->fetch(lib->fetcher, uri, &response,
+ DBG1(" requesting ocsp status from '%s' ...", location->uri);
+ if (lib->fetcher->fetch(lib->fetcher, location->uri, &response,
FETCH_REQUEST_DATA, request,
FETCH_REQUEST_TYPE, "application/ocsp-request",
FETCH_END) == SUCCESS)
@@ -436,17 +405,16 @@ static void fetch_ocsp_status(ocsp_location_t* location)
}
else
{
- DBG1("ocsp request to %s failed", uri);
+ DBG1("ocsp request to %s failed", location->uri);
}
- free(uri);
free(request.ptr);
chunk_free(&location->nonce);
/* increment the trial counter of the unresolved fetch requests */
{
ocsp_certinfo_t *certinfo = location->certinfo;
-
+
while (certinfo != NULL)
{
certinfo->trials++;
@@ -482,6 +450,9 @@ static void* fetch_thread(void *arg)
{
struct timespec wait_interval;
+ /* the fetching thread is only cancellable while waiting for new events */
+ thread_cancelability(FALSE);
+
DBG(DBG_CONTROL,
DBG_log("fetch thread started")
)
@@ -498,8 +469,11 @@ static void* fetch_thread(void *arg)
DBG(DBG_CONTROL,
DBG_log("next regular crl check in %ld seconds", crl_check_interval)
)
+
+ thread_cancelability(TRUE);
status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
, &wait_interval);
+ thread_cancelability(FALSE);
if (status == ETIMEDOUT)
{
@@ -519,22 +493,22 @@ static void* fetch_thread(void *arg)
fetch_ocsp();
fetch_crls(cache_crls);
}
+ return NULL;
}
#endif /* THREADS*/
/**
* Initializes curl and starts the fetching thread
*/
-void init_fetch(void)
+void fetch_initialize(void)
{
if (crl_check_interval > 0)
{
#ifdef THREADS
- int status = pthread_create( &thread, NULL, fetch_thread, NULL);
-
- if (status != 0)
+ thread = thread_create((thread_main_t)fetch_thread, NULL);
+ if (thread == NULL)
{
- plog("fetching thread could not be started, status = %d", status);
+ plog("fetching thread could not be started");
}
#else /* !THREADS */
plog("warning: not compiled with pthread support");
@@ -542,6 +516,23 @@ void init_fetch(void)
}
}
+/**
+ * Terminates the fetching thread
+ */
+void fetch_finalize(void)
+{
+ if (crl_check_interval > 0)
+ {
+#ifdef THREADS
+ if (thread)
+ {
+ thread->cancel(thread);
+ thread->join(thread);
+ }
+#endif
+ }
+}
+
void free_crl_fetch(void)
{
lock_crl_fetch_list("free_crl_fetch");
@@ -568,62 +559,93 @@ void free_ocsp_fetch(void)
/**
+ * Add an additional distribution point
+ */
+void add_distribution_point(linked_list_t *points, char *new_point)
+{
+ char *point;
+ bool add = TRUE;
+ enumerator_t *enumerator;
+
+ if (new_point == NULL || *new_point == '\0')
+ {
+ return;
+ }
+
+ enumerator = points->create_enumerator(points);
+ while (enumerator->enumerate(enumerator, &point))
+ {
+ if (streq(point, new_point))
+ {
+ add = FALSE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (add)
+ {
+ points->insert_last(points, strdup(new_point));
+ }
+}
+
+/**
* Add additional distribution points
*/
-void add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints)
+void add_distribution_points(linked_list_t *points, linked_list_t *new_points)
{
- while (newPoints != NULL)
+ char *new_point;
+ enumerator_t *enumerator;
+
+ enumerator = new_points->create_enumerator(new_points);
+ while (enumerator->enumerate(enumerator, &new_point))
{
- /* skip empty distribution point */
- if (newPoints->name.len > 0)
- {
- bool add = TRUE;
- generalName_t *gn = *distributionPoints;
+ bool add = TRUE;
+ char *point;
+ enumerator_t *enumerator;
- while (gn != NULL)
+ enumerator = points->create_enumerator(points);
+ while (enumerator->enumerate(enumerator, &point))
+ {
+ if (streq(point, new_point))
{
- 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;
+ add = FALSE;
+ break;
}
+ }
+ enumerator->destroy(enumerator);
- 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;
- }
+ if (add)
+ {
+ points->insert_last(points, strdup(new_point));
}
- newPoints = newPoints->next;
}
+ enumerator->destroy(enumerator);
}
-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(identification_t *issuer,
+ chunk_t authKeyID,
+ linked_list_t *distributionPoints)
{
+ char *point;
+ enumerator_t *enumerator;
fetch_req_t *req = malloc_thing(fetch_req_t);
- *req = empty_fetch_req;
- /* note current time */
- req->installed = time(NULL);
+ memset(req, 0, sizeof(fetch_req_t));
+ req->distributionPoints = linked_list_create();
/* clone fields */
- req->issuer = chunk_clone(issuer);
- req->authKeySerialNumber = chunk_clone(authKeySerialNumber);
+ req->issuer = issuer->clone(issuer);
req->authKeyID = chunk_clone(authKeyID);
/* copy distribution points */
- add_distribution_points(gn, &req->distributionPoints);
+ enumerator = distributionPoints->create_enumerator(distributionPoints);
+ while (enumerator->enumerate(enumerator, &point))
+ {
+ req->distributionPoints->insert_last(req->distributionPoints,
+ strdup(point));
+ }
+ enumerator->destroy(enumerator);
return req;
}
@@ -640,9 +662,8 @@ void add_crl_fetch_request(fetch_req_t *req)
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)))
+ if (req->authKeyID.ptr ? same_keyid(req->authKeyID, r->authKeyID) :
+ req->issuer->equals(req->issuer, r->issuer))
{
/* there is already a fetch request */
DBG(DBG_CONTROL,
@@ -650,7 +671,8 @@ void add_crl_fetch_request(fetch_req_t *req)
)
/* there might be new distribution points */
- add_distribution_points(req->distributionPoints, &r->distributionPoints);
+ add_distribution_points(r->distributionPoints,
+ req->distributionPoints);
unlock_crl_fetch_list("add_crl_fetch_request");
free_fetch_request(req);
@@ -686,17 +708,20 @@ void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
/**
* List all distribution points
*/
-void list_distribution_points(const generalName_t *gn)
+void list_distribution_points(linked_list_t *distributionPoints)
{
- bool first_gn = TRUE;
+ char *point;
+ bool first_point = TRUE;
+ enumerator_t *enumerator;
- while (gn != NULL)
+ enumerator = distributionPoints->create_enumerator(distributionPoints);
+ while (enumerator->enumerate(enumerator, &point))
{
- whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: "
- :" ", (int)gn->name.len, gn->name.ptr);
- first_gn = FALSE;
- gn = gn->next;
+ whack_log(RC_COMMENT, " %s '%s'",
+ (first_point)? "distPts: " : " ", point);
+ first_point = FALSE;
}
+ enumerator->destroy(enumerator);
}
/**
@@ -712,29 +737,17 @@ void list_crl_fetch_requests(bool utc)
if (req != NULL)
{
whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of CRL fetch requests:");
- whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, "List of CRL Fetch Requests:");
}
while (req != NULL)
{
- 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)
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, " trials: %d", req->trials);
+ whack_log(RC_COMMENT, " issuer: \"%Y\"", req->issuer);
+ if (req->authKeyID.ptr)
{
- datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ whack_log(RC_COMMENT, " authkey: %#B", &req->authKeyID);
}
list_distribution_points(req->distributionPoints);
req = req->next;
diff --git a/src/pluto/fetch.h b/src/pluto/fetch.h
index f7b4eb074..265dc5fe7 100644
--- a/src/pluto/fetch.h
+++ b/src/pluto/fetch.h
@@ -13,6 +13,9 @@
* for more details.
*/
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+
#include "x509.h"
#define FETCH_CMD_TIMEOUT 10 /* seconds */
@@ -27,13 +30,11 @@ typedef enum {
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;
+ int trials;
+ identification_t *issuer;
+ chunk_t authKeyID;
+ linked_list_t *distributionPoints;
};
#ifdef THREADS
@@ -61,16 +62,20 @@ extern void wake_fetch_thread(const char *who);
#define unlock_certs_and_keys(who) /* do nothing */
#define wake_fetch_thread(who) /* do nothing */
#endif
-extern void init_fetch(void);
+extern void fetch_initialize(void);
+extern void fetch_finalize(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);
-extern fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber
- , chunk_t authKeyID, const generalName_t *gn);
+extern void add_distribution_point(linked_list_t *points, char* new_point);
+extern void add_distribution_points(linked_list_t *points,
+ linked_list_t *new_points);
+extern fetch_req_t* build_crl_fetch_request(identification_t *issuer,
+ chunk_t authKeyID,
+ linked_list_t *distributionPoints);
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);
+extern void add_ocsp_fetch_request(struct ocsp_location *location,
+ chunk_t serialNumber);
+extern void list_distribution_points(linked_list_t *distributionPoints);
extern void list_crl_fetch_requests(bool utc);
extern void list_ocsp_fetch_requests(bool utc);
extern size_t write_buffer(void *ptr, size_t size, size_t nmemb, void *data);
diff --git a/src/pluto/foodgroups.c b/src/pluto/foodgroups.c
index ed9853fc4..e4f9a1d01 100644
--- a/src/pluto/foodgroups.c
+++ b/src/pluto/foodgroups.c
@@ -48,7 +48,7 @@ static size_t fg_path_space = 0;
struct fg_groups {
struct fg_groups *next;
- struct connection *connection;
+ connection_t *connection;
};
static struct fg_groups *groups = NULL;
@@ -78,8 +78,7 @@ struct fg_targets *new_targets;
* It returns -1, 0, or +1 if a is, respectively,
* less than, equal to, or greater than b.
*/
-static int
-ipcmp(ip_address *a, ip_address *b)
+static int ipcmp(ip_address *a, ip_address *b)
{
if (addrtypeof(a) != addrtypeof(b))
{
@@ -105,8 +104,7 @@ ipcmp(ip_address *a, ip_address *b)
* It returns -1, 0, or +1 if a is, respectively,
* less than, equal to, or greater than b.
*/
-static int
-subnetcmp(const ip_subnet *a, const ip_subnet *b)
+static int subnetcmp(const ip_subnet *a, const ip_subnet *b)
{
ip_address neta, maska, netb, maskb;
int r;
@@ -121,8 +119,7 @@ subnetcmp(const ip_subnet *a, const ip_subnet *b)
return r;
}
-static void
-read_foodgroup(struct fg_groups *g)
+static void read_foodgroup(struct fg_groups *g)
{
const char *fgn = g->connection->name;
const ip_subnet *lsn = &g->connection->spd.this.client;
@@ -244,8 +241,7 @@ read_foodgroup(struct fg_groups *g)
}
}
-static void
-free_targets(void)
+static void free_targets(void)
{
while (targets != NULL)
{
@@ -257,8 +253,7 @@ free_targets(void)
}
}
-void
-load_groups(void)
+void load_groups(void)
{
passert(new_targets == NULL);
@@ -341,8 +336,7 @@ load_groups(void)
}
-void
-add_group(struct connection *c)
+void add_group(connection_t *c)
{
struct fg_groups *g = malloc_thing(struct fg_groups);
@@ -352,8 +346,7 @@ add_group(struct connection *c)
g->connection = c;
}
-static struct fg_groups *
-find_group(const struct connection *c)
+static struct fg_groups *find_group(const connection_t *c)
{
struct fg_groups *g;
@@ -362,8 +355,7 @@ find_group(const struct connection *c)
return g;
}
-void
-route_group(struct connection *c)
+void route_group(connection_t *c)
{
/* it makes no sense to route a connection that is ISAKMP-only */
if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
@@ -381,7 +373,7 @@ route_group(struct connection *c)
{
if (t->group == g)
{
- struct connection *ci = con_by_name(t->name, FALSE);
+ connection_t *ci = con_by_name(t->name, FALSE);
if (ci != NULL)
{
@@ -395,8 +387,7 @@ route_group(struct connection *c)
}
}
-void
-unroute_group(struct connection *c)
+void unroute_group(connection_t *c)
{
struct fg_groups *g = find_group(c);
struct fg_targets *t;
@@ -407,7 +398,7 @@ unroute_group(struct connection *c)
{
if (t->group == g)
{
- struct connection *ci = con_by_name(t->name, FALSE);
+ connection_t *ci = con_by_name(t->name, FALSE);
if (ci != NULL)
{
@@ -419,8 +410,7 @@ unroute_group(struct connection *c)
}
}
-void
-delete_group(const struct connection *c)
+void delete_group(const connection_t *c)
{
struct fg_groups *g;
diff --git a/src/pluto/id.c b/src/pluto/id.c
deleted file mode 100644
index f34775e68..000000000
--- a/src/pluto/id.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
- * Copyright (C) 1999-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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/socket.h>
-#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 */
-#endif
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "id.h"
-#include "log.h"
-#include "connections.h"
-#include "packet.h"
-#include "whack.h"
-
-const struct id empty_id; /* ID_ANY */
-
-enum myid_state myid_state = MYID_UNKNOWN;
-struct id myids[MYID_SPECIFIED+1]; /* %myid */
-char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */
-
-/* initialize id module
- * Fills in myid from environment variable IPSECmyid or defaultrouteaddr
- */
-void
-init_id(void)
-{
- 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++)
- {
- free_id_content(&myids[s]);
- free(myid_str[s]);
- }
-}
-
-static void
-calc_myid_str(enum myid_state s)
-{
- /* preformat the ID name */
- char buf[BUF_LEN];
-
- 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
- {
- 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 */
-
- {
- 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];
-
- (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.
- * Note that if the id is to be kept, unshare_id_content will be necessary.
- */
-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"))
- {
- /* 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
- {
- 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;
-}
-
-
-/*
- * Converts a binary key ID into hexadecimal format
- */
-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;
-}
-
-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;
-}
-
-int
-idtoa(const struct id *id, char *dst, size_t dstlen)
-{
- 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
- * by escape sequences consisting of their octal values
- */
-void
-escape_metachar(const char *src, char *dst, size_t dstlen)
-{
- while (*src != '\0' && dstlen > 4)
- {
- 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++;
- }
- *dst = '\0';
-}
-
-
-/* Make private copy of string in struct id.
- * This is needed if the result of atoid is to be kept.
- */
-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 = 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:
- 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_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_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;
-}
-
-/* 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_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_ANY:
- return MAX_WILDCARDS;
- case ID_DER_ASN1_DN:
- return dn_count_wildcards(id->name);
- default:
- return 0;
- }
-}
-
-/* build an ID payload
- * Note: no memory is allocated for the body of the payload (tl->ptr).
- * We assume it will end up being a pointer into a sufficiently
- * stable datastructure. It only needs to last a short time.
- */
-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_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);
- }
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
diff --git a/src/pluto/id.h b/src/pluto/id.h
deleted file mode 100644
index dc2dcdfa6..000000000
--- a/src/pluto/id.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
- * Copyright (C) 1999-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.
- */
-
-#ifndef _ID_H
-#define _ID_H
-
-#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 */
-};
-
-extern void init_id(void);
-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 */
-};
-
-extern enum myid_state myid_state;
-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);
-#define resolve_myid(id) ((id)->kind == ID_MYID? &myids[myid_state] : (id))
-extern void set_myFQDN(void);
-
-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
-extern void escape_metachar(const char *src, char *dst, size_t dstlen);
-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
-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) */
-extern void
- 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 f833f85b5..7521dd33b 100644
--- a/src/pluto/ike_alg.c
+++ b/src/pluto/ike_alg.c
@@ -23,6 +23,8 @@
#include <library.h>
#include <debug.h>
+#include <credentials/keys/public_key.h>
+#include <credentials/keys/private_key.h>
#include <crypto/hashers/hasher.h>
#include <crypto/crypters/crypter.h>
#include <crypto/prfs/prf.h>
@@ -126,7 +128,7 @@ struct dh_desc *ike_alg_get_dh_group(u_int alg)
/**
* Get pfsgroup for this connection
*/
-const struct dh_desc *ike_alg_pfsgroup(struct connection *c, lset_t policy)
+const struct dh_desc *ike_alg_pfsgroup(connection_t *c, lset_t policy)
{
const struct dh_desc *ret = NULL;
@@ -141,7 +143,7 @@ const struct dh_desc *ike_alg_pfsgroup(struct connection *c, lset_t policy)
/**
* Create an OAKLEY proposal based on alg_info and policy
*/
-struct db_context *ike_alg_db_new(struct connection *c, lset_t policy)
+struct db_context *ike_alg_db_new(connection_t *c, lset_t policy)
{
struct alg_info_ike *ai = c->alg_info_ike;
struct db_context *db_ctx = NULL;
@@ -176,13 +178,13 @@ struct db_context *ike_alg_db_new(struct connection *c, lset_t policy)
enum_show(&oakley_enc_names, ealg));
continue;
}
- if (!ike_alg_get_hasher(halg))
+ 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))
+ if (!ike_alg_get_dh_group(modp))
{
plog("ike alg: dh group %s not present",
enum_show(&oakley_group_names, modp));
@@ -193,20 +195,43 @@ struct db_context *ike_alg_db_new(struct connection *c, lset_t policy)
if (policy & POLICY_PUBKEY)
{
int auth_method = 0;
- private_key_t *key = get_private_key(c);
+ size_t key_size = 0;
+ key_type_t key_type = KEY_ANY;
- if (key == NULL)
+
+ if (c->spd.this.cert)
+ {
+ certificate_t *certificate = c->spd.this.cert->cert;
+ public_key_t *key = certificate->get_public_key(certificate);
+
+ if (key == NULL)
+ {
+ plog("ike alg: unable to retrieve my public key");
+ continue;
+ }
+ key_type = key->get_type(key);
+ key_size = key->get_keysize(key);
+ key->destroy(key);
+ }
+ else
{
- plog("ike alg: unable to locate my private key");
- continue;
+ private_key_t *key = get_private_key(c);
+
+ if (key == NULL)
+ {
+ plog("ike alg: unable to retrieve my private key");
+ continue;
+ }
+ key_type = key->get_type(key);
+ key_size = key->get_keysize(key);
}
- switch (key->get_type(key))
+ switch (key_type)
{
case KEY_RSA:
auth_method = OAKLEY_RSA_SIG;
break;
case KEY_ECDSA:
- switch (key->get_keysize(key))
+ switch (key_size)
{
case 32:
auth_method = OAKLEY_ECDSA_256;
@@ -344,7 +369,7 @@ void ike_alg_list(void)
* Show IKE algorithms for this connection (result from ike= string)
* and newest SA
*/
-void ike_alg_show_connection(struct connection *c, const char *instance)
+void ike_alg_show_connection(connection_t *c, const char *instance)
{
struct state *st = state_with_serialno(c->newest_isakmp_sa);
diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c
index 57f4fb54b..1f8917d79 100644
--- a/src/pluto/ipsec_doi.c
+++ b/src/pluto/ipsec_doi.c
@@ -25,7 +25,6 @@
#include <resolv.h>
#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
-#include <sys/time.h> /* for gettimeofday */
#include <freeswan.h>
@@ -36,12 +35,14 @@
#include <crypto/rngs/rng.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
+#include <utils/identification.h>
#include "constants.h"
#include "defs.h"
+#include "myid.h"
#include "state.h"
-#include "id.h"
#include "x509.h"
+#include "ac.h"
#include "crl.h"
#include "ca.h"
#include "certs.h"
@@ -101,21 +102,24 @@
* 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 != ISAKMP_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)
+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 */
+ }
}
/* Compute DH shared secret from our local secret and the peer's public value.
@@ -172,13 +176,13 @@ static notification_t accept_KE(chunk_t *dest, const char *val_name,
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;
+ return ISAKMP_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;
+ return ISAKMP_NOTHING_WRONG;
}
/* accept_PFS_KE
@@ -197,7 +201,7 @@ static notification_t accept_PFS_KE(struct msg_digest *md, chunk_t *dest,
if (st->st_pfs_group != NULL)
{
loglog(RC_LOG_SERIOUS, "missing KE payload in %s message", msg_name);
- return INVALID_KEY_INFORMATION;
+ return ISAKMP_INVALID_KEY_INFORMATION;
}
}
else
@@ -206,16 +210,16 @@ static notification_t accept_PFS_KE(struct msg_digest *md, chunk_t *dest,
{
loglog(RC_LOG_SERIOUS, "%s message KE payload requires a GROUP_DESCRIPTION attribute in SA"
, msg_name);
- return INVALID_KEY_INFORMATION;
+ return ISAKMP_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 ISAKMP_INVALID_KEY_INFORMATION; /* ??? */
}
return accept_KE(dest, val_name, st->st_pfs_group, &ke_pd->pbs);
}
- return NOTHING_WRONG;
+ return ISAKMP_NOTHING_WRONG;
}
static bool build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np,
@@ -231,39 +235,42 @@ static bool build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np,
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 linked_list_t* collect_rw_ca_candidates(struct msg_digest *md)
{
- struct connection *d = find_host_connection(&md->iface->addr
- , pluto_port, (ip_address*)NULL, md->sender_port, LEMPTY);
+ linked_list_t *list = linked_list_create();
+ connection_t *d;
+
+ 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)
+ if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO) &&
+ d->spd.that.ca)
{
- generalName_t *gn;
+ enumerator_t *enumerator;
+ identification_t *ca;
bool new_entry = TRUE;
- for (gn = *top; gn != NULL; gn = gn->next)
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ca))
{
- if (same_dn(gn->name, d->spd.that.ca))
+ if (ca->equals(ca, d->spd.that.ca))
{
new_entry = FALSE;
break;
- }
+ }
}
+ enumerator->destroy(enumerator);
+
if (new_entry)
{
- gn = malloc_thing(generalName_t);
- gn->kind = GN_DIRECTORY_NAME;
- gn->name = d->spd.that.ca;
- gn->next = *top;
- *top = gn;
+ list->insert_last(list, d->spd.that.ca->clone(d->spd.that.ca));
}
}
}
- return *top != NULL;
+ return list;
}
static bool build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs,
@@ -276,8 +283,9 @@ static bool build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs,
/* 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 */
@@ -323,24 +331,33 @@ static void send_notification(struct state *sndst, u_int16_t type,
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))
+ 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 */
}
@@ -358,7 +375,9 @@ static void send_notification(struct state *sndst, u_int16_t type,
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);
}
@@ -393,8 +412,9 @@ static void send_notification(struct state *sndst, u_int16_t type,
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);
@@ -405,8 +425,10 @@ static void send_notification(struct state *sndst, u_int16_t type,
}
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);
@@ -475,7 +497,7 @@ void send_notification_from_md(struct msg_digest *md, u_int16_t type)
* st_connection->interface
*/
struct state st;
- struct connection cnx;
+ connection_t cnx;
passert(md);
@@ -569,10 +591,14 @@ void send_delete(struct state *st)
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) */
}
@@ -595,7 +621,9 @@ void send_delete(struct state *st)
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
@@ -615,7 +643,9 @@ void send_delete(struct state *st)
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);
}
}
@@ -656,8 +686,9 @@ void send_delete(struct state *st)
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;
@@ -755,14 +786,15 @@ void accept_delete(struct state *st, struct msg_digest *md,
}
else
{
- struct connection *oldc;
-
+ connection_t *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);
@@ -790,18 +822,19 @@ void accept_delete(struct state *st, struct msg_digest *md,
}
else
{
- struct connection *rc = dst->st_connection;
- struct connection *oldc;
-
+ connection_t *rc = dst->st_connection;
+ connection_t *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.
*
@@ -855,7 +888,9 @@ void close_message(pb_stream *pbs)
size_t padding = pad_up(pbs_offset(pbs), 4);
if (padding != 0)
+ {
(void) out_zero(padding, pbs, "message padding");
+ }
close_output_pbs(pbs);
}
@@ -864,15 +899,14 @@ void close_message(pb_stream *pbs)
* Note: this is not called from demux.c
*/
static stf_status
-main_outI1(int whack_sock, struct connection *c, struct state *predecessor
+main_outI1(int whack_sock, connection_t *c, struct state *predecessor
, 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 */
@@ -883,30 +917,48 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
/* 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)
+ }
+ if (c->spd.this.cert &&
+ c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
+ {
vids_to_send++;
+ }
if (SEND_XAUTH_VID)
+ {
vids_to_send++;
+ }
+
/* always send DPD Vendor ID */
- vids_to_send++;
+ 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) */
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);
+ }
/* set up reply */
init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
@@ -970,7 +1022,8 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
/* 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 (c->spd.this.cert &&
+ c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
{
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
, &rbody, VID_OPENPGP))
@@ -1042,7 +1095,7 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
return STF_OK;
}
-void ipsecdoi_initiate(int whack_sock, struct connection *c, lset_t policy,
+void ipsecdoi_initiate(int whack_sock, connection_t *c, lset_t policy,
unsigned long try, so_serial_t replacing)
{
/* If there's already an ISAKMP SA established, use that and
@@ -1155,7 +1208,7 @@ static bool skeyid_preshared(struct state *st)
{
loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
pseudo_random_function_names, prf_alg);
- return FALSE;
+ return FALSE;
}
free(st->st_skeyid.ptr);
prf->set_key(prf, *pss);
@@ -1166,8 +1219,7 @@ static bool skeyid_preshared(struct state *st)
}
}
-static bool
-skeyid_digisig(struct state *st)
+static bool skeyid_digisig(struct state *st)
{
chunk_t nir;
pseudo_random_function_t prf_alg;
@@ -1234,12 +1286,9 @@ static bool generate_skeyids_iv(struct state *st)
/* 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 seed_skeyid_d = chunk_from_chars(0x00);
+ chunk_t seed_skeyid_a = chunk_from_chars(0x01);
+ chunk_t seed_skeyid_e = chunk_from_chars(0x02);
chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE };
pseudo_random_function_t prf_alg;
@@ -1254,7 +1303,7 @@ static bool generate_skeyids_iv(struct state *st)
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);
+ prf->allocate_bytes(prf, seed_skeyid_d, &st->st_skeyid_d);
/* SKEYID_A */
free(st->st_skeyid_a.ptr);
@@ -1262,7 +1311,7 @@ static bool generate_skeyids_iv(struct state *st)
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);
+ prf->allocate_bytes(prf, seed_skeyid_a, &st->st_skeyid_a);
/* SKEYID_E */
free(st->st_skeyid_e.ptr);
@@ -1270,7 +1319,7 @@ static bool generate_skeyids_iv(struct state *st)
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->allocate_bytes(prf, seed_skeyid_e, &st->st_skeyid_e);
prf->destroy(prf);
}
@@ -1289,7 +1338,7 @@ static bool generate_skeyids_iv(struct state *st)
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);
@@ -1302,15 +1351,14 @@ static bool generate_skeyids_iv(struct state *st)
*/
{
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);
+ chunk_t seed = chunk_from_chars(0x00);
size_t prf_block_size, i;
pseudo_random_function_t prf_alg;
prf_t *prf;
@@ -1319,7 +1367,7 @@ static bool generate_skeyids_iv(struct state *st)
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]);
@@ -1336,7 +1384,7 @@ static bool generate_skeyids_iv(struct state *st)
else
{
st->st_enc_key = chunk_create(st->st_skeyid_e.ptr, keysize);
- }
+ }
st->st_enc_key = chunk_clone(st->st_enc_key);
}
@@ -1421,7 +1469,7 @@ static bool generate_skeyids_iv(struct state *st)
* Use PKCS#1 version 1.5 encryption of hash (called
* RSAES-PKCS1-V1_5) in PKCS#2.
*/
-static size_t sign_hash(signature_scheme_t scheme, struct connection *c,
+static size_t sign_hash(signature_scheme_t scheme, connection_t *c,
u_char sig_val[RSA_MAX_OCTETS], chunk_t hash)
{
size_t sz = 0;
@@ -1469,7 +1517,9 @@ static size_t sign_hash(signature_scheme_t scheme, struct connection *c,
)
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;
@@ -1487,7 +1537,7 @@ static size_t sign_hash(signature_scheme_t scheme, struct connection *c,
*/
struct tac_state {
struct state *st;
- chunk_t hash;
+ chunk_t hash;
chunk_t sig;
int tried_cnt; /* number of keys tried */
};
@@ -1495,17 +1545,18 @@ struct tac_state {
static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
{
public_key_t *pub_key = kr->public_key;
- identification_t *keyid = pub_key->get_id(pub_key, ID_PUBKEY_INFO_SHA1);
+ chunk_t keyid = chunk_empty;
signature_scheme_t scheme;
s->tried_cnt++;
scheme = oakley_to_signature_scheme(s->st->st_oakley.auth);
+ pub_key->get_fingerprint(pub_key, KEY_ID_PUBKEY_INFO_SHA1, &keyid);
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)
+ DBG_log("%s check passed with keyid %#B",
+ 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);
@@ -1514,14 +1565,14 @@ static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
else
{
DBG(DBG_CRYPT,
- DBG_log("%s check failed with keyid %Y",
- enum_show(&oakley_auth_names, s->st->st_oakley.auth), keyid)
+ DBG_log("%s check failed with keyid %#B",
+ enum_show(&oakley_auth_names, s->st->st_oakley.auth), &keyid)
)
return FALSE;
}
}
-static stf_status check_signature(key_type_t key_type, const struct id* peer,
+static stf_status check_signature(key_type_t key_type, identification_t* peer,
struct state *st, chunk_t hash,
const pb_stream *sig_pbs,
#ifdef USE_KEYRR
@@ -1529,7 +1580,7 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
#endif /* USE_KEYRR */
const struct gw_info *gateways_from_dns)
{
- const struct connection *c = st->st_connection;
+ const connection_t *c = st->st_connection;
struct tac_state s;
s.st = st;
@@ -1545,7 +1596,8 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
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)&&
+ if (gw->gw_key_present &&
+ gw->gw_id->equals(gw->gw_id, c->spd.that.id) &&
take_a_crack(&s, gw->key))
{
return STF_OK;
@@ -1564,7 +1616,7 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
pubkey_t *key = p->key;
key_type_t type = key->public_key->get_type(key->public_key);
- if (type == key_type && same_id(peer, &key->id))
+ if (type == key_type && peer->equals(peer, key->id))
{
time_t now = time(NULL);
@@ -1576,7 +1628,6 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
*pp = free_public_keyentry(p);
continue; /* continue with next public key */
}
-
if (take_a_crack(&s, key))
{
return STF_OK;
@@ -1628,34 +1679,30 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
/* no acceptable key was found: diagnose */
{
- char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
-
- idtoa(peer, id_buf, sizeof(id_buf));
-
if (s.tried_cnt == 0)
{
- loglog(RC_LOG_SERIOUS, "no public key known for '%s'", id_buf);
+ loglog(RC_LOG_SERIOUS, "no public key known for '%Y'", peer);
}
else if (s.tried_cnt == 1)
{
- loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
- " wrong key?; tried %d", id_buf, s.tried_cnt);
+ loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
+ " wrong key?; tried %d", peer, s.tried_cnt);
DBG(DBG_CONTROL,
- DBG_log("public key for '%s' failed: "
- "decrypted SIG payload into a malformed ECB", id_buf)
+ DBG_log("public key for '%Y' failed: "
+ "decrypted SIG payload into a malformed ECB", peer)
)
}
else
{
- loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
- "tried %d keys but none worked.", id_buf, s.tried_cnt);
+ loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
+ "tried %d keys but none worked.", peer, s.tried_cnt);
DBG(DBG_CONTROL,
- DBG_log("all %d public keys for '%s' failed: "
+ DBG_log("all %d public keys for '%Y' failed: "
"best decrypted SIG payload into a malformed ECB",
- s.tried_cnt, id_buf)
+ s.tried_cnt, peer)
)
}
- return STF_FAIL + INVALID_KEY_INFORMATION;
+ return STF_FAIL + ISAKMP_INVALID_KEY_INFORMATION;
}
}
@@ -1669,12 +1716,12 @@ static notification_t accept_nonce(struct msg_digest *md, chunk_t *dest,
{
loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"
, name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
- return PAYLOAD_MALFORMED; /* ??? */
+ return ISAKMP_PAYLOAD_MALFORMED; /* ??? */
}
free(dest->ptr);
*dest = chunk_create(nonce_pbs->cur, len);
*dest = chunk_clone(*dest);
- return NOTHING_WRONG;
+ return ISAKMP_NOTHING_WRONG;
}
/* encrypt message, sans fixed part of header
@@ -1682,8 +1729,7 @@ static notification_t accept_nonce(struct msg_digest *md, chunk_t *dest,
* The theory is that there will be no "backing out", so we commit to IV.
* We also close the pbs.
*/
-bool
-encrypt_message(pb_stream *pbs, struct state *st)
+bool encrypt_message(pb_stream *pbs, struct state *st)
{
u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr);
size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr);
@@ -1723,7 +1769,7 @@ encrypt_message(pb_stream *pbs, struct state *st)
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);
@@ -1755,7 +1801,7 @@ static size_t quick_mode_hash12(u_char *dest, u_char *start, u_char *roof,
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);
@@ -1775,13 +1821,12 @@ static size_t quick_mode_hash12(u_char *dest, u_char *start, u_char *roof,
*/
static size_t quick_mode_hash3(u_char *dest, struct state *st)
{
- char seed_buf[] = { 0x00 };
- chunk_t seed_chunk = chunk_from_buf(seed_buf);
+ chunk_t seed_chunk = chunk_from_chars(0x00);
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);
@@ -1814,7 +1859,7 @@ void init_phase2_iv(struct state *st, const msgid_t *msgid)
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);
@@ -1846,27 +1891,30 @@ static bool emit_subnet_id(ip_subnet *net, u_int8_t np, u_int8_t 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;
-
+ }
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;
}
stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
- struct connection *c, lset_t policy, unsigned long try,
+ connection_t *c, lset_t policy, unsigned long try,
so_serial_t replacing)
{
struct state *st = duplicate_state(isakmp_sa);
@@ -1878,10 +1926,27 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
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;
+ if (c->spd.this.modecfg && !c->spd.this.has_client &&
+ isanyaddr(&c->spd.this.host_srcip))
+ {
+ connection_t *ph1_c = isakmp_sa->st_connection;
+
+ if (ph1_c->spd.this.modecfg && !isanyaddr(&ph1_c->spd.this.host_srcip))
+ {
+ char srcip[ADDRTOT_BUF];
+
+ c->spd.this.host_srcip = ph1_c->spd.this.host_srcip;
+ c->spd.this.client = ph1_c->spd.this.client;
+ c->spd.this.has_client = TRUE;
+ addrtot(&c->spd.this.host_srcip, 0, srcip, sizeof(srcip));
+ plog("inheriting virtual IP source address %s from ModeCfg", srcip);
+ }
+ }
+
st->st_whack_sock = whack_sock;
st->st_connection = c;
set_cur_state(st); /* we must reset before exit */
@@ -1899,27 +1964,30 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
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);
+ {
+ 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);
-
+ {
+ 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)
@@ -1957,13 +2025,15 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_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)
#endif
/* If PFS specified, use the same group as during Phase 1:
@@ -1979,11 +2049,12 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
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))
+ }
+ 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;
@@ -2063,14 +2134,18 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
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;
}
@@ -2092,35 +2167,45 @@ static void decode_cert(struct msg_digest *md)
blob.len = pbs_left(&p->pbs);
if (cert->isacert_type == CERT_X509_SIGNATURE)
{
- x509cert_t cert = empty_x509cert;
- if (parse_x509cert(blob, 0, &cert))
+ cert_t x509cert = cert_empty;
+
+ x509cert.cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, blob,
+ BUILD_END);
+ if (x509cert.cert)
{
- if (verify_x509cert(&cert, strict_crl_policy, &valid_until))
+ if (verify_x509cert(&x509cert, strict_crl_policy, &valid_until))
{
DBG(DBG_PARSING,
DBG_log("Public key validated")
)
- add_x509_public_key(&cert, valid_until, DAL_SIGNED);
+ add_public_key_from_cert(&x509cert, 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);
+ x509cert.cert->destroy(x509cert.cert);
}
else
+ {
plog("Syntax error in X.509 certificate");
+ }
}
else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509)
{
- x509cert_t *cert = NULL;
+ linked_list_t *certs = linked_list_create();
- if (pkcs7_parse_signedData(blob, NULL, &cert, NULL, NULL))
- store_x509certs(&cert, strict_crl_policy);
+ if (pkcs7_parse_signedData(blob, NULL, certs, NULL, NULL))
+ {
+ store_x509certs(certs, strict_crl_policy);
+ }
else
+ {
plog("Syntax error in PKCS#7 wrapped X.509 certificates");
+ }
+ certs->destroy_offset(certs, offsetof(certificate_t, destroy));
}
else
{
@@ -2134,7 +2219,7 @@ static void decode_cert(struct msg_digest *md)
/*
* 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, connection_t *c)
{
struct payload_digest *p;
@@ -2142,7 +2227,7 @@ static void decode_cr(struct msg_digest *md, struct connection *c)
{
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;
@@ -2150,32 +2235,37 @@ static void decode_cr(struct msg_digest *md, struct connection *c)
if (cr->isacr_type == CERT_X509_SIGNATURE)
{
- char buf[BUF_LEN];
-
if (ca_name.len > 0)
{
- generalName_t *gn;
-
+ identification_t *ca;
+
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;
+ }
+ if (c->requested_ca == NULL)
+ {
+ c->requested_ca = linked_list_create();
+ }
+ ca = identification_create_from_encoding(ID_DER_ASN1_DN, ca_name);
+ c->requested_ca->insert_last(c->requested_ca, ca);
+ DBG(DBG_PARSING | DBG_CONTROL,
+ DBG_log("requested CA: \"%Y\"", ca)
+ )
+ }
+ else
+ {
+ DBG(DBG_PARSING | DBG_CONTROL,
+ DBG_log("requested CA: %%any")
+ )
}
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));
+ }
}
}
@@ -2184,12 +2274,13 @@ static void decode_cr(struct msg_digest *md, struct connection *c)
* We must be called before SIG or HASH are decoded since we
* 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, identification_t **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;
+ chunk_t id_payload;
/* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
* It talks about the protocol ID and Port fields of the ID
@@ -2218,74 +2309,50 @@ static bool decode_peer_id(struct msg_digest *md, struct id *peer)
return FALSE;
}
- peer->kind = id->isaid_idtype;
+ id_payload = chunk_create(id_pbs->cur, pbs_left(id_pbs));
- switch (peer->kind)
+ switch (id->isaid_idtype)
{
- 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)
+ case ID_IPV4_ADDR:
+ if (id_payload.len != 4)
{
- loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s"
- , enum_show(&ident_names, peer->kind), ugh);
- /* XXX Could send notification back */
+ loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
+ enum_show(&ident_names, id->isaid_idtype));
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));
+ break;
+ case ID_IPV6_ADDR:
+ if (id_payload.len != 16)
+ {
+ loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
+ enum_show(&ident_names, id->isaid_idtype));
+ return FALSE;
+ }
+ break;
+ case ID_USER_FQDN:
+ case ID_FQDN:
+ if (memchr(id_payload.ptr, '\0', id_payload.len) != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s Phase 1 ID payload contains "
+ "a NUL character",
+ enum_show(&ident_names, id->isaid_idtype));
+ return FALSE;
+ }
+ break;
+ case ID_KEY_ID:
+ case ID_DER_ASN1_DN:
+ break;
+ default:
+ /* XXX Could send notification back */
+ loglog(RC_LOG_SERIOUS, "unacceptable identity type (%s) "
+ "in Phase 1 ID payload",
+ enum_show(&ident_names, id->isaid_idtype));
return FALSE;
- }
-
- /* ??? ought to do some more sanity check, but what? */
-
- peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
- 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:
- 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;
}
+ *peer = identification_create_from_encoding(id->isaid_idtype, id_payload);
- {
- char buf[BUF_LEN];
-
- idtoa(peer, buf, sizeof(buf));
- plog("Peer ID is %s: '%s'",
- enum_show(&ident_names, id->isaid_idtype), buf);
- }
+ plog("Peer ID is %s: '%Y'", enum_show(&ident_names, id->isaid_idtype),
+ *peer);
/* check for certificates */
decode_cert(md);
@@ -2298,45 +2365,51 @@ static bool 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,
+static bool switch_connection(struct msg_digest *md, identification_t *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 : chunk_empty;
+ connection_t *c = st->st_connection;
+ identification_t *peer_ca;
- DBG(DBG_CONTROL,
- char buf[BUF_LEN];
-
- dntoa_or_null(buf, BUF_LEN, peer_ca, "%none");
- DBG_log("peer CA: '%s'", buf);
- )
+ peer_ca = st->st_peer_pubkey ? st->st_peer_pubkey->issuer : NULL;
+ if (peer_ca)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("peer CA: \"%Y\"", peer_ca)
+ )
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("peer CA: %%none")
+ )
+ }
if (initiator)
{
int pathlen;
- if (!same_id(&c->spd.that.id, peer))
+ if (!peer->equals(peer, c->spd.that.id))
{
- 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);
+ loglog(RC_LOG_SERIOUS,
+ "we require peer to have ID '%Y', but peer declares '%Y'",
+ c->spd.that.id, peer);
return FALSE;
}
- DBG(DBG_CONTROL,
- char buf[BUF_LEN];
-
- dntoa_or_null(buf, BUF_LEN, c->spd.that.ca, "%none");
- DBG_log("required CA: '%s'", buf);
- )
+ if (c->spd.that.ca)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("required CA: \"%s\"", c->spd.that.ca);
+ )
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("required CA: %%none");
+ )
+ }
if (!trusted_ca(peer_ca, c->spd.that.ca, &pathlen))
{
@@ -2347,7 +2420,7 @@ static bool switch_connection(struct msg_digest *md, struct id *peer,
}
else
{
- struct connection *r;
+ connection_t *r;
/* check for certificate requests */
decode_cr(md, c);
@@ -2355,24 +2428,31 @@ static bool switch_connection(struct msg_digest *md, struct id *peer,
r = refine_host_connection(st, peer, peer_ca);
/* delete the collected certificate requests */
- free_generalNames(c->requested_ca, TRUE);
- c->requested_ca = NULL;
+ if (c->requested_ca)
+ {
+ c->requested_ca->destroy_offset(c->requested_ca,
+ offsetof(identification_t, destroy));
+ c->requested_ca = NULL;
+ }
if (r == NULL)
{
- char buf[BUF_LEN];
-
- idtoa(peer, buf, sizeof(buf));
- loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%s'", buf);
+ loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%Y'", peer);
return FALSE;
}
- DBG(DBG_CONTROL,
- char buf[BUF_LEN];
-
- dntoa_or_null(buf, BUF_LEN, r->spd.this.ca, "%none");
- DBG_log("offered CA: '%s'", buf);
- )
+ if (r->spd.this.ca)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("offered CA: \"%Y\"", r->spd.this.ca)
+ )
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("offered CA: %%none")
+ )
+ }
if (r != c)
{
@@ -2396,10 +2476,9 @@ static bool switch_connection(struct msg_digest *md, struct id *peer,
}
else if (c->spd.that.has_id_wildcards)
{
- free_id_content(&c->spd.that.id);
- c->spd.that.id = *peer;
+ c->spd.that.id->destroy(c->spd.that.id);
+ c->spd.that.id = peer->clone(peer);
c->spd.that.has_id_wildcards = FALSE;
- unshare_id_content(&c->spd.that.id);
}
}
return TRUE;
@@ -2489,13 +2568,19 @@ static bool decode_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
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)"
@@ -2528,8 +2613,10 @@ static bool decode_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
}
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"
@@ -2540,7 +2627,9 @@ static bool decode_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
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];
@@ -2582,8 +2671,9 @@ static bool check_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
ip_subnet net_temp;
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)
{
@@ -2598,7 +2688,7 @@ static bool check_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
*/
static bool has_preloaded_public_key(struct state *st)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
/* do not consider rw connections since
* the peer's identity must be known
@@ -2613,7 +2703,8 @@ static bool has_preloaded_public_key(struct state *st)
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) &&
+ if (type == KEY_RSA &&
+ c->spd.that.id->equals(c->spd.that.id, key->id) &&
key->until_time == UNDEFINED_TIME)
{
/* found a preloaded public key */
@@ -2646,7 +2737,7 @@ static void compute_proto_keymat(struct state *st, u_int8_t protoid,
if (needed_len && pi->attrs.key_len)
{
needed_len = pi->attrs.key_len / BITS_PER_BYTE;
- }
+ }
switch (pi->attrs.transid)
{
@@ -2745,7 +2836,7 @@ static void compute_proto_keymat(struct state *st, u_int8_t protoid,
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 */
@@ -2785,9 +2876,13 @@ static void compute_proto_keymat(struct state *st, u_int8_t protoid,
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 bool uses_pubkey_auth(int auth)
@@ -2807,6 +2902,38 @@ static bool uses_pubkey_auth(int auth)
}
}
+/* build an ID payload
+ * Note: no memory is allocated for the body of the payload (tl->ptr).
+ * We assume it will end up being a pointer into a sufficiently
+ * stable datastructure. It only needs to last a short time.
+ */
+static void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
+{
+ identification_t *id = resolve_myid(end->id);
+
+ zero(hd);
+ hd->isaiid_idtype = id->get_type(id);
+
+ switch (id->get_type(id))
+ {
+ 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_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ case ID_FQDN:
+ case ID_USER_FQDN:
+ case ID_DER_ASN1_DN:
+ case ID_KEY_ID:
+ *tl = id->get_encoding(id);
+ break;
+ default:
+ bad_case(id->get_type(id));
+ }
+}
+
/* State Transition Functions.
*
* The definition of state_microcode_table in demux.c is a good
@@ -2833,7 +2960,7 @@ 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;
+ connection_t *c;
struct isakmp_proposal proposal;
pb_stream proposal_pbs;
pb_stream r_sa_pbs;
@@ -2877,7 +3004,7 @@ stf_status main_inI1_outR1(struct msg_digest *md)
* but Food Groups kind of assumes one.
*/
{
- struct connection *d;
+ connection_t *d;
d = find_host_connection(&md->iface->addr
, pluto_port, (ip_address*)NULL, md->sender_port, policy);
@@ -2936,7 +3063,7 @@ stf_status main_inI1_outR1(struct msg_digest *md)
/* 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);
+ c = rw_instantiate(c, &md->sender, md->sender_port, NULL, c->spd.that.id);
}
/* Set up state */
@@ -3126,7 +3253,7 @@ stf_status main_inR1_outI2(struct msg_digest *md)
{
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(ISAKMP_BAD_PROPOSAL_SYNTAX);
}
RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
, &proposal_pbs, &proposal, NULL, st, TRUE));
@@ -3155,35 +3282,46 @@ stf_status main_inR1_outI2(struct msg_digest *md)
/* 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);
}
#else
/* 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;
+ }
}
/* finish message */
@@ -3251,15 +3389,18 @@ stf_status main_inI2_outR2(struct msg_digest *md)
/* 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
+ 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 */
@@ -3267,9 +3408,13 @@ stf_status main_inI2_outR2(struct msg_digest *md)
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
@@ -3284,33 +3429,50 @@ stf_status main_inI2_outR2(struct msg_digest *md)
{
if (st->st_connection->kind == CK_PERMANENT)
{
- if (!build_and_ship_CR(CERT_X509_SIGNATURE
- , st->st_connection->spd.that.ca
- , &md->rbody, np))
+ identification_t *ca = st->st_connection->spd.that.ca;
+ chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty;
+
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE, cr, &md->rbody, np))
+ {
return STF_INTERNAL_ERROR;
+ }
}
else
{
- generalName_t *ca = NULL;
+ linked_list_t *list = collect_rw_ca_candidates(md);
+ int count = list->get_count(list);
+ bool error = FALSE;
- if (collect_rw_ca_candidates(md, &ca))
+ if (count)
{
- generalName_t *gn;
+ enumerator_t *enumerator;
+ identification_t *ca;
- for (gn = ca; gn != NULL; gn = gn->next)
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ca))
{
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, gn->name
- , &md->rbody
- , gn->next == NULL ? np : ISAKMP_NEXT_CR))
- return STF_INTERNAL_ERROR;
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE,
+ ca->get_encoding(ca), &md->rbody,
+ --count ? ISAKMP_NEXT_CR : np))
+ {
+ error = TRUE;
+ break;
+ }
}
- free_generalNames(ca, FALSE);
+ enumerator->destroy(enumerator);
}
else
{
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, chunk_empty
- , &md->rbody, np))
- return STF_INTERNAL_ERROR;
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE, chunk_empty,
+ &md->rbody, np))
+ {
+ error = TRUE;
+ }
+ }
+ list->destroy_offset(list, offsetof(identification_t, destroy));
+ if (error)
+ {
+ return STF_INTERNAL_ERROR;
}
}
}
@@ -3318,7 +3480,9 @@ stf_status main_inI2_outR2(struct msg_digest *md)
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 */
@@ -3329,7 +3493,9 @@ stf_status main_inI2_outR2(struct msg_digest *md)
*/
compute_dh_shared(st, st->st_gi);
if (!generate_skeyids_iv(st))
- return STF_FAIL + AUTHENTICATION_FAILED;
+ {
+ return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
+ }
update_iv(st);
return STF_OK;
@@ -3350,9 +3516,10 @@ 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;
+
+ connection_t *c = st->st_connection;
+ certpolicy_t cert_policy = c->spd.this.sendcert;
+ cert_t *mycert = c->spd.this.cert;
bool requested, send_cert, send_cr;
bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
@@ -3365,22 +3532,26 @@ stf_status main_inR2_outI3(struct msg_digest *md)
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);
+ c->got_certrequest = FALSE;
+ decode_cr(md, c);
/* 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;
+ if (c->requested_ca)
+ {
+ c->requested_ca->destroy_offset(c->requested_ca,
+ offsetof(identification_t, destroy));
+ c->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);
+ requested = cert_policy == CERT_SEND_IF_ASKED && c->got_certrequest;
+ send_cert = pubkey_auth && mycert &&
+ mycert->cert->get_type(mycert->cert) == CERT_X509 &&
+ (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);
@@ -3388,8 +3559,9 @@ stf_status main_inR2_outI3(struct msg_digest *md)
/* done parsing; initialize crypto */
compute_dh_shared(st, st->st_gr);
if (!generate_skeyids_iv(st))
- return STF_FAIL + AUTHENTICATION_FAILED;
-
+ {
+ return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
+ }
if (st->nat_traversal & NAT_T_WITH_NATD)
{
nat_traversal_natd_lookup(md);
@@ -3413,11 +3585,13 @@ stf_status main_inR2_outI3(struct msg_digest *md)
struct isakmp_ipsec_id id_hd;
chunk_t id_b;
- build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this);
+ build_id_payload(&id_hd, &id_b, &c->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);
}
@@ -3427,12 +3601,14 @@ stf_status main_inR2_outI3(struct msg_digest *md)
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
)
- if (mycert.type != CERT_NONE)
+ if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
{
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);
}
@@ -3443,31 +3619,43 @@ stf_status main_inR2_outI3(struct msg_digest *md)
}
if (send_cert)
{
+ bool success;
+ chunk_t cert_encoding;
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;
+ cert_hd.isacert_type = CERT_X509_SIGNATURE;
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"))
+ }
+ cert_encoding = mycert->cert->get_encoding(mycert->cert);
+ success = out_chunk(cert_encoding, &cert_pbs, "CERT");
+ free(cert_encoding.ptr);
+ if (!success)
+ {
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))
+ identification_t *ca = st->st_connection->spd.that.ca;
+ chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty;
+
+ if (!build_and_ship_CR(CERT_X509_SIGNATURE, cr, &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);
+ chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
main_mode_hash(st, &hash, TRUE, &id_pbs);
@@ -3489,16 +3677,18 @@ stf_status main_inR2_outI3(struct msg_digest *md)
scheme = oakley_to_signature_scheme(st->st_oakley.auth);
- sig_len = sign_hash(scheme, st->st_connection, sig_val, hash);
+ sig_len = sign_hash(scheme, c, sig_val, hash);
if (sig_len == 0)
{
loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
- return STF_FAIL + AUTHENTICATION_FAILED;
+ return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
}
if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
, &md->rbody, sig_val, sig_len, "SIG_I"))
+ {
return STF_INTERNAL_ERROR;
+ }
}
}
@@ -3506,8 +3696,9 @@ stf_status main_inR2_outI3(struct msg_digest *md)
/* 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;
}
@@ -3534,13 +3725,10 @@ struct key_continuation {
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)
+static void report_key_dns_failure(identification_t *id, err_t ugh)
{
- 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);
+ loglog(RC_LOG_SERIOUS, "no RSA public key known for '%Y'"
+ "; DNS search for KEY failed (%s)", id, ugh);
}
@@ -3558,15 +3746,16 @@ main_id_and_auth(struct msg_digest *md
, const struct key_continuation *kc /* current state, can be NULL */
)
{
- u_char hash_buf[MAX_DIGEST_LEN];
- chunk_t hash = chunk_from_buf(hash_buf);
+ chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
struct state *st = md->st;
- struct id peer;
+ identification_t *peer;
stf_status r = STF_OK;
/* ID Payload in */
if (!decode_peer_id(md, &peer))
- return STF_FAIL + INVALID_ID_INFORMATION;
+ {
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
+ }
/* Hash the ID Payload.
* main_mode_hash requires idpl->cur to be at end of payload
@@ -3596,7 +3785,7 @@ main_id_and_auth(struct msg_digest *md
, 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;
+ r = STF_FAIL + ISAKMP_INVALID_HASH_INFORMATION;
}
}
break;
@@ -3604,14 +3793,14 @@ main_id_and_auth(struct msg_digest *md
case OAKLEY_RSA_SIG:
case XAUTHInitRSA:
case XAUTHRespRSA:
- r = check_signature(KEY_RSA, &peer, st, hash,
- &md->chain[ISAKMP_NEXT_SIG]->pbs,
+ 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
+ kc == NULL ? NULL : kc->ac.gateways_from_dns
);
-
+
if (r == STF_SUSPEND)
{
/* initiate/resume asynchronous DNS lookup for key */
@@ -3634,22 +3823,14 @@ main_id_and_auth(struct msg_digest *md
#ifdef USE_KEYRR
nkc->failure_ok = TRUE;
#endif
- ugh = start_adns_query(&peer
- , &peer /* SG itself */
- , T_TXT
- , cont_fn
- , &nkc->ac);
+ ugh = start_adns_query(peer, peer, 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);
+ ugh = start_adns_query(peer, NULL, T_KEY, cont_fn, &nkc->ac);
break;
#endif /* USE_KEYRR */
@@ -3659,9 +3840,9 @@ main_id_and_auth(struct msg_digest *md
if (ugh != NULL)
{
- report_key_dns_failure(&peer, ugh);
+ report_key_dns_failure(peer, ugh);
st->st_suspended_md = NULL;
- r = STF_FAIL + INVALID_KEY_INFORMATION;
+ r = STF_FAIL + ISAKMP_INVALID_KEY_INFORMATION;
}
}
break;
@@ -3669,7 +3850,7 @@ main_id_and_auth(struct msg_digest *md
case OAKLEY_ECDSA_256:
case OAKLEY_ECDSA_384:
case OAKLEY_ECDSA_521:
- r = check_signature(KEY_ECDSA, &peer, st, hash,
+ r = check_signature(KEY_ECDSA, peer, st, hash,
&md->chain[ISAKMP_NEXT_SIG]->pbs,
#ifdef USE_KEYRR
NULL,
@@ -3681,16 +3862,20 @@ main_id_and_auth(struct msg_digest *md
bad_case(st->st_oakley.auth);
}
if (r != STF_OK)
+ {
+ peer->destroy(peer);
return r;
-
+ }
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;
-
+ if (!switch_connection(md, peer, initiator))
+ {
+ r = STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
+ }
+ peer->destroy(peer);
return r;
}
@@ -3715,7 +3900,7 @@ 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,
+static void key_continue(struct adns_continuation *cr, err_t ugh,
key_tail_fn *tail)
{
struct key_continuation *kc = (void *)cr;
@@ -3734,8 +3919,8 @@ static void key_continue(struct adns_continuation *cr, err_t ugh,
if (!kc->failure_ok && ugh != NULL)
{
- report_key_dns_failure(&st->st_connection->spd.that.id, ugh);
- r = STF_FAIL + INVALID_KEY_INFORMATION;
+ report_key_dns_failure(st->st_connection->spd.that.id, ugh);
+ r = STF_FAIL + ISAKMP_INVALID_KEY_INFORMATION;
}
else
{
@@ -3751,7 +3936,9 @@ static void key_continue(struct adns_continuation *cr, err_t ugh,
complete_state_transition(&kc->md, r);
}
if (kc->md != NULL)
+ {
release_md(kc->md);
+ }
cur_state = NULL;
}
@@ -3786,7 +3973,7 @@ main_inI3_outR3_tail(struct msg_digest *md
u_int8_t auth_payload;
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
certpolicy_t cert_policy;
- cert_t mycert;
+ cert_t *mycert;
bool pubkey_auth, send_cert, requested;
/* ID and HASH_I or SIG_I in
@@ -3798,7 +3985,9 @@ main_inI3_outR3_tail(struct msg_digest *md
, kc);
if (r != STF_OK)
+ {
return r;
+ }
}
/* send certificate if pubkey authentication is used, we have one
@@ -3809,7 +3998,8 @@ main_inI3_outR3_tail(struct msg_digest *md
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 &&
+ send_cert = pubkey_auth && mycert &&
+ mycert->cert->get_type(mycert->cert) == CERT_X509 &&
(cert_policy == CERT_ALWAYS_SEND || requested);
/*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
@@ -3840,7 +4030,9 @@ main_inI3_outR3_tail(struct msg_digest *md
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);
}
@@ -3850,12 +4042,14 @@ main_inI3_outR3_tail(struct msg_digest *md
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
)
- if (mycert.type != CERT_NONE)
+ if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
{
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);
}
@@ -3866,23 +4060,31 @@ main_inI3_outR3_tail(struct msg_digest *md
}
if (send_cert)
{
+ bool success;
+ chunk_t cert_encoding;
pb_stream cert_pbs;
-
struct isakmp_cert cert_hd;
+
cert_hd.isacert_np = ISAKMP_NEXT_SIG;
- cert_hd.isacert_type = mycert.type;
+ cert_hd.isacert_type = CERT_X509_SIGNATURE;
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;
+ }
+ cert_encoding = mycert->cert->get_encoding(mycert->cert);
+ success = out_chunk(cert_encoding, &cert_pbs, "CERT");
+ free(cert_encoding.ptr);
+ if (!success)
+ {
return STF_INTERNAL_ERROR;
+ }
close_output_pbs(&cert_pbs);
}
/* HASH_R or SIG_R out */
{
- u_char hash_buf[MAX_DIGEST_LEN];
- chunk_t hash = chunk_from_buf(hash_buf);
+ chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
main_mode_hash(st, &hash, FALSE, &r_id_pbs);
@@ -3908,19 +4110,23 @@ main_inI3_outR3_tail(struct msg_digest *md
if (sig_len == 0)
{
loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
- return STF_FAIL + AUTHENTICATION_FAILED;
+ return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
}
if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
, &md->rbody, sig_val, sig_len, "SIG_R"))
+ {
return STF_INTERNAL_ERROR;
+ }
}
}
/* encrypt message, sans fixed part of header */
if (!encrypt_message(&md->rbody, st))
+ {
return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
+ }
/* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
@@ -3969,7 +4175,9 @@ static stf_status main_inR3_tail(struct msg_digest *md,
stf_status r = main_id_and_auth(md, TRUE, main_inR3_continue, kc);
if (r != STF_OK)
+ {
return r;
+ }
}
/**************** done input ****************/
@@ -4103,7 +4311,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b
stf_status quick_inI1_outR1(struct msg_digest *md)
{
const struct state *const p1st = md->st;
- struct connection *c = p1st->st_connection;
+ connection_t *c = p1st->st_connection;
struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
struct verify_oppo_bundle b;
@@ -4127,12 +4335,16 @@ stf_status quick_inI1_outR1(struct msg_digest *md)
if (!decode_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
, &b.his.net, "peer client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
+ {
+ return STF_FAIL + ISAKMP_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 */
@@ -4144,8 +4356,9 @@ stf_status quick_inI1_outR1(struct msg_digest *md)
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;
-
+ {
+ return STF_FAIL + ISAKMP_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);
@@ -4154,8 +4367,9 @@ stf_status quick_inI1_outR1(struct msg_digest *md)
{
/* 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;
@@ -4224,7 +4438,7 @@ static void quick_inI1_outR1_continue(struct adns_continuation *cr, err_t ugh)
if (!b->failure_ok && ugh != NULL)
{
report_verify_failure(b, ugh);
- r = STF_FAIL + INVALID_ID_INFORMATION;
+ r = STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
}
else
{
@@ -4233,7 +4447,9 @@ static void quick_inI1_outR1_continue(struct adns_continuation *cr, err_t ugh)
complete_state_transition(&b->md, r);
}
if (b->md != NULL)
+ {
release_md(b->md);
+ }
cur_state = NULL;
}
@@ -4242,11 +4458,11 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
{
struct msg_digest *md = b->md;
struct state *p1st = md->st;
- struct connection *c = p1st->st_connection;
+ connection_t *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 */
+ identification_t *id; /* subject of query */
+ identification_t *our_id; /* needed for myid playing */
+ identification_t *our_id_space; /* ephemeral: no need for unshare_id_content */
ip_address client;
err_t ugh = NULL;
@@ -4282,20 +4498,20 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
* %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)
+ our_id = resolve_myid(c->spd.this.id);
+ if (our_id->get_type(our_id) == ID_ANY)
{
- iptoid(&c->spd.this.host_addr, &our_id_space);
- our_id = &our_id_space;
+ our_id_space = identification_create_from_sockaddr((sockaddr_t*)&c->spd.this.host_addr);
+ our_id = our_id_space;
}
switch (next_step)
{
case vos_our_client:
networkof(&b->my.net, &client);
- iptoid(&client, &id);
+ id = identification_create_from_sockaddr((sockaddr_t*)&client);
vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&id
+ ugh = start_adns_query(id
, our_id
, T_TXT
, quick_inI1_outR1_continue
@@ -4324,10 +4540,10 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
case vos_his_client:
networkof(&b->his.net, &client);
- iptoid(&client, &id);
+ id = identification_create_from_sockaddr((sockaddr_t*)&client);
vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&id
- , &c->spd.that.id
+ ugh = start_adns_query(id
+ , c->spd.that.id
, T_TXT
, quick_inI1_outR1_continue
, &vc->ac);
@@ -4345,7 +4561,7 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
*/
report_verify_failure(b, ugh);
p1st->st_suspended_md = NULL;
- return STF_FAIL + INVALID_ID_INFORMATION;
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
}
else
{
@@ -4358,7 +4574,7 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
struct adns_continuation *ac,
struct state *p1st)
{
- struct connection *c = p1st->st_connection;
+ connection_t *c = p1st->st_connection;
enum verify_oppo_step next_step = vos_our_client;
err_t ugh = NULL;
@@ -4491,14 +4707,12 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
next_step = vos_done;
{
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)
@@ -4510,10 +4724,8 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
* 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))
- )
+ if (!gwp->gw_key_present ||
+ pub_key->equals(pub_key, gwp->key->public_key))
{
ugh = NULL; /* good! */
break;
@@ -4539,7 +4751,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
{
struct msg_digest *md = b->md;
struct state *const p1st = md->st;
- struct connection *c = p1st->st_connection;
+ connection_t *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;
@@ -4552,7 +4764,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
* a suitable connection (our current one only matches for hosts).
*/
{
- struct connection *p = find_client_connection(c
+ connection_t *p = find_client_connection(c
, our_net, his_net, b->my.proto, b->my.port, b->his.proto, b->his.port);
if (p == NULL)
@@ -4582,7 +4794,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
plog("cannot respond to IPsec SA request"
" because no connection is known for %s"
, buf);
- return STF_FAIL + INVALID_ID_INFORMATION;
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
}
else if (p != c)
{
@@ -4609,14 +4821,18 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
next_step = quick_inI1_outR1_process_answer(b, ac, p1st);
if (next_step == vos_fail)
- return STF_FAIL + INVALID_ID_INFORMATION;
+ {
+ return STF_FAIL + ISAKMP_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,
@@ -4633,7 +4849,9 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
/* 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
@@ -4643,7 +4861,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
* 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
+ p = oppo_instantiate(p, &c->spd.that.host_addr, c->spd.that.id
, NULL, &our_client, &his_client);
}
else
@@ -4652,7 +4870,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
* instantiate, carrying over authenticated peer ID
*/
p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
- , his_net, &c->spd.that.id);
+ , his_net, c->spd.that.id);
}
}
#ifdef DEBUG
@@ -4680,7 +4898,9 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
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 */
@@ -4708,7 +4928,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
if (st->st_connection != c)
{
- struct connection *t = st->st_connection;
+ connection_t *t = st->st_connection;
st->st_connection = c;
set_cur_connection(c);
@@ -4781,7 +5001,9 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
/* 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;
@@ -4794,7 +5016,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
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; /* ??? */
+ return STF_FAIL + ISAKMP_NO_PROPOSAL_CHOSEN;
}
/* Ni in */
@@ -4811,7 +5033,9 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
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) */
@@ -4819,7 +5043,9 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
{
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;
+ {
+ return STF_INTERNAL_ERROR;
+ }
/* MPZ-Operations might be done after sending the packet... */
compute_dh_shared(st, st->st_gi);
@@ -4831,13 +5057,17 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
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;
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;
}
@@ -4873,12 +5103,16 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
* 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 */
if (!encrypt_message(&md->rbody, st))
+ {
return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
+ }
return STF_OK;
}
@@ -4891,14 +5125,16 @@ 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);
@@ -4914,7 +5150,7 @@ static void dpd_init(struct state *st)
stf_status quick_inR1_outI2(struct msg_digest *md)
{
struct state *const st = md->st;
- const struct connection *c = st->st_connection;
+ const connection_t *c = st->st_connection;
/* HASH(2) in */
CHECK_QUICK_HASH(md
@@ -4937,7 +5173,9 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1"));
if (st->st_pfs_group != NULL)
+ {
compute_dh_shared(st, st->st_gr);
+ }
/* [ IDci, IDcr ] in; these must match what we sent */
@@ -4954,7 +5192,9 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
, &st->st_myuserprotoid, &st->st_myuserport
, &st->st_connection->spd.this.client
, "our client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
+ {
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
+ }
/* IDcr (responder is peer) */
@@ -4962,7 +5202,9 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
, &st->st_peeruserprotoid, &st->st_peeruserport
, &st->st_connection->spd.that.client
, "peer client"))
- return STF_FAIL + INVALID_ID_INFORMATION;
+ {
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
+ }
}
else
{
@@ -4972,35 +5214,40 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
{
loglog(RC_LOG_SERIOUS, "IDci, IDcr payloads missing in message"
" but default does not match proposal");
- return STF_FAIL + INVALID_ID_INFORMATION;
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
}
}
}
/* check the peer's group attributes */
-
{
- const ietfAttrList_t *peer_list = NULL;
-
- get_peer_ca_and_groups(st->st_connection, &peer_list);
+ identification_t *peer_ca = NULL;
+ ietf_attributes_t *peer_attributes = NULL;
+ bool match;
- if (!group_membership(peer_list, st->st_connection->name
- , st->st_connection->spd.that.groups))
+ get_peer_ca_and_groups(st->st_connection, &peer_ca, &peer_attributes);
+ match = match_group_membership(peer_attributes,
+ st->st_connection->name,
+ st->st_connection->spd.that.groups);
+ DESTROY_IF(peer_attributes);
+
+ if (!match)
{
- char buf[BUF_LEN];
+ ietf_attributes_t *groups = st->st_connection->spd.that.groups;
- 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;
+ loglog(RC_LOG_SERIOUS,
+ "peer with attributes '%s' is not a member of the groups '%s'",
+ peer_attributes->get_string(peer_attributes),
+ groups->get_string(groups));
+ return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
}
}
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_NATOA))
- {
- nat_traversal_natoa_lookup(md);
- }
+ 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).
@@ -5029,32 +5276,37 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
* failure won't look like success.
*/
if (!install_ipsec_sa(st, TRUE))
+ {
return STF_INTERNAL_ERROR;
+ }
/* encrypt message, except for fixed part of header */
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)"
+ 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->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();
+ }
/* 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;
}
@@ -5078,17 +5330,17 @@ stf_status quick_inI2(struct msg_digest *md)
* 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)"
+ 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->spd.eroute_owner)
+ )
st->st_connection->newest_ipsec_sa = st->st_serialno;
update_iv(st); /* not actually used, but tidy */
@@ -5098,13 +5350,16 @@ stf_status quick_inI2(struct msg_digest *md)
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;
}
@@ -5117,9 +5372,9 @@ static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
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* */
@@ -5134,7 +5389,9 @@ static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
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);
@@ -5147,22 +5404,32 @@ static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
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_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;
+ {
+ return STF_INTERNAL_ERROR;
+ }
if (!out_raw(st->st_rcookie, COOKIE_SIZE, &notify_pbs, "notify rcookie"))
- return STF_INTERNAL_ERROR;
+ {
+ return STF_INTERNAL_ERROR;
+ }
if (data != NULL && len > 0)
+ {
if (!out_raw(data, len, &notify_pbs, "notify data"))
- return STF_INTERNAL_ERROR;
+ {
+ return STF_INTERNAL_ERROR;
+ }
+ }
close_output_pbs(&notify_pbs);
}
-
+
{
- /* finish computing HASH */
+ /* 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;
@@ -5197,8 +5464,10 @@ static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
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);
@@ -5241,7 +5510,9 @@ void dpd_outI(struct state *p2st)
/* 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);
@@ -5329,7 +5600,7 @@ dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *p
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;
+ return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
}
if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
@@ -5338,7 +5609,7 @@ dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *p
/* 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;
+ return STF_FAIL + ISAKMP_INVALID_COOKIE;
#endif
}
pbs->cur += COOKIE_SIZE;
@@ -5346,7 +5617,7 @@ dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *p
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;
+ return STF_FAIL + ISAKMP_INVALID_COOKIE;
}
pbs->cur += COOKIE_SIZE;
@@ -5354,7 +5625,7 @@ dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *p
{
loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid data length (%d)"
, (int) pbs_left(pbs));
- return STF_FAIL + PAYLOAD_MALFORMED;
+ return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
}
seqno = ntohl(*(u_int32_t *)pbs->cur);
@@ -5403,7 +5674,7 @@ stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
loglog(RC_LOG_SERIOUS
, "DPD: R_U_THERE_ACK has invalid SPI length (%d)"
, n->isan_spisize);
- return STF_FAIL + PAYLOAD_MALFORMED;
+ return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
}
if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
@@ -5412,7 +5683,7 @@ stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
/* Ignore it, cisco sends odd icookies */
#else
loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid icookie");
- return STF_FAIL + INVALID_COOKIE;
+ return STF_FAIL + ISAKMP_INVALID_COOKIE;
#endif
}
pbs->cur += COOKIE_SIZE;
@@ -5423,7 +5694,7 @@ stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
/* Ignore it, cisco sends odd icookies */
#else
loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid rcookie");
- return STF_FAIL + INVALID_COOKIE;
+ return STF_FAIL + ISAKMP_INVALID_COOKIE;
#endif
}
pbs->cur += COOKIE_SIZE;
@@ -5433,7 +5704,7 @@ stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
loglog(RC_LOG_SERIOUS
, " DPD: R_U_THERE_ACK has invalid data length (%d)"
, (int) pbs_left(pbs));
- return STF_FAIL + PAYLOAD_MALFORMED;
+ return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
}
seqno = ntohl(*(u_int32_t *)pbs->cur);
@@ -5447,7 +5718,7 @@ stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
loglog(RC_LOG_SERIOUS
, "DPD: R_U_THERE_ACK has unexpected sequence number %u (expected %u)"
, seqno, st->st_dpd_expectseqno);
- return STF_FAIL + PAYLOAD_MALFORMED;
+ return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
}
st->st_dpd_expectseqno = 0;
@@ -5466,7 +5737,7 @@ void
dpd_timeout(struct state *st)
{
struct state *newest_phase1_st;
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
int action = st->st_connection->dpd_action;
char cname[BUF_LEN];
@@ -5501,14 +5772,18 @@ dpd_timeout(struct state *st)
*/
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,
@@ -5521,7 +5796,9 @@ dpd_timeout(struct state *st)
strncpy(cname, c->name, BUF_LEN);
if (c->kind == CK_INSTANCE)
+ {
delete_connection(c, TRUE);
+ }
initiate_connection(cname, NULL_FD);
break;
default:
diff --git a/src/pluto/ipsec_doi.h b/src/pluto/ipsec_doi.h
index 2e242e903..c11edaa94 100644
--- a/src/pluto/ipsec_doi.h
+++ b/src/pluto/ipsec_doi.h
@@ -12,6 +12,11 @@
* for more details.
*/
+#ifndef _IPSEC_DOI_H
+#define _IPSEC_DOI_H
+
+#include "defs.h"
+
extern void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np);
extern void ipsecdoi_initiate(int whack_sock, struct connection *c
@@ -95,8 +100,9 @@ extern void dpd_timeout(struct state *st);
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; \
+ return STF_FAIL + ISAKMP_INVALID_HASH_INFORMATION; \
} \
}
+#endif /* _IPSEC_DOI_H */
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index 46edac1cd..fe4655d3f 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -45,7 +45,6 @@
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "connections.h"
#include "state.h"
#include "timer.h"
@@ -151,7 +150,7 @@ static void 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,
+static bool shunt_eroute(connection_t *c, struct spd_route *sr,
enum routing_t rt_kind, unsigned int op,
const char *opname);
@@ -347,14 +346,43 @@ ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel)
latest_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;
-
+ }
return htonl((ipsec_spi_t)latest_cpi);
}
+/* Replace the shell metacharacters ', \, ", `, and $ in a character string
+ * by escape sequences consisting of their octal values
+ */
+static void escape_metachar(const char *src, char *dst, size_t dstlen)
+{
+ while (*src != '\0' && dstlen > 4)
+ {
+ 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++;
+ }
+ *dst = '\0';
+}
+
/* invoke the updown script to do the routing and firewall commands required
*
* The user-specified updown script is run. Parameters are fed to it in
@@ -392,7 +420,7 @@ ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel)
# define DEFAULT_UPDOWN "ipsec _updown"
#endif
-static bool do_command(struct connection *c, struct spd_route *sr,
+static bool do_command(connection_t *c, struct spd_route *sr,
const char *verb)
{
char cmd[1536]; /* arbitrary limit on shell command length */
@@ -469,7 +497,7 @@ static bool do_command(struct connection *c, struct spd_route *sr,
}
addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
- idtoa(&sr->this.id, myid_str, sizeof(myid_str));
+ snprintf(myid_str, sizeof(myid_str), "%Y", sr->this.id);
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);
@@ -478,7 +506,7 @@ static bool do_command(struct connection *c, struct spd_route *sr,
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));
+ snprintf(peerid_str, sizeof(peerid_str), "%Y", sr->that.id);
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);
@@ -492,11 +520,19 @@ static bool do_command(struct connection *c, struct spd_route *sr,
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) &&
+ if (type == KEY_RSA &&
+ sr->that.id->equals(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));
+ if (key->issuer)
+ {
+ snprintf(peerca_str, BUF_LEN, "%Y", key->issuer);
+ escape_metachar(peerca_str, secure_peerca_str, BUF_LEN);
+ }
+ else
+ {
+ secure_peerca_str[0] = '\0';
+ }
break;
}
}
@@ -653,10 +689,10 @@ enum routability {
route_farconflict = 3
};
-static enum routability could_route(struct connection *c)
+static enum routability could_route(connection_t *c)
{
struct spd_route *esr, *rosr;
- struct connection *ero /* who, if anyone, owns our eroute? */
+ connection_t *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 */
@@ -710,8 +746,8 @@ static enum routability could_route(struct connection *c)
/* 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;
+ connection_t *ero2, *ero_top;
+ connection_t *inside, *outside;
/*
* note, wavesec (PERMANENT) goes *outside* and
@@ -797,7 +833,7 @@ static enum routability could_route(struct connection *c)
return route_easy;
}
-bool trap_connection(struct connection *c)
+bool trap_connection(connection_t *c)
{
switch (could_route(c))
{
@@ -825,7 +861,7 @@ bool trap_connection(struct connection *c)
/**
* Delete any eroute for a connection and unroute it if route isn't shared
*/
-void unroute_connection(struct connection *c)
+void unroute_connection(connection_t *c)
{
struct spd_route *sr;
enum routing_t cr;
@@ -847,7 +883,9 @@ void unroute_connection(struct connection *c)
/* only unroute if no other connection shares it */
if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL)
+ {
(void) do_command(c, sr, "unroute");
+ }
}
}
@@ -868,7 +906,7 @@ static void set_text_said(char *text_said, const ip_address *dst,
* this allows the entry to be deleted.
*/
static struct bare_shunt** bare_shunt_ptr(const ip_subnet *ours,
- const ip_subnet *his,
+ const ip_subnet *his,
int transport_proto)
{
struct bare_shunt *p, **pp;
@@ -942,8 +980,8 @@ 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,
+ ipsec_spi_t spi,
+ unsigned int proto,
unsigned int satype,
unsigned int transport_proto,
const struct pfkey_proto_info *proto_info,
@@ -1072,8 +1110,9 @@ static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
, "eroute_connection %s", opname);
if (proto == SA_INT)
+ {
peer = aftoinfo(addrtypeof(peer))->any;
-
+ }
return raw_eroute(&sr->this.host_addr, &sr->this.client
, peer
, &sr->that.client
@@ -1083,7 +1122,7 @@ static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
/* assign a bare hold to a connection */
-bool assign_hold(struct connection *c USED_BY_DEBUG, struct spd_route *sr,
+bool assign_hold(connection_t *c USED_BY_DEBUG, struct spd_route *sr,
int transport_proto,
const ip_address *src,
const ip_address *dst)
@@ -1225,7 +1264,7 @@ static bool sag_eroute(struct state *st, struct spd_route *sr,
/* compute a (host-order!) SPI to implement the policy in connection c */
ipsec_spi_t
-shunt_policy_spi(struct connection *c, bool prospective)
+shunt_policy_spi(connection_t *c, bool prospective)
{
/* note: these are in host order :-( */
static const ipsec_spi_t shunt_spi[] =
@@ -1256,7 +1295,7 @@ 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,
+static bool shunt_eroute(connection_t *c, struct spd_route *sr,
enum routing_t rt_kind,
unsigned int op, const char *opname)
{
@@ -1316,7 +1355,7 @@ static bool shunt_eroute(struct connection *c, struct spd_route *sr,
{
/* maybe we are uneclipsing something */
struct spd_route *esr;
- struct connection *ue = eclipsed(c, &esr);
+ connection_t *ue = eclipsed(c, &esr);
if (ue != NULL)
{
@@ -1359,15 +1398,20 @@ static const char *read_proto(const char * s, size_t * len, int * transport_prot
l = *len;
p = memchr(s, ':', l);
- if (p == 0) {
+ 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;
@@ -1429,7 +1473,9 @@ void scan_proc_shunts(void)
f = fopen(procname, "r");
if (f == NULL)
+ {
return;
+ }
/* for each line... */
for (lino = 1; ; lino++)
@@ -1445,7 +1491,9 @@ void scan_proc_shunts(void)
cp = fgets(buf, sizeof(buf), f);
if (cp == NULL)
+ {
break;
+ }
/* break out each field
* Note: if there are too many fields, just stop;
@@ -1461,7 +1509,9 @@ void scan_proc_shunts(void)
field[fi] = chunk_create(cp, w);
cp += w;
if (w == 0)
+ {
break;
+ }
}
/* This odd do-hickey is to share error reporting code.
@@ -1473,9 +1523,13 @@ void scan_proc_shunts(void)
* 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";
@@ -1501,7 +1555,9 @@ void scan_proc_shunts(void)
context = "count field is malformed: ";
ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count);
if (ugh != NULL)
+ {
break;
+ }
}
/* our client */
@@ -1509,21 +1565,27 @@ void scan_proc_shunts(void)
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);
@@ -1666,7 +1728,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
{
/* Build an inbound or outbound SA */
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
ip_subnet src, dst;
ip_subnet src_client, dst_client;
ipsec_spi_t inner_spi = 0;
@@ -1738,9 +1800,13 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
ipip_spi = htonl(++last_tunnel_spi);
if (inbound)
+ {
st->st_tunnel_in_spi = ipip_spi;
+ }
else
+ {
st->st_tunnel_out_spi = ipip_spi;
+ }
}
set_text_said(text_said
@@ -1797,10 +1863,10 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
said_next->text_said = text_said;
if (!kernel_ops->add_sa(said_next, replace))
+ {
goto fail;
-
+ }
said_next++;
-
encapsulation = ENCAPSULATION_MODE_TRANSPORT;
}
@@ -1861,7 +1927,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
if (ei == &esp_info[countof(esp_info)])
{
/* Check for additional kernel alg */
- if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid,
+ if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid,
st->st_esp.attrs.auth))!=NULL)
{
break;
@@ -1873,7 +1939,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
* 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(&esp_transform_names, st->st_esp.attrs.transid)
, enum_name(&auth_alg_names, st->st_esp.attrs.auth));
goto fail;
}
@@ -1892,7 +1958,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
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),
+ enum_name(&esp_transform_names, st->st_esp.attrs.transid),
(int)key_len, (int)ei->enckeylen);
goto fail;
}
@@ -1906,7 +1972,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
{
case ESP_3DES:
/* 168 bits in kernel, need 192 bits for keymat_len */
- if (key_len == 21)
+ if (key_len == 21)
{
key_len = 24;
}
@@ -1914,7 +1980,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
case ESP_DES:
/* 56 bits in kernel, need 64 bits for keymat_len */
if (key_len == 7)
- {
+ {
key_len = 8;
}
break;
@@ -1930,7 +1996,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
key_len += 4;
break;
default:
- break;
+ break;
}
/* divide up keying material */
@@ -2032,7 +2098,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
{
struct pfkey_proto_info proto_info[4];
int i = 0;
-
+
if (st->st_ipcomp.present)
{
proto_info[i].proto = IPPROTO_COMP;
@@ -2040,7 +2106,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
proto_info[i].reqid = c->spd.reqid + 2;
i++;
}
-
+
if (st->st_esp.present)
{
proto_info[i].proto = IPPROTO_ESP;
@@ -2048,7 +2114,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
proto_info[i].reqid = c->spd.reqid + 1;
i++;
}
-
+
if (st->st_ah.present)
{
proto_info[i].proto = IPPROTO_AH;
@@ -2056,9 +2122,9 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
proto_info[i].reqid = c->spd.reqid;
i++;
}
-
+
proto_info[i].proto = 0;
-
+
if (kernel_ops->inbound_eroute
&& encapsulation == ENCAPSULATION_MODE_TUNNEL)
{
@@ -2068,7 +2134,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
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
@@ -2079,11 +2145,11 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
}
/* If there are multiple SPIs, group them. */
-
+
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.
@@ -2095,15 +2161,15 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
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;
@@ -2135,7 +2201,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
* 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;
+ connection_t *c = st->st_connection;
struct {
unsigned proto;
struct ipsec_proto_info *info;
@@ -2227,7 +2293,7 @@ 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;
+ connection_t *c = st->st_connection;
*use_time = UNDEFINED_TIME;
@@ -2353,7 +2419,7 @@ void init_kernel(void)
*/
bool install_inbound_ipsec_sa(struct state *st)
{
- struct connection *const c = st->st_connection;
+ connection_t *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
@@ -2367,7 +2433,7 @@ bool install_inbound_ipsec_sa(struct state *st)
for (;;)
{
struct spd_route *esr;
- struct connection *o = route_owner(c, &esr, NULL, NULL);
+ connection_t *o = route_owner(c, &esr, NULL, NULL);
if (o == NULL)
{
@@ -2417,20 +2483,20 @@ bool 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,
+bool route_and_eroute(connection_t *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? */
+ connection_t *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;
+ connection_t *ero_top;
struct bare_shunt **bspp;
DBG(DBG_CONTROLMORE,
@@ -2438,7 +2504,7 @@ bool route_and_eroute(struct connection *c USED_BY_KLIPS,
, c->name
, (c->policy_next ? c->policy_next->name : "none")
, ero ? ero->name : "null"
- , esr
+ , esr
, ro ? ro->name : "null"
, rosr
, st ? st->st_serialno : 0));
@@ -2472,11 +2538,14 @@ bool route_and_eroute(struct connection *c USED_BY_KLIPS,
/* 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)
@@ -2588,7 +2657,7 @@ bool route_and_eroute(struct connection *c USED_BY_KLIPS,
else if (ero != NULL && ero != c)
{
/* check if ero is an ancestor of c. */
- struct connection *ero2;
+ connection_t *ero2;
for (ero2 = c; ero2 != NULL && ero2 != c; ero2 = ero2->policy_next)
;
@@ -2788,7 +2857,7 @@ void delete_ipsec_sa(struct state *st USED_BY_KLIPS,
/* If the state is the eroute owner, we must adjust
* the routing for the connection.
*/
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
struct spd_route *sr;
passert(st->st_connection);
@@ -2837,9 +2906,9 @@ void delete_ipsec_sa(struct state *st USED_BY_KLIPS,
#ifdef KLIPS
static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
char text_said[SATOT_BUF];
- struct kernel_sa sa;
+ 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;
@@ -2924,7 +2993,7 @@ bool was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time)
ret = *idle_time >= idle_max;
}
}
- else
+ else
{
while (f != NULL)
{
diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c
index 7e7d25872..bf67315e6 100644
--- a/src/pluto/kernel_alg.c
+++ b/src/pluto/kernel_alg.c
@@ -90,7 +90,7 @@ static struct sadb_alg* sadb_alg_ptr (int satype, int exttype, int alg_id,
default:
return NULL;
}
-
+
return alg_p;
}
@@ -154,7 +154,7 @@ bool kernel_alg_esp_enc_ok(u_int alg_id, u_int key_len,
if (!ret) goto out;
alg_p = &esp_ealg[alg_id];
-
+
/*
* test #2: if key_len specified, it must be in range
*/
@@ -195,8 +195,8 @@ out:
return ret;
}
-/*
- * ML: make F_STRICT logic consider enc,auth algorithms
+/*
+ * ML: make F_STRICT logic consider enc,auth algorithms
*/
bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg,
struct alg_info_esp *alg_info)
@@ -237,14 +237,14 @@ bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg,
{
loglog(RC_LOG_SERIOUS
, "You should NOT use insecure ESP algorithms [%s (%d)]!"
- , enum_name(&esp_transformid_names, ealg), key_len);
+ , enum_name(&esp_transform_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(&esp_transform_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;
@@ -252,7 +252,7 @@ bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg,
return TRUE;
}
-/**
+/**
* Load kernel_alg arrays from /proc used in manual mode from klips/utils/spi.c
*/
int kernel_alg_proc_read(void)
@@ -312,7 +312,7 @@ int kernel_alg_proc_read(void)
return 0;
}
-/**
+/**
* 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)
@@ -380,6 +380,7 @@ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen)
)
/* if AES_CBC is registered then also register AES_CCM and AES_GCM */
if (satype == SADB_SATYPE_ESP &&
+ supp_exttype == SADB_EXT_SUPPORTED_ENCRYPT &&
sadb.alg->sadb_alg_id == SADB_X_EALG_AESCBC)
{
struct sadb_alg alg = *sadb.alg;
@@ -395,6 +396,16 @@ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen)
}
}
}
+ /* if SHA2_256 is registered then also register SHA2_256_96 */
+ if (satype == SADB_SATYPE_ESP &&
+ supp_exttype == SADB_EXT_SUPPORTED_AUTH &&
+ sadb.alg->sadb_alg_id == SADB_X_AALG_SHA2_256HMAC)
+ {
+ struct sadb_alg alg = *sadb.alg;
+
+ alg.sadb_alg_id = SADB_X_AALG_SHA2_256_96HMAC;
+ kernel_alg_add(satype, supp_exttype, &alg);
+ }
}
}
}
@@ -422,7 +433,7 @@ u_int kernel_alg_esp_enc_keylen(u_int alg_id)
break;
}
-none:
+none:
DBG(DBG_KLIPS,
DBG_log("kernel_alg_esp_enc_keylen(): alg_id=%d, keylen=%d",
alg_id, keylen)
@@ -461,7 +472,7 @@ void kernel_alg_list(void)
if (ESP_EALG_PRESENT(sadb_id))
{
n = snprintf(pos, len, " %s",
- enum_name(&esp_transformid_names, sadb_id));
+ enum_name(&esp_transform_names, sadb_id));
pos += n;
len -= n;
if (len <= 0)
@@ -471,7 +482,7 @@ void kernel_alg_list(void)
}
}
whack_log(RC_COMMENT, " encryption:%s", buf);
-
+
pos = buf;
*pos = '\0';
len = BUF_LEN;
@@ -493,7 +504,7 @@ void kernel_alg_list(void)
whack_log(RC_COMMENT, " integrity: %s", buf);
}
-void kernel_alg_show_connection(struct connection *c, const char *instance)
+void kernel_alg_show_connection(connection_t *c, const char *instance)
{
struct state *st = state_with_serialno(c->newest_ipsec_sa);
@@ -502,12 +513,12 @@ void kernel_alg_show_connection(struct connection *c, const char *instance)
const char *aalg_name, *pfsgroup_name;
aalg_name = (c->policy & POLICY_AUTHENTICATE) ?
- enum_show(&ah_transformid_names, st->st_ah.attrs.transid):
+ enum_show(&ah_transform_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 && c->alg_info_esp->esp_pfsgroup) ?
+ enum_show(&oakley_group_names,
c->alg_info_esp->esp_pfsgroup) :
"<Phase1>" : "<N/A>";
@@ -516,7 +527,7 @@ void kernel_alg_show_connection(struct connection *c, const char *instance)
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),
+ enum_show(&esp_transform_names, st->st_esp.attrs.transid),
st->st_esp.attrs.key_len, aalg_name, pfsgroup_name);
}
else
@@ -524,7 +535,7 @@ void kernel_alg_show_connection(struct connection *c, const char *instance)
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),
+ enum_show(&esp_transform_names, st->st_esp.attrs.transid),
aalg_name, pfsgroup_name);
}
}
@@ -634,7 +645,7 @@ static bool kernel_alg_db_add(struct db_context *db_ctx,
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 */
esp_info->esp_aalg_id != AUTH_ALGORITHM_NONE)
{
@@ -666,11 +677,11 @@ static bool kernel_alg_db_add(struct db_context *db_ctx,
{
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
*
@@ -694,12 +705,6 @@ struct db_context* kernel_alg_db_new(struct alg_info_esp *alg_info,
/* pass aprox. number of transforms and attributes */
ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2);
- /*
- * 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 ...
- */
-
if (alg_info)
{
int i;
@@ -710,28 +715,6 @@ struct db_context* kernel_alg_db_new(struct alg_info_esp *alg_info,
kernel_alg_db_add(ctx_new, &tmp_esp_info, policy);
}
}
- else
- {
- u_int ealg_id;
-
- ESP_EALG_FOR_EACH_UPDOWN(ealg_id)
- {
- 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);
return ctx_new;
}
diff --git a/src/pluto/kernel_netlink.c b/src/pluto/kernel_netlink.c
index 0376e817b..289714b50 100644
--- a/src/pluto/kernel_netlink.c
+++ b/src/pluto/kernel_netlink.c
@@ -40,6 +40,11 @@
#include "whack.h" /* for RC_LOG_SERIOUS */
#include "kernel_alg.h"
+/** required for Linux 2.6.26 kernel and later */
+#ifndef XFRM_STATE_AF_UNSPEC
+#define XFRM_STATE_AF_UNSPEC 32
+#endif
+
/* Minimum priority number in SPD used by pluto. */
#define MIN_SPD_PRIORITY 1024
@@ -80,15 +85,15 @@ static sparse_names xfrm_type_names = {
/* 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" },
+ { SADB_X_AALG_NULL, "digest_null" },
+ { SADB_AALG_MD5HMAC, "md5" },
+ { SADB_AALG_SHA1HMAC, "sha1" },
+ { SADB_X_AALG_SHA2_256_96HMAC, "sha256" },
+ { SADB_X_AALG_SHA2_256HMAC, "hmac(sha256)" },
+ { SADB_X_AALG_SHA2_384HMAC, "hmac(sha384)" },
+ { SADB_X_AALG_SHA2_512HMAC, "hmac(sha512)" },
+ { SADB_X_AALG_RIPEMD160HMAC, "ripemd160" },
+ { SADB_X_AALG_AES_XCBC_MAC, "xcbc(aes)"},
{ 0, sparse_end }
};
@@ -183,7 +188,7 @@ static void init_netlink(void)
* @param hdr - Data to be sent.
* @param rbuf - Return Buffer - contains data returned from the send.
* @param rbuf_len - Length of rbuf
- * @param description - String - user friendly description of what is
+ * @param description - String - user friendly description of what is
* being attempted. Used for diagnostics
* @param text_said - String
* @return bool True if the message was succesfully sent.
@@ -343,6 +348,7 @@ static bool netlink_policy(struct nlmsghdr *hdr, bool enoent_ok,
struct {
struct nlmsghdr n;
struct nlmsgerr e;
+ char data[1024];
} rsp;
int error;
@@ -382,7 +388,7 @@ static bool netlink_policy(struct nlmsghdr *hdr, bool enoent_ok,
* @param proto int (Currently unused) Contains protocol (u=tcp, 17=udp, etc...)
* @param transport_proto int (Currently unused) 0=tunnel, 1=transport
* @param satype int
- * @param proto_info
+ * @param proto_info
* @param lifetime (Currently unused)
* @param ip int
* @return boolean True if successful
@@ -518,9 +524,9 @@ static bool netlink_raw_eroute(const ip_address *this_host
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].family = that_host->u.v4.sin_family;
tmpl[i].mode =
proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;
-
if (!tmpl[i].mode)
{
continue;
@@ -590,7 +596,7 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
char data[1024];
} req;
struct rtattr *attr;
- u_int16_t icv_size = 64;
+ u_int16_t icv_size = 64;
memset(&req, 0, sizeof(req));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -602,7 +608,15 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
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);
+ if (sa->encapsulation == ENCAPSULATION_MODE_TUNNEL)
+ {
+ req.p.mode = XFRM_MODE_TUNNEL;
+ req.p.flags |= XFRM_STATE_AF_UNSPEC;
+ }
+ else
+ {
+ req.p.mode = XFRM_MODE_TRANSPORT;
+ }
req.p.replay_window = sa->replay_window;
req.p.reqid = sa->reqid;
req.p.lft.soft_byte_limit = XFRM_INF;
@@ -616,7 +630,6 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
if (sa->authalg)
{
- struct xfrm_algo algo;
const char *name;
name = sparse_name(aalg_list, sa->authalg);
@@ -632,16 +645,37 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
sa->authkeylen * BITS_PER_BYTE)
)
- strcpy(algo.alg_name, name);
- algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE;
+ if (sa->authalg == SADB_X_AALG_SHA2_256HMAC)
+ {
+ struct xfrm_algo_auth algo;
- attr->rta_type = XFRMA_ALG_AUTH;
- attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen);
+ /* the kernel uses SHA256 with 96 bit truncation by default,
+ * use specified truncation size supported by newer kernels */
+ strcpy(algo.alg_name, name);
+ algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE;
+ algo.alg_trunc_len = 128;
- memcpy(RTA_DATA(attr), &algo, sizeof(algo));
- memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->authkey
- , sa->authkeylen);
+ attr->rta_type = XFRMA_ALG_AUTH_TRUNC;
+ 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);
+ }
+ else
+ {
+ struct xfrm_algo algo;
+
+ 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);
}
@@ -674,19 +708,19 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
}
DBG(DBG_CRYPT,
DBG_log("configured esp encryption algorithm %s with key size %d",
- enum_show(&esp_transformid_names, sa->encalg),
+ enum_show(&esp_transform_names, sa->encalg),
sa->enckeylen * BITS_PER_BYTE)
)
attr->rta_type = XFRMA_ALG_AEAD;
attr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + sa->enckeylen);
req.n.nlmsg_len += attr->rta_len;
-
+
algo = (struct xfrm_algo_aead*)RTA_DATA(attr);
algo->alg_key_len = sa->enckeylen * BITS_PER_BYTE;
algo->alg_icv_len = icv_size;
strcpy(algo->alg_name, name);
memcpy(algo->alg_key, sa->enckey, sa->enckeylen);
-
+
attr = (struct rtattr *)((char *)attr + attr->rta_len);
break;
}
@@ -704,7 +738,7 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
}
DBG(DBG_CRYPT,
DBG_log("configured esp encryption algorithm %s with key size %d",
- enum_show(&esp_transformid_names, sa->encalg),
+ enum_show(&esp_transform_names, sa->encalg),
sa->enckeylen * BITS_PER_BYTE)
)
attr->rta_type = XFRMA_ALG_CRYPT;
@@ -962,7 +996,7 @@ static void linux_pfkey_register(void)
/** Create ip_address out of xfrm_address_t.
*
- * @param family
+ * @param family
* @param src xfrm formatted IP address
* @param dst ip_address formatted destination
* @return err_t NULL if okay, otherwise an error
@@ -1001,7 +1035,7 @@ static err_t xfrm_sel_to_ip_pair(const struct xfrm_selector *sel,
if ((ugh = xfrm_to_ip_address(family, &sel->saddr, src))
|| (ugh = xfrm_to_ip_address(family, &sel->daddr, dst)))
- {
+ {
return ugh;
}
diff --git a/src/pluto/kernel_noklips.c b/src/pluto/kernel_noklips.c
index 82a6ab648..e99efe062 100644
--- a/src/pluto/kernel_noklips.c
+++ b/src/pluto/kernel_noklips.c
@@ -107,7 +107,7 @@ 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,
diff --git a/src/pluto/kernel_pfkey.c b/src/pluto/kernel_pfkey.c
index 7ac405fd4..99ba4ff30 100644
--- a/src/pluto/kernel_pfkey.c
+++ b/src/pluto/kernel_pfkey.c
@@ -73,7 +73,7 @@ static sparse_names pfkey_type_names = {
NE(SADB_X_DELFLOW),
NE(SADB_X_DEBUG),
NE(SADB_X_NAT_T_NEW_MAPPING),
- NE(SADB_MAX),
+ NE(SADB_MAX),
{ 0, sparse_end }
};
@@ -531,7 +531,7 @@ pfkeyext_protocol(int transport_proto
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
- return (transport_proto == 0)? TRUE
+ return (transport_proto == 0)? TRUE
: pfkey_build(
pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL, transport_proto)
, description, text_said, extensions);
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index 516872e8e..8cf28ace1 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -36,12 +36,11 @@
#include <library.h>
#include <asn1/asn1.h>
+#include <credentials/certificates/pgp_certificate.h>
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "x509.h"
-#include "pgpcert.h"
#include "certs.h"
#include "smartcard.h"
#include "connections.h"
@@ -61,7 +60,7 @@ const char *shared_secrets_file = SHARED_SECRETS_FILE;
typedef struct id_list id_list_t;
struct id_list {
- struct id id;
+ identification_t *id;
id_list_t *next;
};
@@ -84,9 +83,9 @@ struct secret {
*/
static void free_public_key(pubkey_t *pk)
{
+ DESTROY_IF(pk->id);
DESTROY_IF(pk->public_key);
- free_id_content(&pk->id);
- free(pk->issuer.ptr);
+ DESTROY_IF(pk->issuer);
free(pk->serial.ptr);
free(pk);
}
@@ -97,7 +96,7 @@ 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,
+static const secret_t* get_secret(const connection_t *c,
enum PrivateKeyKind kind, bool asym)
{
enum { /* bits */
@@ -109,14 +108,14 @@ static const secret_t* get_secret(const struct connection *c,
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;
+ identification_t *my_id, *his_id;
/* is there a certificate assigned to this connection? */
- if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
+ if (kind == PPK_PUBKEY && c->spd.this.cert)
{
- public_key_t *pub_key = cert_get_public_key(c->spd.this.cert);
+ certificate_t *certificate = c->spd.this.cert->cert;
+
+ public_key_t *pub_key = certificate->get_public_key(certificate);
for (s = secrets; s != NULL; s = s->next)
{
@@ -127,26 +126,28 @@ static const secret_t* get_secret(const struct connection *c,
break; /* we have found the private key - no sense in searching further */
}
}
+ pub_key->destroy(pub_key);
return best;
}
+ my_id = c->spd.this.id;
+
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;
+ his_id = identification_create_from_string("%any");
}
- 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))))
+ else if (kind == PPK_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) &&
+ ((c->kind == CK_TEMPLATE &&
+ c->spd.that.id->get_type(c->spd.that.id) == 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;
+ his_id = identification_create_from_string("%any");
+ }
+ else
+ {
+ his_id = c->spd.that.id->clone(c->spd.that.id);
}
for (s = secrets; s != NULL; s = s->next)
@@ -169,11 +170,11 @@ static const secret_t* get_secret(const struct connection *c,
for (i = s->ids; i != NULL; i = i->next)
{
- if (same_id(my_id, &i->id))
+ if (my_id->equals(my_id, i->id))
{
match |= match_me;
}
- if (same_id(his_id, &i->id))
+ if (his_id->equals(his_id, i->id))
{
match |= match_him;
}
@@ -239,6 +240,7 @@ static const secret_t* get_secret(const struct connection *c,
}
}
}
+ his_id->destroy(his_id);
return best;
}
@@ -246,7 +248,7 @@ static const secret_t* get_secret(const struct connection *c,
* 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 connection_t *c)
{
const secret_t *s = get_secret(c, PPK_PSK, FALSE);
@@ -262,11 +264,11 @@ const chunk_t* get_preshared_secret(const struct connection *c)
/* 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;
- public_key_t *pub_key = cert_get_public_key(cert);
+ public_key_t *pub_key = cert->cert->get_public_key(cert->cert);
for (s = secrets; s != NULL; s = s->next)
{
@@ -277,31 +279,37 @@ bool has_private_key(cert_t cert)
break;
}
}
+ pub_key->destroy(pub_key);
return has_key;
}
/*
* get the matching private key belonging to a given X.509 certificate
*/
-private_key_t* get_x509_private_key(const x509cert_t *cert)
+private_key_t* get_x509_private_key(const cert_t *cert)
{
+ public_key_t *public_key = cert->cert->get_public_key(cert->cert);
+ private_key_t *private_key = NULL;
secret_t *s;
for (s = secrets; s != NULL; s = s->next)
{
+
if (s->kind == PPK_PUBKEY &&
- s->u.private_key->belongs_to(s->u.private_key, cert->public_key))
+ s->u.private_key->belongs_to(s->u.private_key, public_key))
{
- return s->u.private_key;
+ private_key = s->u.private_key;
+ break;
}
}
- return NULL;
+ public_key->destroy(public_key);
+ return private_key;
}
/* find the appropriate private key (see get_secret).
* Failure is indicated by a NULL pointer.
*/
-private_key_t* get_private_key(const struct connection *c)
+private_key_t* get_private_key(const connection_t *c)
{
const secret_t *s = get_secret(c, PPK_PUBKEY, TRUE);
@@ -392,7 +400,7 @@ enum rsa_private_key_part_t {
RSA_PART_EXPONENT1 = 5,
RSA_PART_EXPONENT2 = 6,
RSA_PART_COEFFICIENT = 7
-};
+};
const char *rsa_private_key_part_names[] = {
"Modulus",
@@ -408,20 +416,17 @@ const char *rsa_private_key_part_names[] = {
/**
* 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(private_key_t **key)
{
- chunk_t asn1_chunk[countof(rsa_private_key_part_names)];
- chunk_t pkcs1_chunk;
+ chunk_t rsa_chunk[countof(rsa_private_key_part_names)];
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;
+ size_t sz;
err_t ugh;
for (part = RSA_PART_MODULUS; part <= RSA_PART_COEFFICIENT; part++)
{
- chunk_t rsa_private_key_part;
const char *keyword = rsa_private_key_part_names[part];
if (!shift())
@@ -448,9 +453,8 @@ static err_t process_rsa_secret(private_key_t **key)
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;
+ rsa_chunk[part] = chunk_create(buf, sz);
+ rsa_chunk[part] = chunk_clone(rsa_chunk[part]);
}
/* We require an (indented) '}' and the end of the record.
@@ -468,21 +472,17 @@ static err_t process_rsa_secret(private_key_t **key)
goto end;
}
- 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);
+ BUILD_RSA_MODULUS, rsa_chunk[RSA_PART_MODULUS],
+ BUILD_RSA_PUB_EXP, rsa_chunk[RSA_PART_PUBLIC_EXPONENT],
+ BUILD_RSA_PRIV_EXP, rsa_chunk[RSA_PART_PRIVATE_EXPONENT],
+ BUILD_RSA_PRIME1, rsa_chunk[RSA_PART_PRIME1],
+ BUILD_RSA_PRIME2, rsa_chunk[RSA_PART_PRIME2],
+ BUILD_RSA_EXP1, rsa_chunk[RSA_PART_EXPONENT1],
+ BUILD_RSA_EXP2, rsa_chunk[RSA_PART_EXPONENT2],
+ BUILD_RSA_COEFF, rsa_chunk[RSA_PART_COEFFICIENT],
+ BUILD_END);
+
if (*key == NULL)
{
ugh = "parsing of RSA private key failed";
@@ -492,9 +492,9 @@ end:
/* clean up and return */
for (p = RSA_PART_MODULUS ; p < part; p++)
{
- free(asn1_chunk[p].ptr);
+ chunk_clear(&rsa_chunk[p]);
}
- return ugh;
+ return ugh;
}
/**
@@ -722,7 +722,7 @@ static err_t process_pin(secret_t *s, int whackfd)
}
}
else
- {
+ {
/* we read the pin directly from ipsec.secrets */
err_t ugh = process_psk_secret(&sc->pin);
if (ugh != NULL)
@@ -762,16 +762,12 @@ static void log_psk(secret_t *s)
{
do
{
- n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
+ n += snprintf(buf + n, BUF_LEN - n, "%Y ", id_list->id);
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);
@@ -948,42 +944,12 @@ static void process_secret_records(int whackfd)
/* an id
* See RFC2407 IPsec Domain of Interpretation 4.6.2
*/
- struct id id;
- err_t ugh;
+ id_list_t *i = malloc_thing(id_list_t);
- 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);
- }
+ i->id = identification_create_from_string(tok);
+ i->next = s->ids;
+ s->ids = i;
- 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 */
@@ -1071,11 +1037,11 @@ void free_preshared_secrets(void)
{
id_list_t *i, *ni;
- ns = s->next; /* grab before freeing s */
+ ns = s->next;
for (i = s->ids; i != NULL; i = ni)
{
- ni = i->next; /* grab before freeing i */
- free_id_content(&i->id);
+ ni = i->next;
+ i->id->destroy(i->id);
free(i);
}
switch (s->kind)
@@ -1119,8 +1085,8 @@ pubkey_t* public_key_from_rsa(public_key_t *key)
pubkey_t *p = malloc_thing(pubkey_t);
zero(p);
- p->id = empty_id; /* don't know, doesn't matter */
- p->issuer = chunk_empty;
+ p->id = identification_create_from_string("%any"); /* don't know, doesn't matter */
+ p->issuer = NULL;
p->serial = chunk_empty;
p->public_key = key;
@@ -1128,7 +1094,6 @@ pubkey_t* public_key_from_rsa(public_key_t *key)
* invariant: recount > 0.
*/
p->refcnt = 1;
- time(&p->installed_time);
return p;
}
@@ -1207,25 +1172,14 @@ static void install_public_key(pubkey_t *pk, pubkey_list_t **head)
{
pubkey_list_t *p = malloc_thing(pubkey_list_t);
- unshare_id_content(&pk->id);
-
- /* copy issuer dn */
- pk->issuer = chunk_clone(pk->issuer);
-
- /* copy serial number */
- pk->serial = chunk_clone(pk->serial);
-
- /* 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;
}
-void delete_public_keys(const struct id *id, key_type_t type,
- chunk_t issuer, chunk_t serial)
+void delete_public_keys(identification_t *id, key_type_t type,
+ identification_t *issuer, chunk_t serial)
{
pubkey_list_t **pp, *p;
pubkey_t *pk;
@@ -1236,10 +1190,10 @@ void delete_public_keys(const struct id *id, key_type_t type,
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))
+ if (id->equals(id, pk->id) && pk_type == type
+ && (issuer == NULL || pk->issuer == NULL
+ || issuer->equals(issuer, pk->issuer))
+ && (serial.ptr == NULL || chunk_equals(serial, pk->serial)))
{
*pp = free_public_keyentry(p);
}
@@ -1252,25 +1206,26 @@ void delete_public_keys(const struct id *id, key_type_t type,
pubkey_t* reference_key(pubkey_t *pk)
{
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" ref key: %p %p cnt %d '%Y'",
+ pk, pk->public_key, pk->refcnt, pk->id)
+ )
pk->refcnt++;
return pk;
}
-void
-unreference_key(pubkey_t **pkp)
+void unreference_key(pubkey_t **pkp)
{
pubkey_t *pk = *pkp;
- char b[BUF_LEN];
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)
+ DBG_log("unref key: %p %p cnt %d '%Y'",
+ pk, pk->public_key, pk->refcnt, pk->id)
)
/* cancel out the pointer */
@@ -1284,7 +1239,7 @@ unreference_key(pubkey_t **pkp)
}
}
-bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
+bool add_public_key(identification_t *id, enum dns_auth_level dns_auth_level,
enum pubkey_alg alg, chunk_t rfc3110_key,
pubkey_list_t **head)
{
@@ -1296,7 +1251,7 @@ bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
{
case PUBKEY_ALG_RSA:
key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
- BUILD_BLOB_RFC_3110, rfc3110_key,
+ BUILD_BLOB_DNSKEY, rfc3110_key,
BUILD_END);
if (key == NULL)
{
@@ -1310,90 +1265,97 @@ bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
pk = malloc_thing(pubkey_t);
zero(pk);
pk->public_key = key;
- pk->id = *id;
+ pk->id = id->clone(id);
pk->dns_auth_level = dns_auth_level;
pk->until_time = UNDEFINED_TIME;
- pk->issuer = chunk_empty;
+ pk->issuer = NULL;
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
+/**
+ * Extract id and public key a 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_public_key_from_cert(cert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
- generalName_t *gn;
+ certificate_t *certificate = cert->cert;
+ identification_t *subject = certificate->get_subject(certificate);
+ identification_t *issuer = NULL;
+ identification_t *id;
+ chunk_t serialNumber = chunk_empty;
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->public_key = certificate->get_public_key(certificate);
+ pk_type = pk->public_key->get_type(pk->public_key);
+ pk->id = subject->clone(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);
+ if (certificate->get_type(certificate) == CERT_X509)
+ {
+ x509_t *x509 = (x509_t*)certificate;
- gn = cert->subjectAltName;
+ issuer = certificate->get_issuer(certificate);
+ serialNumber = x509->get_serial(x509);
+ pk->issuer = issuer->clone(issuer);
+ pk->serial = chunk_clone(serialNumber);
+ }
+ delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
- while (gn != NULL) /* insert all subjectAltNames */
+ if (certificate->get_type(certificate) == CERT_X509)
{
- struct id id = empty_id;
+ x509_t *x509 = (x509_t*)certificate;
+ enumerator_t *enumerator;
- gntoid(&id, gn);
- if (id.kind != ID_ANY)
+ /* insert all subjectAltNames from X.509 certificates */
+ enumerator = x509->create_subjectAltName_enumerator(x509);
+ while (enumerator->enumerate(enumerator, &id))
{
- 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);
+ if (id->get_type(id) != ID_ANY)
+ {
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->id = id->clone(id);
+ pk->public_key = certificate->get_public_key(certificate);
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ pk->issuer = issuer->clone(issuer);
+ pk->serial = chunk_clone(serialNumber);
+ delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
+ }
}
- gn = gn->next;
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
+ chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
+
+ /* add v3 or v4 PGP fingerprint */
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->id = identification_create_from_encoding(ID_KEY_ID, fingerprint);
+ pk->public_key = certificate->get_public_key(certificate);
+ pk->dns_auth_level = dns_auth_level;
+ pk->until_time = until;
+ delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
+ install_public_key(pk, &pubkeys);
}
-}
-
-/* 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)
-{
- 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 cert_t *cert)
{
- public_key_t *revoked_key = cert->public_key;
+ public_key_t *revoked_key = cert->cert->get_public_key(cert->cert);
pubkey_list_t *p, **pp;
p = pubkeys;
@@ -1413,6 +1375,7 @@ void remove_x509_public_key(const x509cert_t *cert)
}
p =*pp;
}
+ revoked_key->destroy(revoked_key);
}
/*
@@ -1426,34 +1389,32 @@ void list_public_keys(bool utc)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of Public Keys:");
- whack_log(RC_COMMENT, " ");
}
while (p != NULL)
{
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];
+ chunk_t keyid;
- 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",
+ whack_log(RC_COMMENT, " ");
+ whack_log(RC_COMMENT, " identity: '%Y'", key->id);
+ 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)
+ if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ {
+ whack_log(RC_COMMENT," keyid: %#B", &keyid);
+ }
+ if (key->issuer)
{
- dntoa(buf, BUF_LEN, key->issuer);
- whack_log(RC_COMMENT," issuer: '%s'", buf);
+ whack_log(RC_COMMENT," issuer: \"%Y\"", key->issuer);
}
- if (key->serial.len > 0)
+ if (key->serial.len)
{
- datatot(key->serial.ptr, key->serial.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT," serial: %s", buf);
+ whack_log(RC_COMMENT," serial: %#B", &key->serial);
}
p = p->next;
}
diff --git a/src/pluto/keys.h b/src/pluto/keys.h
index 8bc94d839..d856c0009 100644
--- a/src/pluto/keys.h
+++ b/src/pluto/keys.h
@@ -16,6 +16,7 @@
#ifndef _KEYS_H
#define _KEYS_H
+#include <utils/identification.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
@@ -44,22 +45,19 @@ struct connection;
extern const chunk_t *get_preshared_secret(const struct connection *c);
extern private_key_t *get_private_key(const struct connection *c);
-extern private_key_t *get_x509_private_key(const x509cert_t *cert);
+extern private_key_t *get_x509_private_key(const cert_t *cert);
/* public key machinery */
typedef struct pubkey pubkey_t;
struct pubkey {
- struct id id;
+ identification_t *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;
+ time_t last_tried_time, last_worked_time, until_time;
+ identification_t *issuer;
chunk_t serial;
public_key_t *public_key;
};
@@ -77,23 +75,19 @@ 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, key_type_t type,
- chunk_t issuer, chunk_t serial);
+extern void delete_public_keys(identification_t *id, key_type_t type,
+ identification_t *issuer, chunk_t serial);
extern pubkey_t *reference_key(pubkey_t *pk);
extern void unreference_key(pubkey_t **pkp);
-
-extern bool add_public_key(const struct id *id,
+extern bool add_public_key(identification_t *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);
-extern void add_pgp_public_key(pgpcert_t *cert, time_t until
- , enum dns_auth_level dns_auth_level);
-extern void remove_x509_public_key(const x509cert_t *cert);
+extern bool has_private_key(cert_t *cert);
+extern void add_public_key_from_cert(cert_t *cert, time_t until,
+ enum dns_auth_level dns_auth_level);
+extern void remove_x509_public_key(const cert_t *cert);
extern void list_public_keys(bool utc);
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
diff --git a/src/pluto/log.c b/src/pluto/log.c
index e34409f1c..2f3536ff3 100644
--- a/src/pluto/log.c
+++ b/src/pluto/log.c
@@ -38,12 +38,13 @@
#include "server.h"
#include "state.h"
#include "connections.h"
+#include "myid.h"
#include "kernel.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(connection_t *c); /* forward */
bool
@@ -77,7 +78,7 @@ static TAILQ_HEAD(perpeer, connection) perpeer_list;
*/
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 */
+connection_t *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 */
@@ -99,12 +100,12 @@ static void pluto_dbg(int level, char *fmt, ...)
else if (cur_debugging & DBG_RAW)
{
debug_level = 3;
- }
+ }
else if (cur_debugging & DBG_PARSING)
{
debug_level = 2;
}
- else
+ else
{
debug_level = 1;
}
@@ -245,7 +246,7 @@ 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
+ connection_t *c = cur_state != NULL ? cur_state->st_connection
: cur_connection;
buf[0] = '\0';
@@ -293,7 +294,7 @@ fmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap)
}
static void
-perpeer_logclose(struct connection *c)
+perpeer_logclose(connection_t *c)
{
/* only free/close things if we had used them! */
if (c->log_file != NULL)
@@ -308,7 +309,7 @@ perpeer_logclose(struct connection *c)
}
void
-perpeer_logfree(struct connection *c)
+perpeer_logfree(connection_t *c)
{
perpeer_logclose(c);
if (c->log_file_name != NULL)
@@ -321,7 +322,7 @@ perpeer_logfree(struct connection *c)
/* open the per-peer log */
static void
-open_peerlog(struct connection *c)
+open_peerlog(connection_t *c)
{
syslog(LOG_INFO, "opening log file for conn %s", c->name);
@@ -725,7 +726,7 @@ lset_t
cur_debugging = DBG_NONE;
void
-extra_debugging(const struct connection *c)
+extra_debugging(const connection_t *c)
{
if(c == NULL)
{
@@ -835,8 +836,8 @@ static void show_loaded_plugins()
char buf[BUF_LEN], *plugin;
int len = 0;
enumerator_t *enumerator;
-
- buf[0] = '\0';
+
+ buf[0] = '\0';
enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
while (len < BUF_LEN && enumerator->enumerate(enumerator, &plugin))
{
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
index 228827f2a..03ec7f41f 100644
--- a/src/pluto/modecfg.c
+++ b/src/pluto/modecfg.c
@@ -26,6 +26,7 @@
#include <freeswan.h>
#include <library.h>
+#include <attributes/attributes.h>
#include <crypto/prfs/prf.h>
#include "constants.h"
@@ -81,11 +82,10 @@ struct internal_addr
bool xauth_status;
};
-/*
+/**
* Initialize an internal_addr struct
*/
-static void
-init_internal_addr(internal_addr_t *ia)
+static void init_internal_addr(internal_addr_t *ia)
{
int i;
@@ -106,46 +106,65 @@ init_internal_addr(internal_addr_t *ia)
anyaddr(AF_INET, &ia->dns[i]);
}
- /* initialize WINS server information */
+ /* initialize NBNS server information */
for (i = 0; i < NBNS_SERVER_MAX; i++)
{
anyaddr(AF_INET, &ia->nbns[i]);
}
}
-/*
- * get internal IP address for a connection
+/**
+ * Get internal IP address for a connection
*/
-static void
-get_internal_addr(struct connection *c, internal_addr_t *ia)
+static void get_internal_addr(connection_t *c, host_t *requested_vip,
+ internal_addr_t *ia)
{
int i, dns_idx = 0, nbns_idx = 0;
+ enumerator_t *enumerator;
+ configuration_attribute_type_t type;
+ chunk_t value;
+ host_t *vip = NULL;
if (isanyaddr(&c->spd.that.host_srcip))
{
- /* not defined in connection - fetch it from LDAP */
+ if (c->spd.that.pool)
+ {
+ vip = lib->attributes->acquire_address(lib->attributes,
+ c->spd.that.pool, c->spd.that.id,
+ requested_vip);
+ if (vip)
+ {
+ chunk_t addr = vip->get_address(vip);
+
+ plog("assigning virtual IP %H to peer", vip);
+ initaddr(addr.ptr, addr.len, vip->get_family(vip), &ia->ipaddr);
+
+ }
+ }
+ else
+ {
+ plog("no virtual IP found");
+ }
}
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);
+ vip = host_create_from_sockaddr((sockaddr_t*)&ia->ipaddr);
+ plog("assigning virtual IP %H to peer", vip);
}
if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
{
+ c->spd.that.host_srcip = ia->ipaddr;
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 */
+ /* assign DNS servers from strongswan.conf */
for (i = 1; i <= DNS_SERVER_MAX; i++)
{
char dns_key[16], *dns_str;
@@ -158,20 +177,20 @@ get_internal_addr(struct connection *c, internal_addr_t *ia)
sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET;
ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]);
- if (ugh != NULL)
+ if (ugh)
{
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() */
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
dns_idx++;
}
}
- /* assign WINS servers */
+ /* assign NBNS servers from strongswan.conf */
for (i = 1; i <= NBNS_SERVER_MAX; i++)
{
char nbns_key[16], *nbns_str;
@@ -184,26 +203,93 @@ get_internal_addr(struct connection *c, internal_addr_t *ia)
sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET;
ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]);
- if (ugh != NULL)
+ if (ugh)
{
- plog("error in WINS server address: %s", ugh);
+ plog("error in NBNS server address: %s", ugh);
continue;
}
plog("assigning NBNS server %s to peer", nbns_str);
- /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
nbns_idx++;
}
}
+
+ /* assign attributes from registered providers */
+ enumerator = lib->attributes->create_responder_enumerator(lib->attributes,
+ c->spd.that.id, vip);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ err_t ugh;
+ host_t *server;
+ sa_family_t family = AF_INET;
+
+ switch (type)
+ {
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ /* fallthrough */
+ case INTERNAL_IP4_DNS:
+ if (dns_idx >= DNS_SERVER_MAX)
+ {
+ plog("exceeded the maximum number of %d DNS servers",
+ DNS_SERVER_MAX);
+ break;
+ }
+ ugh = initaddr(value.ptr, value.len, family, &ia->dns[dns_idx]);
+ if (ugh)
+ {
+ plog("error in DNS server address: %s", ugh);
+ break;
+ }
+ server = host_create_from_chunk(family, value, 0);
+ plog("assigning DNS server %H to peer", server);
+ server->destroy(server);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
+ dns_idx++;
+ break;
+
+ case INTERNAL_IP6_NBNS:
+ family = AF_INET6;
+ /* fallthrough */
+ case INTERNAL_IP4_NBNS:
+ if (nbns_idx >= NBNS_SERVER_MAX)
+ {
+ plog("exceeded the maximum number of %d NBNS servers",
+ NBNS_SERVER_MAX);
+ break;
+ }
+ ugh = initaddr(value.ptr, value.len, family, &ia->nbns[nbns_idx]);
+ if (ugh)
+ {
+ plog("error in NBNS server address: %s", ugh);
+ break;
+ }
+ server = host_create_from_chunk(family, value, 0);
+ plog("assigning NBNS server %H to peer", server);
+ server->destroy(server);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ nbns_idx++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ DESTROY_IF(vip);
}
-/*
+/**
* Set srcip and client subnet to internal IP address
*/
-static bool
-set_internal_addr(struct connection *c, internal_addr_t *ia)
+static bool set_internal_addr(connection_t *c, internal_addr_t *ia)
{
if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
&& !isanyaddr(&ia->ipaddr))
@@ -227,7 +313,7 @@ set_internal_addr(struct connection *c, internal_addr_t *ia)
plog("replacing virtual IP source address %s by %s"
, old_srcip, new_srcip);
}
-
+
/* setting srcip */
c->spd.this.host_srcip = ia->ipaddr;
@@ -240,7 +326,7 @@ set_internal_addr(struct connection *c, internal_addr_t *ia)
return FALSE;
}
-/*
+/**
* Compute HASH of Mode Config.
*/
static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
@@ -263,19 +349,18 @@ static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
DBG(DBG_CRYPT,
DBG_log("ModeCfg HASH computed:");
DBG_dump("", dest, prf_block_size)
- )
+ )
return prf_block_size;
}
-/*
+/**
* Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS)
*/
-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)
+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_char *r_hash_start, *r_hashval;
@@ -322,7 +407,7 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
is_unity_attr_set = FALSE;
}
}
-
+
dont_advance = FALSE;
if (attr_set & 1)
@@ -384,7 +469,7 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
mask[t] = 0xff;
m -= 8;
}
-#endif
+#endif
if (st->st_connection->spd.this.client.maskbits == 0)
{
mask = 0;
@@ -491,11 +576,11 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
return STF_OK;
}
-/*
+/**
* Send ModeCfg message
*/
-static stf_status
-modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
+static stf_status modecfg_send_msg(struct state *st, int isama_type,
+ internal_addr_t *ia)
{
pb_stream msg;
pb_stream rbody;
@@ -549,11 +634,10 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
return STF_OK;
}
-/*
+/**
* Parse a ModeCfg attribute payload
*/
-static stf_status
-modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
+static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
{
struct isakmp_attribute attr;
pb_stream strattr;
@@ -610,12 +694,12 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]);
if (ugh != NULL)
{
- plog("received invalid IPv4 WINS server address: %s", ugh);
+ plog("received invalid IPv4 NBNS server address: %s", ugh);
}
else
{
addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN);
- plog("received IPv4 WINS server address %s", buf);
+ plog("received IPv4 NBNS server address %s", buf);
nbns_idx++;
}
}
@@ -644,12 +728,12 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]);
if (ugh != NULL)
{
- plog("received invalid IPv6 WINS server address: %s", ugh);
+ plog("received invalid IPv6 NBNS server address: %s", ugh);
}
else
{
addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN);
- plog("received IPv6 WINS server address %s", buf);
+ plog("received IPv6 NBNS server address %s", buf);
nbns_idx++;
}
}
@@ -735,12 +819,11 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
return STF_OK;
}
-/*
+/**
* Parse a ModeCfg message
*/
-static stf_status
-modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
- , 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)
{
struct state *const st = md->st;
struct payload_digest *p;
@@ -788,12 +871,12 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
return STF_IGNORE;
}
-/*
+/**
* Send ModeCfg request message from client to server in pull mode
*/
-stf_status
-modecfg_send_request(struct state *st)
+stf_status modecfg_send_request(struct state *st)
{
+ connection_t *c = st->st_connection;
stf_status stat;
internal_addr_t ia;
@@ -801,6 +884,7 @@ modecfg_send_request(struct state *st)
ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
| LELEM(INTERNAL_IP4_NETMASK);
+ ia.ipaddr = c->spd.this.host_srcip;
plog("sending ModeCfg request");
st->st_state = STATE_MODE_CFG_I1;
@@ -817,14 +901,14 @@ modecfg_send_request(struct state *st)
*
* used in ModeCfg pull mode, on the server (responder)
*/
-stf_status
-modecfg_inR0(struct msg_digest *md)
+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;
+ host_t *requested_vip;
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
@@ -832,9 +916,20 @@ modecfg_inR0(struct msg_digest *md)
return stat;
}
+ if (ia.attr_set & LELEM(INTERNAL_IP4_ADDRESS))
+ {
+ requested_vip = host_create_from_sockaddr((sockaddr_t*)&ia.ipaddr);
+ }
+ else
+ {
+ requested_vip = host_create_any(AF_INET);
+ }
+ plog("peer requested virtual IP %H", requested_vip);
+
want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
init_internal_addr(&ia);
- get_internal_addr(st->st_connection, &ia);
+ get_internal_addr(st->st_connection, requested_vip, &ia);
+ requested_vip->destroy(requested_vip);
if (want_unity_banner)
{
@@ -859,10 +954,9 @@ modecfg_inR0(struct msg_digest *md)
/* STATE_MODE_CFG_I1:
* HDR*, HASH, ATTR(REPLY=IP)
*
- * used in ModeCfg pull mode, on the client (initiator)
+ * used in ModeCfg pull mode, on the client (initiator)
*/
-stf_status
-modecfg_inI1(struct msg_digest *md)
+stf_status modecfg_inI1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -882,17 +976,19 @@ modecfg_inI1(struct msg_digest *md)
}
-/*
+/**
* Send ModeCfg set message from server to client in push mode
*/
-stf_status
-modecfg_send_set(struct state *st)
+stf_status modecfg_send_set(struct state *st)
{
stf_status stat;
internal_addr_t ia;
+ host_t *vip;
init_internal_addr(&ia);
- get_internal_addr(st->st_connection, &ia);
+ vip = host_create_any(AF_INET);
+ get_internal_addr(st->st_connection, vip, &ia);
+ vip->destroy(vip);
#ifdef CISCO_QUIRKS
ia.unity_banner = UNITY_BANNER_STR;
@@ -914,8 +1010,7 @@ modecfg_send_set(struct state *st)
*
* used in ModeCfg push mode, on the client (initiator).
*/
-stf_status
-modecfg_inI0(struct msg_digest *md)
+stf_status modecfg_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -958,8 +1053,7 @@ modecfg_inI0(struct msg_digest *md)
*
* used in ModeCfg push mode, on the server (responder)
*/
-stf_status
-modecfg_inR3(struct msg_digest *md)
+stf_status modecfg_inR3(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -977,11 +1071,10 @@ modecfg_inR3(struct msg_digest *md)
return STF_OK;
}
-/*
+/**
* Send XAUTH credentials request (username + password)
*/
-stf_status
-xauth_send_request(struct state *st)
+stf_status xauth_send_request(struct state *st)
{
stf_status stat;
internal_addr_t ia;
@@ -1005,8 +1098,7 @@ xauth_send_request(struct state *st)
*
* used on the XAUTH client (initiator)
*/
-stf_status
-xauth_inI0(struct msg_digest *md)
+stf_status xauth_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -1111,8 +1203,7 @@ xauth_inI0(struct msg_digest *md)
*
* used on the XAUTH server (responder)
*/
-stf_status
-xauth_inR1(struct msg_digest *md)
+stf_status xauth_inR1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -1148,13 +1239,14 @@ xauth_inR1(struct msg_digest *md)
plog("user password attribute is missing in XAUTH reply");
st->st_xauth.status = FALSE;
}
- else
+ 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));
+ snprintf(peer.id, sizeof(peer.id), "%Y",
+ md->st->st_connection->spd.that.id);
DBG(DBG_CONTROL,
DBG_log("peer xauth user name is '%.*s'"
@@ -1191,8 +1283,7 @@ xauth_inR1(struct msg_digest *md)
*
* used on the XAUTH client (initiator)
*/
-stf_status
-xauth_inI1(struct msg_digest *md)
+stf_status xauth_inI1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -1204,7 +1295,7 @@ xauth_inI1(struct msg_digest *md)
if (stat != STF_OK)
{
/* notification payload - not exactly the right choice, but okay */
- md->note = ATTRIBUTES_NOT_SUPPORTED;
+ md->note = ISAKMP_ATTRIBUTES_NOT_SUPPORTED;
return stat;
}
@@ -1243,8 +1334,7 @@ xauth_inI1(struct msg_digest *md)
*
* used on the XAUTH server (responder)
*/
-stf_status
-xauth_inR2(struct msg_digest *md)
+stf_status xauth_inR2(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h
index 86bfc6ed2..bc1443012 100644
--- a/src/pluto/modecfg.h
+++ b/src/pluto/modecfg.h
@@ -1,7 +1,7 @@
/* Mode Config related functions
* Copyright (C) 2001-2002 Colubris Networks
* Copyright (C) 2003-2004 Xelerance Corporation
- *
+ *
* 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
diff --git a/src/pluto/myid.c b/src/pluto/myid.c
new file mode 100644
index 000000000..ad4eefd15
--- /dev/null
+++ b/src/pluto/myid.c
@@ -0,0 +1,121 @@
+/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
+ * Copyright (C) 1999-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.
+ */
+
+#include <errno.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 */
+#endif
+
+#include <utils/identification.h>
+
+#include <freeswan.h>
+
+#include "myid.h"
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "connections.h"
+#include "packet.h"
+#include "whack.h"
+
+enum myid_state myid_state = MYID_UNKNOWN;
+
+identification_t *myids[MYID_SPECIFIED+1]; /* %myid */
+
+/**
+ * Fills in myid from environment variable IPSECmyid or defaultrouteaddr
+ */
+void init_myid(void)
+{
+ myid_state = MYID_UNKNOWN;
+ {
+ enum myid_state s;
+
+ for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
+ {
+ myids[s] = identification_create_from_string("%any");
+ }
+ }
+ set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
+ set_myid(MYID_IP, getenv("defaultrouteaddr"));
+ set_myFQDN();
+}
+
+/**
+ * Free myid module
+ */
+void free_myid(void)
+{
+ enum myid_state s;
+
+ for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
+ {
+ DESTROY_IF(myids[s]);
+ }
+}
+
+void set_myid(enum myid_state s, char *idstr)
+{
+ if (idstr)
+ {
+ myids[s]->destroy(myids[s]);
+ myids[s] = identification_create_from_string(idstr);
+ if (s == MYID_SPECIFIED)
+ {
+ myid_state = MYID_SPECIFIED;
+ }
+ }
+}
+
+void set_myFQDN(void)
+{
+ char FQDN[HOST_NAME_MAX + 1];
+ int r = gethostname(FQDN, sizeof(FQDN));
+ size_t len;
+
+ if (r != 0)
+ {
+ log_errno((e, "gethostname() failed in set_myFQDN"));
+ }
+ else
+ {
+ FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
+ len = strlen(FQDN);
+
+ if (len > 0 && FQDN[len-1] == '.')
+ {
+ /* nuke trailing . */
+ FQDN[len-1] = '\0';
+ }
+ if (!strcaseeq(FQDN, "localhost.localdomain"))
+ {
+ myids[MYID_HOSTNAME]->destroy(myids[MYID_HOSTNAME]);
+ myids[MYID_HOSTNAME] = identification_create_from_string(FQDN);
+ }
+ }
+}
+
+void show_myid_status(void)
+{
+ whack_log(RC_COMMENT, "%%myid = '%Y'", myids[myid_state]);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:4
+ * c-style: pluto
+ * End:
+ */
diff --git a/src/pluto/myid.h b/src/pluto/myid.h
new file mode 100644
index 000000000..012a34968
--- /dev/null
+++ b/src/pluto/myid.h
@@ -0,0 +1,38 @@
+/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef _MYID_H
+#define _MYID_H
+
+#include <utils/identification.h>
+
+extern void init_myid(void);
+extern void free_myid(void);
+
+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 */
+};
+
+extern enum myid_state myid_state;
+extern identification_t* myids[MYID_SPECIFIED+1]; /* %myid */
+extern void set_myid(enum myid_state s, char *);
+extern void show_myid_status(void);
+extern void set_myFQDN(void);
+
+#define resolve_myid(id) ((id)->get_type(id) == ID_MYID? myids[myid_state] : (id))
+
+#endif /* _MYID_H */
diff --git a/src/pluto/nat_traversal.c b/src/pluto/nat_traversal.c
index de3972fe2..feedf2aad 100644
--- a/src/pluto/nat_traversal.c
+++ b/src/pluto/nat_traversal.c
@@ -147,7 +147,7 @@ static void _natd_hash(const struct hash_desc *oakley_hasher, char *hash,
addr_chunk = chunk_from_thing(ip->u.v6.sin6_addr.s6_addr);
break;
default:
- addr_chunk = chunk_empty; /* should never occur */
+ addr_chunk = chunk_empty; /* should never occur */
}
hasher->get_hash(hasher, addr_chunk, NULL);
hasher->get_hash(hasher, port_chunk, hash);
@@ -310,7 +310,7 @@ bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
DBG(DBG_EMITTING,
DBG_log("sending NATD payloads")
)
-
+
/*
* First one with sender IP & port
*/
@@ -348,7 +348,7 @@ bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
/*
* nat_traversal_natoa_lookup()
- *
+ *
* Look for NAT-OA in message
*/
void nat_traversal_natoa_lookup(struct msg_digest *md)
@@ -435,7 +435,7 @@ void nat_traversal_natoa_lookup(struct msg_digest *md)
{
char ip_t[ADDRTOT_BUF];
addrtot(&ip, 0, ip_t, sizeof(ip_t));
-
+
DBG_log("received NAT-OA: %s", ip_t);
}
)
@@ -514,7 +514,7 @@ void nat_traversal_show_result (u_int32_t nt, u_int16_t sport)
mth = natt_type_bitnames[2];
break;
}
-
+
switch (nt & NAT_T_DETECTED)
{
case 0:
@@ -600,7 +600,7 @@ 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;
+ const connection_t *c = st->st_connection;
if (!c)
return;
@@ -658,7 +658,7 @@ struct _new_mapp_nfo {
static void nat_traversal_find_new_mapp_state (struct state *st, void *data)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;
if (c != NULL
@@ -720,7 +720,7 @@ static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport,
void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st)
{
- struct connection *c = st ? st->st_connection : NULL;
+ connection_t *c = st ? st->st_connection : NULL;
struct iface *i = NULL;
if ((st == NULL) || (c == NULL))
@@ -804,7 +804,7 @@ struct _new_klips_mapp_nfo {
static void nat_t_new_klips_mapp (struct state *st, void *data)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;
if (c != NULL && st->st_esp.present
diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c
index 8e428a759..b1f558ebf 100644
--- a/src/pluto/ocsp.c
+++ b/src/pluto/ocsp.c
@@ -67,19 +67,19 @@ static const char *const response_status_names[] = {
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;
+ identification_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 , /* responder_id_name */
{ NULL, 0 } , /* responder_id_key */
UNDEFINED_TIME, /* produced_at */
{ NULL, 0 } , /* single_response */
@@ -105,16 +105,16 @@ struct single_response {
};
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 */
+ CRL_REASON_UNSPECIFIED, /* revocationReason */
+ UNDEFINED_TIME , /* this_update */
+ UNDEFINED_TIME /* next_update */
};
@@ -126,26 +126,17 @@ struct request_list {
};
/* some OCSP specific prefabricated ASN.1 constants */
-
-static u_char ASN1_nonce_oid_str[] = {
+static const chunk_t ASN1_nonce_oid = chunk_from_chars(
0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
-};
-
-static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str);
-
-static u_char ASN1_response_oid_str[] = {
+);
+static const chunk_t ASN1_response_oid = chunk_from_chars(
0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
-};
-
-static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str);
-
-static u_char ASN1_response_content_str[] = {
+);
+static const chunk_t ASN1_response_content = chunk_from_chars(
0x04, 0x0D,
0x30, 0x0B,
0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
-};
-
-static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str);
+);
/* default OCSP uri */
static chunk_t ocsp_default_uri;
@@ -154,7 +145,7 @@ static chunk_t ocsp_default_uri;
static ocsp_location_t *ocsp_cache = NULL;
/* static temporary storage for ocsp requestor information */
-static x509cert_t *ocsp_requestor_cert = NULL;
+static cert_t *ocsp_requestor_cert = NULL;
static smartcard_t *ocsp_requestor_sc = NULL;
@@ -290,27 +281,38 @@ static const asn1Object_t singleResponseObjects[] = {
* 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 cert_t *cert, ocsp_location_t *location)
{
+ certificate_t *certificate = cert->cert;
+ identification_t *issuer = certificate->get_issuer(certificate);
+ x509_t *x509 = (x509_t*)certificate;
+ chunk_t issuer_dn = issuer->get_encoding(issuer);
+ chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
hasher_t *hasher;
static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */
-
- location->uri = cert->accessLocation;
- if (location->uri.ptr == NULL)
+ enumerator_t *enumerator = x509->create_ocsp_uri_enumerator(x509);
+
+ location->uri = NULL;
+ while (enumerator->enumerate(enumerator, &location->uri))
+ {
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (location->uri == NULL)
{
- ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID);
- if (ca != NULL && ca->ocspuri != NULL)
+ ca_info_t *ca = get_ca_info(issuer, authKeyID);
+ if (ca && ca->ocspuri)
{
- location->uri = chunk_create(ca->ocspuri, strlen(ca->ocspuri));
+ location->uri = 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);
@@ -318,23 +320,22 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
{
return FALSE;
}
- hasher->get_hash(hasher, cert->issuer, digest);
+ hasher->get_hash(hasher, issuer_dn, digest);
hasher->destroy(hasher);
location->next = NULL;
- location->issuer = cert->issuer;
- location->authKeyID = cert->authKeyID;
- location->authKeySerialNumber = cert->authKeySerialNumber;
-
- if (cert->authKeyID.ptr == NULL)
+ location->issuer = issuer;
+ location->authKeyID = authKeyID;
+
+ if (authKeyID.ptr == NULL)
{
- x509cert_t *authcert = get_authcert(cert->issuer
- , cert->authKeySerialNumber, cert->authKeyID, AUTH_CA);
+ cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
- if (authcert != NULL)
+ if (authcert)
{
- location->authKeyID = authcert->subjectKeyID;
- location->authKeySerialNumber = authcert->serialNumber;
+ x509_t *x509 = (x509_t*)authcert->cert;
+
+ location->authKeyID = x509->get_subjectKeyIdentifier(x509);
}
}
@@ -349,11 +350,10 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
*/
static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b)
{
- return ((a->authKeyID.ptr != NULL)
+ return ((a->authKeyID.ptr)
? same_keyid(a->authKeyID, b->authKeyID)
- : (same_dn(a->issuer, b->issuer)
- && same_serial(a->authKeySerialNumber, b->authKeySerialNumber)))
- && chunk_equals(a->uri, b->uri);
+ : a->issuer->equals(a->issuer, b->issuer))
+ && streq(a->uri, b->uri);
}
/**
@@ -362,7 +362,7 @@ static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *
ocsp_location_t* get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain)
{
- while (chain != NULL)
+ while (chain)
{
if (same_ocsp_location(loc, chain))
return chain;
@@ -393,7 +393,7 @@ static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
certinfop = &location->certinfo;
certinfo = *certinfop;
- while (certinfo != NULL)
+ while (certinfo)
{
cmp = chunk_compare(serialNumber, certinfo->serialNumber);
if (cmp <= 0)
@@ -416,30 +416,34 @@ static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
/**
* Verify the ocsp status of a certificate
*/
-cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until,
+cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until,
time_t *revocationDate,
crl_reason_t *revocationReason)
{
+ x509_t *x509 = (x509_t*)cert->cert;
+ chunk_t serialNumber = x509->get_serial(x509);
cert_status_t status;
ocsp_location_t location;
- time_t nextUpdate = 0;
+ time_t nextUpdate = UNDEFINED_TIME;
*revocationDate = UNDEFINED_TIME;
- *revocationReason = REASON_UNSPECIFIED;
-
+ *revocationReason = CRL_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
+ status = get_ocsp_status(&location, 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);
+ add_ocsp_fetch_request(&location, serialNumber);
/* inititate fetching of ocsp status */
wake_fetch_thread("verify_by_ocsp");
@@ -457,14 +461,14 @@ void check_ocsp(void)
lock_ocsp_cache("check_ocsp");
location = ocsp_cache;
-
- while (location != NULL)
+
+ while (location)
{
char buf[BUF_LEN];
bool first = TRUE;
ocsp_certinfo_t *certinfo = location->certinfo;
- while (certinfo != NULL)
+ while (certinfo)
{
if (!certinfo->once)
{
@@ -473,9 +477,8 @@ void check_ocsp(void)
DBG(DBG_CONTROL,
if (first)
{
- dntoa(buf, BUF_LEN, location->issuer);
- DBG_log("issuer: '%s'", buf);
- if (location->authKeyID.ptr != NULL)
+ DBG_log("issuer: \"%Y\"", location->issuer);
+ if (location->authKeyID.ptr)
{
datatot(location->authKeyID.ptr, location->authKeyID.len
, ':', buf, BUF_LEN);
@@ -514,7 +517,7 @@ static void free_certinfos(ocsp_certinfo_t *chain)
{
ocsp_certinfo_t *certinfo;
- while (chain != NULL)
+ while (chain)
{
certinfo = chain;
chain = chain->next;
@@ -527,11 +530,10 @@ static void free_certinfos(ocsp_certinfo_t *chain)
*/
static void free_ocsp_location(ocsp_location_t* location)
{
- free(location->issuer.ptr);
+ DESTROY_IF(location->issuer);
free(location->authNameID.ptr);
free(location->authKeyID.ptr);
- free(location->authKeySerialNumber.ptr);
- free(location->uri.ptr);
+ free(location->uri);
free_certinfos(location->certinfo);
free(location);
}
@@ -541,7 +543,7 @@ static void free_ocsp_location(ocsp_location_t* location)
*/
void free_ocsp_locations(ocsp_location_t **chain)
{
- while (*chain != NULL)
+ while (*chain)
{
ocsp_location_t *location = *chain;
*chain = location->next;
@@ -576,73 +578,55 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests,
{
bool first = TRUE;
- while (location != NULL)
+ while (location)
{
ocsp_certinfo_t *certinfo = location->certinfo;
- if (certinfo != NULL)
+ if (certinfo)
{
- u_char buf[BUF_LEN];
-
if (first)
{
whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of OCSP %s:", requests?
- "fetch requests":"responses");
+ 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)
+ if (location->issuer)
{
- datatot(location->authNameID.ptr, location->authNameID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authname: %s", buf);
+ whack_log(RC_COMMENT, " issuer: \"%Y\"", location->issuer);
}
- if (location->authKeyID.ptr != NULL)
+ whack_log(RC_COMMENT, " uri: '%s'", location->uri);
+ if (location->authNameID.ptr)
{
- datatot(location->authKeyID.ptr, location->authKeyID.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ whack_log(RC_COMMENT, " authname: %#B", &location->authNameID);
}
- if (location->authKeySerialNumber.ptr != NULL)
+ if (location->authKeyID.ptr)
{
- datatot(location->authKeySerialNumber.ptr
- , location->authKeySerialNumber.len, ':', buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ whack_log(RC_COMMENT, " authkey: %#B", &location->authKeyID);
}
- while (certinfo != NULL)
+ while (certinfo)
{
- char thisUpdate[BUF_LEN];
-
- snprintf(thisUpdate, BUF_LEN, "%T", &certinfo->thisUpdate, utc);
-
if (requests)
{
- whack_log(RC_COMMENT, "%s, trials: %d", thisUpdate
- , certinfo->trials);
+ whack_log(RC_COMMENT, " serial: %#B, %d trials",
+ &certinfo->serialNumber, certinfo->trials);
}
else if (certinfo->once)
{
- whack_log(RC_COMMENT, "%s, onetime use%s", thisUpdate
- , (certinfo->nextUpdate < time(NULL))? " (expired)": "");
+ whack_log(RC_COMMENT, " serial: %#B, %s, once%s",
+ &certinfo->serialNumber,
+ cert_status_names[certinfo->status],
+ (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));
+ whack_log(RC_COMMENT, " serial: %#B, %s, until %T %s",
+ &certinfo->serialNumber,
+ cert_status_names[certinfo->status],
+ &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;
}
}
@@ -662,7 +646,7 @@ void list_ocsp_cache(bool utc, bool strict)
static bool get_ocsp_requestor_cert(ocsp_location_t *location)
{
- x509cert_t *cert = NULL;
+ cert_t *cert = NULL;
/* initialize temporary static storage */
ocsp_requestor_cert = NULL;
@@ -671,17 +655,17 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
for (;;)
{
- char buf[BUF_LEN];
+ certificate_t *certificate;
/* looking for a certificate from the same issuer */
- cert = get_x509cert(location->issuer, location->authKeySerialNumber
- ,location->authKeyID, cert);
+ cert = get_x509cert(location->issuer, location->authKeyID, cert);
if (cert == NULL)
+ {
break;
-
+ }
+ certificate = cert->cert;
DBG(DBG_CONTROL,
- dntoa(buf, BUF_LEN, cert->subject);
- DBG_log("candidate: '%s'", buf);
+ DBG_log("candidate: '%Y'", certificate->get_subject(certificate));
)
if (cert->smartcard)
@@ -689,7 +673,7 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
/* look for a matching private key on a smartcard */
smartcard_t *sc = scx_get(cert);
- if (sc != NULL)
+ if (sc)
{
DBG(DBG_CONTROL,
DBG_log("matching smartcard found")
@@ -708,7 +692,7 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
/* look for a matching private key in the chained list */
private_key_t *private = get_x509_private_key(cert);
- if (private != NULL)
+ if (private)
{
DBG(DBG_CONTROL,
DBG_log("matching private key found")
@@ -726,8 +710,7 @@ static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
{
hasher_t *hasher;
u_char *pos;
- u_char digest_buf[HASH_SIZE_SHA1];
- chunk_t digest = chunk_from_buf(digest_buf);
+ chunk_t digest;
chunk_t digest_info, sigdata;
size_t siglen = 0;
@@ -756,15 +739,15 @@ static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
{
return chunk_empty;
}
- hasher->get_hash(hasher, tbs, digest_buf);
+ hasher->allocate_hash(hasher, tbs, &digest);
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"
+ digest_info = asn1_wrap(ASN1_SEQUENCE, "mm"
, asn1_algorithmIdentifier(OID_SHA1)
- , asn1_simple_object(ASN1_OCTET_STRING, digest));
+ , asn1_wrap(ASN1_OCTET_STRING, "m", digest));
pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
*pos++ = 0x00;
@@ -784,9 +767,9 @@ static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
*/
static chunk_t build_signature(chunk_t tbsRequest)
{
- chunk_t sigdata, certs;
+ chunk_t sigdata, cert, certs;
- if (ocsp_requestor_sc != NULL)
+ if (ocsp_requestor_sc)
{
/* RSA signature is done on smartcard */
sigdata = sc_build_sha1_signature(tbsRequest, ocsp_requestor_sc);
@@ -803,15 +786,13 @@ static chunk_t build_signature(chunk_t tbsRequest)
}
/* include our certificate */
- certs = asn1_wrap(ASN1_CONTEXT_C_0, "m"
- , asn1_simple_object(ASN1_SEQUENCE
- , ocsp_requestor_cert->certificate
- )
- );
+ cert = ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert);
+ certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
+ asn1_wrap(ASN1_SEQUENCE, "m", cert));
/* build signature comprising algorithm, signature and cert */
return asn1_wrap(ASN1_CONTEXT_C_0, "m"
- , asn1_wrap(ASN1_SEQUENCE, "cmm"
+ , asn1_wrap(ASN1_SEQUENCE, "mmm"
, asn1_algorithmIdentifier(OID_SHA1_WITH_RSA)
, sigdata
, certs
@@ -825,7 +806,7 @@ static chunk_t build_signature(chunk_t tbsRequest)
*/
static chunk_t build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo)
{
- chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm"
+ chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "mmmm"
, asn1_algorithmIdentifier(OID_SHA1)
, asn1_simple_object(ASN1_OCTET_STRING, location->authNameID)
, asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID)
@@ -847,7 +828,7 @@ static chunk_t build_request_list(ocsp_location_t *location)
size_t datalen = 0;
/* build content */
- while (certinfo != NULL)
+ while (certinfo)
{
/* build request for every certificate in list
* and store them in a chained list
@@ -865,7 +846,7 @@ static chunk_t build_request_list(ocsp_location_t *location)
pos = asn1_build_object(&requestList, ASN1_SEQUENCE, datalen);
/* copy all in chained list, free list afterwards */
- while (reqs != NULL)
+ while (reqs)
{
request_list_t *req = reqs;
@@ -882,9 +863,12 @@ static chunk_t build_request_list(ocsp_location_t *location)
*/
static chunk_t build_requestor_name(void)
{
+ certificate_t *certificate = ocsp_requestor_cert->cert;
+ identification_t *subject = certificate->get_subject(certificate);
+
return asn1_wrap(ASN1_CONTEXT_C_1, "m"
, asn1_simple_object(ASN1_CONTEXT_C_4
- , ocsp_requestor_cert->subject));
+ , subject->get_encoding(subject)));
}
/**
@@ -944,17 +928,13 @@ 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)
+ DBG_log("issuer: \"%Y\"", location->issuer);
+ if (location->authKeyID.ptr)
{
- datatot(location->authKeyID.ptr, location->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
+ DBG_log("authkey: %#B", &location->authKeyID);
}
)
lock_certs_and_keys("build_ocsp_request");
@@ -981,14 +961,13 @@ chunk_t build_ocsp_request(ocsp_location_t *location)
*/
static bool valid_ocsp_response(response_t *res)
{
- int pathlen;
- x509cert_t *authcert;
+ int pathlen, pathlen_constraint;
+ cert_t *authcert;
lock_authcert_list("valid_ocsp_response");
- authcert = get_authcert(res->responder_id_name, chunk_empty
- , res->responder_id_key, AUTH_OCSP | AUTH_CA);
-
+ authcert = get_authcert(res->responder_id_name, res->responder_id_key,
+ X509_OCSP_SIGNER | X509_CA);
if (authcert == NULL)
{
plog("no matching ocsp signer cert found");
@@ -999,7 +978,8 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("ocsp signer cert found")
)
- if (!x509_check_signature(res->tbs, res->signature, res->algorithm, authcert))
+ if (!x509_check_signature(res->tbs, res->signature, res->algorithm,
+ authcert->cert))
{
plog("signature of ocsp response is invalid");
unlock_authcert_list("valid_ocsp_response");
@@ -1010,43 +990,38 @@ static bool valid_ocsp_response(response_t *res)
)
- for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+ for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
{
- u_char buf[BUF_LEN];
- err_t ugh = NULL;
- time_t until;
-
- x509cert_t *cert = authcert;
+ cert_t *cert = authcert;
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
+ identification_t *subject = certificate->get_subject(certificate);
+ identification_t *issuer = certificate->get_issuer(certificate);
+ chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
+ time_t not_before, not_after;
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)
+ DBG_log("subject: '%Y'", subject);
+ DBG_log("issuer: '%Y'", issuer);
+ if (authKeyID.ptr)
{
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
+ DBG_log("authkey: %#B", &authKeyID);
}
)
- ugh = check_validity(authcert, &until);
-
- if (ugh != NULL)
+ if (!certificate->get_validity(certificate, NULL, &not_before, &not_after))
{
- plog("%s", ugh);
+ plog("certificate is invalid (valid from %T to %T)",
+ &not_before, FALSE, &not_after, FALSE);
+
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(issuer, authKeyID, X509_CA);
if (authcert == NULL)
{
plog("issuer cacert not found");
@@ -1057,8 +1032,7 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("issuer cacert found")
)
- if (!x509_check_signature(cert->tbsCertificate, cert->signature,
- cert->algorithm, authcert))
+ if (!certificate->issued_by(certificate, authcert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("valid_ocsp_response");
@@ -1068,17 +1042,28 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("certificate signature is valid")
)
+ /* check path length constraint */
+ pathlen_constraint = x509->get_pathLenConstraint(x509);
+ if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
+ pathlen > pathlen_constraint)
+ {
+ plog("path length of %d violates constraint of %d",
+ pathlen, pathlen_constraint);
+ return FALSE;
+ }
+
/* check if cert is self-signed */
- if (same_dn(cert->issuer, cert->subject))
+ if (x509->get_flags(x509) & X509_SELF_SIGNED)
{
DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca")
+ DBG_log("reached self-signed root ca with a path length of %d",
+ pathlen)
)
unlock_authcert_list("valid_ocsp_response");
return TRUE;
}
}
- plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ plog("maximum path length of %d exceeded", X509_MAX_PATH_LEN);
unlock_authcert_list("valid_ocsp_response");
return FALSE;
}
@@ -1091,7 +1076,6 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
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;
@@ -1116,10 +1100,10 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
}
break;
case BASIC_RESPONSE_ID_BY_NAME:
- res->responder_id_name = object;
+ res->responder_id_name = identification_create_from_encoding(
+ ID_DER_ASN1_DN, object);
DBG(DBG_PARSING,
- dntoa(buf, BUF_LEN, object);
- DBG_log(" '%s'",buf)
+ DBG_log(" '%Y'", res->responder_id_name)
)
break;
case BASIC_RESPONSE_ID_BY_KEY:
@@ -1153,23 +1137,35 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
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))
+ cert_t *cert = malloc_thing(cert_t);
+ x509_t *x509;
+
+ *cert = cert_empty;
+ cert->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, object,
+ BUILD_END);
+ if (cert->cert == NULL)
+ {
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log("parsing of embedded ocsp certificate failed")
+ )
+ cert_free(cert);
+ break;
+ }
+ x509 = (x509_t*)cert->cert;
+
+ if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
+ trust_authcert_candidate(cert, NULL))
{
- add_authcert(cert, AUTH_OCSP);
+ add_authcert(cert, X509_OCSP_SIGNER);
}
else
{
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("embedded ocsp certificate rejected")
)
- free_x509cert(cert);
+ cert_free(cert);
}
}
break;
@@ -1292,7 +1288,7 @@ static bool parse_ocsp_single_response(chunk_t blob, int level0,
break;
case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
sres->revocationReason = (object.len == 1)
- ? *object.ptr : REASON_UNSPECIFIED;
+ ? *object.ptr : CRL_REASON_UNSPECIFIED;
break;
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
sres->status = CERT_UNKNOWN;
@@ -1329,11 +1325,10 @@ ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc,
ocsp_location_t *location = malloc_thing(ocsp_location_t);
/* unshare location fields */
- location->issuer = chunk_clone(loc->issuer);
+ location->issuer = loc->issuer->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->uri = strdup(loc->uri);
location->certinfo = NULL;
/* insert new ocsp location in front of chain */
@@ -1369,7 +1364,7 @@ void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
certinfop = &location->certinfo;
certinfo = *certinfop;
- while (certinfo != NULL)
+ while (certinfo)
{
cmp = chunk_compare(info->serialNumber, certinfo->serialNumber);
if (cmp <= 0)
@@ -1385,10 +1380,11 @@ void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
cnew->serialNumber = chunk_clone(info->serialNumber);
cnew->next = certinfo;
+ cnew->trials = 0;
*certinfop = cnew;
certinfo = cnew;
}
-
+
DBG(DBG_CONTROL,
datatot(info->serialNumber.ptr, info->serialNumber.len, ':'
, buf, BUF_LEN);
@@ -1403,7 +1399,7 @@ void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
if (request)
{
certinfo->status = CERT_UNDEFINED;
-
+
if (cmp != 0)
{
certinfo->thisUpdate = now;
@@ -1415,7 +1411,7 @@ void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
certinfo->status = info->status;
certinfo->revocationTime = info->revocationTime;
certinfo->revocationReason = info->revocationReason;
-
+
certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)?
info->thisUpdate : now;
@@ -1446,12 +1442,12 @@ static void process_single_response(ocsp_location_t *location,
plog("ocsp single response has wrong issuer");
return;
}
-
+
/* traverse list of certinfos in increasing order */
certinfop = &location->certinfo;
certinfo = *certinfop;
- while (certinfo != NULL)
+ while (certinfo)
{
cmp = chunk_compare(sres->serialNumber, certinfo->serialNumber);
if (cmp <= 0)
@@ -1468,14 +1464,14 @@ static void process_single_response(ocsp_location_t *location,
/* 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);
@@ -1486,6 +1482,14 @@ static void process_single_response(ocsp_location_t *location,
}
/**
+ * Destroy a response_t object
+ */
+static void free_response(response_t *res)
+{
+ DESTROY_IF(res->responder_id_name);
+}
+
+/**
* Parse and verify ocsp response and update the ocsp cache
*/
void parse_ocsp(ocsp_location_t *location, chunk_t blob)
@@ -1498,24 +1502,24 @@ void parse_ocsp(ocsp_location_t *location, chunk_t blob)
if (status != STATUS_SUCCESSFUL)
{
plog("error in ocsp response");
- return;
+ goto free;
}
/* check if there was a nonce in the request */
- if (location->nonce.ptr != NULL && res.nonce.ptr == NULL)
+ if (location->nonce.ptr && 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))
+ if (res.nonce.ptr && !chunk_equals(res.nonce, location->nonce))
{
plog("invalid nonce in ocsp response");
- return;
+ goto free;
}
/* check if the response is signed by a trusted key */
if (!valid_ocsp_response(&res))
{
plog("invalid ocsp response");
- return;
+ goto free;
}
DBG(DBG_CONTROL,
DBG_log("valid ocsp response")
@@ -1536,7 +1540,7 @@ void parse_ocsp(ocsp_location_t *location, chunk_t blob)
single_response_t sres = empty_single_response;
if (!parse_ocsp_single_response(object,
- parser->get_level(parser)+1, &sres))
+ parser->get_level(parser)+1, &sres))
{
goto end;
}
@@ -1546,4 +1550,7 @@ void parse_ocsp(ocsp_location_t *location, chunk_t blob)
end:
parser->destroy(parser);
}
+
+free:
+ free_response(&res);
}
diff --git a/src/pluto/ocsp.h b/src/pluto/ocsp.h
index d8ee7bd8c..977cca3c8 100644
--- a/src/pluto/ocsp.h
+++ b/src/pluto/ocsp.h
@@ -15,6 +15,8 @@
#include "constants.h"
+#include <credentials/certificates/crl.h>
+
/* constants */
#define OCSP_BASIC_RESPONSE_VERSION 1
@@ -52,12 +54,11 @@ 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;
+ identification_t *issuer;
+ chunk_t authNameID;
+ chunk_t authKeyID;
+ chunk_t nonce;
+ char *uri;
ocsp_certinfo_t *certinfo;
};
@@ -68,11 +69,11 @@ extern ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc
extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info
, 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
+extern cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until
, 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 void ocsp_cache_add_cert(const cert_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
diff --git a/src/pluto/packet.c b/src/pluto/packet.c
index 01967efed..35fc4afcc 100644
--- a/src/pluto/packet.c
+++ b/src/pluto/packet.c
@@ -227,7 +227,7 @@ static field_desc isat_fields_ah[] = {
{ 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_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transform_names },
{ ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
{ ft_end, 0, NULL, NULL }
};
@@ -242,7 +242,7 @@ static field_desc isat_fields_esp[] = {
{ 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_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transform_names },
{ ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
{ ft_end, 0, NULL, NULL }
};
@@ -535,7 +535,7 @@ struct_desc isakmp_vendor_id_desc = { "ISAKMP Vendor ID Payload", isag_fields, s
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Type ! RESERVED ! Identifier !
+ ! Type ! RESERVED ! Identifier !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Attributes ~
diff --git a/src/pluto/pem.c b/src/pluto/pem.c
deleted file mode 100644
index 1a4a99af7..000000000
--- a/src/pluto/pem.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Loading of PEM encoded files with optional encryption
- * 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
- * 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.
- */
-
-/* decrypt a PEM encoded data block using DES-EDE3-CBC
- * see RFC 1423 PEM: Algorithms, Modes and Identifiers
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stddef.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <asn1/pem.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "whack.h"
-#include "pem.h"
-
-/**
- * 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)
-{
- chunk_t password = chunk_empty;
-
- /* do we prompt for the passphrase? */
- if (pass && pass->prompt && pass->fd != NULL_FD)
- {
- int i;
- chunk_t blob_copy;
- err_t ugh = "invalid passphrase, too many trials";
- status_t status;
-
- 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;
- }
- else
- {
- if (pass)
- {
- password = chunk_create(pass->secret, strlen(pass->secret));
- }
- if (pem_to_bin(blob, password, pgp) == SUCCESS)
- {
- return NULL;
- }
- else
- {
- return "pem to bin conversion failed";
- }
- }
-}
diff --git a/src/pluto/pgpcert.c b/src/pluto/pgpcert.c
deleted file mode 100644
index 1d5b14b26..000000000
--- a/src/pluto/pgpcert.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/* 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 4880
- */
-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)
-{
- chunk_t pubkey_packet = *packet;
- pgp_pubkey_alg_t pubkey_alg;
-
- 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:
- cert->public_key = lib->creds->create(lib->creds,
- CRED_PUBLIC_KEY, KEY_RSA,
- BUILD_BLOB_PGP, *packet,
- BUILD_END);
- if (cert->public_key == NULL)
- {
- return FALSE;
- }
- break;
- default:
- plog(" non RSA public keys not supported");
- return FALSE;
- }
-
- /* compute V4 or V3 fingerprint according to section 12.2 of RFC 4880 */
- if (cert->version == 4)
- {
- char pubkey_packet_header_buf[] = {
- 0x99, pubkey_packet.len / 256, pubkey_packet.len % 256
- };
- chunk_t pubkey_packet_header = chunk_from_buf(pubkey_packet_header_buf);
- chunk_t hash;
- hasher_t *hasher;
-
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (hasher == NULL)
- {
- plog("no SHA-1 hasher available");
- return FALSE;
- }
- hasher->allocate_hash(hasher, pubkey_packet_header, NULL);
- hasher->allocate_hash(hasher, pubkey_packet, &hash);
- hasher->destroy(hasher);
- cert->fingerprint = identification_create_from_encoding(ID_KEY_ID, hash);
- free(hash.ptr);
- }
- else
- {
- /* V3 fingerprint is computed by public_key_t class */
- cert->fingerprint = cert->public_key->get_id(cert->public_key, ID_KEY_ID);
- if (cert->fingerprint == NULL)
- {
- 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/pgpcert.h b/src/pluto/pgpcert.h
deleted file mode 100644
index 727648391..000000000
--- a/src/pluto/pgpcert.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 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.
- */
-
-#ifndef _PGPCERT_H
-#define _PGPCERT_H
-
-#include <crypto/hashers/hasher.h>
-#include <credentials/keys/private_key.h>
-#include <credentials/keys/public_key.h>
-
-/*
- * Length of PGP V3 fingerprint
- */
-#define PGP_FINGERPRINT_SIZE HASH_SIZE_MD5
-
-typedef char fingerprint_t[PGP_FINGERPRINT_SIZE];
-
-/* access structure for an OpenPGP certificate */
-
-typedef struct pgpcert pgpcert_t;
-
-struct pgpcert {
- 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 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);
-extern void list_pgp_end_certs(bool utc);
-extern void release_pgpcert(pgpcert_t *cert);
-extern void free_pgpcert(pgpcert_t *cert);
-
-#endif /* _PGPCERT_H */
diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c
index 7248b042f..733dd2623 100644
--- a/src/pluto/pkcs7.c
+++ b/src/pluto/pkcs7.c
@@ -17,8 +17,7 @@
#include <stdlib.h>
#include <string.h>
-
-#include <freeswan.h>
+#include <time.h>
#include <library.h>
#include <debug.h>
@@ -27,11 +26,8 @@
#include <asn1/oid.h>
#include <crypto/rngs/rng.h>
#include <crypto/crypters/crypter.h>
+#include <credentials/certificates/x509.h>
-#include "constants.h"
-#include "defs.h"
-#include "x509.h"
-#include "certs.h"
#include "pkcs7.h"
const contentInfo_t empty_contentInfo = {
@@ -84,10 +80,12 @@ static const asn1Object_t signedDataObjects[] = {
{ 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
+#define PKCS7_SIGNED_VERSION 1
#define PKCS7_DIGEST_ALG 3
#define PKCS7_SIGNED_CONTENT_INFO 5
#define PKCS7_SIGNED_CERT 7
#define PKCS7_SIGNER_INFO 13
+#define PKCS7_SIGNER_INFO_VERSION 14
#define PKCS7_SIGNED_ISSUER 16
#define PKCS7_SIGNED_SERIAL_NUMBER 17
#define PKCS7_DIGEST_ALGORITHM 18
@@ -128,81 +126,6 @@ static const asn1Object_t envelopedDataObjects[] = {
#define PKCS7_ENVELOPED_ROOF 15
/**
- * PKCS7 contentInfo OIDs
- */
-
-static u_char ASN1_pkcs7_data_oid_str[] = {
- 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
-};
-
-static u_char ASN1_pkcs7_enveloped_data_oid_str[] = {
- 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
-};
-
-static u_char ASN1_pkcs7_digested_data_oid_str[] = {
- 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
-};
-
-static const chunk_t ASN1_pkcs7_data_oid =
- chunk_from_buf(ASN1_pkcs7_data_oid_str);
-static const chunk_t ASN1_pkcs7_signed_data_oid =
- chunk_from_buf(ASN1_pkcs7_signed_data_oid_str);
-static const chunk_t ASN1_pkcs7_enveloped_data_oid =
- chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str);
-static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid =
- chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str);
-static const chunk_t ASN1_pkcs7_digested_data_oid =
- chunk_from_buf(ASN1_pkcs7_digested_data_oid_str);
-static const chunk_t ASN1_pkcs7_encrypted_data_oid =
- chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str);
-
-/**
- * 3DES and DES encryption OIDs
- */
-
-static u_char ASN1_3des_ede_cbc_oid_str[] = {
- 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
-};
-
-static const chunk_t ASN1_3des_ede_cbc_oid =
- chunk_from_buf(ASN1_3des_ede_cbc_oid_str);
-static const chunk_t ASN1_des_cbc_oid =
- chunk_from_buf(ASN1_des_cbc_oid_str);
-
-/**
- * PKCS#7 attribute type OIDs
- */
-
-static u_char ASN1_contentType_oid_str[] = {
- 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
-};
-
-static const chunk_t ASN1_contentType_oid =
- chunk_from_buf(ASN1_contentType_oid_str);
-static const chunk_t ASN1_messageDigest_oid =
- 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)
@@ -242,15 +165,16 @@ end:
/**
* 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,
+ linked_list_t *certs,
+ chunk_t *attributes, certificate_t *cacert)
{
- 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 version;
int objectID;
bool success = FALSE;
@@ -267,7 +191,7 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
return FALSE;
}
- parser = asn1_parser_create(signedDataObjects, blob);
+ parser = asn1_parser_create(signedDataObjects, cInfo.content);
parser->set_top_level(parser, 2);
while (parser->iterate(parser, &objectID, &object))
@@ -276,6 +200,10 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
switch (objectID)
{
+ case PKCS7_SIGNED_VERSION:
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(" v%d", version);
+ break;
case PKCS7_DIGEST_ALG:
digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
break;
@@ -286,33 +214,36 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
}
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;
+ certificate_t *cert;
DBG2(" parsing pkcs7-wrapped certificate");
- if (parse_x509cert(cert_blob, level+1, newcert))
- {
- newcert->next = *cert;
- *cert = newcert;
- }
- else
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, object,
+ BUILD_END);
+ if (cert)
{
- free_x509cert(newcert);
+ certs->insert_last(certs, cert);
}
}
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_SIGNER_INFO_VERSION:
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(" v%d", version);
+ break;
+ case PKCS7_SIGNED_ISSUER:
+ {
+ identification_t *issuer = identification_create_from_encoding(
+ ID_DER_ASN1_DN, object);
+ DBG2(" \"%Y\"", issuer);
+ issuer->destroy(issuer);
+ break;
+ }
case PKCS7_AUTH_ATTRIBUTES:
if (attributes != NULL)
{
@@ -340,9 +271,15 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
/* check the signature only if a cacert is available */
if (cacert != NULL)
{
- public_key_t *key = cacert->public_key;
- signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+ public_key_t *key;
+ signature_scheme_t scheme;
+ scheme = signature_scheme_from_oid(digest_alg);
+ if (scheme == SIGN_UNKNOWN)
+ {
+ DBG1("unsupported signature scheme");
+ return FALSE;
+ }
if (signerInfos == 0)
{
DBG1("no signerInfo object found");
@@ -364,11 +301,11 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
return FALSE;
}
- /* determine signature scheme */
- scheme = signature_scheme_from_oid(digest_alg);
-
- if (scheme == SIGN_UNKNOWN)
+ /* verify the signature */
+ key = cacert->get_public_key(cacert);
+ if (key == NULL)
{
+ DBG1("no public key found in CA certificate");
return FALSE;
}
if (key->verify(key, scheme, *attributes, encrypted_digest))
@@ -378,10 +315,11 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
else
{
DBG1("invalid signature");
- return FALSE;
+ success = FALSE;
}
+ key->destroy(key);
}
- return TRUE;
+ return success;
}
/**
@@ -399,9 +337,9 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
crypter_t *crypter = NULL;
- u_char buf[BUF_LEN];
int enc_alg = OID_UNKNOWN;
int content_enc_alg = OID_UNKNOWN;
+ int version;
int objectID;
bool success = FALSE;
@@ -428,37 +366,45 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
switch (objectID)
{
case PKCS7_ENVELOPED_VERSION:
- if (*object.ptr != 0)
- {
- DBG1("envelopedData version is not 0");
- goto end;
- }
- break;
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(" v%d", version);
+ if (version != 0)
+ {
+ DBG1("envelopedData version is not 0");
+ goto end;
+ }
+ break;
case PKCS7_RECIPIENT_INFO_VERSION:
- if (*object.ptr != 0)
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(" v%d", version);
+ if (version != 0)
{
DBG1("recipient info version is not 0");
goto end;
}
break;
case PKCS7_ISSUER:
- dntoa(buf, BUF_LEN, object);
- DBG2(" '%s'", buf);
- break;
+ {
+ identification_t *issuer = identification_create_from_encoding(
+ ID_DER_ASN1_DN, object);
+ DBG2(" \"%Y\"", issuer);
+ issuer->destroy(issuer);
+ break;
+ }
case PKCS7_SERIAL_NUMBER:
if (!chunk_equals(serialNumber, object))
{
DBG1("serial numbers do not match");
goto end;
- }
- break;
+ }
+ 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))
@@ -477,7 +423,7 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
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");
@@ -578,19 +524,20 @@ failed:
*/
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, "mm",
+ asn1_build_known_oid(OID_PKCS9_CONTENT_TYPE),
+ asn1_wrap(ASN1_SET, "m",
+ asn1_build_known_oid(OID_PKCS7_DATA)));
}
/**
* @brief Builds a messageDigest attribute
- *
- *
+ *
+ *
* @param[in] blob content to create digest of
* @param[in] digest_alg digest algorithm to be used
* @return ASN.1 encoded messageDigest attribute
- *
+ *
*/
chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
{
@@ -603,12 +550,10 @@ chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_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)
- )
- );
+ return asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_PKCS9_MESSAGE_DIGEST),
+ asn1_wrap(ASN1_SET, "m",
+ asn1_wrap(ASN1_OCTET_STRING, "m", digest)));
}
/**
@@ -616,83 +561,59 @@ chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
*/
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:
- 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)
- );
+ return (cInfo->content.ptr) ?
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(cInfo->type),
+ asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content)) :
+ asn1_build_known_oid(cInfo->type);
}
/**
* build issuerAndSerialNumber object
*/
-chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert)
+chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
{
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , cert->issuer
- , asn1_integer("c", cert->serialNumber));
+ identification_t *issuer = cert->get_issuer(cert);
+ x509_t *x509 = (x509_t*)cert;
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ issuer->get_encoding(issuer),
+ asn1_integer("c", x509->get_serial(x509)));
}
/**
* create a signed pkcs7 contentInfo object
*/
chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
- const x509cert_t *cert, int digest_alg,
+ certificate_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);
+ chunk_t authenticatedAttributes = chunk_empty;
+ chunk_t encryptedDigest = chunk_empty;
+ chunk_t signerInfo, cInfo, signature;
+ signature_scheme_t scheme = signature_scheme_from_oid(digest_alg);
- if (attributes.ptr != NULL)
+ if (attributes.ptr)
{
- encryptedDigest = x509_build_signature(attributes, digest_alg, key,
- FALSE);
- authenticatedAttributes = chunk_clone(attributes);
- *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ if (key->sign(key, scheme, attributes, &signature))
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
+ authenticatedAttributes = chunk_clone(attributes);
+ *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ }
}
- else
+ else if (data.ptr)
{
- encryptedDigest = (data.ptr == NULL)? chunk_empty
- : x509_build_signature(data, digest_alg, key, FALSE);
- authenticatedAttributes = chunk_empty;
+ if (key->sign(key, scheme, data, &signature))
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
+ }
}
-
- signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm"
+ signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm"
, ASN1_INTEGER_1
, pkcs7_build_issuerAndSerialNumber(cert)
- , digestAlgorithm
+ , asn1_algorithmIdentifier(digest_alg)
, authenticatedAttributes
, asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
, encryptedDigest);
@@ -704,9 +625,9 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
signedData.type = OID_PKCS7_SIGNED_DATA;
signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
, ASN1_INTEGER_1
- , asn1_simple_object(ASN1_SET, digestAlgorithm)
+ , asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg))
, pkcs7_build_contentInfo(&pkcs7Data)
- , asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate)
+ , asn1_wrap(ASN1_CONTEXT_C_0, "m", cert->get_encoding(cert))
, asn1_wrap(ASN1_SET, "m", signerInfo));
cInfo = pkcs7_build_contentInfo(&signedData);
@@ -720,7 +641,7 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
/**
* create a symmetrically encrypted pkcs7 contentInfo object
*/
-chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_alg)
+chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg)
{
encryption_algorithm_t alg;
size_t alg_key_size;
@@ -739,7 +660,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
/* 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);
@@ -760,7 +681,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
in.ptr = malloc(in.len);
DBG2("padding %u bytes of data to multiple block size of %u bytes",
- data.len, in.len);
+ data.len, in.len);
/* copy data */
memcpy(in.ptr, data.ptr, data.len);
@@ -773,26 +694,41 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
crypter->set_key(crypter, symmetricKey);
crypter->encrypt(crypter, in, iv, &out);
crypter->destroy(crypter);
+ chunk_clear(&in);
DBG3("encrypted data %B", &out);
- cert->public_key->encrypt(cert->public_key, symmetricKey, &protectedKey);
+ /* protect symmetric key by public key encryption */
+ {
+ public_key_t *key = cert->get_public_key(cert);
- /* build pkcs7 enveloped data object */
+ if (key == NULL)
+ {
+ DBG1("public key not found in encryption certificate");
+ chunk_clear(&symmetricKey);
+ chunk_free(&iv);
+ chunk_free(&out);
+ return chunk_empty;
+ }
+ key->encrypt(key, symmetricKey, &protectedKey);
+ key->destroy(key);
+ }
+
+ /* 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
+
+ chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm"
+ , asn1_build_known_oid(OID_PKCS7_DATA)
, 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"
+ chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm"
, ASN1_INTEGER_0
, pkcs7_build_issuerAndSerialNumber(cert)
, asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
@@ -810,10 +746,9 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
cInfo = pkcs7_build_contentInfo(&envelopedData);
DBG3("envelopedData %B", &cInfo);
- free(envelopedData.content.ptr);
- free(symmetricKey.ptr);
- free(in.ptr);
- free(iv.ptr);
+ chunk_free(&envelopedData.content);
+ chunk_free(&iv);
+ chunk_clear(&symmetricKey);
return cInfo;
}
}
diff --git a/src/pluto/pkcs7.h b/src/pluto/pkcs7.h
index 028822dfe..1743ea9c4 100644
--- a/src/pluto/pkcs7.h
+++ b/src/pluto/pkcs7.h
@@ -18,10 +18,10 @@
#ifndef _PKCS7_H
#define _PKCS7_H
+#include <utils/linked_list.h>
#include <crypto/crypters/crypter.h>
#include <credentials/keys/private_key.h>
-#include "defs.h"
-#include "x509.h"
+#include <credentials/certificates/certificate.h>
/* Access structure for a PKCS#7 ContentInfo object */
@@ -35,17 +35,19 @@ struct contentInfo {
extern const contentInfo_t empty_contentInfo;
extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
- contentInfo_t *cInfo);
+ contentInfo_t *cInfo);
extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
- x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert);
+ linked_list_t *cert, chunk_t *attributes,
+ certificate_t *cacert);
extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
- chunk_t serialNumber, private_key_t *key);
+ 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_issuerAndSerialNumber(certificate_t *cert);
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);
+ certificate_t *cert, int digest_alg,
+ private_key_t *key);
+extern chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert,
+ int enc_alg);
#endif /* _PKCS7_H */
diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c
index 5d0e008f3..8b922df8c 100644
--- a/src/pluto/plutomain.c
+++ b/src/pluto/plutomain.c
@@ -48,7 +48,7 @@
#include "constants.h"
#include "defs.h"
-#include "id.h"
+#include "myid.h"
#include "ca.h"
#include "certs.h"
#include "ac.h"
@@ -73,6 +73,7 @@
#include "virtual.h"
#include "timer.h"
#include "vendor.h"
+#include "builder.h"
static void usage(const char *mess)
{
@@ -128,7 +129,7 @@ static void usage(const char *mess)
" [--debug-private]"
" [--debug-natt]"
#endif
- " \\\n\t"
+ " \\\n\t"
"[--nat_traversal] [--keep_alive <delay_sec>]"
" \\\n\t"
"[--force_keepalive] [--disable_port_floating]"
@@ -233,8 +234,8 @@ static void print_plugins()
char buf[BUF_LEN], *plugin;
int len = 0;
enumerator_t *enumerator;
-
- buf[0] = '\0';
+
+ buf[0] = '\0';
enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
while (len < BUF_LEN && enumerator->enumerate(enumerator, &plugin))
{
@@ -260,7 +261,7 @@ int main(int argc, char **argv)
#endif /* CAPABILITIES */
/* initialize library and optionsfrom */
- if (!library_init(STRONGSWAN_CONF))
+ if (!library_init(NULL))
{
library_deinit();
exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
@@ -651,10 +652,14 @@ int main(int argc, char **argv)
}
/* load plugins, further infrastructure may need it */
- lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR,
- lib->settings->get_str(lib->settings, "pluto.load", PLUGINS));
+ if (!lib->plugins->load(lib->plugins, NULL,
+ lib->settings->get_str(lib->settings, "pluto.load", PLUGINS)))
+ {
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
print_plugins();
+ init_builder();
if (!init_secret() || !init_crypto())
{
plog("initialization failed - aborting pluto");
@@ -668,12 +673,13 @@ int main(int argc, char **argv)
init_demux();
init_kernel();
init_adns();
- init_id();
- init_fetch();
+ init_myid();
+ fetch_initialize();
+ ac_initialize();
/* drop unneeded capabilities and change UID/GID */
prctl(PR_SET_KEEPCAPS, 1);
-
+
#ifdef IPSEC_GROUP
{
struct group group, *grp;
@@ -715,15 +721,15 @@ int main(int argc, char **argv)
#endif /* CAPABILITIES */
/* loading X.509 CA certificates */
- load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
+ load_authcerts("ca", CA_CERT_PATH, X509_CA);
/* loading X.509 AA certificates */
- load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
+ load_authcerts("aa", AA_CERT_PATH, X509_AA);
/* loading X.509 OCSP certificates */
- load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
+ load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER);
/* loading X.509 CRLs */
load_crls();
/* loading attribute certificates (experimental) */
- load_acerts();
+ ac_load_certs();
daily_log_event();
call_server();
@@ -744,22 +750,24 @@ void exit_pluto(int status)
free_preshared_secrets();
free_remembered_public_keys();
delete_every_connection();
+ fetch_finalize(); /* stop fetching thread */
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();
+ ac_finalize(); /* free X.509 attribute certificates */
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_myid(); /* free myids */
free_events(); /* free remaining events */
- free_vendorid(); /* free all vendor id records */
+ free_vendorid(); /* free all vendor id records */
+ free_builder();
delete_lock();
options->destroy(options);
library_deinit();
diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c
index 013deb446..826a1aa6e 100644
--- a/src/pluto/rcv_whack.c
+++ b/src/pluto/rcv_whack.c
@@ -33,7 +33,6 @@
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "ca.h"
#include "certs.h"
#include "ac.h"
@@ -55,16 +54,16 @@
#include "fetch.h"
#include "ocsp.h"
#include "crl.h"
-
+#include "myid.h"
#include "kernel_alg.h"
#include "ike_alg.h"
+
/* helper variables and function to decode strings from whack message */
static char *next_str
, *str_roof;
-static bool
-unpack_str(char **p)
+static bool unpack_str(char **p)
{
char *end = memchr(next_str, '\0', str_roof - next_str);
@@ -103,19 +102,13 @@ struct key_add_continuation {
enum key_add_attempt lookingfor;
};
-static void
-key_add_ugh(const struct id *keyid, err_t ugh)
+static void key_add_ugh(identification_t *keyid, err_t ugh)
{
- 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);
+ loglog(RC_NOKEY, "failure to fetch key for %'Y' from DNS: %s", keyid, ugh);
}
/* last one out: turn out the lights */
-static void
-key_add_merge(struct key_add_common *oc, const struct id *keyid)
+static void key_add_merge(struct key_add_common *oc, identification_t *keyid)
{
if (oc->refCount == 0)
{
@@ -123,9 +116,12 @@ key_add_merge(struct key_add_common *oc, const struct id *keyid)
/* if no success, print all diagnostics */
if (!oc->success)
+ {
for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ {
key_add_ugh(keyid, oc->diag[kaa]);
-
+ }
+ }
for (kaa = ka_TXT; kaa != ka_roof; kaa++)
{
free(oc->diag[kaa]);
@@ -135,8 +131,7 @@ key_add_merge(struct key_add_common *oc, const struct id *keyid)
}
}
-static void
-key_add_continue(struct adns_continuation *ac, err_t ugh)
+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;
@@ -159,95 +154,87 @@ key_add_continue(struct adns_continuation *ac, err_t ugh)
}
oc->refCount--;
- key_add_merge(oc, &ac->id);
+ key_add_merge(oc, ac->id);
whack_log_fd = NULL_FD;
}
-static void
-key_add_request(const whack_message_t *msg)
+static void key_add_request(const whack_message_t *msg)
{
- struct id keyid;
- err_t ugh = atoid(msg->keyid, &keyid, FALSE);
+ identification_t *key_id;
- if (ugh != NULL)
+ key_id = identification_create_from_string(msg->keyid);
+
+ if (!msg->whack_addkey)
{
- loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh);
+ delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty);
}
- else
+ if (msg->keyval.len == 0)
{
- if (!msg->whack_addkey)
- delete_public_keys(&keyid, msg->pubkey_alg
- , chunk_empty, chunk_empty);
+ struct key_add_common *oc = malloc_thing(struct key_add_common);
+ enum key_add_attempt kaa;
+ err_t ugh;
- if (msg->keyval.len == 0)
+ /* 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_common *oc = malloc_thing(struct key_add_common);
- enum key_add_attempt kaa;
+ struct key_add_continuation *kc;
- /* initialize state shared by queries */
- oc->refCount = 0;
- oc->whack_fd = dup_any(whack_log_fd);
- oc->success = FALSE;
+ oc->diag[kaa] = NULL;
+ oc->refCount++;
+ kc = malloc_thing(struct key_add_continuation);
+ kc->common = oc;
+ kc->lookingfor = kaa;
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ switch (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);
+ ugh = start_adns_query(key_id
+ , key_id /* 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);
+ ugh = start_adns_query(key_id
+ , NULL
+ , T_KEY
+ , key_add_continue
+ , &kc->ac);
break;
#endif /* USE_KEYRR */
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);
- }
- else
- {
- if (!add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
- &pubkeys))
+ if (ugh)
{
- loglog(RC_LOG_SERIOUS, "failed to add public key");
+ oc->diag[kaa] = clone_str(ugh);
+ oc->refCount--;
}
}
+
+ /* Done launching queries. Handle total failure case. */
+ key_add_merge(oc, key_id);
+ }
+ else
+ {
+ if (!add_public_key(key_id, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
+ &pubkeys))
+ {
+ loglog(RC_LOG_SERIOUS, "failed to add public key");
+ }
}
+ key_id->destroy(key_id);
}
/* Handle a kernel request. Supposedly, there's a message in
* the kernelsock socket.
*/
-void
-whack_handle(int whackctlfd)
+void whack_handle(int whackctlfd)
{
whack_message_t msg;
struct sockaddr_un whackaddr;
@@ -319,24 +306,26 @@ whack_handle(int whackctlfd)
|| !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 */
+ || !unpack_str(&msg.left.sourceip) /* string 7 */
+ || !unpack_str(&msg.left.virt) /* string 8 */
+ || !unpack_str(&msg.right.id) /* string 9 */
+ || !unpack_str(&msg.right.cert) /* string 10 */
+ || !unpack_str(&msg.right.ca) /* string 11 */
+ || !unpack_str(&msg.right.groups) /* string 12 */
+ || !unpack_str(&msg.right.updown) /* string 13 */
+ || !unpack_str(&msg.right.sourceip) /* string 14 */
+ || !unpack_str(&msg.right.virt) /* string 15 */
+ || !unpack_str(&msg.keyid) /* string 16 */
+ || !unpack_str(&msg.myid) /* string 17 */
+ || !unpack_str(&msg.cacert) /* string 18 */
+ || !unpack_str(&msg.ldaphost) /* string 19 */
+ || !unpack_str(&msg.ldapbase) /* string 20 */
+ || !unpack_str(&msg.crluri) /* string 21 */
+ || !unpack_str(&msg.crluri2) /* string 22 */
+ || !unpack_str(&msg.ocspuri) /* string 23 */
+ || !unpack_str(&msg.ike) /* string 24 */
+ || !unpack_str(&msg.esp) /* string 25 */
+ || !unpack_str(&msg.sc_data) /* string 26 */
|| str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
{
ugh = "message from whack contains bad string";
@@ -372,7 +361,7 @@ whack_handle(int whackctlfd)
}
else if (!msg.whack_connection)
{
- struct connection *c = con_by_name(msg.name, TRUE);
+ connection_t *c = con_by_name(msg.name, TRUE);
if (c != NULL)
{
@@ -424,7 +413,7 @@ whack_handle(int whackctlfd)
if (msg.whack_ca && msg.cacert != NULL)
add_ca_info(&msg);
-
+
/* process "listen" before any operation that could require it */
if (msg.whack_listen)
{
@@ -451,22 +440,22 @@ whack_handle(int whackctlfd)
if (msg.whack_reread & REREAD_CACERTS)
{
- load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
+ load_authcerts("ca", CA_CERT_PATH, X509_CA);
}
if (msg.whack_reread & REREAD_AACERTS)
{
- load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
+ load_authcerts("aa", AA_CERT_PATH, X509_AA);
}
if (msg.whack_reread & REREAD_OCSPCERTS)
{
- load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
+ load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER);
}
if (msg.whack_reread & REREAD_ACERTS)
{
- load_acerts();
+ ac_load_certs();
}
if (msg.whack_reread & REREAD_CRLS)
@@ -487,32 +476,27 @@ whack_handle(int whackctlfd)
if (msg.whack_list & LIST_CERTS)
{
- list_certs(msg.whack_utc);
+ cert_list(msg.whack_utc);
}
if (msg.whack_list & LIST_CACERTS)
{
- list_authcerts("CA", AUTH_CA, msg.whack_utc);
+ list_authcerts("CA", X509_CA, msg.whack_utc);
}
if (msg.whack_list & LIST_AACERTS)
{
- list_authcerts("AA", AUTH_AA, msg.whack_utc);
+ list_authcerts("AA", X509_AA, msg.whack_utc);
}
if (msg.whack_list & LIST_OCSPCERTS)
{
- list_authcerts("OCSP", AUTH_OCSP, msg.whack_utc);
+ list_authcerts("OCSP", X509_OCSP_SIGNER, 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);
+ ac_list_certs(msg.whack_utc);
}
if (msg.whack_list & LIST_CAINFOS)
@@ -562,7 +546,7 @@ whack_handle(int whackctlfd)
}
else
{
- struct connection *c = con_by_name(msg.name, TRUE);
+ connection_t *c = con_by_name(msg.name, TRUE);
if (c != NULL && c->ikev1)
{
@@ -588,7 +572,7 @@ whack_handle(int whackctlfd)
}
else
{
- struct connection *c = con_by_name(msg.name, TRUE);
+ connection_t *c = con_by_name(msg.name, TRUE);
if (c != NULL && c->ikev1)
{
diff --git a/src/pluto/rsaref/pkcs11.h b/src/pluto/rsaref/pkcs11.h
index 9261e1e4c..3283bdc89 100644
--- a/src/pluto/rsaref/pkcs11.h
+++ b/src/pluto/rsaref/pkcs11.h
@@ -7,10 +7,10 @@
* License is also granted to make and use derivative works provided that
* such works are identified as "derived from the RSA Security Inc. PKCS #11
- * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
* referencing the derived work.
- * RSA Security Inc. makes no representations concerning either the
+ * RSA 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.
@@ -275,7 +275,7 @@ extern "C" {
#define CK_PKCS11_FUNCTION_INFO(name) \
__PASTE(CK_,name) name;
-
+
struct CK_FUNCTION_LIST {
CK_VERSION version; /* Cryptoki version */
diff --git a/src/pluto/rsaref/pkcs11f.h b/src/pluto/rsaref/pkcs11f.h
index dec6315dd..54b884aed 100644
--- a/src/pluto/rsaref/pkcs11f.h
+++ b/src/pluto/rsaref/pkcs11f.h
@@ -7,10 +7,10 @@
* License is also granted to make and use derivative works provided that
* such works are identified as "derived from the RSA Security Inc. PKCS #11
- * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
* referencing the derived work.
- * RSA Security Inc. makes no representations concerning either the
+ * RSA 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.
@@ -564,7 +564,7 @@ CK_PKCS11_FUNCTION_INFO(C_Sign)
/* C_SignUpdate continues a multiple-part signature operation,
- * where the signature is (will be) an appendix to the data,
+ * where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
#ifdef CK_NEED_ARG_LIST
@@ -576,7 +576,7 @@ CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
#endif
-/* C_SignFinal finishes a multiple-part signature operation,
+/* C_SignFinal finishes a multiple-part signature operation,
* returning the signature. */
CK_PKCS11_FUNCTION_INFO(C_SignFinal)
#ifdef CK_NEED_ARG_LIST
@@ -625,12 +625,12 @@ CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
- CK_OBJECT_HANDLE hKey /* verification key */
+ CK_OBJECT_HANDLE hKey /* verification key */
);
#endif
-/* C_Verify verifies a signature in a single-part operation,
+/* C_Verify verifies a signature in a single-part operation,
* where the signature is an appendix to the data, and plaintext
* cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_Verify)
@@ -646,7 +646,7 @@ CK_PKCS11_FUNCTION_INFO(C_Verify)
/* C_VerifyUpdate continues a multiple-part verification
- * operation, where the signature is an appendix to the data,
+ * operation, where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
#ifdef CK_NEED_ARG_LIST
@@ -772,7 +772,7 @@ CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
#endif
-/* C_GenerateKeyPair generates a public-key/private-key pair,
+/* C_GenerateKeyPair generates a public-key/private-key pair,
* creating new key objects. */
CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
#ifdef CK_NEED_ARG_LIST
diff --git a/src/pluto/smartcard.c b/src/pluto/smartcard.c
index 7e4452d89..f1a3932a6 100644
--- a/src/pluto/smartcard.c
+++ b/src/pluto/smartcard.c
@@ -31,6 +31,7 @@
#include <asn1/asn1.h>
#include <credentials/keys/public_key.h>
+#include <credentials/certificates/x509.h>
#include "constants.h"
@@ -58,21 +59,21 @@ 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 */
+ 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 */
@@ -115,7 +116,7 @@ static const char *const pkcs11_return_name_10[] = {
};
static const char *const pkcs11_return_name_20[] = {
- "CKR_DATA_INVALID",
+ "CKR_DATA_INVALID",
"CKR_DATA_LEN_RANGE"
};
@@ -386,8 +387,7 @@ static enum_names pkcs11_return_names =
* The calling application is responsible for cleaning up
* and calling C_Finalize()
*/
-static CK_RV
-scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
+static CK_RV scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
{
if (!mod || mod->_magic != SCX_MAGIC)
return CKR_ARGUMENTS_BAD;
@@ -400,8 +400,8 @@ scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
return CKR_OK;
}
-static scx_pkcs11_module_t*
-scx_load_pkcs11_module(const char *name, CK_FUNCTION_LIST_PTR_PTR funcs)
+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;
@@ -437,14 +437,13 @@ failed: scx_unload_pkcs11_module(mod);
/*
* retrieve a certificate object
*/
-static bool
-scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
-, smartcard_t *sc, cert_t *cert)
+static cert_t* scx_find_cert_object(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE object, smartcard_t *sc)
{
size_t hex_len, label_len;
u_char *hex_id = NULL;
+ cert_t *cert;
chunk_t blob;
- x509cert_t *x509cert;
CK_ATTRIBUTE attr[] = {
{ CKA_ID, NULL_PTR, 0L },
@@ -452,16 +451,13 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
{ 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;
+ return NULL;
}
free(sc->label);
@@ -486,7 +482,7 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
free(hex_id);
free(sc->label);
free(blob.ptr);
- return FALSE;
+ return NULL;
}
free(sc->id);
@@ -500,26 +496,30 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
sc->label[label_len] = '\0';
/* parse the retrieved cert */
- x509cert = malloc_thing(x509cert_t);
- *x509cert = empty_x509cert;
- x509cert->smartcard = TRUE;
- if (!parse_x509cert(blob, 0, x509cert))
+ /* initialize the return argument */
+ cert = malloc_thing(cert_t);
+ *cert = cert_empty;
+ cert->smartcard = TRUE;
+ cert->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, blob,
+ BUILD_END);
+ if (cert->cert)
{
- plog("failed to load cert from smartcard, error in X.509 certificate");
- free_x509cert(x509cert);
- return FALSE;
+ return cert;
}
- cert->type = CERT_X509_SIGNATURE;
- cert->u.x509 = x509cert;
- return TRUE;
+
+ plog("failed to load cert from smartcard, error in X.509 certificate");
+ cert_free(cert);
+ return NULL;
}
+
/*
* search a given slot for PKCS#11 certificate objects
*/
-static void
-scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
+static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
CK_RV rv;
CK_OBJECT_CLASS class = CKO_CERTIFICATE;
@@ -537,10 +537,10 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
CK_OBJECT_HANDLE object;
CK_ULONG obj_count = 0;
- err_t ugh;
time_t valid_until;
smartcard_t *sc;
- x509cert_t *cert;
+ certificate_t *certificate;
+ x509_t *x509;
rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count);
if (rv != CKR_OK)
@@ -559,8 +559,8 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
*sc = empty_sc;
sc->any_slot = FALSE;
sc->slot = slot;
-
- if (!scx_find_cert_object(session, object, sc, &sc->last_cert))
+ sc->last_cert = scx_find_cert_object(session, object, sc);
+ if (sc->last_cert == NULL)
{
scx_free(sc);
continue;
@@ -571,37 +571,31 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
)
/* check validity of certificate */
- cert = sc->last_cert.u.x509;
- valid_until = cert->notAfter;
- ugh = check_validity(cert, &valid_until);
- if (ugh != NULL)
+ certificate = sc->last_cert->cert;
+ if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{
- plog(" %s", ugh);
- free_x509cert(cert);
scx_free(sc);
continue;
}
- else
- {
- DBG(DBG_CONTROL,
- DBG_log(" certificate is valid")
- )
- }
+ DBG(DBG_CONTROL,
+ DBG_log(" certificate is valid")
+ )
sc = scx_add(sc);
+ x509 = (x509_t*)certificate;
/* put end entity and ca certificates into different chains */
- if (cert->isCA)
+ if (x509->get_flags(x509) & X509_CA)
{
- sc->last_cert.u.x509 = add_authcert(cert, AUTH_CA);
+ sc->last_cert = add_authcert(sc->last_cert, X509_CA);
}
else
{
- add_x509_public_key(cert, valid_until, DAL_LOCAL);
- sc->last_cert.u.x509 = add_x509cert(cert);
+ add_public_key_from_cert(sc->last_cert, valid_until, DAL_LOCAL);
+ sc->last_cert = cert_add(sc->last_cert);
}
- share_cert(sc->last_cert);
+ cert_share(sc->last_cert);
time(&sc->last_load);
}
@@ -616,8 +610,7 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
/*
* search all slots for PKCS#11 certificate objects
*/
-static void
-scx_find_all_cert_objects(void)
+static void scx_find_all_cert_objects(void)
{
CK_RV rv;
CK_SLOT_ID_PTR slots = NULL_PTR;
@@ -659,7 +652,7 @@ scx_find_all_cert_objects(void)
, enum_show(&pkcs11_return_names, rv));
continue;
}
-
+
if (!(info.flags & CKF_TOKEN_PRESENT))
{
plog("no token present in slot %lu", slot);
@@ -696,8 +689,7 @@ scx_find_all_cert_objects(void)
* init_args should be unused when we have a PKCS#11 compliant module,
* but NSS softoken breaks that API.
*/
-void
-scx_init(const char* module, const char *init_args)
+void scx_init(const char* module, const char *init_args)
{
#ifdef SMARTCARD
CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, };
@@ -750,10 +742,9 @@ scx_init(const char* module, const char *init_args)
}
/*
- * finalize and unload PKCS#11 cryptoki module
+ * finalize and unload PKCS#11 cryptoki module
*/
-void
-scx_finalize(void)
+void scx_finalize(void)
{
#ifdef SMARTCARD
while (smartcards != NULL)
@@ -783,21 +774,18 @@ scx_finalize(void)
/*
* does a filename contain the token %smartcard?
*/
-bool
-scx_on_smartcard(const char *filename)
+bool scx_on_smartcard(const char *filename)
{
return strneq(filename, SCX_TOKEN, strlen(SCX_TOKEN));
}
#ifdef SMARTCARD
/*
- * find a specific object on the smartcard
+ * 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)
+static bool 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];
@@ -848,8 +836,7 @@ scx_pkcs11_find_object( CK_SESSION_HANDLE session,
/*
* check if a given certificate object id is found in a slot
*/
-static bool
-scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
+static bool scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
{
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE object;
@@ -863,7 +850,7 @@ scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
, enum_show(&pkcs11_return_names, rv));
return FALSE;
}
-
+
if (!(info.flags & CKF_TOKEN_PRESENT))
{
plog("no token present in slot %lu", slot);
@@ -891,7 +878,7 @@ scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
sc->session_opened = TRUE;
return TRUE;
}
-
+
rv = pkcs11_functions->C_CloseSession(session);
if (rv != CKR_OK)
{
@@ -905,8 +892,7 @@ scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
/*
* Connect to the smart card in the reader and select the correct slot
*/
-bool
-scx_establish_context(smartcard_t *sc)
+bool scx_establish_context(smartcard_t *sc)
{
#ifdef SMARTCARD
bool id_found = FALSE;
@@ -983,8 +969,7 @@ scx_establish_context(smartcard_t *sc)
/*
* log in to a session
*/
-bool
-scx_login(smartcard_t *sc)
+bool scx_login(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -996,7 +981,7 @@ scx_login(smartcard_t *sc)
)
return TRUE;
}
-
+
if (sc->pin.ptr == NULL)
{
plog("unable to log in without PIN!");
@@ -1009,7 +994,7 @@ scx_login(smartcard_t *sc)
return FALSE;
}
- rv = pkcs11_functions->C_Login(sc->session, CKU_USER
+ 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)
{
@@ -1031,11 +1016,10 @@ scx_login(smartcard_t *sc)
/*
* logout from a session
*/
-static void
-scx_logout(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"
@@ -1052,8 +1036,7 @@ scx_logout(smartcard_t *sc)
/*
* Release context and disconnect from card
*/
-void
-scx_release_context(smartcard_t *sc)
+void scx_release_context(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1067,7 +1050,7 @@ scx_release_context(smartcard_t *sc)
scx_logout(sc);
sc->session_opened = FALSE;
-
+
rv = pkcs11_functions->C_CloseSession(sc->session);
if (rv != CKR_OK)
plog("error in C_CloseSession: %s"
@@ -1083,68 +1066,66 @@ scx_release_context(smartcard_t *sc)
/*
* Load host certificate from smartcard
*/
-bool
-scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert
-, bool *cached)
+cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached)
{
#ifdef SMARTCARD /* compile with smartcard support */
- CK_OBJECT_HANDLE object;
-
const char *number_slot_id = filename + strlen(SCX_TOKEN);
-
- smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id));
+ CK_OBJECT_HANDLE object;
+ smartcard_t *sc;
+ cert_t *cert = NULL;
/* return the smartcard object */
- *scp = sc;
+ *scp = sc = scx_add(scx_parse_number_slot_id(number_slot_id));
/* is there a cached smartcard certificate? */
- *cached = sc->last_cert.type != CERT_NONE
- && (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
+ *cached = sc->last_cert &&
+ (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;
+ return sc->last_cert;
}
if (!scx_establish_context(sc))
{
scx_release_context(sc);
- return FALSE;
+ return NULL;
}
/* find the certificate object */
if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
{
scx_release_context(sc);
- return FALSE;
+ return NULL;
}
/* retrieve the certificate object */
- if (!scx_find_cert_object(sc->session, object, sc, cert))
+ cert = scx_find_cert_object(sc->session, object, sc);
+ if (cert == NULL)
{
scx_release_context(sc);
- return FALSE;
+ return NULL;
}
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);
- return TRUE;
+ return cert;
#else
plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
- return FALSE;
+ return NULL;
#endif
}
@@ -1158,8 +1139,7 @@ scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert
* %smartcard:45 - - 45
* %smartcard0:45 - 0 45
*/
-smartcard_t*
-scx_parse_number_slot_id(const char *number_slot_id)
+smartcard_t* scx_parse_number_slot_id(const char *number_slot_id)
{
int len = strlen(number_slot_id);
smartcard_t *sc = malloc_thing(smartcard_t);
@@ -1169,7 +1149,7 @@ scx_parse_number_slot_id(const char *number_slot_id)
if (len == 0) /* default: use certificate #1 */
{
- sc->number = 1;
+ sc->number = 1;
}
else if (*number_slot_id == '#') /* #number scheme */
{
@@ -1218,12 +1198,11 @@ scx_parse_number_slot_id(const char *number_slot_id)
/*
* Verify pin on card
*/
-bool
-scx_verify_pin(smartcard_t *sc)
+bool scx_verify_pin(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
-
+
if (!sc->pinpad)
sc->valid = FALSE;
@@ -1270,9 +1249,8 @@ scx_verify_pin(smartcard_t *sc)
/*
* Sign hash on smartcard
*/
-bool
-scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
-, u_char *out, size_t outlen)
+bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
+ size_t outlen)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1377,12 +1355,11 @@ scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
#endif
}
-/*
+/*
* encrypt data block with an RSA public key
*/
-bool
-scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
-, u_char *out, size_t *outlen)
+bool scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
+ size_t *outlen)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1423,7 +1400,7 @@ scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
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)
{
@@ -1467,7 +1444,7 @@ scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
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,
+ 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)
@@ -1527,12 +1504,11 @@ scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
return FALSE;
#endif
}
-/*
+/*
* decrypt a data block with an RSA private key
*/
-bool
-scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
-, u_char *out, size_t *outlen)
+bool scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
+ size_t *outlen)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1570,7 +1546,7 @@ scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
scx_release_context(sc);
return FALSE;
}
-
+
DBG(DBG_CONTROL,
DBG_log("doing RSA decryption on smartcard")
)
@@ -1606,9 +1582,8 @@ scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
* decrypt it using a private RSA key and
* return the decrypted data block via whack
*/
-bool
-scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
-, const char* keyid, int whackfd)
+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];
@@ -1680,7 +1655,7 @@ scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
DBG_dump("smartcard output data:\n", inbuf, outlen)
)
- if (outbase == 0) /* use default base */
+ if (outbase == 0) /* use default base */
outbase = DEFAULT_BASE;
if (outbase == 256) /* ascii plain text */
@@ -1701,8 +1676,7 @@ scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
/*
* get length of RSA key in bytes
*/
-size_t
-scx_get_keylength(smartcard_t *sc)
+size_t scx_get_keylength(smartcard_t *sc)
{
#ifdef SMARTCARD
CK_RV rv;
@@ -1737,8 +1711,7 @@ scx_get_keylength(smartcard_t *sc)
/*
* prompt for pin and verify it
*/
-bool
-scx_get_pin(smartcard_t *sc, int whackfd)
+bool scx_get_pin(smartcard_t *sc, int whackfd)
{
#ifdef SMARTCARD
char pin[BUF_LEN];
@@ -1796,8 +1769,7 @@ scx_get_pin(smartcard_t *sc, int whackfd)
/*
* free the pin code
*/
-void
-scx_free_pin(chunk_t *pin)
+void scx_free_pin(chunk_t *pin)
{
if (pin->ptr != NULL)
{
@@ -1811,12 +1783,12 @@ scx_free_pin(chunk_t *pin)
/*
* frees a smartcard record
*/
-void
-scx_free(smartcard_t *sc)
+void scx_free(smartcard_t *sc)
{
if (sc != NULL)
{
scx_release_context(sc);
+ cert_release(sc->last_cert);
free(sc->id);
free(sc->label);
scx_free_pin(&sc->pin);
@@ -1827,8 +1799,7 @@ scx_free(smartcard_t *sc)
/* release of a smartcard record decreases the count by one
" the record is freed when the counter reaches zero
*/
-void
-scx_release(smartcard_t *sc)
+void scx_release(smartcard_t *sc)
{
if (sc != NULL && --sc->count == 0)
{
@@ -1836,7 +1807,6 @@ scx_release(smartcard_t *sc)
while (*pp != sc)
pp = &(*pp)->next;
*pp = sc->next;
- release_cert(sc->last_cert);
scx_free(sc);
}
}
@@ -1844,8 +1814,7 @@ scx_release(smartcard_t *sc)
/*
* compare two smartcard records by comparing their slots and ids
*/
-static bool
-scx_same(smartcard_t *a, smartcard_t *b)
+static bool scx_same(smartcard_t *a, smartcard_t *b)
{
if (a->number && b->number)
{
@@ -1863,8 +1832,7 @@ scx_same(smartcard_t *a, smartcard_t *b)
/* for each link pointing to the smartcard record
" increase the count by one
*/
-void
-scx_share(smartcard_t *sc)
+void scx_share(smartcard_t *sc)
{
if (sc != NULL)
sc->count++;
@@ -1873,8 +1841,7 @@ scx_share(smartcard_t *sc)
/*
* adds a smartcard record to the chained list
*/
-smartcard_t*
-scx_add(smartcard_t *smartcard)
+smartcard_t* scx_add(smartcard_t *smartcard)
{
smartcard_t *sc = smartcards;
smartcard_t **psc = &smartcards;
@@ -1903,15 +1870,16 @@ scx_add(smartcard_t *smartcard)
/*
* get the smartcard that belongs to an X.509 certificate
*/
-smartcard_t*
-scx_get(x509cert_t *cert)
+smartcard_t* scx_get(cert_t *cert)
{
smartcard_t *sc = smartcards;
while (sc != NULL)
{
- if (sc->last_cert.u.x509 == cert)
+ if (sc->last_cert == cert)
+ {
return sc;
+ }
sc = sc->next;
}
return NULL;
@@ -1920,8 +1888,7 @@ scx_get(x509cert_t *cert)
/*
* prints either the slot number or 'any slot'
*/
-char *
-scx_print_slot(smartcard_t *sc, const char *whitespace)
+char *scx_print_slot(smartcard_t *sc, const char *whitespace)
{
char *buf = temporary_cyclic_buffer();
@@ -1935,8 +1902,7 @@ scx_print_slot(smartcard_t *sc, const char *whitespace)
/*
* list all smartcard info records in a chained list
*/
-void
-scx_list(bool utc)
+void scx_list(bool utc)
{
smartcard_t *sc = smartcards;
@@ -1944,32 +1910,28 @@ scx_list(bool utc)
{
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"
+ whack_log(RC_COMMENT, " ");
+ 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->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);
+ 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)
+ whack_log(RC_COMMENT, " label: '%s'", sc->label);
+ if (sc->last_cert)
{
- char buf[BUF_LEN];
+ certificate_t *certificate = sc->last_cert->cert;
- dntoa(buf, BUF_LEN, sc->last_cert.u.x509->subject);
- whack_log(RC_COMMENT, " subject: '%s'", buf);
+ whack_log(RC_COMMENT, " subject: '%Y'",
+ certificate->get_subject(certificate));
}
sc = sc->next;
}
diff --git a/src/pluto/smartcard.h b/src/pluto/smartcard.h
index 60a0fccfc..7a2229794 100644
--- a/src/pluto/smartcard.h
+++ b/src/pluto/smartcard.h
@@ -42,7 +42,7 @@ typedef struct smartcard smartcard_t;
struct smartcard {
smartcard_t *next;
time_t last_load;
- cert_t last_cert;
+ cert_t *last_cert;
int count;
int number;
unsigned long slot;
@@ -75,8 +75,7 @@ extern void scx_finalize(void);
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);
+extern cert_t* scx_load_cert(const char *filename, smartcard_t **scp, 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
@@ -90,7 +89,7 @@ extern bool scx_op_via_whack(const char* msg, int inbase, int outbase
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);
-extern smartcard_t* scx_get(x509cert_t *cert);
+extern smartcard_t* scx_get(cert_t *cert);
extern void scx_release(smartcard_t *sc);
extern void scx_release_context(smartcard_t *sc);
extern void scx_free_pin(chunk_t *pin);
diff --git a/src/pluto/spdb.c b/src/pluto/spdb.c
index a86c9f215..cdf2cb21b 100644
--- a/src/pluto/spdb.c
+++ b/src/pluto/spdb.c
@@ -24,7 +24,6 @@
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "connections.h"
#include "state.h"
#include "packet.h"
@@ -607,7 +606,7 @@ static u_int32_t decode_long_duration(pb_stream *pbs)
}
/* Preparse the body of an ISAKMP SA Payload and
- * return body of ISAKMP Proposal Payload
+ * return body of ISAKMP Proposal Payload
*
* Only IPsec DOI is accepted (what is the ISAKMP DOI?).
* Error response is rudimentary.
@@ -624,20 +623,20 @@ preparse_isakmp_sa_body(const struct isakmp_sa *sa
{
loglog(RC_LOG_SERIOUS, "Unknown/unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
/* XXX Could send notification back */
- return DOI_NOT_SUPPORTED;
+ return ISAKMP_DOI_NOT_SUPPORTED;
}
/* Situation */
if (!in_struct(ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
{
- return SITUATION_NOT_SUPPORTED;
+ return ISAKMP_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;
+ return ISAKMP_SITUATION_NOT_SUPPORTED;
}
/* The rules for ISAKMP SAs are scattered.
@@ -647,20 +646,20 @@ preparse_isakmp_sa_body(const struct isakmp_sa *sa
*/
if (!in_struct(proposal, &isakmp_proposal_desc, sa_pbs, proposal_pbs))
{
- return PAYLOAD_MALFORMED;
+ return ISAKMP_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;
+ return ISAKMP_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;
+ return ISAKMP_INVALID_PROTOCOL_ID;
}
/* Just what should we accept for the SPI field?
@@ -694,15 +693,15 @@ preparse_isakmp_sa_body(const struct isakmp_sa *sa
u_char junk_spi[MAX_ISAKMP_SPI_SIZE];
if (!in_raw(junk_spi, proposal->isap_spisize, proposal_pbs, "Oakley SPI"))
- return PAYLOAD_MALFORMED;
+ return ISAKMP_PAYLOAD_MALFORMED;
}
else
{
loglog(RC_LOG_SERIOUS, "invalid SPI size (%u) in Oakley Proposal"
, (unsigned)proposal->isap_spisize);
- return INVALID_SPI;
+ return ISAKMP_INVALID_SPI;
}
- return NOTHING_WRONG;
+ return ISAKMP_NOTHING_WRONG;
}
static struct {
@@ -750,14 +749,14 @@ notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans,
if (!in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs))
{
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_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;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
last_transnum = trans.isat_transnum;
@@ -765,7 +764,7 @@ notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans,
{
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;
+ return ISAKMP_INVALID_TRANSFORM_ID;
}
attr_start = trans_pbs.cur;
@@ -779,7 +778,7 @@ notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans,
if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
{
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
@@ -822,7 +821,7 @@ notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans,
DBG_log("preparse_isakmp_policy: peer requests %s authentication"
, prettypolicy(*policy))
)
- return NOTHING_WRONG;
+ return ISAKMP_NOTHING_WRONG;
}
/**
@@ -831,23 +830,22 @@ notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans,
static err_t find_preshared_key(struct state* st)
{
err_t ugh = NULL;
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
if (get_preshared_secret(c) == NULL)
{
- char my_id[BUF_LEN], his_id[BUF_LEN];
+ char 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));
+ snprintf(his_id, sizeof(his_id), "%Y", c->spd.that.id);
}
- ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
- , my_id, his_id);
+ ugh = builddiag("Can't authenticate: no preshared key found "
+ "for '%Y' and '%s'", c->spd.this.id, his_id);
}
return ugh;
}
@@ -868,7 +866,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
struct state *st,
bool initiator)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
unsigned no_trans_left;
/* for each transform payload... */
@@ -892,7 +890,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
if (no_trans_left == 0)
{
loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs);
@@ -908,7 +906,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
u_int32_t val; /* room for larger values */
if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
@@ -917,7 +915,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
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;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
@@ -1071,7 +1069,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
loglog(RC_LOG_SERIOUS
, "attribute OAKLEY_LIFE_TYPE value %s repeated"
, enum_show(&oakley_lifetime_names, val));
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
seen_durations |= LELEM(val);
life_type = val;
@@ -1114,7 +1112,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
, (long) val
, OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
#endif
- }
+ }
ta.life_seconds = val;
break;
case OAKLEY_LIFE_KILOBYTES:
@@ -1210,7 +1208,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
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;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
}
/* We must have liked this transform.
@@ -1264,7 +1262,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
/* copy over the results */
st->st_oakley = ta;
- return NOTHING_WRONG;
+ return ISAKMP_NOTHING_WRONG;
}
/* on to next transform */
@@ -1275,7 +1273,7 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
if (no_trans_left != 0)
{
loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
break;
}
@@ -1283,11 +1281,11 @@ notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
{
loglog(RC_LOG_SERIOUS, "unexpected %s payload in Oakley Proposal"
, enum_show(&payload_names, proposal->isap_np));
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
}
loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform");
- return NO_PROPOSAL_CHOSEN;
+ return ISAKMP_NO_PROPOSAL_CHOSEN;
}
/* Parse the body of an IPsec SA Payload (i.e. Phase 2 / Quick Mode).
@@ -1712,7 +1710,7 @@ parse_ipsec_sa_body(
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;
+ const connection_t *c = st->st_connection;
u_int32_t ipsecdoisit;
pb_stream next_proposal_pbs;
@@ -1726,19 +1724,19 @@ parse_ipsec_sa_body(
{
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;
+ return ISAKMP_DOI_NOT_SUPPORTED;
}
/* Situation */
if (!in_struct(&ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
- return SITUATION_NOT_SUPPORTED;
+ return ISAKMP_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;
+ return ISAKMP_SITUATION_NOT_SUPPORTED;
}
/* The rules for IPsec SAs are scattered.
@@ -1755,7 +1753,7 @@ parse_ipsec_sa_body(
*/
if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
/* for each conjunction of proposals... */
while (next_full)
@@ -1797,13 +1795,13 @@ parse_ipsec_sa_body(
if (!in_raw(filler, sizeof(filler)
, &next_proposal_pbs, "CPI filler")
|| !all_zero(filler, sizeof(filler)))
- return INVALID_SPI;
+ return ISAKMP_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;
+ return ISAKMP_INVALID_SPI;
}
/* We store CPI in the low order of a network order
@@ -1813,7 +1811,7 @@ parse_ipsec_sa_body(
if (!in_raw((u_char *)&next_spi
+ IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
, IPCOMP_CPI_SIZE, &next_proposal_pbs, "CPI"))
- return INVALID_SPI;
+ return ISAKMP_INVALID_SPI;
/* If sanity ruled, CPIs would have to be such that
* the SAID (the triple (CPI, IPCOM, destination IP))
@@ -1832,7 +1830,7 @@ parse_ipsec_sa_body(
{
loglog(RC_LOG_SERIOUS
, "IPsec Proposal contains well-known CPI that I cannot uniquify");
- return INVALID_SPI;
+ return ISAKMP_INVALID_SPI;
}
break;
default:
@@ -1841,7 +1839,7 @@ parse_ipsec_sa_body(
{
loglog(RC_LOG_SERIOUS, "IPsec Proposal contains CPI from non-negotiated range (0x%lx)"
, (unsigned long) ntohl(next_spi));
- return INVALID_SPI;
+ return ISAKMP_INVALID_SPI;
}
break;
}
@@ -1853,11 +1851,11 @@ parse_ipsec_sa_body(
{
loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper SPI size (%u)"
, next_proposal.isap_spisize);
- return INVALID_SPI;
+ return ISAKMP_INVALID_SPI;
}
if (!in_raw((u_char *)&next_spi, sizeof(next_spi), &next_proposal_pbs, "SPI"))
- return INVALID_SPI;
+ return ISAKMP_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
@@ -1867,14 +1865,14 @@ parse_ipsec_sa_body(
{
loglog(RC_LOG_SERIOUS, "IPsec Proposal contains invalid SPI (0x%lx)"
, (unsigned long) ntohl(next_spi));
- return INVALID_SPI;
+ return ISAKMP_INVALID_SPI;
}
}
if (next_proposal.isap_notrans == 0)
{
loglog(RC_LOG_SERIOUS, "IPsec Proposal contains no Transforms");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
switch (next_proposal.isap_protoid)
@@ -1883,7 +1881,7 @@ parse_ipsec_sa_body(
if (ah_seen)
{
loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous AH Proposals");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
ah_seen = TRUE;
ah_prop_pbs = next_proposal_pbs;
@@ -1895,7 +1893,7 @@ parse_ipsec_sa_body(
if (esp_seen)
{
loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous ESP Proposals");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
esp_seen = TRUE;
esp_prop_pbs = next_proposal_pbs;
@@ -1907,7 +1905,7 @@ parse_ipsec_sa_body(
if (ipcomp_seen)
{
loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous IPCOMP Proposals");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
ipcomp_seen = TRUE;
ipcomp_prop_pbs = next_proposal_pbs;
@@ -1918,7 +1916,7 @@ parse_ipsec_sa_body(
default:
loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) in IPsec Proposal"
, enum_show(&protocol_names, next_proposal.isap_protoid));
- return INVALID_PROTOCOL_ID;
+ return ISAKMP_INVALID_PROTOCOL_ID;
}
/* refill next_proposal */
@@ -1931,11 +1929,11 @@ parse_ipsec_sa_body(
{
loglog(RC_LOG_SERIOUS, "unexpected in Proposal: %s"
, enum_show(&payload_names, next_proposal.isap_np));
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
} while (next_proposal.isap_proposal == propno);
/* Now that we have all conjuncts, we should try
@@ -1968,7 +1966,7 @@ parse_ipsec_sa_body(
, tn == ah_proposal.isap_notrans - 1
, FALSE
, st))
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
previous_transnum = ah_trans.isat_transnum;
@@ -1988,7 +1986,7 @@ parse_ipsec_sa_body(
{
case AUTH_ALGORITHM_NONE:
loglog(RC_LOG_SERIOUS, "AUTH_ALGORITHM attribute missing in AH Transform");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
case AUTH_ALGORITHM_HMAC_MD5:
ok_auth = TRUE;
@@ -2010,8 +2008,8 @@ parse_ipsec_sa_body(
{
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;
+ , enum_show(&ah_transform_names, ah_attrs.transid));
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
if (!ok_auth)
{
@@ -2019,7 +2017,7 @@ parse_ipsec_sa_body(
, 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)
+ , enum_show(&ah_transform_names, ah_attrs.transid)
, ip_str(&c->spd.that.host_addr)));
continue; /* try another */
}
@@ -2050,7 +2048,7 @@ parse_ipsec_sa_body(
, tn == esp_proposal.isap_notrans - 1
, FALSE
, st))
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
previous_transnum = esp_trans.isat_transnum;
@@ -2087,7 +2085,7 @@ parse_ipsec_sa_body(
default:
DBG(DBG_CONTROL | DBG_CRYPT
, DBG_log("unsupported ESP Transform %s from %s"
- , enum_show(&esp_transformid_names, esp_attrs.transid)
+ , enum_show(&esp_transform_names, esp_attrs.transid)
, ip_str(&c->spd.that.host_addr)));
continue; /* try another */
}
@@ -2138,7 +2136,7 @@ parse_ipsec_sa_body(
}
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)
@@ -2186,7 +2184,7 @@ parse_ipsec_sa_body(
if (well_known_cpi != 0 && !ah_seen && !esp_seen)
{
plog("illegal proposal: bare IPCOMP used with well-known CPI");
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
for (tn = 0; tn != ipcomp_proposal.isap_notrans; tn++)
@@ -2201,14 +2199,14 @@ parse_ipsec_sa_body(
, tn == ipcomp_proposal.isap_notrans - 1
, TRUE
, st))
- return BAD_PROPOSAL_SYNTAX;
+ return ISAKMP_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;
+ return ISAKMP_BAD_PROPOSAL_SYNTAX;
}
switch (ipcomp_attrs.transid)
@@ -2309,9 +2307,9 @@ parse_ipsec_sa_body(
if (ipcomp_seen)
st->st_ipcomp.attrs = ipcomp_attrs;
- return NOTHING_WRONG;
+ return ISAKMP_NOTHING_WRONG;
}
loglog(RC_LOG_SERIOUS, "no acceptable Proposal in IPsec SA");
- return NO_PROPOSAL_CHOSEN;
+ return ISAKMP_NO_PROPOSAL_CHOSEN;
}
diff --git a/src/pluto/state.c b/src/pluto/state.c
index 5bef36c5c..29d78fb3d 100644
--- a/src/pluto/state.c
+++ b/src/pluto/state.c
@@ -277,7 +277,7 @@ void release_whack(struct state *st)
*/
void delete_state(struct state *st)
{
- struct connection *const c = st->st_connection;
+ connection_t *const c = st->st_connection;
struct state *old_cur_state = cur_state == st? NULL : cur_state;
set_cur_state(st);
@@ -371,7 +371,7 @@ void delete_state(struct state *st)
/**
* Is a connection in use by some state?
*/
-bool states_use_connection(struct connection *c)
+bool states_use_connection(connection_t *c)
{
/* are there any states still using it? */
struct state *st = NULL;
@@ -390,7 +390,7 @@ bool states_use_connection(struct connection *c)
* 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(connection_t *c, bool relations)
{
int pass;
/* this kludge avoids an n^2 algorithm */
@@ -448,7 +448,7 @@ void delete_states_by_connection(struct connection *c, bool relations)
}
}
}
-
+
sr = &c->spd;
while (sr != NULL)
{
@@ -480,7 +480,7 @@ void delete_states_by_peer(ip_address *peer)
{
struct state *this = st;
struct spd_route *sr;
- struct connection *c = this->st_connection;
+ connection_t *c = this->st_connection;
st = st->st_hashchain_next; /* before this is deleted */
@@ -521,7 +521,7 @@ struct state *duplicate_state(struct state *st)
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;
@@ -646,7 +646,7 @@ struct state *find_phase2_state_to_delete(const struct state *p1st,
/**
* 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 connection_t *c, lset_t ok_states)
{
struct state
*st,
@@ -674,7 +674,7 @@ void state_eroute_usage(ip_subnet *ours, ip_subnet *his, unsigned long count,
{
for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- struct connection *c = st->st_connection;
+ connection_t *c = st->st_connection;
/* XXX spd-enum */
if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
@@ -708,7 +708,7 @@ 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;
+ const connection_t *c = st->st_connection;
long delta = st->st_event->ev_time >= n
? (long)(st->st_event->ev_time - n)
@@ -724,7 +724,7 @@ void fmt_state(bool all, struct state *st, time_t n, char *state_buf,
? "; 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);
@@ -824,9 +824,9 @@ void fmt_state(bool all, struct state *st, time_t n, char *state_buf,
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;
+ connection_t *ca = sap->st_connection;
const struct state *sbp = *(const struct state *const *)b;
- struct connection *cb = sbp->st_connection;
+ connection_t *cb = sbp->st_connection;
/* DBG_log("comparing %s to %s", ca->name, cb->name); */
diff --git a/src/pluto/state.h b/src/pluto/state.h
index a059c52b4..35ffe5a5b 100644
--- a/src/pluto/state.h
+++ b/src/pluto/state.h
@@ -21,6 +21,7 @@
#include <crypto/diffie_hellman.h>
+#include "defs.h"
#include "connections.h"
/* Message ID mechanism.
diff --git a/src/pluto/timer.c b/src/pluto/timer.c
index 89082f88e..74806a40c 100644
--- a/src/pluto/timer.c
+++ b/src/pluto/timer.c
@@ -143,7 +143,7 @@ void event_schedule(enum event_type type, time_t tm, struct state *st)
bool init_secret(void)
{
rng_t *rng;
-
+
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (rng == NULL)
@@ -166,7 +166,7 @@ void handle_timer_event(void)
struct event *ev = evlist;
int type;
struct state *st;
- struct connection *c = NULL;
+ connection_t *c = NULL;
ip_address peer;
if (ev == (struct event *) NULL) /* Just paranoid */
@@ -216,7 +216,7 @@ void handle_timer_event(void)
passert(st->st_dpd_event == ev);
st->st_dpd_event = NULL;
}
- else
+ else
{
passert(st->st_event == ev);
st->st_event = NULL;
diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c
index a532e50f2..7d3c96c87 100644
--- a/src/pluto/vendor.c
+++ b/src/pluto/vendor.c
@@ -158,7 +158,7 @@ static struct vid_struct _vid_tab[] = {
{ 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,
+ { VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH,
NULL, "Cisco IOS Device", { "\x3e\x98\x40\x48", 4 } },
/*
@@ -197,7 +197,9 @@ static struct vid_struct _vid_tab[] = {
/*
* strongSwan
*/
- DEC_MD5_VID(STRONGSWAN, "strongSwan 4.3.4")
+ DEC_MD5_VID(STRONGSWAN, "strongSwan")
+ DEC_MD5_VID(STRONGSWAN_4_3_5, "strongSwan 4.3.5")
+ DEC_MD5_VID(STRONGSWAN_4_3_4, "strongSwan 4.3.4")
DEC_MD5_VID(STRONGSWAN_4_3_3, "strongSwan 4.3.3")
DEC_MD5_VID(STRONGSWAN_4_3_2, "strongSwan 4.3.2")
DEC_MD5_VID(STRONGSWAN_4_3_1, "strongSwan 4.3.1")
@@ -296,7 +298,7 @@ static struct vid_struct _vid_tab[] = {
DEC_MD5_VID(NATT_RFC, "RFC 3947")
/* misc */
-
+
{ VID_MISC_XAUTH, VID_KEEP, NULL, "XAUTH",
{ "\x09\x00\x26\x89\xdf\xd6\xb7\x12", 8 } },
@@ -304,7 +306,7 @@ static struct vid_struct _vid_tab[] = {
{ "\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")
/**
@@ -338,9 +340,9 @@ void init_vendorid(void)
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);
+ hasher->allocate_hash(hasher, vid_data, &vid->vid);
}
if (vid->descr == NULL)
diff --git a/src/pluto/vendor.h b/src/pluto/vendor.h
index 8aa2f6348..3df1a8196 100644
--- a/src/pluto/vendor.h
+++ b/src/pluto/vendor.h
@@ -138,6 +138,8 @@ enum known_vendorid {
VID_STRONGSWAN_4_3_1 =119,
VID_STRONGSWAN_4_3_2 =120,
VID_STRONGSWAN_4_3_3 =121,
+ VID_STRONGSWAN_4_3_4 =122,
+ VID_STRONGSWAN_4_3_5 =123,
/* 101 - 200 : NAT-Traversal */
VID_NATT_STENBERG_01 =151,
diff --git a/src/pluto/virtual.c b/src/pluto/virtual.c
index 2067bde01..3e8d5fcba 100644
--- a/src/pluto/virtual.c
+++ b/src/pluto/virtual.c
@@ -180,7 +180,7 @@ init_virtual_ip(const char *private_list)
* ex: vhost:%no,%dhcp,%priv,%v4:192.168.1.0/24
*/
struct virtual_t
-*create_virtual(const struct connection *c, const char *string)
+*create_virtual(const connection_t *c, const char *string)
{
unsigned short flags=0, n_net=0, i;
const char *str = string, *next, *first_net=NULL;
@@ -227,7 +227,7 @@ struct virtual_t
}
else
goto fail;
-
+
str = *next ? next+1 : NULL;
}
@@ -267,14 +267,13 @@ is_virtual_end(const struct end *that)
}
bool
-is_virtual_connection(const struct connection *c)
+is_virtual_connection(const connection_t *c)
{
return ((c->spd.that.virt)?TRUE:FALSE);
}
-static bool
-net_in_list(const ip_subnet *peer_net, const ip_subnet *list,
- unsigned short len)
+static bool net_in_list(const ip_subnet *peer_net, const ip_subnet *list,
+ unsigned short len)
{
unsigned short i;
@@ -289,9 +288,8 @@ net_in_list(const ip_subnet *peer_net, const ip_subnet *list,
return FALSE;
}
-bool
-is_virtual_net_allowed(const struct connection *c, const ip_subnet *peer_net,
- const ip_address *his_addr)
+bool is_virtual_net_allowed(const connection_t *c, const ip_subnet *peer_net,
+ const ip_address *his_addr)
{
if (c->spd.that.virt == NULL)
return FALSE;
@@ -312,7 +310,7 @@ is_virtual_net_allowed(const struct connection *c, const ip_subnet *peer_net,
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 **/
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
index 0953f18f5..d8e887955 100644
--- a/src/pluto/x509.c
+++ b/src/pluto/x509.c
@@ -26,14 +26,13 @@
#include <freeswan.h>
#include <asn1/asn1.h>
-#include <asn1/asn1_parser.h>
-#include <asn1/oid.h>
#include <crypto/hashers/hasher.h>
+#include <utils/enumerator.h>
+#include <utils/identification.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
#include "x509.h"
#include "crl.h"
#include "ca.h"
@@ -44,1000 +43,6 @@
#include "ocsp.h"
/**
- * Chained lists of X.509 end certificates
- */
-static x509cert_t *x509certs = NULL;
-
-/**
- * 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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define BASIC_CONSTRAINTS_CA 1
-
-/**
- * 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_CERT_ISSUER 3
-#define AUTH_KEY_ID_CERT_SERIAL 5
-
-/**
- * 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
-
-/**
- * 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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define EXT_KEY_USAGE_PURPOSE_ID 1
-
-/**
- * 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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define GENERAL_NAMES_GN 1
-
-/**
- * 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, "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_DIRECTORY_NAME 8
-#define GN_OBJ_EDI_PARTY_NAME 10
-#define GN_OBJ_URI 12
-#define GN_OBJ_IP_ADDRESS 14
-#define GN_OBJ_REGISTERED_ID 16
-
-/**
- * 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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define ON_OBJ_ID_TYPE 0
-#define ON_OBJ_VALUE 1
-
-/**
- * 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, "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
-
-/**
- * ASN.1 definition of an X.509v3 x509_cert
- */
-static const asn1Object_t certObjects[] = {
- { 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_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 */
- 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;
-} x501rdn_t;
-
-/* X.501 acronyms for well known object identifiers (OIDs) */
-
-static u_char oid_ND[] = {0x02, 0x82, 0x06, 0x01,
- 0x0A, 0x07, 0x14};
-static u_char oid_UID[] = {0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x01};
-static u_char oid_DC[] = {0x09, 0x92, 0x26, 0x89, 0x93,
- 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};
-static u_char oid_C[] = {0x55, 0x04, 0x06};
-static u_char oid_L[] = {0x55, 0x04, 0x07};
-static u_char oid_ST[] = {0x55, 0x04, 0x08};
-static u_char oid_O[] = {0x55, 0x04, 0x0A};
-static u_char oid_OU[] = {0x55, 0x04, 0x0B};
-static u_char oid_T[] = {0x55, 0x04, 0x0C};
-static u_char oid_D[] = {0x55, 0x04, 0x0D};
-static u_char oid_N[] = {0x55, 0x04, 0x29};
-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};
-static u_char oid_E[] = {0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x01};
-static u_char oid_UN[] = {0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x02};
-static u_char oid_TCGID[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0x89,
- 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B};
-
-static const x501rdn_t x501rdns[] = {
- {"ND" , {oid_ND, 7}, ASN1_PRINTABLESTRING},
- {"UID" , {oid_UID, 10}, ASN1_PRINTABLESTRING},
- {"DC" , {oid_DC, 10}, ASN1_PRINTABLESTRING},
- {"CN" , {oid_CN, 3}, ASN1_PRINTABLESTRING},
- {"S" , {oid_S, 3}, ASN1_PRINTABLESTRING},
- {"SN" , {oid_SN, 3}, ASN1_PRINTABLESTRING},
- {"serialNumber" , {oid_SN, 3}, ASN1_PRINTABLESTRING},
- {"C" , {oid_C, 3}, ASN1_PRINTABLESTRING},
- {"L" , {oid_L, 3}, ASN1_PRINTABLESTRING},
- {"ST" , {oid_ST, 3}, ASN1_PRINTABLESTRING},
- {"O" , {oid_O, 3}, ASN1_PRINTABLESTRING},
- {"OU" , {oid_OU, 3}, ASN1_PRINTABLESTRING},
- {"T" , {oid_T, 3}, ASN1_PRINTABLESTRING},
- {"D" , {oid_D, 3}, ASN1_PRINTABLESTRING},
- {"N" , {oid_N, 3}, ASN1_PRINTABLESTRING},
- {"G" , {oid_G, 3}, ASN1_PRINTABLESTRING},
- {"I" , {oid_I, 3}, ASN1_PRINTABLESTRING},
- {"ID" , {oid_ID, 3}, ASN1_PRINTABLESTRING},
- {"EN" , {oid_EN, 10}, ASN1_PRINTABLESTRING},
- {"employeeNumber" , {oid_EN, 10}, ASN1_PRINTABLESTRING},
- {"E" , {oid_E, 9}, ASN1_IA5STRING},
- {"Email" , {oid_E, 9}, ASN1_IA5STRING},
- {"emailAddress" , {oid_E, 9}, ASN1_IA5STRING},
- {"UN" , {oid_UN, 9}, ASN1_IA5STRING},
- {"unstructuredName", {oid_UN, 9}, ASN1_IA5STRING},
- {"TCGID" , {oid_TCGID, 12}, ASN1_PRINTABLESTRING}
-};
-
-#define X501_RDN_ROOF 26
-
-static u_char ASN1_subjectAltName_oid_str[] = {
- 0x06, 0x03, 0x55, 0x1D, 0x11
-};
-
-static const chunk_t ASN1_subjectAltName_oid = chunk_from_buf(ASN1_subjectAltName_oid_str);
-
-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;
-}
-
-
-/**
- * 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)
-{
- *rdn = chunk_empty;
- *attribute = chunk_empty;
-
- /* a DN is a SEQUENCE OF RDNs */
-
- if (*dn.ptr != ASN1_SEQUENCE)
- {
- return "DN is not a SEQUENCE";
- }
-
- rdn->len = asn1_length(&dn);
-
- if (rdn->len == ASN1_INVALID_LENGTH)
- {
- return "Invalid RDN length";
- }
- rdn->ptr = dn.ptr;
-
- /* are there any RDNs ? */
- *next = rdn->len > 0;
-
- 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)
-{
- chunk_t body;
-
- /* 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";
- }
- body.ptr = attribute->ptr;
-
- /* advance to start of next attribute */
- attribute->ptr += body.len;
- attribute->len -= body.len;
-
- /* attribute type is an OID */
- if (*body.ptr != ASN1_OID)
- {
- return "attributeType is not an OID";
- }
-
- /* extract OID */
- oid->len = asn1_length(&body);
-
- if (oid->len == ASN1_INVALID_LENGTH)
- {
- return "Invalid attribute OID length";
- }
- oid->ptr = body.ptr;
-
- /* advance to the attribute value */
- body.ptr += oid->len;
- body.len -= oid->len;
-
- /* extract string type */
- *type = *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;
-
- return NULL;
-}
-
-/**
- * Parses an ASN.1 distinguished name int its OID/value pairs
- */
-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;
-
- err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
-
- if (ugh != NULL) /* a parsing error has occured */
- {
- return ugh;
- }
-
- while (next)
- {
- ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
-
- 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,", "));
- }
-
- /* 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;
-}
-
-/**
- * Count the number of wildcard RDNs in a distinguished name
- */
-int dn_count_wildcards(chunk_t dn)
-{
- chunk_t rdn, attribute, oid, value;
- asn1_t type;
- bool next;
- int wildcards = 0;
-
- err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
-
- if (ugh != NULL) /* a parsing error has occured */
- {
- return -1;
- }
-
- 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;
-}
-
-/**
- * Prints a binary string in hexadecimal form
- */
-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++));
-}
-
-
-/** 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)
-{
- err_t ugh = NULL;
- chunk_t str;
-
- str.ptr = dst;
- str.len = dstlen;
- 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)
-{
- 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
- {
- 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
- * ASN.1 distinguished name into binary DER-encoded format
- */
-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 = 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
- {
- switch (state)
- {
- 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;
- }
- } 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
- */
-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;
-
- /* same lengths for the DNs */
- if (a.len != b.len)
- {
- return FALSE;
- }
-
- /* try a binary comparison first */
- if (memeq(a.ptr, b.ptr, b.len))
- {
- 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;
- }
-
- /* 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;
- }
-
- /* 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;
- }
- }
- }
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- {
- return FALSE;
- }
-
- /* the two DNs are equal! */
- return TRUE;
-}
-
-
-/**
- * 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)
-{
- 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 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)
- {
- 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 == '*')
- {
- (*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;
- }
- }
- }
-
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- {
- return FALSE;
- }
-
- /* the two DNs match! */
- return TRUE;
-}
-
-/**
- * Compare two X.509 certificates by comparing their signatures
- */
-bool same_x509cert(const x509cert_t *a, const x509cert_t *b)
-{
- return chunk_equals(a->signature, b->signature);
-}
-
-/**
- * For each link pointing to the certificate increase the count by one
- */
-void share_x509cert(x509cert_t *cert)
-{
- if (cert != NULL)
- {
- cert->count++;
- }
-}
-
-/**
- * Add a X.509 user/host certificate to the chained list
- */
-x509cert_t* add_x509cert(x509cert_t *cert)
-{
- x509cert_t *c = x509certs;
-
- while (c != NULL)
- {
- if (same_x509cert(c, cert)) /* already in chain, free cert */
- {
- free_x509cert(cert);
- return c;
- }
- 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;
-}
-
-/**
- * Choose either subject DN or a subjectAltName as connection end ID
- */
-void select_x509cert_id(x509cert_t *cert, struct id *end_id)
-{
- bool copy_subject_dn = TRUE; /* ID is subject DN */
-
- if (end_id->kind != ID_ANY) /* check for matching subjectAltName */
- {
- generalName_t *gn = cert->subjectAltName;
-
- 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_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);
- }
- 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
*/
bool same_keyid(chunk_t a, chunk_t b)
@@ -1050,271 +55,118 @@ bool same_keyid(chunk_t a, chunk_t b)
}
/**
- * Check for equality between two serial numbers
- */
-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 chunk_equals(a, b);
-}
-
-/**
- * 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 *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)))
- {
- return cert;
- }
- cert = cert->next;
- }
- return NULL;
-}
-
-/**
- * Encode a linked list of subjectAltNames
- */
-chunk_t build_subjectAltNames(generalName_t *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;
- }
-
- pos = asn1_build_object(&names, ASN1_SEQUENCE, len);
-
- 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));
-}
-
-/**
- * Build a to-be-signed X.509 certificate body
- */
-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);
-
- chunk_t extensions = chunk_empty;
-
- chunk_t key = rsa->get_encoding(rsa);
-
- 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
- */
-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 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);
-}
-
-/**
- * Free the dynamic memory used to store generalNames
- */
-void free_generalNames(generalName_t* gn, bool free_name)
-{
- while (gn != NULL)
- {
- generalName_t *gn_top = gn;
- if (free_name)
- {
- free(gn->name.ptr);
- }
- gn = gn->next;
- free(gn_top);
- }
-}
-
-/**
- * Free a X.509 certificate
- */
-void free_x509cert(x509cert_t *cert)
-{
- 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
- */
-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);
- }
-}
-
-/**
* Stores a chained list of end certs and CA certs
*/
-void store_x509certs(x509cert_t **firstcert, bool strict)
+void store_x509certs(linked_list_t *certs, bool strict)
{
- x509cert_t *cacerts = NULL;
- x509cert_t **pp = firstcert;
+ cert_t *x509cert, *cacerts = NULL;
+ certificate_t *cert;
+ enumerator_t *enumerator;
- /* first extract CA certs, discarding root CA certs */
+ /* first extract CA certs, ignoring self-signed root CA certs */
- while (*pp != NULL)
+ enumerator = certs->create_enumerator(certs);
+ while (enumerator->enumerate(enumerator, &cert))
{
- x509cert_t *cert = *pp;
+ x509_t *x509 = (x509_t*)cert;
+ x509_flag_t flags;
- if (cert->isCA)
+ flags = x509->get_flags(x509);
+ if (flags & X509_CA)
{
- *pp = cert->next;
-
/* we don't accept self-signed CA certs */
- if (same_dn(cert->issuer, cert->subject))
+ if (flags & X509_SELF_SIGNED)
{
plog("self-signed cacert rejected");
- free_x509cert(cert);
}
else
{
/* insertion into temporary chain of candidate CA certs */
- cert->next = cacerts;
- cacerts = cert;
+ x509cert = malloc_thing(cert_t);
+ *x509cert = cert_empty;
+ x509cert->cert = cert->get_ref(cert);
+ x509cert->next = cacerts;
+ cacerts = x509cert;
}
}
- else
- {
- pp = &cert->next;
- }
}
+ enumerator->destroy(enumerator);
/* now verify the candidate CA certs */
-
- while (cacerts != NULL)
+
+ while (cacerts)
{
- x509cert_t *cert = cacerts;
-
+ cert_t *cert = cacerts;
+
cacerts = cacerts->next;
if (trust_authcert_candidate(cert, cacerts))
{
- add_authcert(cert, AUTH_CA);
+ add_authcert(cert, X509_CA);
}
else
{
plog("intermediate cacert rejected");
- free_x509cert(cert);
+ cert_free(cert);
}
}
-
- /* now verify the end certificates */
- pp = firstcert;
+ /* now verify the end certificates */
- while (*pp != NULL)
+ enumerator = certs->create_enumerator(certs);
+ while (enumerator->enumerate(enumerator, &cert))
{
time_t valid_until;
- x509cert_t *cert = *pp;
+ x509_t *x509 = (x509_t*)cert;
- if (verify_x509cert(cert, strict, &valid_until))
+ if (!(x509->get_flags(x509) & X509_CA))
{
- 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");
+ x509cert = malloc_thing(cert_t);
+ *x509cert = cert_empty;
+ x509cert->cert = cert->get_ref(cert);
+
+ if (verify_x509cert(x509cert, strict, &valid_until))
+ {
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log("public key validated")
+ )
+ add_public_key_from_cert(x509cert, valid_until, DAL_SIGNED);
+ }
+ else
+ {
+ plog("X.509 certificate rejected");
+ cert_free(x509cert);
+ }
}
- *pp = cert->next;
- free_x509cert(cert);
}
+ enumerator->destroy(enumerator);
}
/**
* Check if a signature over binary blob is genuine
*/
bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
- const x509cert_t *issuer_cert)
+ certificate_t *issuer_cert)
{
- public_key_t *key = issuer_cert->public_key;
- signature_scheme_t scheme = signature_scheme_from_oid(algorithm);
+ bool success;
+ public_key_t *key;
+ signature_scheme_t scheme;
+ scheme = signature_scheme_from_oid(algorithm);
if (scheme == SIGN_UNKNOWN)
{
return FALSE;
}
- return key->verify(key, scheme, tbs, sig);
+
+ key = issuer_cert->get_public_key(issuer_cert);
+ if (key == NULL)
+ {
+ return FALSE;
+ }
+ success = key->verify(key, scheme, tbs, sig);
+ key->destroy(key);
+
+ return success;
}
/**
@@ -1329,631 +181,58 @@ chunk_t x509_build_signature(chunk_t tbs, int algorithm, private_key_t *key,
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
- */
-static bool parse_basicConstraints(chunk_t blob, int level0)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- bool isCA = FALSE;
-
- parser = asn1_parser_create(basicConstraintsObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- if (objectID == BASIC_CONSTRAINTS_CA)
- {
- isCA = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(isCA)?"TRUE":"FALSE");
- )
- }
- }
- parser->destroy(parser);
-
- return isCA;
-}
-
-/**
- * Converts a X.500 generalName into an ID
- */
-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 */
- {
- 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);
- }
- 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;
- }
-}
-
-/**
- * Compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280
- * as the 160 bit SHA-1 hash of the public key
- */
-bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID)
-{
- 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
- */
-static bool parse_otherName(chunk_t blob, int level0)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- int oid = OID_UNKNOWN;
- bool success = FALSE;
-
- parser = asn1_parser_create(otherNameObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID)
- {
- 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;
- }
- }
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
- return success;
-}
-
-
-/**
- * Extracts a generalName
- */
-static generalName_t* parse_generalName(chunk_t blob, int level0)
-{
- u_char buf[BUF_LEN];
- asn1_parser_t *parser;
- chunk_t object;
- generalName_t *gn = NULL;
- int objectID;
-
- parser = asn1_parser_create(generalNameObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- 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;
- }
-
- if (valid_gn)
- {
- gn = malloc_thing(generalName_t);
- gn->kind = (objectID - GN_OBJ_OTHER_NAME) / 2;
- gn->name = object;
- gn->next = NULL;
- goto end;
- }
- }
-
-end:
- parser->destroy(parser);
- return gn;
-}
-
-/**
- * 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_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 top_gn;
-}
-
-/**
- * Returns a directoryName
- */
-chunk_t get_directoryName(chunk_t blob, int level, bool implicit)
-{
- chunk_t name = chunk_empty;
- generalName_t * gn = parse_generalNames(blob, level, implicit);
-
- if (gn != NULL && gn->kind == GN_DIRECTORY_NAME)
- {
- name= gn->name;
- }
- free_generalNames(gn, FALSE);
- return name;
-}
-
-/**
- * Extracts an authoritykeyIdentifier
- */
-void parse_authorityKeyIdentifier(chunk_t blob, int level0,
- chunk_t *authKeyID,
- chunk_t *authKeySerialNumber)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
-
- 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);
-
- free_generalNames(gn, FALSE);
- }
- break;
- case AUTH_KEY_ID_CERT_SERIAL:
- *authKeySerialNumber = object;
- break;
- default:
- break;
- }
- }
- parser->destroy(parser);
-}
-
-/**
- * Extracts an authorityInfoAcess location
- */
-static void parse_authorityInfoAccess(chunk_t blob, int level0,
- chunk_t *accessLocation)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- int accessMethod = OID_UNKNOWN;
-
- parser = asn1_parser_create(authInfoAccessObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID)
- {
- case AUTH_INFO_ACCESS_METHOD:
- accessMethod = asn1_known_oid(object);
- break;
- case AUTH_INFO_ACCESS_LOCATION:
- {
- 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;
- }
- }
- break;
- default:
- break;
- }
- }
-
-end:
- parser->destroy(parser);
-}
-
-/**
- * Extracts extendedKeyUsage OIDs
- */
-static bool parse_extendedKeyUsage(chunk_t blob, int level0)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- bool ocsp_signing = FALSE;
-
- 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);
-
- return ocsp_signing;
-}
-
-/**
- * Extracts one or several crlDistributionPoints
- * and puts them into a chained list
- */
-static generalName_t* parse_crlDistributionPoints(chunk_t blob, int level0)
-{
- 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 */
-
- parser = asn1_parser_create(crlDistributionPointsObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- 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;
- }
- }
- }
- parser->destroy(parser);
-
- return top_gn;
-}
-
-/**
- * Parses an X.509v3 certificate
- */
-bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
-{
- 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;
- }
- }
- success = parser->success(parser);
- time(&cert->installed);
-
-end:
- parser->destroy(parser);
- return success;
-}
-
-/**
- * Verify the validity of a certificate by
- * checking the notBefore and notAfter dates
- */
-err_t check_validity(const x509cert_t *cert, time_t *until)
-{
- time_t current_time;
-
- 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 (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
*/
-bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
+bool verify_x509cert(cert_t *cert, bool strict, time_t *until)
{
- int pathlen;
+ int pathlen, pathlen_constraint;
- *until = cert->notAfter;
+ *until = 0;
- for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+ for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
{
- x509cert_t *issuer_cert;
- u_char buf[BUF_LEN];
- err_t ugh = NULL;
+ certificate_t *certificate = cert->cert;
+ identification_t *subject = certificate->get_subject(certificate);
+ identification_t *issuer = certificate->get_issuer(certificate);
+ x509_t *x509 = (x509_t*)certificate;
+ chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
+ cert_t *issuer_cert;
+ time_t notBefore, notAfter;
+ bool valid;
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)
+ DBG_log("subject: '%Y'", subject);
+ DBG_log("issuer: '%Y'", issuer);
+ if (authKeyID.ptr)
{
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
+ DBG_log("authkey: %#B", &authKeyID);
}
)
- ugh = check_validity(cert, until);
-
- if (ugh != NULL)
+ valid = certificate->get_validity(certificate, NULL,
+ &notBefore, &notAfter);
+ if (*until == UNDEFINED_TIME || notAfter < *until)
{
- plog("%s", ugh);
+ *until = notAfter;
+ }
+ if (!valid)
+ {
+ plog("certificate is invalid (valid from %T to %T)",
+ &notBefore, FALSE, &notAfter, FALSE);
return FALSE;
}
-
DBG(DBG_CONTROL,
DBG_log("certificate is valid")
)
lock_authcert_list("verify_x509cert");
- issuer_cert = get_authcert(cert->issuer, cert->authKeySerialNumber
- , cert->authKeyID, AUTH_CA);
-
+ issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
if (issuer_cert == NULL)
{
plog("issuer cacert not found");
@@ -1964,8 +243,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
DBG_log("issuer cacert found")
)
- if (!x509_check_signature(cert->tbsCertificate, cert->signature,
- cert->algorithm, issuer_cert))
+ if (!certificate->issued_by(certificate, issuer_cert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("verify_x509cert");
@@ -1976,11 +254,22 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
)
unlock_authcert_list("verify_x509cert");
+ /* check path length constraint */
+ pathlen_constraint = x509->get_pathLenConstraint(x509);
+ if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
+ pathlen > pathlen_constraint)
+ {
+ plog("path length of %d violates constraint of %d",
+ pathlen, pathlen_constraint);
+ return FALSE;
+ }
+
/* check if cert is a self-signed root ca */
- if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
+ if (pathlen >= 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
{
DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca")
+ DBG_log("reached self-signed root ca with a path length of %d",
+ pathlen)
)
return TRUE;
}
@@ -1988,7 +277,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
{
time_t nextUpdate = *until;
time_t revocationDate = UNDEFINED_TIME;
- crl_reason_t revocationReason = REASON_UNSPECIFIED;
+ crl_reason_t revocationReason = CRL_REASON_UNSPECIFIED;
/* first check certificate revocation using ocsp */
cert_status_t status = verify_by_ocsp(cert, &nextUpdate
@@ -2017,7 +306,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
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
*/
@@ -2048,15 +337,15 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
/* go up one step in the trust chain */
cert = issuer_cert;
}
- plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ plog("maximum path length of %d exceeded", X509_MAX_PATH_LEN);
return FALSE;
}
/**
* 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, cert_t* cert,
+ x509_flag_t flags, bool utc)
{
bool first = TRUE;
time_t now;
@@ -2064,74 +353,107 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
/* determine the current time */
time(&now);
- while (cert != NULL)
+ while (cert)
{
- 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;
+ certificate_t *certificate = cert->cert;
+ x509_t *x509 = (x509_t*)certificate;
- c.type = CERT_X509_SIGNATURE;
- c.u.x509 = cert;
+ if (certificate->get_type(certificate) == CERT_X509 &&
+ (flags == X509_NONE || (flags & x509->get_flags(x509))))
+ {
+ enumerator_t *enumerator;
+ char buf[BUF_LEN];
+ char *pos = buf;
+ int len = BUF_LEN, pathlen;
+ bool first_altName = TRUE;
+ identification_t *id;
+ time_t notBefore, notAfter;
+ public_key_t *key;
+ chunk_t serial, keyid, subjkey, authkey;
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, " ");
- 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)
+ enumerator = x509->create_subjectAltName_enumerator(x509);
+ while (enumerator->enumerate(enumerator, &id))
{
- datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':',
- buf, BUF_LEN);
- whack_log(RC_COMMENT, " subjkey: %s", buf);
+ int written;
+
+ if (first_altName)
+ {
+ written = snprintf(pos, len, "%Y", id);
+ first_altName = FALSE;
+ }
+ else
+ {
+ written = snprintf(pos, len, ", %Y", id);
+ }
+ pos += written;
+ len -= written;
+ }
+ enumerator->destroy(enumerator);
+ if (!first_altName)
+ {
+ whack_log(RC_COMMENT, " altNames: %s", buf);
+ }
+
+ whack_log(RC_COMMENT, " subject: \"%Y\"",
+ certificate->get_subject(certificate));
+ whack_log(RC_COMMENT, " issuer: \"%Y\"",
+ certificate->get_issuer(certificate));
+ serial = x509->get_serial(x509);
+ whack_log(RC_COMMENT, " serial: %#B", &serial);
+
+ /* list validity */
+ certificate->get_validity(certificate, &now, &notBefore, &notAfter);
+ whack_log(RC_COMMENT, " validity: not before %T %s",
+ &notBefore, utc,
+ (notBefore < now)?"ok":"fatal (not valid yet)");
+ whack_log(RC_COMMENT, " not after %T %s",
+ &notAfter, utc,
+ check_expiry(notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
+
+ key = certificate->get_public_key(certificate);
+ if (key);
+ {
+ 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(cert)? ", has private key" : ""));
+
+ if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ {
+ whack_log(RC_COMMENT, " keyid: %#B", &keyid);
+ }
+ if (key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &subjkey))
+ {
+ whack_log(RC_COMMENT, " subjkey: %#B", &subjkey);
+ }
+ key->destroy(key);
}
- if (cert->authKeyID.ptr != NULL)
+
+ /* list optional authorityKeyIdentifier */
+ authkey = x509->get_authKeyIdentifier(x509);
+ if (authkey.ptr)
{
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':',
- buf, BUF_LEN);
- whack_log(RC_COMMENT, " authkey: %s", buf);
+ whack_log(RC_COMMENT, " authkey: %#B", &authkey);
}
- if (cert->authKeySerialNumber.ptr != NULL)
+
+ /* list optional pathLenConstraint */
+ pathlen = x509->get_pathLenConstraint(x509);
+ if (pathlen != X509_NO_PATH_LEN_CONSTRAINT)
{
- datatot(cert->authKeySerialNumber.ptr,
- cert->authKeySerialNumber.len, ':', buf, BUF_LEN);
- whack_log(RC_COMMENT, " aserial: %s", buf);
+ whack_log(RC_COMMENT, " pathlen: %d", pathlen);
}
+
}
cert = cert->next;
}
}
-/**
- * List all X.509 end certificates in a chained list
- */
-void list_x509_end_certs(bool utc)
-{
- list_x509cert_chain("End", x509certs, AUTH_NONE, utc);
-}
diff --git a/src/pluto/x509.h b/src/pluto/x509.h
index ab0fbac9e..e904618b3 100644
--- a/src/pluto/x509.h
+++ b/src/pluto/x509.h
@@ -18,122 +18,23 @@
#ifndef _X509_H
#define _X509_H
-#include <credentials/keys/public_key.h>
+#include <utils/identification.h>
+#include <utils/linked_list.h>
#include <credentials/keys/private_key.h>
+#include <credentials/certificates/x509.h>
#include "constants.h"
-#include "id.h"
+#include "certs.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
-} generalNames_t;
-
-/* access structure for a GeneralName */
-
-typedef struct generalName generalName_t;
-
-struct generalName {
- generalName_t *next;
- generalNames_t kind;
- chunk_t name;
-};
-
-/* access structure for an X.509v3 certificate */
-
-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;
- 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 */
-extern const x509cert_t empty_x509cert;
-
-extern bool same_serial(chunk_t a, chunk_t b);
extern bool same_keyid(chunk_t a, chunk_t b);
-extern bool same_dn(chunk_t a, chunk_t b);
-extern bool match_dn(chunk_t a, chunk_t b, int *wildcards);
-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 err_t atodn(char *src, chunk_t *dn);
-extern void gntoid(struct id *id, const generalName_t *gn);
-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);
-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 x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
- const x509cert_t *issuer_cert);
+ certificate_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, 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 bool verify_x509cert(cert_t *cert, bool strict, time_t *until);
+extern void store_x509certs(linked_list_t *certs, bool strict);
+extern void list_x509cert_chain(const char *caption, cert_t* cert,
+ x509_flag_t flags, bool utc);
extern void list_x509_end_certs(bool utc);
-extern void free_generalNames(generalName_t* gn, bool free_name);
#endif /* _X509_H */
diff --git a/src/pluto/xauth.c b/src/pluto/xauth.c
index af2d72d71..2086a92cc 100644
--- a/src/pluto/xauth.c
+++ b/src/pluto/xauth.c
@@ -1,7 +1,7 @@
/* Initialization and finalization of the dynamic XAUTH module
* Copyright (C) 2006 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
@@ -23,7 +23,7 @@
#include "keys.h"
#include "log.h"
-void
+void
xauth_init(void)
{
#ifdef XAUTH_DEFAULT_LIB
diff --git a/src/pluto/xauth.h b/src/pluto/xauth.h
index 8ab125ac4..23cae3ed8 100644
--- a/src/pluto/xauth.h
+++ b/src/pluto/xauth.h
@@ -1,7 +1,7 @@
/* Interface definition of the XAUTH server and|or client module
* Copyright (C) 2006 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